特征向量的数值求法

-对于正定的对称矩阵,奇异值等于特征值,奇异向量等于特征向量。在这种情况下用奇异值分解就把特征值和特征向量求出来了。但是只要是方阵,它就有特征值和特征向量,对于一般的方阵,特征值和特征向量怎么求呢(当然我指的是数值求法)?这就要用本文即将介绍的“幂法”。

Power Method幂法

Definition 如果λ1是矩阵A的所有特征值中绝对值最大的那一个,则称λ1是A的主特征值;与λ1对应的特征向量v1是A的主特征向量。

幂法是用来计算方阵的主特征值(即绝对值最大的特征值)和主特征向量的。由此延伸出来的反幂法用来计算在给定点附近的特征值和特征向量(下文把“特征值和特征向量”简称为“特征对”)。

Definition 特征向量V的归一化是指:V的每一个元素除以V中绝对值最大的那个元素。

Theorem(Power Method) 设A是n×n的方阵,有n个不同的特征值,且|λ1| > |λ2| >= |λ3| >= ... >= |λn|。选择一个合适的X0,序列和{ck}由下列递归式产生:

其中

经过多次迭代后Xk趋于主特征向量V1,ck趋于主特征值λ1

Remark 如果X0选取的刚好是一个特征向量,且X0又不是主特征向量,则X0需要重新选取。

Speed of Convergence收敛加速

幂法的收敛速度取决于,也就是说它的收敛速度是线性的。Aitken 加速法可用于任何线性收敛的序列当中,它采用的加速方式是:

用Aitken来加速我们的幂法,Xk的调整公式为:

Shifted-Inverse Power Method平移反幂法

使用位移反幂法首先需要提供一个好的起始点,这个点要接近一个特征向量,然后我们的位移反幂法才能够以更高的精度算出这个特征向量。QM和Given's method可以用来获得这种初始点,这里不介绍了。在实际情况中,特征值可能是复数,有多个特征相同或很接近,这都会使得计算变得很复杂需要更高级的算法。我们只考虑简单的情况,所有的特征值各不相同。

Theorem (Shifting Eigenvalues) 假设λ和V是A的一个特征对,a是任何常量,那么λ-a,V就是矩阵的一个特征对。

Theorem (Inverse Eigenvalues) 假设λ和V是A的一个特征对,,那么,V是A-1的一个特征对。

Theorem (Shifted-Inverse Eigenvalues) 假设λ和V是A的一个特征对,,那么,V是的一个特征对。

Theorem (Shifted-Inverse Power Method) 假设A是一个n×n的矩阵,有n个互不相同的特征值λ1,λ2,...,λn。对于其中之一个特征值λj,可以选择一个常数a,使得是的主特征值。进一步地,如果选择一个合适的X0,序列和{ck}可由下列递归式产生:

 

其中

 经过多次迭代后Xk趋于的主特征向量Vj,Xk同时也是A的主特征向量,ck趋于的主特征值u1。最终我们可以求出A的主特征值:

在求解(3)式时需要解一个线性方程组,常用的方法是雅可比迭代和高斯-赛德尔迭代。当然你也可以用的方法进行初等行变换来求得矩阵的逆,那样就不用解线性方程组。不过你要衡量哪种方式快一些,而且矩阵的逆不存在怎么办。

高斯-赛德尔迭代公式为:

注意aii即系数矩阵主对角线上的元素不能有0,否则需要事先进行行变换,把0移走。

Exercise

用幂法求一个矩阵的主特征对。

取最大迭代次数为50,收敛时误差为0.000001。

matrix.h

#ifndef _MATRIX_H
#define _MATRIX_H
   
#include
#include
#include
 
//初始化一个二维矩阵
double** getMatrix(int rows,int columns){
    double **rect=(double**)calloc(rows,sizeof(double*));
    int i;
    for(i=0;i

power.c

#include"matrix.h"
#include

#define ROW 6
#define ITERATION 50
#define EPSILON 0.000002

//找出矩阵元素绝对值最大者
double getMaxEle(double **matrix,int rows,int cols){
	double rect=0;
	int i,j;
	for(i=0;irect)
				rect=fabs(matrix[i][j]);
		}
	}
	return rect;
}

int main(){
	//给矩阵A赋值
	double **A=getMatrix(ROW,ROW);
	double A1[ROW*ROW]={87,270,-12,-49,-276,40,-14,-45,6,10,46,-4,-50,-156,4,25,162,-25,94,294,-5,-47,-306,49,1,1,3,1,0,2,16,48,1,-6,-48,8};
	getFromArray(A,ROW,ROW,A1);
	//取初始X
	double **X=getMatrix(ROW,1);
	double X0[ROW]={1,1,1,1,1,1};
	getFromArray(X,ROW,1,X0);
	//初始化c
	double c=0;
	//初始化Y
	double **Y=getMatrix(ROW,1);
	//开始迭代
	int iteration=0;
	while(iteration++0);
		double **newX=dotProduct(Y,ROW,1,1/c);
		int i;
		//计算前后两次X的差值
		double epsilon=0.0;
		for(i=0;i

用位移反幂法求下列矩阵在a=4.2附近的特征值及对应的特征向量。

取最大迭代次数为50,收敛误差为0.000002。

GS.h  (高斯-赛德尔迭代)

#ifndef _GS_H
#define _GS_H

#include"matrix.h"
#include

double** Gauss_Seidel(double **A,int row,double **B){
	double **X=getMatrix(row,row);
	int i;
	for(i=0;i

InversePower.c

#include"GS.h"

#define ROW 3
#define ITERATION 50
#define EPSILON 0.0000001
#define ALPHA 4.2

//找出矩阵元素绝对值最大者
double getMaxEle(double **matrix,int rows,int cols){
	double rect=0;
	int i,j;
	for(i=0;irect)
				rect=fabs(matrix[i][j]);
		}
	}
	return rect;
}

int main(){
	int i;
	//给矩阵A赋值
	double **A=getMatrix(ROW,ROW);
	double A1[ROW*ROW]={0,11,-5,-2,17,-7,-4,26,-10};
	getFromArray(A,ROW,ROW,A1);
	//取初始X
	double **X=getMatrix(ROW,1);
	for(i=0;i0);
		double **newX=dotProduct(Y,ROW,1,1/c);
		//计算前后两次X的差值
		double epsilon=0.0;
		for(i=0;i

你可能感兴趣的:(人工智能)