【问题标题】:Function to invert Eigen matrix without branching statements for auto differentiation用于反转特征矩阵的函数,无需用于自动微分的分支语句
【发布时间】:2021-12-24 06:27:47
【问题描述】:

我需要反转一个特征矩阵(在我的特定情况下为 9x9)作为我想使用 CppAD 自动区分的代码的一部分。为此,执行反转的代码不能包含任何分支,例如 if 或 switch 语句。不幸的是,Eigen 的反函数包含分支,使得 CppAD 的算法微分失败。

从数学上讲,应该可以提出一个公式,该公式不需要为保证可逆的固定矩阵大小进行分支。对吗?

你知道有什么库可以在没有分支的情况下实现这种逆运算吗?

【问题讨论】:

  • 我使用了块矩阵求逆和 Eigen 的固定大小矢量化求逆例程(4 x 4 或更小)来计算 10 x 10 的逆。您需要知道对角线上的特定子块(比如左上角)在编译时是否可逆。在我的例子中,它实际上比 LU 分解要快得多,而且和 LU 分解一样准确。 en.wikipedia.org/wiki/Block_matrix#Block_matrix_inversion
  • 感谢您的宝贵意见!我有一个特殊情况,右下角矩阵 D 实际上为零,因此可以显着加快速度。不幸的是,我的左上角矩阵 A 已经是 7x7 维数。但我想我可以使用相同的块逆技术来获得 A 的逆。非常感谢!
  • 完全正确 - 您可以混合和匹配块大小以满足您的特定标准(例如,对角线上的 4 x 4 和 3 x 3 块用于 7 x 7)。

标签: c++ matrix eigen matrix-inverse differentiation


【解决方案1】:

一般来说,可以在没有分支的情况下反转任意大(可逆)矩阵,但这对于更大的矩阵来说效率很低。 Eigen 仅对大小为 4x4 的矩阵执行此操作。

如果你想求逆的推导,只需使用恒等式

deriv (inv(A)) = - inv(A) * deriv(A) * inv(A)

即计算普通矩阵的逆矩阵,然后计算上面的表达式。

【讨论】:

  • 谢谢,我已经在考虑使用那个身份了。它有点绕开了在没有分支而不是解决它的情况下评估矩阵逆的问题。在我的例子中,A 矩阵是向量 x 的非线性函数:A(x)。其中 x 是我想要区分 A 的向量。但我可以使用 CppAD 自动区分 dA(x)/dx 并在我的计算中使用它。感谢您的建议。
【解决方案2】:

对于算术函数,存在从分支到无分支的机械转换。

复制您在每个分支中使用的所有变量,并计算两半。在块的末尾,将if 分支乘以condition,将else 分支乘以!condition,然后将它们相加。

同样对于一个开关,计算所有情况,然后乘以value == case

例如

Mat frob_branch(Mat a, Mat b) {
    if (a.baz()) {
        return a * b;
    } else {
        return b * a;
    }
}

变成

Mat frob_no_branch(Mat a, Mat b) {
    auto if_true = a * b;
    auto if_false = b * a;
    bool condition = a.baz();
    return (if_true * condition) + (if_false * !condition);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-17
    • 2016-02-20
    • 1970-01-01
    • 2022-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多