系列语:本系列是nlp-tutorial代码注释系列,github上原项目地址为:nlp-tutorial,本系列每一篇文章的大纲是相关知识点介绍 + 详细代码注释。

本文知识点介绍来自斯坦福大学CS224N课程lecture6语言模型部分

语言模型

语言模型可以预测一个序列接下来会出现什么词。即给定一个单词序列,语言模型计算出下一个单词是词汇表中各个词的概率分布。
还有一种理解是语言模型可以计算一个句子出现的概率,计算公式如下(条件概率):

n-gram语言模型:

含义:通过前(n-1)个词去预测某个单词。
n-gram有一个基本的假设:假设某个词的出现仅取决于它前面的n-1个单词。根据条件概率公式,某个词的出现概率计算公式为:

计算上图n-gram和(n-1)-gram的比例是通过计算他们在大型语料库中出现的次数的比例:

举个例子:As the proctor started the clock, the students open their ___. 预测这句话空格处的词,假设这里是一个4-gram的语言模型。那么就是通过前三个词:students open their去预测下一个词,语料库中students open their books出现的次数最多,故4-gram模型预测的空格处的词就应该是books。

然而回顾整个句子,前文出现了proctor,所以这个空是exams的概率应该最大,而4-gram模型只考虑前三个词,忽略了前面的词proctor,故导致预测错误。n-gram语言模型的一个缺点:每次预测时只考虑前n-1个词,忽略了再之前的上下文。

sparsity problem:

n-gram模型对于下图的计算式会出现两个问题:

1、分子为0,即语料库中没有相应的n元组,一个解决方法是在一开始给每一个单词增加很小的次数,这个方法叫smoothing;
2、分母为0,即语料库中没有相应的n-1元组,一个解决方法是退化成n-1-gram,即考虑所预测单词前n-2个单词出现的次数。
更糟的是,对于上一个问题,即每次只考虑前n-1个词而忽略了更之前的上下文,可能有个解决方法是增大N。而增大N会导致更严重的sparsity problem。通常N不超过5。

storage problem:

增加N会增加模型大小。

语言模型可以用作文本生成,以下是一个3-gram的语言模型生成的一段文本。但显然,这段文本非常的不连贯且奇怪,因为它的每个词仅仅是依据前两个词生成的,增大N可以改善这个问题,而增大N又会带来很多副作用:sparsity、storage problem。

利用n-gram训练词向量的代码详细注释:
(源代码为github上nlp-tutorial项目,项目地址:nlp-tutorial)

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.FloatTensorsentences = [ "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 = {w: i for i, w in enumerate(word_list)}       #单词转换为序号
number_dict = {i: w for i, w in enumerate(word_list)}     #序号转换为单词
n_class = len(word_dict)                 # number of Vocabulary# NNLM Parameter
n_step = 2 # n-1 in paper                #步长,即根据多少个词来预测下一个词,这里是根据前两个词预测第三个词
n_hidden = 2 # h in paper                #隐藏层神经元个数
m = 2 # m in paper                       #词向量维度def make_batch(sentences):               #作用是将训练集中的句子的最后一个词和前面的词分开input_batch = []                     #空列表,用来存放输入target_batch = []                    #存放一次输入对应的输出for sen in sentences:                #对于训练集中的每个句子word = sen.split()               #先将句子中每个单词按空格分开input = [word_dict[n] for n in word[:-1]]       #[:-1]切片,即输入是一直到最后一个词,最后一个词不要target = word_dict[word[-1]]                    #target是最后一个词input_batch.append(input)                       #将分离出来的input添加到输入列表target_batch.append(target)                     #将分离出来的target添加到标记列表return input_batch, target_batch                    #返回输入和标记列表# Model
class NNLM(nn.Module):def __init__(self):super(NNLM, self).__init__()#文章中计算式为y = b + Wx + U * tanh(d + Hx),这里设置各个参数self.C = nn.Embedding(n_class, m)         #C是词向量矩阵,行数是单词的数量,列数是词向量的维度#H是输入层到隐层的权重矩阵,维数是(输入的个数 * 隐层单元个数),输入的个数是(输入的单词个数 * 词向量维数),即n_step * mself.H = nn.Parameter(torch.randn(n_step * m, n_hidden).type(dtype))#W是一个直连输入层和输出层的权重矩阵,维数是(输入的个数 * 输出层单元个数)self.W = nn.Parameter(torch.randn(n_step * m, n_class).type(dtype))#d是输入层到隐层的偏置常数,维数是(n_hidden * 1)self.d = nn.Parameter(torch.randn(n_hidden).type(dtype))#U是隐层到输出层的权重矩阵,维数是(隐层单元个数 * 输出层单元个数),要输出词典中每一个单词是下一个词的概率,输出的个数应该是单词的个数self.U = nn.Parameter(torch.randn(n_hidden, n_class).type(dtype))#b是隐层到输出层的偏置常数,维数是(输出层单元个数 * 1)self.b = nn.Parameter(torch.randn(n_class).type(dtype))def forward(self, X):        #前向传播,计算公式y = b + Wx + U * tanh(d + Hx)X = self.C(X)            #输入的X是单词的序号,序号X对应的词向量是词向量矩阵C的第X行,取出此词向量X = X.view(-1, n_step * m)                         #reshape矩阵Xtanh = torch.tanh(self.d + torch.mm(X, self.H))    #torch.mm是矩阵相乘output = self.b + torch.mm(X, self.W) + torch.mm(tanh, self.U) #根据上述公式计算输出return outputmodel = NNLM()
criterion = nn.CrossEntropyLoss()                    #损失函数为交叉熵损失函数
optimizer = optim.Adam(model.parameters(), lr=0.001) #使用Adam算法进行优化
input_batch, target_batch = make_batch(sentences)          #使用make_batch从训练集中获得输入和对应的标记input_batch = Variable(torch.LongTensor(input_batch))      #这两行是将输入变成variable,但现在的torch版本直接用tensor即可
target_batch = Variable(torch.LongTensor(target_batch))# Training
for epoch in range(5000):                        #训练5000次optimizer.zero_grad()                        #每次训练前清除梯度缓存output = model(input_batch)                  #对模型输入input_batch,获得输出output# output : [batch_size, n_class], target_batch : [batch_size] (LongTensor, not one-hot)loss = criterion(output, target_batch)       #使用损失函数计算loss,损失函数的输入为模型的输出output和标记targetif (epoch + 1)%1000 == 0:                    #每优化1000次打印一次查看cost的变化print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))loss.backward()                              #反向传播、自动求导optimizer.step()                             #优化、更新参数# Predict
predict = model(input_batch).data.max(1, keepdim=True)[1]       #用.max[1]挑出输出中最大的那一个# Test
print([sen.split()[:2] for sen in sentences], '->', [number_dict[n.item()] for n in predict.squeeze()])

nlp-tutorial代码注释1-1,语言模型、n-gram简介相关推荐

  1. nlp-tutorial代码注释笔记

    系列语:本系列是nlp-tutorial代码注释系列,github上原项目地址为:nlp-tutorial,本系列每一篇文章的大纲是相关知识点介绍 + 详细代码注释. 传送门: nlp-tutoria ...

  2. nlp-tutorial代码注释3-3,双向RNN简介

    系列语:本系列是nlp-tutorial代码注释系列,github上原项目地址为:nlp-tutorial,本系列每一篇文章的大纲是相关知识点介绍 + 详细代码注释. 前言:3-1节介绍了普通的RNN ...

  3. tensorflow笔记:流程,概念和简单代码注释

    tensorflow是google在2015年开源的深度学习框架,可以很方便的检验算法效果.这两天看了看官方的tutorial,极客学院的文档,以及综合tensorflow的源码,把自己的心得整理了一 ...

  4. DeepLearning tutorial(4)CNN卷积神经网络原理简介+代码详解

    FROM: http://blog.csdn.net/u012162613/article/details/43225445 DeepLearning tutorial(4)CNN卷积神经网络原理简介 ...

  5. nlp-tutorial代码注释3-2,LSTM简介

    系列语:本系列是nlp-tutorial代码注释系列,github上原项目地址为:nlp-tutorial,本系列每一篇文章的大纲是相关知识点介绍 + 详细代码注释. 前言:上一节笔记是RNN相关,链 ...

  6. nlp-tutorial代码注释3-1,RNN简介

    系列语:本系列是nlp-tutorial代码注释系列,github上原项目地址为:nlp-tutorial,本系列每一篇文章的大纲是相关知识点介绍 + 详细代码注释. 前言:针对之前n-gram等具有 ...

  7. 一步步读懂Pytorch Chatbot Tutorial代码(二) - 数据处理

    文章目录 自述 代码出处 目录 代码 Create formatted data file (为了方便理解,把代码的顺序略微改一下, 此章节略长.) 1. `loadLines` 将文件的每一行拆分为 ...

  8. GraphDTA论文阅读小白笔记(附代码注释和复现流程)

    目录 摘要 背景 数据和方法 GraphDTA概述 药物表征 蛋白表征 分子图的深度学习 GCN GAT GIN GAT-GCN 基准 模型解释 结果讨论 图模型的表现超过了其它模型 图模型发现已知药 ...

  9. ns3中first.cc~fourth.cc代码注释

    参考博客: ubuntu 18.04安装NS-3教程(详细安装过程) ns-3脚本初识--点对点有线网络:first脚本 ns-3中的数据跟踪与采集--Tracing系统综述及fourth脚本 --- ...

最新文章

  1. unity 开启外部摄像头
  2. 24-移动端app数据爬取
  3. P2498 [SDOI2012]拯救小云公主
  4. SharePoint 跨域还原网站一则
  5. Clojure 的 Enlive 库尝试
  6. 电子元器件筛选公司/费用-电子元器件筛选方法与技术要求
  7. PyTorch 激励函数
  8. 邮件营销如何“爆增”潜在客户?
  9. Python标准库32个模块的整理
  10. vbs编程中 on error resume next的意思
  11. 四旋翼无人机PID调节(无数次实验总结经验和理论支持)
  12. 计算机如何设定远程,电脑远程控制功能怎么设置
  13. think php5 离线手册,thinkphp5.0离线手册下载
  14. 怎么改图片大小kb像素不变?一键快速修改jpg图片大小?
  15. java IO流之一 IO流介绍
  16. 如何测试一支笔之我见
  17. 自由曲面光学元件的OAM测量
  18. IOS 版 Opera 已不再更新
  19. c语言计算器开题报告,基于单片机的简易电子计算器设计开题报告.doc
  20. JavaWeb网上书城项目总结(初步1.0)

热门文章

  1. PHP 中 new static 和 new self 的区别
  2. algorithm design manual: 8-19
  3. cross apply
  4. 团队作业4——第一次项目冲刺(Alpha版本)2017.4.23
  5. cmd下运行java文件时,找不到或无法加载主类的解决方法
  6. Andriod Studio 使用心得,持续更新中
  7. 转:POJ先做完这50题再说
  8. [HttpPost] vs [AcceptVerbs(HttpVerbs.Post)]
  9. MyEclipse下开发Web Service(转)
  10. Redis入门之Redis安装、配置及常用指令