优化具有重复矩阵但下标不同的爱因斯坦求和

Optimize Einstein Summation with Repeating Matrices but Different Subscript

免责声明:确实虽然关于发布到数学堆栈交换或某种类型。但我从我主修数学的朋友那里听说,他们并没有真正经常使用爱因斯坦求和,但我确实知道机器学习使用了很多。因此我在这里发布了这个问题(作为优化算法性能)。

在研究矩阵计算时(例如至少需要多少个元素乘法),我试图计算以下梯度:

其中 ABC 表示在第一个轴上收缩三个矩阵 (例如 2x32x42x5 变为3x4x52 轴相加)。基本上,它计算 3 矩阵收缩范数 ABC 相对于 A 的梯度。然后再次计算关于 A 的梯度范数。

这相当于:

或者简化一点(由autograd证明):

我们可以用 Einstein Summation 形式写这个(被很多包的 einsum 函数使用,例如 numpytensorflow 等)

np.einsum('ia,ib,ic,jb,jc,jd,je,kd,ke->ka', A, B, C, B, C, B, C, B, C)

写这篇文章时,我发现矩阵 BC 在求和中是一种一次又一次的重复。我想知道我可以 将那些 "lots of B and Cs" 简化为某种矩阵幂 吗?那应该使事情以对数方式更快。我尝试手动简化但没有弄清楚。

非常感谢!如果我说的不对,请指正。

我发现我可以先广播(即外积)B(形状ib)和C(形状ic)得到一个BC 形状张量 ibc:

BC = np.einsum('ib,ic->ibc', B, C)

然后我可以用它的转置张量收缩它得到一个方阵:

JUMP = np.einsum('ibc,cbj->ij', BC, BC.T)

这个矩阵 JUMP 是正方形的,其作用类似于 "gradient jump" 运算符,可以跳转梯度顺序。例如,如果我想获得问题中提到的二阶梯度,我可以简单地将此 JUMP 与一阶梯度相乘得到:

g2 = JUMP @ g1

要得到三阶,乘以它的矩阵平方:

g3 = JUMP @ JUMP @ g1

为了得到四次方,乘以它的矩阵四次方(不是立方):

g4 = np.linalg.matrix_power(JUMP, 4) @ g1