解释numpy';埃因苏姆酒店
我目前正在做一些关于用einsum函数计算numpy中的四阶张量的研究 我正在计算的张量是用爱因斯坦符号写的,函数einsun做得很好!但我想知道它在以下情况下做了什么:解释numpy';埃因苏姆酒店,numpy,numpy-ndarray,numpy-einsum,Numpy,Numpy Ndarray,Numpy Einsum,我目前正在做一些关于用einsum函数计算numpy中的四阶张量的研究 我正在计算的张量是用爱因斯坦符号写的,函数einsun做得很好!但我想知道它在以下情况下做了什么: import numpy as np a=np.array([[2,0,3],[0,1,0],[0, 0, 4]]) b= np.eye(3) r1=np.einsum("ij,kl->ijkl", a, b) r2=np.einsum("ik,jl->ijkl", a,
import numpy as np
a=np.array([[2,0,3],[0,1,0],[0, 0, 4]])
b= np.eye(3)
r1=np.einsum("ij,kl->ijkl", a, b)
r2=np.einsum("ik,jl->ijkl", a, b)
在r1
中,我基本上是在做标准的张量积(相当于np.tensordot(a,b,axes=0)
)
在r2
中呢
我知道我可以通过执行a[:,None,:,None]*b[None,:,None,:]
来获取值,但我不知道索引在做什么。这个操作有名字吗
抱歉,如果这太基本了 我尝试使用转置定义来更改多个轴 它适用于
'ij,kl->ijkl'、'ik,jl->ijkl'、'kl,ij->ijkl'
但是对于“il,jk->ijkl”、“jl,ik->ijkl”和“jk,il->ijkl”失败。
import numpy as np
a=np.eye(3)
a[0][0]=2
a[0][-1]=3
a[-1][-1]=4
b=np.eye(3)
def permutation(str_,Arr):
Arr=np.reshape(Arr,[3,3,3,3])
def splitString(str_):
tmp1=str_.split(',')
tmp2=tmp1[1].split('->')
str_idx1=tmp1[0]
str_idx2=tmp2[0]
str_idx_out=tmp2[1]
return str_idx1,str_idx2, str_idx_out
idx_a, idx_b, idx_out=splitString(str_)
dict_={'i':0,'j':1,'k':2,'l':3}
def split(word):
return [char for char in word]
a,b=split(idx_a)
c,d=split(idx_b)
Arr=np.transpose(Arr,(dict_[a],dict_[b],dict_[c],dict_[d]))
return Arr
str_='jk,il->ijkl'
d=np.outer(a,b)
f=np.einsum(str_, a,b)
check=permutation(str_,d)
if (np.count_nonzero(f-check)==0):
print ('Code is working!')
else:
print("Something is wrong...")
感谢您的建议 我尝试使用转置定义来更改多个轴 它适用于
'ij,kl->ijkl'、'ik,jl->ijkl'、'kl,ij->ijkl'
但是对于“il,jk->ijkl”、“jl,ik->ijkl”和“jk,il->ijkl”失败。
import numpy as np
a=np.eye(3)
a[0][0]=2
a[0][-1]=3
a[-1][-1]=4
b=np.eye(3)
def permutation(str_,Arr):
Arr=np.reshape(Arr,[3,3,3,3])
def splitString(str_):
tmp1=str_.split(',')
tmp2=tmp1[1].split('->')
str_idx1=tmp1[0]
str_idx2=tmp2[0]
str_idx_out=tmp2[1]
return str_idx1,str_idx2, str_idx_out
idx_a, idx_b, idx_out=splitString(str_)
dict_={'i':0,'j':1,'k':2,'l':3}
def split(word):
return [char for char in word]
a,b=split(idx_a)
c,d=split(idx_b)
Arr=np.transpose(Arr,(dict_[a],dict_[b],dict_[c],dict_[d]))
return Arr
str_='jk,il->ijkl'
d=np.outer(a,b)
f=np.einsum(str_, a,b)
check=permutation(str_,d)
if (np.count_nonzero(f-check)==0):
print ('Code is working!')
else:
print("Something is wrong...")
感谢您的建议
r2
与r1
基本上是相同的张量,但索引被重新排列。特别地,r2[i,j,k,l]
等于a[i,k]*b[k,l]
例如:
>>> r2[0,1,2,1]
3.0
这与a[0,2]*b[1,1]
是3*1
这一事实相对应,实际上是3
考虑这一点的另一种方法是观察
a[:,j,:,l]
在j==l时等于a
,否则为零矩阵。r2
与r1
基本上是相同的张量,但索引被重新排列。特别地,r2[i,j,k,l]
等于a[i,k]*b[k,l]
例如:
>>> r2[0,1,2,1]
3.0
这与a[0,2]*b[1,1]
是3*1
这一事实相对应,实际上是3
思考这个问题的另一种方法是观察
a[:,j,:,l]
在j==l时等于a
,反之则为零矩阵。我认为r1
和r2
都是外积。第二个只是对4d结果的轴重新排序。矩阵积可以做同样的乘法,但它对一个或多个轴求和(共享索引)。在你的例子中,没有乘积之和r1
也可以通过广播写入-只需重新排列None
np。tensordot
重塑并转置输入,直到可以生成标准的2ddot
产品,然后将结果转换回来。我的记忆是,单个数字轴参数被转换为轴的扩展元组。我发现einsum
索引更清晰、更强大。至于你关于索引在做什么的问题,你的意思并不清楚,但听起来你好像在问None
在做什么。它创建了一个大小为1的额外维度,这样数组就可以兼容乘法了。它被称为广播。r2只是R11的轴置换版本。我认为,r1
和r2
都是外部产品。第二个只是对4d结果的轴重新排序。矩阵积可以做同样的乘法,但它对一个或多个轴求和(共享索引)。在你的例子中,没有乘积之和r1
也可以通过广播写入-只需重新排列None
np。tensordot
重塑并转置输入,直到可以生成标准的2ddot
产品,然后将结果转换回来。我的记忆是,单个数字轴参数被转换为轴的扩展元组。我发现einsum
索引更清晰、更强大。至于你关于索引在做什么的问题,你的意思并不清楚,但听起来你好像在问None
在做什么。它创建了一个大小为1的额外维度,这样数组就可以兼容乘法了。它被称为广播。r2只是r1的轴置换版本