【问题标题】:the parameter of RNN in Theano tutorialTheano教程中RNN的参数
【发布时间】:2016-07-16 12:12:11
【问题描述】:
class RNNSLU(object):
''' elman neural net model '''
def __init__(self, nh, nc, ne, de, cs):
    '''
    nh :: dimension of the hidden layer
    nc :: number of classes
    ne :: number of word embeddings in the vocabulary
    de :: dimension of the word embeddings
    cs :: word window context size
    '''
    # parameters of the model
    self.emb = theano.shared(name='embeddings',
                             value=0.2 * numpy.random.uniform(-1.0, 1.0,
                             (ne+1, de))
                             # add one for padding at the end
                             .astype(theano.config.floatX))
    self.wx = theano.shared(name='wx',
                            value=0.2 * numpy.random.uniform(-1.0, 1.0,
                            (de * cs, nh))
                            .astype(theano.config.floatX))
    self.wh = theano.shared(name='wh',
                            value=0.2 * numpy.random.uniform(-1.0, 1.0,
                            (nh, nh))
                            .astype(theano.config.floatX))
    self.w = theano.shared(name='w',
                           value=0.2 * numpy.random.uniform(-1.0, 1.0,
                           (nh, nc))
                           .astype(theano.config.floatX))
    self.bh = theano.shared(name='bh',
                            value=numpy.zeros(nh,
                            dtype=theano.config.floatX))
    self.b = theano.shared(name='b',
                           value=numpy.zeros(nc,
                           dtype=theano.config.floatX))
    self.h0 = theano.shared(name='h0',
                            value=numpy.zeros(nh,
                            dtype=theano.config.floatX))

    # bundle
    self.params = [self.emb, self.wx, self.wh, self.w, self.bh, self.b, self.h0]



def recurrence(x_t, h_tm1):
        h_t = T.nnet.sigmoid(T.dot(x_t, self.wx)
                             + T.dot(h_tm1, self.wh) + self.bh)
        s_t = T.nnet.softmax(T.dot(h_t, self.w) + self.b)
        return [h_t, s_t]

[h, s], = theano.scan(fn=recurrence,
                            sequences=x,
                            outputs_info=[self.h0, None],
                            n_steps=x.shape[0])

我正在关注这个关于 RNN 的 Theano 教程。(http://deeplearning.net/tutorial/rnnslu.html) 但我有两个问题。 第一的。在本教程中,递归函数是这样的:

def recurrence(x_t, h_tm1): h_t = T.nnet.sigmoid(T.dot(x_t, self.wx) + T.dot(h_tm1, self.wh) + self.bh) s_t = T.nnet.softmax(T.dot(h_t, self.w) + self.b) return [h_t, s_t]

我为什么不在 h_t 中加上 h0 ? (即h_t = T.nnet.sigmoid(T.dot(x_t, self.wx) + T.dot(h_tm1, self.wh) + self.bh + self.h0)

第二,为什么是outputs_info=[self.h0, None]?我知道 output_info 是初始化结果。所以我认为outputs_info=[self.bh+self.h0, T.nnet.softmax(T.dot(self.bh+self.h0, self.w_h2y) + self.b_h2y)]

【问题讨论】:

    标签: theano deep-learning recurrent-neural-network


    【解决方案1】:
    def recurrence(x_t, h_tm1):
            h_t = T.nnet.sigmoid(T.dot(x_t, self.wx)
                                 + T.dot(h_tm1, self.wh) + self.bh)
            s_t = T.nnet.softmax(T.dot(h_t, self.w) + self.b)
            return [h_t, s_t]
    

    所以,首先你要问为什么我们不在递归函数中使用 h0。让我们分解这部分,

       h_t = T.nnet.sigmoid(T.dot(x_t, self.wx)+ T.dot(h_tm1, self.wh) + self.bh)
    

    我们期望的是 3 个术语。

    1. 第一项是输入层乘以权重矩阵T.dot(x_t, self.wx)

    2. 第二项是隐藏层乘以另一个加权矩阵(这就是它重复出现的原因)T.dot(h_tm1, self.wh)。注意你必须有一个权重矩阵,你建议基本添加self.h0作为偏置。

    3. 第三项是隐藏层的偏差,self.bh

    现在,在每次迭代之后,我们想要跟踪隐藏层激活,包含在 self.h0 中。但是,self.h0 意味着包含当前的激活,我们需要的是以前的激活。

    [h, s], _ = theano.scan(fn=recurrence,
                                sequences=x,
                                outputs_info=[self.h0, None],
                                n_steps=x.shape[0])
    

    所以,再看看扫描功能。 outputs_info=[self.h0, None] 初始化值是对的,但这些值也与输出相关联。 recurrence()有两个输出,即[h_t, s_t]

    因此,outputs_info 的作用也是在每次迭代后,self.h0 的值被h_t 的值(第一个返回值)覆盖。 output_info 的第二个元素是None,因为我们不会在任何地方保存或初始化s_t 的值(outputs_info 的第二个参数以这种方式链接到递归函数的返回值。)

    在下一次迭代中,outputs_info 的第一个参数再次用作输入,使得h_tm1self.h0 的值相同。但是,因为我们必须有一个h_tm 的参数,所以我们必须初始化这个值。由于我们不需要在outputs_info 中初始化第二个参数,因此我们将第二个项保留为None

    当然,theano.scan() 函数有时非常令人困惑,我也是新手。但是,这就是我从同一个教程中所理解的。

    【讨论】:

    • 感谢您的回答。太有用了,我想我明白你的意思了,非常感谢