Theano 中共享矩阵的逐元素更新

Elementwise updates of shared matrix in Theano

我正在尝试计算能量函数的梯度,E(phi, theta, psi),其中 phi、theta、psi 分别是围绕 Z、Y 和 X 轴的欧拉角。 R是由欧拉角转换而来的旋转矩阵。 其中列是旋转向量。 对于室内房间的点云,点云中的每个点都有法线 N。 N 的形状为 (numPoints x 3)

现在 E = sum(1-max(N.dot(R))

我想求 E 相对于欧拉角的梯度。

首先,我尝试使用 Theano 从欧拉角计算旋转矩阵 R。 请在下面找到代码。

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

phi = theano.shared(value=np.pi/3, name='phi')
theta = theano.shared(value=np.pi/3, name='theta')
psi = theano.shared(value=np.pi/3, name='psi')

# phi = T.dscalar(name='phi')
# theta = T.dscalar(name='theta')
# psi = T.dscalar(name='psi')

R = theano.shared(value=np.zeros([3, 3]), name='R')

R00 = T.set_subtensor(R[0, 0],  T.cos(theta)*T.cos(phi))
R10 = T.set_subtensor(R[1, 0],  T.cos(theta)*T.sin(phi))

R20 = T.set_subtensor(R[2, 0],  -T.sin(theta))

R01 = T.set_subtensor(R[0, 1],  T.sin(psi)*T.sin(theta)*T.cos(phi) - T.cos(psi)*T.sin(phi))
R11 = T.set_subtensor(R[1, 1],  T.sin(psi)*T.sin(theta)*T.sin(phi) + T.cos(psi)*T.cos(phi))
R21 = T.set_subtensor(R[2, 1],  T.sin(psi)*T.cos(theta))

R02 = T.set_subtensor(R[0, 2],  T.cos(psi)*T.sin(theta)*T.cos(phi) + T.sin(psi)*T.sin(phi))
R12 = T.set_subtensor(R[1, 2],  T.cos(psi)*T.sin(theta)*T.sin(phi) - T.sin(psi)*T.cos(phi))
R22 = T.set_subtensor(R[2, 2],  T.cos(psi)*T.cos(theta))

f = theano.function([phi, theta, psi], updates=[(R, R00, R10, R20, R01, R11, R21, R02, R12, R22)])

theano.printing.pydotprint(f, outfile="./test.png", var_with_name_simple=True)

但这让我在两个不同的阶段出错,

Traceback (most recent call last):
  File "/theanotest.py", line 38, in <module>
    f = theano.function([phi, theta, psi], updates=[(R, R00, R10, R20, R01, R11, R21, R02, R12, R22)])
  File "/usr/local/lib/python2.7/dist-packages/theano/compile/function.py", line 266, in function
    profile=profile)
  File "/usr/local/lib/python2.7/dist-packages/theano/compile/pfunc.py", line 489, in pfunc
    no_default_updates=no_default_updates)
  File "/usr/local/lib/python2.7/dist-packages/theano/compile/pfunc.py", line 186, in rebuild_collect_shared
    ' variable via the `givens` parameter') % v)
TypeError: Cannot use a shared variable (phi) as explicit input. Consider substituting a non-shared variable via the `givens` parameter

如果我将欧拉角更改为标量值,我会得到如下错误

Traceback (most recent call last):
  File "/theanotest.py", line 38, in <module>
    f = theano.function([phi, theta, psi], updates=[(R, R00, R10, R20, R01, R11, R21, R02, R12, R22)])
  File "/usr/local/lib/python2.7/dist-packages/theano/compile/function.py", line 266, in function
    profile=profile)
  File "/usr/local/lib/python2.7/dist-packages/theano/compile/pfunc.py", line 489, in pfunc
    no_default_updates=no_default_updates)
  File "/usr/local/lib/python2.7/dist-packages/theano/compile/pfunc.py", line 191, in rebuild_collect_shared
    for (store_into, update_val) in iter_over_pairs(updates):
ValueError: too many values to unpack

谁能帮我解决这个问题?

第一个错误与消息所指示的完全相同:您不能提供共享变量作为 Theano 函数的输入。使用没有输入参数的共享变量或常规张量作为输入参数。

第二个错误是由于不正确updates。更新应该是一对列表。每对应包含要更新的共享变量和描述应如何计算更新的符号表达式。

在这种情况下,更新可能会像这样计算(未经测试):

Rnew = T.set_subtensor(R[0, 0],  T.cos(theta)*T.cos(phi))
Rnew = T.set_subtensor(Rnew[1, 0],  T.cos(theta)*T.sin(phi))
Rnew = T.set_subtensor(Rnew[2, 0],  -T.sin(theta))

Rnew = T.set_subtensor(Rnew[0, 1],  T.sin(psi)*T.sin(theta)*T.cos(phi) - T.cos(psi)*T.sin(phi))
Rnew = T.set_subtensor(Rnew[1, 1],  T.sin(psi)*T.sin(theta)*T.sin(phi) + T.cos(psi)*T.cos(phi))
Rnew = T.set_subtensor(Rnew[2, 1],  T.sin(psi)*T.cos(theta))

Rnew = T.set_subtensor(Rnew[0, 2],  T.cos(psi)*T.sin(theta)*T.cos(phi) + T.sin(psi)*T.sin(phi))
Rnew = T.set_subtensor(Rnew[1, 2],  T.cos(psi)*T.sin(theta)*T.sin(phi) - T.sin(psi)*T.cos(phi))
Rnew = T.set_subtensor(Rnew[2, 2],  T.cos(psi)*T.cos(theta))

f = theano.function([phi, theta, psi], updates=[(R, Rnew)])