最近尝试将一个MATLAB程序通过codegen编译成C++库调用,好不容易编译通过但是运行结果不对,一步步跟踪下来发现是eig函数的问题,记录一下。
现象如同这个例子Matlab Codgen eig() function - strange behaviour。原本在MATLAB中工作正常的程序,编译成库后由于eig函数的结果出现了不同的排序方式和符号,导致最终的错误。例子中的回答也给出了解决方法:手动再对特征值和特征向量进行规范化处理——
1.Normalize all eigenvectors to length 1 (example: [-0.4472,-0.4472,-0.4472,0.4472,0.4472]’ instead of [-1,-1,-1,1,1]‘). Could be achieved using b=bsxfun(@rdivide,b,sqrt(sum(b.^2,1))).
2.For each eigenvectors with a negative value in the first component, take the negative value. (example: [0.4472,0.4472,0.4472,-0.4472,-0.4472]’ instead of [-0.4472,-0.4472,-0.4472,0.4472,0.4472]'). Could be achieved using b=bsxfun(@times,sign(b(1,:)),b).
3.Sort eigenvectors and eigenvalues in ascending order of the eigenvalues.
[V,D] = eig(A);
[D,I] = sort(diag(D));
V = V(:, I);
其实MATLAB的帮助文档中Differences Between Generated Code and MATLAB Code也提到了:
Certain mathematical operations, such as singular value decomposition and eigenvalue decomposition of a matrix, can have multiple answers. Two different algorithms implementing such an operation can return different outputs for identical input values. Two different implementations of the same algorithm can also exhibit the same behavior.
For such mathematical operations, the corresponding functions in the generated code and MATLAB might return different outputs for identical input values. To see if a function has this behavior, in the corresponding function reference page, see the C/C++ Code Generation section under Extended Capabilities. Examples of such functions include svd and eig.
做PCA的时候也很有可能遇到类似的问题(因为其中就用到了eig)。还有svd函数也是类似的。
这个来自SAS公司的博客The curse of non-unique eigenvectors也是同样的议题。
附上线性代数复习,from No bullshit guide to linear algebra ——
