系列语:本系列是nlp-tutorial代码注释系列,github上原项目地址为:nlp-tutorial,本系列每一篇文章的大纲是相关知识点介绍 + 详细代码注释。
前言:针对之前n-gram等具有fixed-window size的模型的缺点,例如无法处理任意长度的输入、不具有记忆性等,提出了一个新的模型:循环神经网络(RNN)。下对其做简要介绍:
RNN:
RNN的特点是有多少输入就有多少对应的激活值。可以看成输入是在时间上有先后的,每一次输入是一个时间步,每一个时间步产生激活值,也可能产生预测值(根据需要)。
RNN的不同点是,它不是仅用本时间步的输入值来预测,而是同时使用前一步的激活值和本步的输入值来预测结果。
RNN想法的核心:不同的时间步都使用相同的权重矩阵W。
RNN语言模型:
RNN的输入可以是任意长度,这里以输入个数为四个单词为例介绍RNN语言模型。
1、将四个单词都转换为相应的词向量;
2、输入第一个单词,这是RNN需要通过前一个时间步的激活值和此时的输入来计算激活值,由于这是第一次输入,是没有前一个时间步的激活值的,这里可以把第0个时间步的激活值当成一个参数来学习,也可以将其初始化为一个值,如0;
3、将剩下的单词依次输入,每个时间步根据前一个时间步的激活值和本时间步的输入计算激活值并喂给下一个时间步,直到最后一个时间步计算出一个激活值(公式见下图hidden states部分);
4、将最后一个时间步计算出的激活值喂给softmax单元,预测下一个单词是词典中所有词的概率分布。
RNN语言模型优点:
1、可以处理任意长度的输入,长的输入不会增加模型的规模;
2、由于每个时间步需要考虑前一个时间步的计算激活值,每一个时间步的计算可以利用多个时间步之前的结果;
3、每个时间步的权重矩阵都是共享的,故学习结果也是可以共享的,学习效率高;
RNN语言模型优点:
1、RNN计算慢,因为每一个时间步都需要前一个时间步的计算结果,不同的输入不能并行处理,只能一个接一个的来;
2、在实践中仍然较难顾及到多个时间步之前的信息。
代码实现:
pytorch代码及详细注释如下:(源代码为github中nlp-tutorial项目,项目地址:nlp-tutorial)
首先import一些需要的库,并设置元素默认的type为float:
import numpy as np #引入numpy库
import torch #引入torch
import torch.nn as nn #torch.nn是torch的神经网络库
import torch.optim as optim #torch.optim是优化库,包含很多优化函数
from torch.autograd import Variable #现在的pytorch版本variable已经回归tensor了,直接用tensor即可
dtype = torch.FloatTensor
接着处理训练集,建立词典,建立词典中各个词和其序号的索引:
sentences = [ "i like dog", "i love coffee", "i hate milk"] #训练集
word_list = " ".join(sentences).split() #先用" ".join(),以空格为分隔,将sentences中的句子连接起来,再用split()以空格为分割点,将每个词分出来
word_list = list(set(word_list)) #先用set合并重复的单词,再用list创建单词列表
word_dict