MATLAB:翻转特征向量符号的有效方法

MATLAB: efficient way to flip the sign of eigenvectors

[V D] = eig(A)

给出符号不一致的特征向量,有时第一项为正,有时为负。对于一般用途来说还可以,但不幸的是,对于我的工作,我需要标志保持一致。例如在针对不同 A 的一系列此类评估中。例如,我希望所有特征向量的第一个条目都是正的。有哪些有效的方法可以实现这一目标?

这是我的想法:翻转符号的 if-else 语句(如果第一个条目为负数,则翻转)。但它似乎效率不高,因为我必须多次评估特征向量。

您可以使用第一个元素确定符号并翻转矩阵:

 [V, D] = eig(A * sign(A(1)));

希望对您有所帮助。

只有计时会告诉我们哪个表现更好,但从复杂性的角度来看,查看第一个元素非常有效,并且只有在发现符号错误时才对整个向量进行操作。

所以如果你有

E = rand(n)-0.5;

那么这个解决方案:

if E(1)<0
   E = -E;
end

平均会对 1+n/2 个元素进行操作

虽然

E = E * sign(E(1))

将对 1+n 个元素进行操作。

话虽如此,如果您发现值得优化的速度差异,我会感到很惊讶,所以请随意选择最直观的解决方案。

首先,一般来说,特征值和特征向量可以是复数。当我们谈论 sign 时应该考虑到这一点。在这里,我假设您希望所有特征向量的第一个元素为 realpositive.

这可以使用 bsxfun 以这种方式矢量化:

[V, D] = eig(A);
% get the sign of the first row:
signs = sign(V(1, :));
% multiply all columns by the complex conjugate of sign of the first element:
V = bsxfun(@times, V, conj(signs));

基准测试:

如果将此方法的速度与 if 语句的循环进行比较,您会发现我的建议要慢一些。但顺便说一句,这种方法应该与能够处理复杂值的等效循环进行比较。这是我的测试结果:

% the loop solution:
for ii = 1:size(V, 2)
        V(:, ii) = V(:, ii) * conj(sign(V(1, ii)));
end

% A = rand(2);
------------------- With BSXFUN
Elapsed time is 0.744195 seconds.
------------------- With LOOP
Elapsed time is 0.500803 seconds.

% A = rand(10);
------------------- With BSXFUN
Elapsed time is 0.828464 seconds.
------------------- With LOOP
Elapsed time is 0.835429 seconds.

% A = rand(100);
------------------- With BSXFUN
Elapsed time is 1.421716 seconds.
------------------- With LOOP
Elapsed time is 4.286256 seconds.

如您所见,这取决于您的应用程序。如果您有很多很多小矩阵,循环解决方案看起来更方便。另一方面,如果您要处理更大的矩阵,那么矢量化解决方案肯定会更有效地完成工作。