MATLAB 中的幂法
Power Method in MATLAB
我想在 MATLAB 中实现 Power Method 以确定矩阵的主特征值和特征向量。
这是我到目前为止写的:
%function to implement power method to compute dominant
%eigenvalue/eigenevctor
function [m,y_final]=power_method(A,x);
m=0;
n=length(x);
y_final=zeros(n,1);
y_final=x;
tol=1e-3;
while(1)
mold=m;
y_final=A*y_final;
m=max(y_final);
y_final=y_final/m;
if (m-mold)<tol
break;
end
end
end
使用上面的代码,这里是一个数值示例:
A=[1 1 -2;-1 2 1; 0 1 -1]
A =
1 1 -2
-1 2 1
0 1 -1
>> x=[1 1 1];
>> x=x';
>> [m,y_final]=power_method(A,x);
>> A*x
ans =
0
2
0
在MATLAB中比较上述矩阵的特征值和特征向量时,我做了:
[V,D]=eig(A)
V =
0.3015 -0.8018 0.7071
0.9045 -0.5345 0.0000
0.3015 -0.2673 0.7071
D =
2.0000 0 0
0 1.0000 0
0 0 -1.0000
特征值重合,但特征向量应该趋近[1/3 1 1/3]
。在这里,我得到:
y_final
y_final =
0.5000
1.0000
0.5000
看到这种不准确是否可以接受,还是我犯了一些错误?
你有正确的实现,但你没有检查特征向量和特征值是否收敛。您只是检查收敛的特征值。幂法估计突出的特征向量和特征值,因此检查 both 是否收敛可能是个好主意。当我这样做时,我设法得到 [1/3 1 1/3]
。以下是我如何修改您的代码以促进此操作:
function [m,y_final]=power_method(A,x)
m=0;
n=length(x);
y_final=x;
tol=1e-10; %// Change - make tolerance more small to ensure convergence
while(1)
mold = m;
y_old=y_final; %// Change - Save old eigenvector
y_final=A*y_final;
m=max(y_final);
y_final=y_final/m;
if abs(m-mold) < tol && norm(y_final-y_old,2) < tol %// Change - Check for both
break;
end
end
end
当我 运行 上述代码与您的示例输入时,我得到:
>> [m,y_final]=power_method(A,x)
m =
2
y_final =
0.3333
1.0000
0.3333
关于 eig
的旁注,MATLAB 很可能使用另一个范数缩放该特征向量。请记住,特征向量 不是唯一的 并且精确到比例。如果你想确定,只需取V
的第一列,与主导特征向量重合,除以最大值,这样我们就可以得到一个要归一化为1的分量,就像幂法:
>> [V,D] = eig(A);
>> V(:,1) / max(abs(V(:,1)))
ans =
0.3333
1.0000
0.3333
这与您观察到的一致。
我想在 MATLAB 中实现 Power Method 以确定矩阵的主特征值和特征向量。
这是我到目前为止写的:
%function to implement power method to compute dominant
%eigenvalue/eigenevctor
function [m,y_final]=power_method(A,x);
m=0;
n=length(x);
y_final=zeros(n,1);
y_final=x;
tol=1e-3;
while(1)
mold=m;
y_final=A*y_final;
m=max(y_final);
y_final=y_final/m;
if (m-mold)<tol
break;
end
end
end
使用上面的代码,这里是一个数值示例:
A=[1 1 -2;-1 2 1; 0 1 -1]
A =
1 1 -2
-1 2 1
0 1 -1
>> x=[1 1 1];
>> x=x';
>> [m,y_final]=power_method(A,x);
>> A*x
ans =
0
2
0
在MATLAB中比较上述矩阵的特征值和特征向量时,我做了:
[V,D]=eig(A)
V =
0.3015 -0.8018 0.7071
0.9045 -0.5345 0.0000
0.3015 -0.2673 0.7071
D =
2.0000 0 0
0 1.0000 0
0 0 -1.0000
特征值重合,但特征向量应该趋近[1/3 1 1/3]
。在这里,我得到:
y_final
y_final =
0.5000
1.0000
0.5000
看到这种不准确是否可以接受,还是我犯了一些错误?
你有正确的实现,但你没有检查特征向量和特征值是否收敛。您只是检查收敛的特征值。幂法估计突出的特征向量和特征值,因此检查 both 是否收敛可能是个好主意。当我这样做时,我设法得到 [1/3 1 1/3]
。以下是我如何修改您的代码以促进此操作:
function [m,y_final]=power_method(A,x)
m=0;
n=length(x);
y_final=x;
tol=1e-10; %// Change - make tolerance more small to ensure convergence
while(1)
mold = m;
y_old=y_final; %// Change - Save old eigenvector
y_final=A*y_final;
m=max(y_final);
y_final=y_final/m;
if abs(m-mold) < tol && norm(y_final-y_old,2) < tol %// Change - Check for both
break;
end
end
end
当我 运行 上述代码与您的示例输入时,我得到:
>> [m,y_final]=power_method(A,x)
m =
2
y_final =
0.3333
1.0000
0.3333
关于 eig
的旁注,MATLAB 很可能使用另一个范数缩放该特征向量。请记住,特征向量 不是唯一的 并且精确到比例。如果你想确定,只需取V
的第一列,与主导特征向量重合,除以最大值,这样我们就可以得到一个要归一化为1的分量,就像幂法:
>> [V,D] = eig(A);
>> V(:,1) / max(abs(V(:,1)))
ans =
0.3333
1.0000
0.3333
这与您观察到的一致。