优化具有重复矩阵但下标不同的爱因斯坦求和
Optimize Einstein Summation with Repeating Matrices but Different Subscript
免责声明:我确实虽然关于发布到数学堆栈交换或某种类型。但我从我主修数学的朋友那里听说,他们并没有真正经常使用爱因斯坦求和,但我确实知道机器学习使用了很多。因此我在这里发布了这个问题(作为优化算法性能)。
在研究矩阵计算时(例如至少需要多少个元素乘法),我试图计算以下梯度:
其中 ABC
表示在第一个轴上收缩三个矩阵 (例如 2x3
、2x4
和 2x5
变为3x4x5
与 2
轴相加)。基本上,它计算 3 矩阵收缩范数 ABC
相对于 A
的梯度。然后再次计算关于 A
的梯度范数。
这相当于:
或者简化一点(由autograd
证明):
我们可以用 Einstein Summation 形式写这个(被很多包的 einsum
函数使用,例如 numpy
、tensorflow
等)
np.einsum('ia,ib,ic,jb,jc,jd,je,kd,ke->ka', A, B, C, B, C, B, C, B, C)
写这篇文章时,我发现矩阵 B
和 C
在求和中是一种一次又一次的重复。我想知道我可以 将那些 "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
免责声明:我确实虽然关于发布到数学堆栈交换或某种类型。但我从我主修数学的朋友那里听说,他们并没有真正经常使用爱因斯坦求和,但我确实知道机器学习使用了很多。因此我在这里发布了这个问题(作为优化算法性能)。
在研究矩阵计算时(例如至少需要多少个元素乘法),我试图计算以下梯度:
其中 ABC
表示在第一个轴上收缩三个矩阵 (例如 2x3
、2x4
和 2x5
变为3x4x5
与 2
轴相加)。基本上,它计算 3 矩阵收缩范数 ABC
相对于 A
的梯度。然后再次计算关于 A
的梯度范数。
这相当于:
或者简化一点(由autograd
证明):
我们可以用 Einstein Summation 形式写这个(被很多包的 einsum
函数使用,例如 numpy
、tensorflow
等)
np.einsum('ia,ib,ic,jb,jc,jd,je,kd,ke->ka', A, B, C, B, C, B, C, B, C)
写这篇文章时,我发现矩阵 B
和 C
在求和中是一种一次又一次的重复。我想知道我可以 将那些 "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