前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >char-rnn 语言模型

char-rnn 语言模型

原创
作者头像
我爱自然语言处理
修改2018-08-30 15:01:30
1.5K0
修改2018-08-30 15:01:30
举报
文章被收录于专栏:我的python我的python

项目GitHub地址:https://github.com/ClownW/Char-RNN-Pytorch

char-rnn 语言模型 1.char-rnn 语言模型介绍 1.1 rnn的多种结构: 1.2 char-rnn模型 2.项目的几个模块 2.1 数据预处理模块 2.2 rnn模型搭建 2.3 训练模块 3.其他

1.char-rnn 语言模型介绍

1.1 rnn的多种结构:

RNN的多种结构
RNN的多种结构

1.2 char-rnn模型

char-rnn模型
char-rnn模型
  • 训练时,将预料库中的句子输入,希望得到一个与输入有一个偏移的输出
  • 采样时,将前一步的输出作为下一步的输入

这样也导致训练和实际应用时的场景差异,不可避免会影响网络性能。

2.项目的几个模块

2.1 数据预处理模块

在进行预处理之前,需要对数据进行去噪处理,尤其是在数据集较小时对网络性能有很好提升。

此模块需要实现的功能:

  1. 建立单词表,给每个字一个索引
  2. 将一串文本转换成一串索引
  3. 将一串索引转换成一串文本

2.2 rnn模型搭建

网络结构图:

网络结构
网络结构
  • 若输入是中文,则需要经过embedding层
  • 若输入是英文,将每个字符转换成one-hot vector后直接输入

2.3 训练模块

1. 定义网络的输入输出

  • 输入:一串字符对应的字典的索引值
  • 输出:输入的偏移,y[:, :-1], y[:, -1] = x[:, 1:], x[:,0]

2. 定义损失函数

Softmax搭配CrossEntropy函数,但在Pytorch中CrossEntropy内置了Softmax。为了得到softmax的输出,这里采用NLLLoss。(softmax的输出取对数后利用NLLLoss计算的loss就是CrossEntropy)

3. 采用学习率衰减策略

4. 一些训练中的小tips

  • 每个epoch打印出输入字符、期待得到的输出字符和实际得到的输出字符,效果如下:
每个epoch都打印输入输出
每个epoch都打印输入输出
  • 每两个eopch打印出验证集的输入字符、期待得到的输出字符和实际得到的输出字符,效果如下:
每两个epoch打印验证集输入输出
每两个epoch打印验证集输入输出
  • 比较训练集合集合验证集的loss来知道网络是欠拟合还是过拟合

2.4 采样模块

有多种采样策略。采样策略的不同,得到的文本结果效果差异也很大。

  1. 输入为一个单字,取softmax中最大的那个概率作为输出,再将输出作为下一次采样的输入。这样每次采样输入都是一个单字。
  2. 输入为一个单字,先取softmax中最大的5个概率,归一化后按照np.random.choice()方法来选择输出,再将输出作为下一次采样的输入。同样,每次采样输入都是一个单字。
  3. 输入为多个字组成的序列,同样用np.random.choice()来得到每个输出,这样输出也是同样长度的序列。再将整个输出作为下一次采样的输入。这样每次采样输入都是一个序列。
  4. 输入为多个字组成的序列,同样用np.random.choice()来得到每个输出,不同于策略3,这次只取输出序列的最后一个字符拼接到输入之后,并丢弃输入的第一个字符,来产生下一次采样是输入。

实际是按照1->4的策略不断改变的,最终的采样策略为策略4。

策略1:采样结果容易得到ABCABC……的循环,或者全是输出空格

策略2:解决了1中采样结果死循环的问题,能产生一些合理的词语,但句子不够通顺

策略3:能够得到通顺的句子,不好控制产生的序列长度

策略4:能够得到通顺的句子,目前上下文之间语意还不够连贯。这应该是char-rnn的局限性了,每次输入只有若干 字符,完整的段落被切成很多片段并且每次训练时都打乱。

3.其他

1.训练过程中的输出观察

应该输出"因为"却输出“隐为”
应该输出"因为"却输出“隐为”

原本应该输出因为,结果输出隐为,说明“因”和“隐”两个字经过训练后得到相似的词向量,整个训练中没有给 出任何注音信息,两个词词义相差也很大,能够得到相似的词向量在意料之外。

应该输出“怒削而下”却输出“暴削而下”
应该输出“怒削而下”却输出“暴削而下”

原本应该得到“怒削而下”,却得到“暴削而下”,说明意义相近的词能够得到相近的词向量。

应该输出“进入”却输出“出入”
应该输出“进入”却输出“出入”

原本应该得到“进入了修炼状态”,却得到“出入了修炼状态”,“进”和“出”都是表示相同的动作,只是方向不一样。也得到了相似的词向量。

2.验证集的设置

之前没有设置验证集,发现loss已经降到很低时,在采样时得到的结果却依然很差,设置验证集后发现验证集的loss并没有随着训练集一起下降。网络发生严重的过拟合。

解决方案:

  • 若减少隐藏层大小或者增加drop out不会较大得影响训练集上的表现,则减少隐藏层大小和增加drop out概率
  • 若减少隐藏层大小或者增加drop out对训练集的表现影响很大,则说明数据量不足

3.踩过的Pytorch中的坑

  • CrossEntropyLoss中包含了softmax的计算,如果网络中又加了一层softmax会导致loss无法下降
  • 用NLLLoss来计算CrossEntropy时要先对输出取对数,如果输出中包含0则会导致梯度爆炸。解决方案:计算loss时加上1e-20(一个很小的量)进行平滑。
  • nn.Dropout()中参数的含义为drop probability,在TensorFlow中为keep probability

4.使用小说《斗破苍穹》做训练集时的采样结果:

代码语言:javascript
复制
        之内有着一个极为微小的冰落,一时间,只见得一道能量涟截扩散而开,只见得那地方,便是有着不少势力稍弱的强者会自爆,这种魔兽,实在是出人意料,难道这便是我第一次来到这里,所为的,便是能够轻复将之得罪,也不用太过据心……
    “待!”
    望着那被萧炎握住脖诺心尖与那火毒爆裂而开的龙力丹,顿时,一钱漆黑的凭体,顿时,一股雪白的能量涟截暴涌而出,让得人心头寒意。
    “这些该死的魔炎谷,革是此

5.使用18M小学生作文做训练集时的采样结果:

代码语言:javascript
复制
                    走,夏天听到了!
     还带一年晚的时光里,我们只看了看,仿佛在说:“我终于来到我了!”
    我们找了一条小本,我穿着长长的河水,掩出土地点点头,有点像小摆一样,不然,我溜车起来。有事老爷爷给我踩了一大块的纸片。每到冲天,到了秋天的丰收,和庐去给大地母亲的线抱,大自然也会鼓鼓无动。
             ——题记
空歌想就知道这些都是为了自己的做好事而又有一种力。
代码语言:javascript
复制
                         没有钱,我便在那边,我一边听,边说边走开,把我送到沙滩。我拿着瓶子,跑到了小黄鼠的身后,大声得对小草说:“你们真是不可思灭呀!不会这么做,就一个小小的举世中,我们不能与同学打架,但那比太阳、云去的雪白的阳光照在我心里。我有着心灵的感觉,仿佛是是在寻找下面要怎么办?怎么办?这下凤了!
    可是,老师不吸为什么老师而不对我们继续说的,

          我的妈妈是一个伟大的母爱。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.char-rnn 语言模型介绍
    • 1.1 rnn的多种结构:
      • 1.2 char-rnn模型
      • 2.项目的几个模块
        • 2.1 数据预处理模块
          • 2.2 rnn模型搭建
            • 2.3 训练模块
              • 2.4 采样模块
              • 3.其他
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档