在Theano中定义关于子张量的梯度

9 投票
1 回答
2988 浏览
提问于 2025-04-18 11:26

我有一个关于Theano的简单问题,但一直找不到答案(我得承认,尽管看了很多教程,我还是不太明白共享变量是怎么工作的)。

我想实现一个“反卷积网络”;具体来说,我有一个3维的输入张量(每个输入是一个2D图像)和一个4维的代码张量;对于第i个输入,codes[i]代表一组代码词,这些代码词一起编码输入i。

我在搞清楚如何对这些代码词进行梯度下降时遇到了很多麻烦。以下是我代码中相关的部分:

idx = T.lscalar()
pre_loss_conv = conv2d(input = codes[idx].dimshuffle('x', 0, 1,2),
                       filters = dicts.dimshuffle('x', 0,1, 2),
                       border_mode = 'valid')
loss_conv = pre_loss_conv.reshape((pre_loss_conv.shape[2], pre_loss_conv.shape[3]))
loss_in = inputs[idx]
loss = T.sum(1./2.*(loss_in - loss_conv)**2) 

del_codes = T.grad(loss, codes[idx])
delc_fn = function([idx], del_codes)
train_codes = function([input_index], loss, updates = [
    [codes, T.set_subtensor(codes[input_index], codes[input_index] - 
                            learning_rate*del_codes[input_index])     ]])

(这里的codes和dicts是共享的张量变量)。Theano对此不太满意,特别是在定义时

del_codes = T.grad(loss, codes[idx])

我收到的错误信息是:theano.gradient.DisconnectedInputError: grad方法被要求计算一个不在成本计算图中的变量的梯度,或者只被一个不可微分的操作使用:Subtensor{int64}.0

我猜它想要一个符号变量,而不是codes[idx];但我不太确定如何将所有东西连接起来以达到预期的效果。我想我可能需要把最后一行改成类似于

learning_rate*del_codes)     ]])

有人能给我一些关于如何正确定义这个函数的建议吗?我觉得我可能在使用Theano时漏掉了一些基本的东西,但我不太确定是什么。

提前谢谢你们!

-Justin

更新:Kyle的建议效果很好。这是我使用的具体代码

current_codes = T.tensor3('current_codes')
current_codes = codes[input_index]
pre_loss_conv = conv2d(input = current_codes.dimshuffle('x', 0, 1,2),
                       filters = dicts.dimshuffle('x', 0,1, 2),
                       border_mode = 'valid')
loss_conv = pre_loss_conv.reshape((pre_loss_conv.shape[2], pre_loss_conv.shape[3]))
loss_in = inputs[input_index]
loss = T.sum(1./2.*(loss_in - loss_conv)**2)  

del_codes = T.grad(loss, current_codes)
train_codes = function([input_index], loss)
train_dicts = theano.function([input_index], loss, updates = [[dicts, dicts - learning_rate*del_dicts]])
codes_update = ( codes, T.set_subtensor(codes[input_index], codes[input_index] - learning_rate*del_codes) )
codes_update_fn = function([input_index], updates = [codes_update])

for i in xrange(num_inputs):
     current_loss = train_codes(i)
     codes_update_fn(i)

1 个回答

10

总结一下发现的内容:

首先,把 grad_var = codes[idx] 这行代码写上,然后创建一个新变量,比如:subgrad = T.set_subtensor(codes[input_index], codes[input_index] - learning_rate*del_codes[input_index])

接着调用 train_codes = function([input_index], loss, updates = [[codes, subgrad]]) 似乎就解决了问题。一般来说,我会尽量为尽可能多的东西创建变量。有时候,试图在一行代码里做太多事情会导致一些棘手的问题,而且后面调试和理解起来也很困难!另外,在这个情况下,我觉得theano需要一个共享变量,但如果这个共享变量是在需要它的函数内部创建的,就会出现问题。

很高兴这个方法对你有效!

撰写回答