我正在努力学习如何在python中有效地实现各种神经网络,并且我正在尝试实现这个模型
。
但是,我在使用numpy操作来实现求和时遇到了麻烦。
我一直关注this existing implementation并试图简化它,但我并不完全清楚正在执行的所有阵列操作是什么。我的解释是C乘以R的每一列并求和。但是,我的einsum实现np.einsum('ijk,km->ij', C, R)
似乎没有产生所需的结果。
我希望有一些简化此实现的指示。我目前的尝试是使用np.einsum
,但到目前为止还没有让我到任何地方。
简化代码(在图像/第一个链接中解释):
batchsize = X.shape[0]
R = self.R
C = self.C
bw = self.bw
# Obtain word features
tmp = R.as_numpy_array()[:,X.flatten()].flatten(order='F')
tmp = tmp.reshape((batchsize, self.K * self.context))
words = np.zeros((batchsize, self.K, self.context))
for i in range(batchsize):
words[i,:,:] = tmp[i,:].reshape((self.K, self.context), order='F')
words = gpu.garray(words)
# Compute the hidden layer (predicted next word representation)
acts = gpu.zeros((batchsize, self.K))
for i in range(self.context):
acts = acts + gpu.dot(words[:,:,i], C[i,:,:])
答案 0 :(得分:2)
创建小words
:
In [565]: words = np.zeros((2,3,4))
In [566]: tmp = np.arange(2*3*4).reshape((2,3*4))
In [567]: for i in range(2):
...: words[i,:,:] = tmp[i,:].reshape((3,4),order='F')
...:
In [568]: tmp
Out[568]:
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]])
In [569]: words
Out[569]:
array([[[ 0., 3., 6., 9.],
[ 1., 4., 7., 10.],
[ 2., 5., 8., 11.]],
[[ 12., 15., 18., 21.],
[ 13., 16., 19., 22.],
[ 14., 17., 20., 23.]]])
我很确定这可以在没有循环的情况下完成
In [577]: C = np.ones((4,3,3))
In [578]: acts = np.zeros((2,3))
In [579]: for i in range(4):
...: acts += np.dot(words[:,:,i], C[i,:,:])
...:
In [580]: acts
Out[580]:
array([[ 66., 66., 66.],
[ 210., 210., 210.]])
此dot
循环可以einsum
表示为:
In [581]: np.einsum('ijk,kjm->im', words, C)
Out[581]:
array([[ 66., 66., 66.],
[ 210., 210., 210.]])
这是j
和k
的总结。在循环版本中,j
上的总和在dot
中完成,k
上的总和在循环中完成。但是对于非常大的数组,并且gpu
加速,循环版本可能更快。如果问题空间太大,einsum
可能会很慢,甚至会出现内存错误(尽管最新版本有一些优化选项)。
words
可以从tmp
创建,无需循环:
In [585]: tmp.reshape(2,3,4, order='F')
Out[585]:
array([[[ 0, 3, 6, 9],
[ 1, 4, 7, 10],
[ 2, 5, 8, 11]],
[[12, 15, 18, 21],
[13, 16, 19, 22],
[14, 17, 20, 23]]])