Python 如何使用tf.einsum正确地乘以N维张量?

Python 如何使用tf.einsum正确地乘以N维张量?,python,tensorflow,linear-algebra,tensor,Python,Tensorflow,Linear Algebra,Tensor,在我的问题中,我有一批矩阵,用shap的张量表示[批,序列,数据]。我有一个函数把这个张量的最后一个轴转换成笛卡尔坐标。它首先用纯Python实现,然后我用TF实现 最初,该函数在批处理张量的单个元素上执行计算。但是现在(下面的代码)它可以应用于批处理轴。如果我只向函数输入了一个示例(x=(1,SEQUENCE,DATA)),则函数工作正常。当示例数(批处理>1)增加时,函数无法正常工作,从而导致计算错误 我已经用最初的numpy函数和TF实现进行了测试。我把范围缩小到tf.einsum呼叫。这

在我的问题中,我有一批矩阵,用shap的张量表示[批,序列,数据]。我有一个函数把这个张量的最后一个轴转换成笛卡尔坐标。它首先用纯Python实现,然后我用TF实现

最初,该函数在批处理张量的单个元素上执行计算。但是现在(下面的代码)它可以应用于批处理轴。如果我只向函数输入了一个示例(x=(1,SEQUENCE,DATA)),则函数工作正常。当示例数(批处理>1)增加时,函数无法正常工作,从而导致计算错误

我已经用最初的numpy函数和TF实现进行了测试。我把范围缩小到tf.einsum呼叫。这里出了什么问题?我该如何改变这种行为

def z2c(zmat):
    cartesian = tf.Variable(tf.zeros(tf.shape(zmat)))

    seq_length = zmat.shape[1]

    batch = zmat.shape[0]
    bead_1 = tf.constant([[zmat[i,1,0], 0., 0] for i in range(batch)])
    cartesian[:,1,:].assign(bead_1)
    bead_2 =             
      [[(zmat[i,2,0]*np.sin(zmat[i,2,1]))+zmat[i,1,0],zmat[i,2,0]*np.cos(zmat[i,2,1]), 0] \
          for i in range(batch)]
    cartesian[:,2,:].assign(bead_2)

    r, theta, phi = zmat[:,:,0], zmat[:,:,1], zmat[:,:,2]

    sinTheta = np.sin(theta)
    cosTheta = np.cos(theta)
    sinPhi = np.sin(phi)
    cosPhi = np.cos(phi)

    x = r * cosTheta
    y = r * cosPhi * sinTheta
    z = r * sinPhi * sinTheta
    xyz = tf.Variable([-x,y,z])

    xyz = tf.transpose(tf.Variable([-x,y,z]), (1,2,0))

    def extend(cartesian, xyz, i):#, x,y,z):
        cartesian = tf.Variable(cartesian)
        a,b,c = cartesian[:,i-3,:], cartesian[:,i-2,:], cartesian[:,i-1,:]
    
        print("Iter: {}".format(i))
        print('a: {}, b: {}, c: {}\n'.format(a,b,c))
        print(a.shape)

        ab = (b - a)
        bc = (c - b) #.normalized()

        bc = bc/tf.linalg.norm(bc)

        n = tf.linalg.cross(ab,bc) 
        n = n/tf.linalg.norm(n)
        ncbc = tf.linalg.cross(n,bc)

        M = tf.Variable([[bc[:,0], ncbc[:,0], n[:,0]],                                     
        [bc[:,1], ncbc[:,1], n[:,1]], [bc[:,2], ncbc[:,2], n[:,2]]])


        pos = xyz[:,i,:]

        cartesian[:,i,:].assign( tf.einsum('bsc,bs->bc', tf.transpose(M), xyz[:,i,:]) + c )

        return cartesian, xyz, i+1
    def cond(cartesian, xyz, i):
   
        return i < seq_len


    i = tf.Variable(3, dtype=tf.int32)
    seq_len = tf.Variable(seq_length,dtype=tf.int32)
    result, _, _ = tf.while_loop(cond = cond,
                      body = extend,
                      loop_vars = (cartesian, xyz, i))


    return result
def z2c(zmat):
笛卡尔=tf.变量(tf.零(tf.形状(zmat)))
seq_length=zmat.形状[1]
批次=zmat.形状[0]
珠子1=tf.常数([[zmat[i,1,0],0,0]表示范围内的i(批次)])
笛卡尔[:,1,:]赋值(珠子1)
胎圈_2=
[zmat[i,2,0]*np.sin(zmat[i,2,1])+zmat[i,1,0],zmat[i,2,0]*np.cos(zmat[i,2,1]),0]\
对于范围内的i(批次)]
笛卡尔[:,2,:]赋值(珠子2)
r、 θ,phi=zmat[:,:,0],zmat[:,:,1],zmat[:,:,2]
sinTheta=np.sin(θ)
cosTheta=np.cos(θ)
sinPhi=np.sin(phi)
cosPhi=np.cos(φ)
x=r*cosTheta
y=r*cosPhi*sinTheta
z=r*sinPhi*sinTheta
xyz=tf.变量([-x,y,z])
xyz=tf.转置(tf.变量([-x,y,z]),(1,2,0))
def扩展(笛卡尔,xyz,i):#,x,y,z):
笛卡尔=tf.变量(笛卡尔)
a、 b,c=笛卡尔的[:,i-3,:],笛卡尔的[:,i-2,:],笛卡尔的[:,i-1,:]
打印(“Iter:{}”。格式(一))
打印('a:{},b:{},c:{}\n'。格式(a,b,c))
印刷品(a.形状)
ab=(b-a)
bc=(c-b)#.normalized()
bc=bc/tf.linalg.norm(bc)
n=tf.直线交叉(ab,bc)
n=n/tf.linalg.norm(n)
ncbc=tf.linalg.cross(n,bc)
M=tf.Variable([[bc[:,0],ncbc[:,0],n[:,0]],
[bc[:,1],ncbc[:,1],n[:,1],[bc[:,2],ncbc[:,2],n[:,2]]
pos=xyz[:,i,:]
笛卡尔[:,i,:]赋值(tf.einsum('bsc,bs->bc',tf.transpose(M),xyz[:,i,:])+c)
返回笛卡尔坐标,xyz,i+1
def cond(笛卡尔坐标,xyz,i):
返回i
快速评论:您不应该像现在这样使用
tf.Variable
。变量用于定义应具有状态的变量,即将在培训期间学习的参数。(.这使得你的代码很难阅读。嘿!!谢谢你的评论,我修改了代码。现在我又出现了一个错误,应该发布另一个问题了。