共轭梯度法解求解大规模稀疏矩阵,对比最速梯度法(C++)

这篇具有很好参考价值的文章主要介绍了共轭梯度法解求解大规模稀疏矩阵,对比最速梯度法(C++)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

记录计算方法大作业,练习C++,欢迎指正。

1,共轭梯度法介绍

共轭梯度法(Conjugate Gradient)是介于最速下降法与牛顿法之间的一个方法,它仅需利用一阶导数信息,但克服了最速下降法收敛慢的缺点,又避免了牛顿法需要存储和计算Hesse矩阵并求逆的缺点。共轭梯度法不仅是解决大型线性方程组最有用的方法之一,也是解大型非线性最优化最有效的算法之一。

在实际应用中,共轭梯度法不仅可以去求解方程组,还可以推广到非二次目标函数的极小值求解。在各种优化算法中,共轭梯度法是非常重要的一种。其优点是所需存储量小,具有步收敛性,稳定性高,而且不需要任何外来参数。

2,共轭梯度法原理

求解 Ax=b时,最简单粗暴的方式为 x=A-1 *b。但是这种方法的问题很明显:矩阵求逆的计算复杂度非常高。即使我们考虑用矩阵分解的方式,仍然会很慢。 因此,我们尽可能考虑用迭代的方式,而不是直接求逆的方式来解这个问题。如果构造一个二次函数:f(x)=xT Ax/2-b T x,求其最小值,即其导数为0时正好是方程Ax=b的解。因此,我们可以将线性方程组求解问题转化为二次函数求极小值问题

在寻优过程中利用当前点xk大规模稀疏矩阵,c++,算法,矩阵 处的残向量rk大规模稀疏矩阵,c++,算法,矩阵 和前一迭代点xk-1大规模稀疏矩阵,c++,算法,矩阵 处的搜索方向dk-1大规模稀疏矩阵,c++,算法,矩阵 对搜索方向进行如下修正:

𝑑𝑘 = 𝑟𝑘 + 𝛽𝑘−1𝑑𝑘−1

其修正系数𝛽𝑘−1的取值有一个约束条件,即要确保𝑑𝑘与𝑑𝑘 , 𝑑𝑘−1 ,⋯, 𝑑0之间满足 关于 A 的共轭关系。这就是共轭梯度法的基本思想。可以看出共轭梯度法的搜 索方向𝑑𝑘的计算只需要梯度向量,不需要海森矩阵 H,可以推广到非二次目标函 数的极小值求解。

下面给出共轭梯度法求解方程组的伪代码:

(1) 给定初始近似向量𝑥 (0)以及精度𝜖 > 0;

(2) 计算𝑟 (0) = 𝑏 − 𝐴𝑥 (0),𝑑 (0) = 𝑟 (0);

(3) for k=0 to n-1 do

      (i) 𝛼𝑘 = 𝑟 (𝑘)𝑇𝑟 (𝑘) 𝑑(𝑘)𝑇𝐴𝑑(𝑘) ;

     (ii) 𝑥 (𝑘+1) = 𝑥 (𝑘) + 𝛼𝑘𝑑 (𝑘) ;

     (iii) 𝑟 (𝑘+1) = 𝑏 − 𝐴𝑥 (𝑘+1) ;

    (iv) 如果|| 𝑟 (𝑘+1) || < 𝜖或者 k+1=n,则输出近似解𝑥 (𝑘+1),停止;否则转(v)

    (v) 𝛽𝑘 = || 𝑟 (𝑘+1) ||2 2 || 𝑟 (𝑘) ||2 2 ;

     (vi) 𝑑 (𝑘+1) = 𝑟 (𝑘+1) + 𝛽𝑘𝑑 (𝑘) ;

end do

3,共轭梯度法和最速下降法的比较

本次计算的实例采用的是课本第 133 页中的例 3.2,分别分析了 n 的取值为 100,200,400 时的情况,并同时用共轭梯度法和最速下降法去求解线性方程, 设置两种方法的精度为 0.0001。

3.1程序说明

该程序只包含一个 cpp 文件。请将要求解的方程组的系数矩阵保存在对应文 件夹下的 data.txt 中。 程序中有共轭梯度法和最速下降法的函数,两种方法求得的结果和对应的迭 代 误 差 保 存 在 对 应 文 件 夹 下 的 ConjugateGradientMethod.txt 和 SteepestDescentMethod.txt 中。文件夹保存和读取的路径都放在程序开头的全局 变量中,可以自行修改。

3.2,迭代误差

大规模稀疏矩阵,c++,算法,矩阵

 图 1-1 共轭梯度法的迭代误差变化 图 1-1 是共轭梯度法迭代过程中的误 差变化,可以看出该方法最终收敛,且共轭梯度解出来的结果是一个全 1 的向 量,也就是所有的未知数都是 1。 通过最速下降法得到的解为[0.5,0,0,0,0,0,……,0,0,0,0.5],即 x1 和 x100 是 0.5, 其他 x 的值为 0,带入到原方程组中发现符合解特征。而且最速下降法只迭代一 次就得到最终解

(2)N=200

大规模稀疏矩阵,c++,算法,矩阵

(3)N=400

大规模稀疏矩阵,c++,算法,矩阵

3.3两种方法比较

(1)迭代结果

大规模稀疏矩阵,c++,算法,矩阵

(2)迭代速度

大规模稀疏矩阵,c++,算法,矩阵

大规模稀疏矩阵,c++,算法,矩阵

 图 1-4 是两种方法解方程组迭代收敛的过程,可以看出共轭梯度在进行四 次迭代时就已经收敛,最速下降法在 9 次迭代之后才收敛。从迭代误差的变化 中可以发现此时梯度下降法的每次迭代的误差总是比上次小,但是最速下降法 每次迭代的误差还可能比前一次大,说明共轭梯度在每次迭代都是向着准确解 的方向移动。

最速下降法相邻两次迭代的方向是正交的,这就说明最速下降法每次迭代 的方向并不是都朝着最优解的方向,而且这种正交性会导致最速下降法向极小点逼近是曲折前进的,这种现象会影响收敛速度。同时这种迭代方式很可能使 迭代陷入局部最优解,影响优化的结果。

4,代码

主函数:

int main()
{
	//vector<vector<double>> A = { {2,0,1},{0,1,0},{1,0,2} };
	//vector<double> B = { 3,1,3 };
	// 
	//定义矩阵
	vector<vector<double>> A;
	vector<double> B;


	//加载算例3.2
	//SuanLi32(A, B,400);
	//加载数据,数据保存路径在全局变量S中
	Load_data(A, B);

	//定义精度
	double Accuracy = 0.0001;
	
	//定义结果x,和迭代的误差erro
	vector<double> x, erro;
	vector<double> x1, erro1;

	//梯度下降法,结果保存在路径S的ConjugateGradientMethod.txt
	ConjugateGradientMethod(A, B, Accuracy, x, erro);

	//显示结果
	for_each(x.begin(), x.end(), PrintV);
	cout << endl;
	for_each(erro.begin(), erro.end(), PrintV);

		//最速下降法,结果保存在路径S的ConjugateGradientMethod.txt
	SteepestDescentMethod(A, B, Accuracy, x1, erro1);

	//显示结果
	for_each(x1.begin(), x1.end(), PrintV);
	cout << endl;
	for_each(erro1.begin(), erro1.end(), PrintV);

	system("pause");
	return 0;
}

 共轭梯度法

void ConjugateGradientMethod(vector<vector<double>>& A, vector<double>& B, 
	double& Accuracy, vector<double>& x, vector<double>& erro)
{
	int n = A.size();
	vector<double> r(n), d(n),Ad(n),xx(n),ad(n),Ax,r1,betad,d1;
	double rr,r1r,dAd,a,beta=0,err=1;
	//赋初值
	x.assign(n, 0);
	r.assign(B.begin(), B.end());
	d.assign(B.begin(), B.end());
	while (err> Accuracy)
	{
		rr = Vect_vec(r, r);
		Ad = Mat_vector(A, d);
		dAd = Vect_vec(d, Ad);
		a = rr / dAd;//i
		ad = Constant_vector(a, d);
		xx = Add_vector(ad, x);//ii
		Ax = Mat_vector(A, xx);
		r1 = Sub_vector(B, Ax);//iii
		r1r = Vect_vec(r1, r1);
		beta = r1r / rr;
		betad = Constant_vector(beta, d);
		d1 = Add_vector(r1, betad);
		err = sqrt(r1r);
		//迭代
		r.assign(r1.begin(), r1.end());
		d.assign(d1.begin(), d1.end());
		x.assign(xx.begin(), xx.end());
		erro.push_back(err);
	}

	//保存结果
	ofstream ofs;
	ofs.open("ConjugateGradientMethod.txt", ios::out | ios::app);
	if (!ofs.is_open())
	{
		cout << "储存文件打开失败!" << endl;
	}
	else
	{
		for (int i = 0; i < n; i++)
		{
			ofs << x[i] << "\t";
		}
		ofs << endl;
		int l = erro.size();
		for (int i = 0; i < l; i++)
		{
			ofs << erro[i] << "\t";
		}
	}
	ofs.close();

	return;
}

void PrintV(const double& a)
{
	cout << a << " ";
}

最速梯度法:

void SteepestDescentMethod(vector<vector<double>>& A, vector<double>& B,
	double& Accuracy, vector<double>& x, vector<double>& erro)
{
	int n = A.size();
	vector<double> r(n), d(n), Ar(n), xx(n), ar(n), Ax, r1, betad, d1;
	double  a=0, err = 1,a1,a2;
	//赋初值
	x.assign(n, 0);
	r.assign(B.begin(), B.end());
	while (err > Accuracy)
	{
		Ar = Mat_vector(A, r);
		a=Vect_vec(r,r)/ Vect_vec(Ar,r);
		//a2=inner_product(Ar.begin(), Ar.end(), r.begin(), 0) ;
		//a = double(inner_product(r.begin(), r.end(), r.begin(), 0) )/double(inner_product(Ar.begin(), Ar.end(), r.begin(), 0));
		ar = Constant_vector(a, r);
		xx = Add_vector(x, ar);
		Ax = Mat_vector(A, xx);
		r1 = Sub_vector(B, Ax);//iii
		err = sqrt(inner_product(r1.begin(),r1.end(),r1.begin(),0));
		//迭代
		r.assign(r1.begin(), r1.end());
		x.assign(xx.begin(), xx.end());
		erro.push_back(err);
		//i++; cout << err << endl;
	}

	//保存结果
	ofstream ofs;
	ofs.open("SteepestDescentMethod.txt", ios::out | ios::app);
	if (!ofs.is_open())
	{
		cout << "储存文件打开失败!" << endl;
	}
	else
	{
		for (int i = 0; i < n; i++)
		{
			ofs << x[i] << "\t";
		}
		ofs << endl;
		int l = erro.size();
		for (int i = 0; i < l; i++)
		{
			ofs << erro[i] << "\t";
		}
	}
	ofs.close();

	return;
}

其他矩阵向量或者函数

vector<double> Mat_vector(vector<vector<double>>& A, vector<double>& d)
{
	vector<double> Ad;
	int m = A.size();
	for (int i = 0; i < m; i++)
	{
		double temp = 0;
		for (int j = 0; j < m; j++)
		{
			temp += A[i][j] * d[j];
		}
		Ad.push_back(temp);
	}
	return Ad;
}

double Vect_vec(vector<double>& a1, vector<double>& a2)
{
	int m = a1.size();
	double a=0;
	for (int i = 0; i < m; i++)
	{
		a += a1[i] * a2[i];
	}
	return a;
}

vector<double> Sub_vector(vector<double>& a1, vector<double>& a2)
{
	int m = a1.size();
	vector<double> a;
	double temp;
	for (int i = 0; i < m; i++)
	{
		temp = a1[i] - a2[i];
		a.push_back(temp);
	}
	return a;
}

vector<double> Add_vector(vector<double>& a1, vector<double>& a2)
{
	int m = a1.size();
	vector<double> a;
	double temp;
	for (int i = 0; i < m; i++)
	{
		temp = a1[i] + a2[i];
		a.push_back(temp);
	}
	return a;
}

vector<double> Constant_vector(double &c,vector<double>& a1)
{
	int m = a1.size();
	vector<double> a;
	double temp;
	for (int i = 0; i < m; i++)
	{
		temp = a1[i]*c;
		a.push_back(temp);
	}
	return a;
}


void SuanLi32(vector<vector<double>>& A, vector<double>& B, int n)
{
	//定义B矩阵
	B.push_back(-1);
	for (int i = 1; i < n - 1; i++)
	{
		B.push_back(0);
	}
	B.push_back(-1);
	//定义A矩阵
	vector<double> a1(n - 2, 0);
	a1.insert(a1.begin(),1);
	a1.insert(a1.begin(), -2);
	A.push_back(a1);
	for (int i = 1; i < n - 1; i++)
	{
		vector<double> a;
		for (int j = 0; j < n; j++)
		{
			if (j == i)
			{
				a.push_back(-2);
			}
			else if (j == i - 1 || j == i + 1)
			{
				a.push_back(1);
			}
			else
			{
				a.push_back(0);
			}
		}
		A.push_back(a);
	}
	vector<double> a2(n - 2, 0);
	a2.push_back(1);
	a2.push_back(-2);
	A.push_back(a2);
}

加载数据

void Load_data(vector<vector<double>>& A, vector<double>& B)
{
	ifstream ifs;
	int n = 0;
	string s;
	double a,b;
	//行数n
	ifs.open(path, ios::in);
	if (ifs.fail())
	{
		cout << "文件打开失败!"<<endl;
	}
	else
	{
		while (getline(ifs, s))
		{
			n++;
		}
	}
	ifs.close();
	ifs.open(path, ios::in);

	while (!ifs.eof())
	{
		for (int i = 0; i < n; i++)
		{
			vector<double> aa;
			for (int j = 0; j < n; j++)
			{
				ifs >> a;
				aa.push_back(a);
			}
			ifs >> b;
			B.push_back(b);
			A.push_back(aa);
		}
	}
	ifs.close();
	return;
}

头文件和全局变量文章来源地址https://www.toymoban.com/news/detail-715259.html

#include<iostream>
#include<vector>
#include<cmath>
#include<algorithm>
#include<fstream>
#include<string>
#include<numeric>

using namespace std;

string path = "data.txt";

到了这里,关于共轭梯度法解求解大规模稀疏矩阵,对比最速梯度法(C++)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 大规模语言模型--LLaMA 家族

    LLaMA 模型集合由 Meta AI 于 2023 年 2 月推出, 包括四种尺寸(7B 、13B 、30B 和 65B)。由于 LLaMA 的 开放性和有效性, 自从 LLaMA 一经发布, 就受到了研究界和工业界的广泛关注。LLaMA 模型在开放基准的各 种方面都取得了非常出色的表现, 已成为迄今为止最流行的开放语言模型。大

    2024年04月25日
    浏览(43)
  • LLaMA(大规模机器学习和分析)

    LLaMA(大规模机器学习和分析)是一个先进的软件平台,是Meta 推出 AI 语言模型 LLaMA,一个有着 上百亿数量级参数的大语言模型用于大规模部署和管理机器学习模型。借助LLaMA,组织可以高效地在大型数据集上训练和部署模型,缩短投放市场的时间,并提高预测模型的准确性。

    2024年02月11日
    浏览(54)
  • 基于Spark的大规模日志分析

    摘要: 本篇文章将从一个实际项目出发,分享如何使用 Spark 进行大规模日志分析,并通过代码演示加深读者的理解。 本文分享自华为云社区《【实战经验分享】基于Spark的大规模日志分析【上进小菜猪大数据系列】》,作者:上进小菜猪。 随着互联网的普及和应用范围的扩

    2024年02月09日
    浏览(54)
  • 服务器单机大规模数据存储方案

    大规模数据存储都需要解决三个核心问题: 1.数据存储容量的问题,既然大数据要解决的是数据 PB 计的数据计算问题,而一般的服务器磁盘容量通常 1~2TB,那么如何存储这么大规模的数据呢? 2.数据读写速度的问题,一般磁盘的连续读写速度为几十 MB,以这样的速度,几十

    2024年02月11日
    浏览(55)
  • 云计算:如何访问和分析大规模数据

    作者:禅与计算机程序设计艺术 随着云计算平台的不断发展,越来越多的企业将他们的数据、应用和服务部署在云端,希望借助云计算的能力来提升效率、降低成本、提高竞争力。但是同时也带来了数据安全、隐私保护、数据可靠性等方面的挑战。对于企业而言,如何更好地

    2024年02月15日
    浏览(45)
  • etcd实现大规模服务治理应用实战

         导读 :服务治理目前越来越被企业建设所重视,特别现在云原生,微服务等各种技术被更多的企业所应用,本文内容是百度小程序团队基于大模型服务治理实战经验的一些总结,同时结合当前较火的分布式开源kv产品etcd,不仅会深入剖析ectd两大核心技术Raft与boltdb的实

    2024年02月12日
    浏览(48)
  • ChatGPT大规模封锁亚洲地区账号

    我是卢松松,点点上面的头像,欢迎关注我哦! 在毫无征兆的情况下,从3月31日开始OpenAI大规模封号,而且主要集中在亚洲地区,特别是ip地址在台湾、日本、香港三地的,命中率目测40%。新注册的账号、Plus也不好使了。 如果你登陆的时候出现“提示无法加载历史信息”或

    2023年04月09日
    浏览(60)
  • 利用Python进行大规模数据处理

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 随着数据量的不断增长,大规模数据处理变得越来越重要。在这个领域,Hadoop和Spark是两个备受关注的技术。本文将介绍如何利用Python编程语

    2024年04月24日
    浏览(39)
  • 高防服务器如何抵御大规模攻击

    高防服务器如何抵御大规模攻击?高防服务器是一种专门设计用于抵御大规模攻击的服务器,具备出色的安全性和可靠性。在当今互联网时代,网络安全问题日益严重,DDOS攻击(分布式拒绝服务攻击)等高强度攻击已成为威胁企业和组织网络安全的重要问题。为了保护网站和

    2024年02月09日
    浏览(53)
  • Apache Doris大规模数据使用指南

    目录 一、发展历史 二、架构介绍 弹性MPP架构-极简架构 逻辑架构 基本访问架构 三、Doris的数据分布

    2024年02月12日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包