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

时间:2016-10-05 02:20:56

标签: matlab performance eigenvector

[V D] = eig(A)

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

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

3 个答案:

答案 0 :(得分:0)

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

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

希望这有帮助。

答案 1 :(得分:0)

只有时间会告诉我们什么表现更好,但复杂性方面,查看第一个元素是非常有效的,只有当你发现它有错误的符号时才对整个向量进行操作。

所以,如果你有

E = rand(n)-0.5;

然后这个解决方案:

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

平均运行1 + n / 2个元素

这样的东西
E = E * sign(E(1))

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

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

答案 2 :(得分:0)

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

这可以通过以下方式使用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.

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