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

标签 algorithm numpy matrix matrix-multiplication numpy-einsum

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

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

high level equation

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

这相当于:

traditional writing

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

enter image description here

我们可以用 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 在求和中是一种一次又一次的重复。我想知道我是否可以将那些“很多 B 和 C”简化为某种矩阵幂?那应该使事情以对数方式更快。我尝试手动简化但没有弄清楚。

非常感谢!如果我说的不正确,请纠正我。

最佳答案

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

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

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

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

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

g2 = JUMP @ g1

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

g3 = JUMP @ JUMP @ g1

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

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

关于algorithm - 优化具有重复矩阵但下标不同的爱因斯坦求和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54107864/

相关文章:

python - Dijkstra 算法在 Python 中的帮助

python - Eigen 收缩 vs Numpy Dot

python - multiprocessing.Pool 挂起如果 child 导致段错误

python - 创建给定长度加起来为 1 的数字数组

python - 三对角矩阵算法 (TDMA) 又名 Thomas 算法,使用 Python 和 NumPy 数组

r - 基于 R 中的函数创建矩阵

Python 代码 - 我卡住了 - 递归

algorithm - 如何计算轮廓的直方图?

javascript - 旋转六边形上的索引

python - 广播从矩阵创建的子张量(Theano)