我已经实现了高斯-牛顿优化过程,该过程涉及通过求解线性化系统 Hx = b
来计算增量。 H
矩阵由 H = J.transpose() * W * J
计算,b
由 b = J 计算。 transpose() * (W * e)
其中 e
是误差 vector 。这里的 Jacobian 是一个 n×6 矩阵,其中 n 以千为单位并且在迭代过程中保持不变,W
是一个 n×n 对角权重矩阵,它将在迭代过程中发生变化(一些对角元素将是设置为零)。但是我遇到了速度问题。
当我不添加权重矩阵W
时,即H = J.transpose()*J
和b = J.transpose()*e
,我的高斯-牛顿过程可以在 0.02 秒内非常快地运行 30 次迭代。但是,当我添加在迭代循环外定义的 W
矩阵时,它变得很慢(30 次迭代为 0.3~0.7 秒),我不明白这是我的编码问题还是正常情况花了这么长时间。
这里的一切都是特征矩阵和 vector 。
我使用 Eigen 库中的 .asDiagonal()
函数从逆方差 vector 定义了我的 W
矩阵。然后就用它来计算 H
和 b
。然后它变得非常缓慢。我希望得到一些关于这种巨大放缓的潜在原因的提示。
编辑:
只有两个矩阵。雅可比绝对是稠密的。权重矩阵由来自密集库的函数 vec.asDiagonal()
从 vector 生成,因此我假设它也是密集的。
代码非常简单,导致时间变化的唯一区别是添加了权重矩阵。这是一个代码片段:
for (int iter=0; iter<max_iter; ++iter) {
// obtain error vector
error = ...
// calculate H and b - the fast one
Eigen::MatrixXf H = J.transpose() * J;
Eigen::VectorXf b = J.transpose() * error;
// calculate H and b - the slow one
Eigen::MatrixXf H = J.transpose() * weight_ * J;
Eigen::VectorXf b = J.transpose() * (weight_ * error);
// obtain delta and update state
del = H.ldlt().solve(b);
T <- T(del) // this is pseudo code, meaning update T with del
}
它在类中的函数中,现在用于调试目的的权重矩阵被定义为函数可以访问的类变量,并在调用函数之前定义。
最佳答案
我猜 weight_
被声明为密集的 MatrixXf
?如果是这样,那么在你使用 weight_
的任何地方用 w.asDiagonal()
替换它,或者使后者成为 asDiagonal
表达式的别名:
auto weight = w.asDiagonal();
这样 Eigen 就会知道 weight
是一个对角矩阵,并且计算将按预期进行优化。
关于c++ - Eigen 中的矩阵乘法非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44938294/