无法理解Theano在RNN NLP分类中的工作原理

import osimport theano, numpyfrom theano import tensor as Tfrom collections import OrderedDictclass RNNSLU(object): """ Elman神经网络""" def __init__(self, nh, nc, ne, de, cs):"""用于初始化的超参数nh : 隐藏层的维度nc : 类别数(标签)ne : 词汇表大小de : 嵌入维度cs : 词上下文窗口大小"""# 要学习的参数:词嵌入self.embeddings = theano.shared(name='embeddings',    value = 0.2 * numpy.random.uniform(-1.0, 1.0, (ne + 1, de))    .astype(theano.config.floatX))# 要学习的参数:将输入映射到隐藏层的权重矩阵(de*cs x nh)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))# 要学习的参数:将隐藏层映射到输出层的权重矩阵(nh x nc)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))# 要学习的参数:时间t=0时的隐藏层self.h0 = theano.shared(name='h0',    value = numpy.zeros(nh,      dtype=theano.config.floatX))# 捆绑参数self.params = [self.embeddings, self.wx, self.wh, self.w, self.bh, self.b, self.h0]self.names  = ['embeddings', 'Wx', 'Wh', 'W', 'bh', 'b', 'h0']#编译训练函数self.prepare_train(de, cs)def prepare_train(self, de, cs):"""训练循环神经网络"""idxs = T.imatrix() # 列数 = 窗口中的词数,行数 = 句子长度# 准备接收输入和输出标签x = self.embeddings[idxs].reshape((idxs.shape[0], de*cs))y = T.iscalar('y') def recurrence(x_t, h_tm1):  """  x_t : 时间t的输入  h_tm1 : 时间t-1的隐藏状态  """  # 计算时间t的隐藏状态  # h_t = g(x_t . w_x + h_tm1 . w_h + b_h)  h_t = T.nnet.sigmoid(T.dot(x_t, self.wx) + T.dot(h_tm1, self.wh) + self.bh)  # 计算输出层  # s_t = g(h_t . w + b)  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])#print h.ndim#print s.ndim# TODO: s的结构是什么?选择轴的作用是什么?p_y_given_sentence = s[:,0,:]y_pred = T.argmax(p_y_given_sentence, axis=1)# 学习率lr = T.scalar('lr')# 句子负对数似然(目标函数)sentence_nll = - T.mean(T.log(p_y_given_sentence)[T.arange(x.shape[0]), y])# 计算参数梯度sentence_gradients = T.grad(sentence_nll, self.params)# 计算更新sentence_updates = OrderedDict((p, p - lr*g) for p,g in zip(self.params, sentence_gradients))# 编译函数self.classify = theano.function(inputs=[idxs], outputs=y_pred)self.sentence_train = theano.function(inputs=[idxs, y, lr], outputs=sentence_nll, updates=sentence_updates)#### 从中调用类的主要函数rnn = RNNSLU(nh=s['nhidden'], nc=nClasses, ne=vocSize, de=s['emb_dimension'], cs=s['win'])for word_batch, label_last_word in zip(words, labels):  rnn.sentence_train(word_batch, label_last_word, s['clr'])  rnn.normalize()

代码解释:

我知道在StackOverflow上这样做不是一个好主意。但我已经努力了一个多星期来解码这个用于训练循环神经网络的代码。我首先是Theano的新手。

word_batch = array([[ -1, -1, -1, 194, 358, 463, 208]], dtype=int32)label_last_word = 126

word_batch是像下面这样的句子的索引:

‘我正在从英国去美国’

这里的word_batch是与特定词(如美国)相关联的上下文窗口。所以,如果上下文窗口大小为七,word batch中的中间值(194)代表该词在数据集中的索引。我想知道,当我将这个作为参数传递给rnn.sentence_train时,RNNSLU类内部是如何进行训练的。我对类中idx、x等变量的使用感到困惑。我知道理论上是如何发生的,但无法明确解码Theano部分。如果我的问题没有意义,请告诉我。

谢谢。


回答:

rnn.sentence_train 是具有 updates=sentence_updates 的Theano函数。这意味着每次调用 rnn.sentence_train 时,sentence_updates 字典键中的所有共享变量都将根据相应的 sentence_updates 字典值中的符号更新表达式进行更新。这些表达式都是经典的梯度下降(当前参数值 – 学习率 * 相对于参数的成本梯度)。

idxs 是训练函数输入的符号占位符。在您的示例中,word_batch 在调用训练函数时填充该占位符。

Related Posts

Keras Dense层输入未被展平

这是我的测试代码: from keras import…

无法将分类变量输入随机森林

我有10个分类变量和3个数值变量。我在分割后直接将它们…

如何在Keras中对每个输出应用Sigmoid函数?

这是我代码的一部分。 model = Sequenti…

如何选择类概率的最佳阈值?

我的神经网络输出是一个用于多标签分类的预测类概率表: …

在Keras中使用深度学习得到不同的结果

我按照一个教程使用Keras中的深度神经网络进行文本分…

‘MatMul’操作的输入’b’类型为float32,与参数’a’的类型float64不匹配

我写了一个简单的TensorFlow代码,但不断遇到T…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注