RNN 与语言模型

RNN 与语言模型

学习笔记,原贴来源: The Unreasonable Effectiveness of Recurrent Neural Networks, May 21, 2015 BY Andrej Karpathy
总结:用 RNN 训练语言模型,并基于此算法介绍 5 个文本生成案例。

1. RNN 的特别之处:处理序列

传统的神经网络和卷积神经网络有很大的局限:只接受固定长度的向量作为 input(比如图片),output 的也同样是一个固定长度的向量(比如每个分类的概率),并且运算的次数也是固定的(指神经网络的层数)。而 RNN 不受限于此,它可以处理序列,可以是 input 序列也可以 output 序列。


图中每个方块代表一个向量:红色方块(input)绿色方块(RNN’s state)蓝色方块(output)。从左到右 5 个模型:
1) 传统神经网络:固定长度的 input 和 output(图像分类)
2) 序列 output(图像识别:输入一个图像,输出一句话描述)
3) 序列 input(情感分析:输入一句评论,输出情感分类)
4) 序列 input 和 output(机器翻译:输入一句英语,输出一句中文)
5) 同步 (synced) 序列 input 和 output(视频逐帧分类)
注意这些模型都没有对序列的长度进行限制,因为循环转换(绿色方块)可以被无限循环使用。

即使输入的不是序列,只是一个固定向量,同样可以使用 RNN 用序列方式进行处理。

2. RNN 的隐藏层:“记忆”

RNN 接收一个 input x,输出一个 output y。注意 y 不只取决于这一次输入的 x,之前历史输入的 x 对它都有影响!!!下面定义的 step 函数体现了这个“记忆”概念。

class RNN:
  # ...
  def step(self, x):
    # update the hidden state
    self.h = np.tanh(np.dot(self.W_hh, self.h) + np.dot(self.W_xh, x))
    # compute the output vector
    y = np.dot(self.W_hy, self.h)
    return y

这个 RNN 模型有 3 组参数 W_hh, W_xh, W_hy(代表权重的矩阵)。隐藏状态 self.h 初始值设为零向量。这里的 tanh 是一个非线性的激活函数。下面的数学公式直观解释上面两行代码:
h t = tanh ⁡ ( W h h h t − 1 + W x h x t ) y = W h y h t \begin{aligned} h_t &= \tanh(W_{hh}h_{t-1}+W_{xh}x_t)\\ y &= W_{hy}h_t \end{aligned} hty=tanh(Whhht1+Wxhxt)=Whyht 在时间 t t t,隐藏状态 h t h_t ht 更新,与前一次的隐藏状态 h t − 1 h_{t-1} ht1 和这一次的 input x t x_t xt 有关。再根据更新后的隐藏状态 h t h_t ht 得到输出结果 y y y

rnn = RNN()
y = rnn.step(x) # x is an input vector, y is the RNN's output vector

更进一步:2 层 RNN

层层叠加的 RNN。下面是两个 RNN 模型,前者的 output 作为后者的 input 继续拓展。

y1 = rnn1.step(x)
y = rnn2.step(y1)

更佳的 RNN:LSTM

更加常用的模型 LSTM 是一种特殊的 RNN,在 self.h = ... 这里的表达式稍微复杂一点。

3. Character-Level 语言模型

RNN 的一个应用:训练 Character-Level 语言模型。输入大量文本语料让 RNN 进行训练,建立一个概率分布模型使得我们可以根据已有的序列预判下一个出现的字母。这个有助于我们进行文本生成,每次生成一个字母。

例. 假设我们有一个词汇表只包含 4 个字母 h e l o,我们在 “hello” 这个序列上用 RNN 进行训练。这个训练序列实际包含 4 个训练样例:

  1. 已有 h 的情况下,e 出现的概率
  2. 已有 he 的情况下,l 出现的概率
  3. 已有 hel 的情况下,l 出现的概率
  4. 已有 hell 的情况下,o 出现的概率

我们把每一个字母进行编码,用向量表示(1-of-k encoding,即除该字母在词汇表所在位置,其他值均为0),然后把每个字母逐个给 RNN 训练(step function)。我们会得到一个 4 维向量的输出(每个字母 1 维),表示下一个出现的所有字母的得分。

上图例子的隐藏层包含 3 个神经元(如第一个方块,(0.3,-0.1,0.9)),显示了输入 “hell” 将会得到的 output 是词汇表里所有字母出现的得分(词汇表:“h,e,l,o”)。训练目的是要使得输入层里绿色的值尽量高,而红色的值尽量低。

比如第一步输入 “h”,下一个为 “h” 的得分为 1.0,“e” 的为 2.2,“l” 为 -3.0,而 “o” 为 4.1。根据我们的训练数据 “hello”,下一个字母应为 “e”,我们要使得 “e” 的得分尽量高,而其他的尽量小。同样的,在每一步(共 4 步)都有一个得分是期望被最大化的。和传统神经网络的训练一样,用 BP 算法调整权重参数。调参后绿色的值会被增大(比如 2.2 变成 2.3),其他值变小。不断地重复训练,直到模型收敛和预测的结果保持稳定,这个模型就可以准确地预测下一个字母。

更深入具体分析这个模型,我们同时在每一次 output 使用 Softmax 分类器(交叉熵损失函数)。RNN 用 mini-batch SGD 进行训练。作者应用 RMSProp 或 Adam (per-parameter adaptive learning rate methods) 来更新模型。

注意第一次输入 “l”,希望输出 “l”;而第二次输入 “l” 则希望输出 “o”。所以 RNN 不能只根据单次的输入来判断,它需要循环读取之前的“记忆”来进行。

4. Python 实现

https://gist.github.com/karpathy/d4dee566867f8291f086

5. 几个有趣的应用

  • Paul Graham generator
  • Shakespeare
  • Wikipedia
  • Algebraic Geometry (Latex)
  • Generating Baby Names

代码地址:https://github.com/karpathy/char-rnn

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值