Python 从矩阵创建的子传感器广播(Theano)

Python 从矩阵创建的子传感器广播(Theano),python,numpy,matrix,theano,Python,Numpy,Matrix,Theano,我想从一个矩阵中创建两个子传感器,使用索引选择相应的行。 一个子传感器有几行,另一个子传感器只有一行,应该广播这些行以允许按元素添加 我的问题是:在给定索引的情况下(subtensorRight,在下面的示例中),我如何表示我希望允许在子张量中的特定维度上进行广播 下面的示例显示了我想要做的事情: import theano import numpy as np import theano.tensor as T def embedding_matrix(D, N, name): W_

我想从一个矩阵中创建两个子传感器,使用索引选择相应的行。 一个子传感器有几行,另一个子传感器只有一行,应该广播这些行以允许按元素添加

我的问题是:在给定索引的情况下(
subtensorRight
,在下面的示例中),我如何表示我希望允许在子张量中的特定维度上进行广播

下面的示例显示了我想要做的事情:

import theano
import numpy as np
import theano.tensor as T

def embedding_matrix(D, N, name):
    W_values = np.random.uniform(size=(D, N))
    return theano.shared(value=W_values, name=name)

rE = embedding_matrix(4, 5, "rE")
lis = T.ivector('lis')# [1,2]
subtensorLeft = rE[lis,:]
ri = T.ivector('ri')#[1]
subtensorRight = rE[ri,:]


def fnsim(left, right):
    return - T.sqrt(T.sum(T.sqr(left - right), axis=1))

distances_test = theano.function(
    inputs=[lis, ri],
    outputs=fnsim(subtensorLeft, subtensorRight)
)

print distances_test([1,2],[1])
它抛出以下错误:

ValueError: Input dimension mis-match. (input[0].shape[0] = 2, input[1].shape[0] = 1)
Apply node that caused the error: Elemwise{Composite{sqr((i0 - i1))}}[(0, 0)](AdvancedSubtensor1.0, AdvancedSubtensor1.0)
Toposort index: 2
Inputs types: [TensorType(float64, matrix), TensorType(float64, matrix)]
Inputs shapes: [(2, 5), (1, 5)]
Inputs strides: [(40, 8), (40, 8)]
Inputs values: ['not shown', array([[ 0.39528934,  0.4414946 ,  0.36837258,  0.52523446,  0.35431748]])]
Outputs clients: [[Sum{axis=[1], acc_dtype=float64}(Elemwise{Composite{sqr((i0 - i1))}}[(0, 0)].0)]]
===

更新1:

当通过以下方式重塑
subtensorRight
时,它停止抱怨并给出预期结果:

subtensorRight = rE[ri,:]
subtensorRight = subtensorRight.reshape((1, subtensorRight.shape[1]))
问题:这是正确的方式吗

更新2:

如果我尝试按以下方式进行重塑(我认为这与上述重塑是等价的),则它不起作用:

错误是:

ValueError: Input dimension mis-match. (input[0].shape[0] = 2, input[1].shape[0] = 1)
Apply node that caused the error: Elemwise{Composite{sqr((i0 - i1))}}[(0, 0)](AdvancedSubtensor1.0, Reshape{2}.0)
Toposort index: 6
Inputs types: [TensorType(float64, matrix), TensorType(float64, matrix)]
Inputs shapes: [(2, 5), (1, 5)]
Inputs strides: [(40, 8), (40, 8)]
Inputs values: ['not shown', array([[ 0.54193252,  0.36793023,  0.89009085,  0.02487759,  0.95955664]])]
Outputs clients: [[Sum{axis=[1], acc_dtype=float64}(Elemwise{Composite{sqr((i0 - i1))}}[(0, 0)].0)]]

问题:为什么从子传感器获取维度0进行重塑会产生不同的结果?

问题在于,theano函数事先不知道右(
ri
)索引只有1个元素(因此,对于所有人来说,您将尝试从MxD矩阵中减去NxD矩阵,这通常不起作用。但是对于您的情况,您只需要N=1。)

解决方案是将您的右索引声明为标量

我相信以下代码符合您的要求:

import theano
import numpy as np
import theano.tensor as T

def embedding_matrix(D, N, name):
    W_values = np.random.uniform(size=(D, N))
    return theano.shared(value=W_values, name=name)

rE = embedding_matrix(4, 5, "rE")
lis = T.ivector('lis')# [1,2]
subtensorLeft = rE[lis,:]
ri = T.iscalar('ri')  # Instead of: ri = T.ivector('ri')
subtensorRight = rE[ri,:]


def fnsim(left, right):
    return - T.sqrt(T.sum(T.sqr(left - right), axis=1))

distances_test = theano.function(
    inputs=[lis, ri],
    outputs=fnsim(subtensorLeft, subtensorRight)
)

print distances_test([1,2],1)  # Instead of: distances_test([1,2],[1])
(输出<代码>[-0.-1.01565315])

无耻的自我推销:

您可以使用该库使theano代码更具可读性。在您的情况下:

from plato.core import symbolic
import numpy as np
import theano.tensor as T

@symbolic
def distances_test(matrix, test_rows, reference_row):
    left = matrix[test_rows]
    right = matrix[reference_row]
    return - T.sqrt(T.sum(T.sqr(left - right), axis=1))

f = distances_test.compile()

print f(np.random.uniform(size=(4, 5)), np.array([1,2]), 1)
from plato.core import symbolic
import numpy as np
import theano.tensor as T

@symbolic
def distances_test(matrix, test_rows, reference_row):
    left = matrix[test_rows]
    right = matrix[reference_row]
    return - T.sqrt(T.sum(T.sqr(left - right), axis=1))

f = distances_test.compile()

print f(np.random.uniform(size=(4, 5)), np.array([1,2]), 1)