【PaddlePaddle】自然语言处理:句词预测
前言
预测词汇的相关性算是自然语言中的HelloWolrd。本文主要根据百度PaddlePaddle示例word2vec,对句子中下一个单词的预测。该示例使用4个词语来预测下一个词。
1. 数据集以及字典、Reader构建
示例采用Penn Treebank (PTB)数据集(经Tomas Mikolov预处理过的版本),直接使用数据集中的data文件夹下的ptb.train.txt和ptb.test.txt即可。这两个文件是英语语句组成的训练集,所以直接读取文件再用split将句子分开既可以得到单词列表。
单词是不定长的,所以往往将单词映射为一个序号。例如'a'用1表示,‘an’用2表示等等。这样以来我们就必须构建字典,然后对字典中的单词进行编号。示例使用了训练集和数据集制作字典,同时统计单词出现的次数,设置了min_word_freq来对出现次数少的单词进行剔除。
def word_count(f, word_freq=None):
if word_freq is None:
word_freq = collections.defaultdict(int)
for l in f:
for w in l.strip().split(): #删除前后端空格,并且切分单词,每个单词计数
word_freq[w] += 1
word_freq['<s>'] += 1
word_freq['<e>'] += 1
return word_freq def build_dict(data_path,min_word_freq=50):
"""
构建字典
"""
train_filename = './simple-examples/data/ptb.train.txt'
test_filename = './simple-examples/data/ptb.valid.txt'
with tarfile.open(data_path) as tf:
trainf = tf.extractfile(train_filename)
testf = tf.extractfile(test_filename)
word_freq = word_count(testf, word_count(trainf))
if '<unk>' in word_freq:
# remove <unk> for now, since we will set it as last index
del word_freq['<unk>']
word_freq = filter(lambda x: x[1] > min_word_freq, word_freq.items()) #滤除掉小于min_word的单词
word_freq_sorted = sorted(word_freq, key=lambda x: (-x[1], x[0])) #排序,次数多优先,首字母次之
words, _ = list(zip(*word_freq_sorted))
word_idx = dict(zip(words, xrange(len(words)))) #构建字典,字典顺序与次序无关
word_idx['<unk>'] = len(words)
return word_idx
Reader的构建也十分简单,直接读取数据集,然后根据字典得到各个单词的索引号即可:
def reader_creator(data_path,filename,word_idx,n):
def reader():
with tarfile.open(data_path) as tf:
f = tf.extractfile(filename)
UNK = word_idx['<e>']
for l in f:#按照每行读取
assert n > -1, 'Invalid gram length'
l = ['<s>'] + l.strip().split() + ['<e>'] #头尾巴添加start 和 end
if len(l) >= n:
l = [word_idx.get(w, UNK) for w in l] #如果字典找不到,则返回'<e>'的索引
for i in range(n, len(l) + 1):
yield tuple(l[i - n:i]) return reader
2. 离散型特征处理
从上面可知,单词可以根据字典从原本一个不定长的字符串映射到一个简单的离散整形数据。但是,这种离散的数据类似于分类问题,而非连续的回归问题,很少会直接作为网络的输入或者输出,而是选择特定的编码进行代替。例如,在手写识别数字识别中,我们希望从网络得到的记过是0~9的数据,但是网络输出采用对10个标签进行softmax的形式来获取最大几率的标签。例如1,则表示为[0 1 0 0 0 0 0 0 0 0],2则表示为[0 0 1 0 0 0 0 0 0 0],以此类推,这种编码称为独热码(one-hot)。显然,在这里同样可以使用独热码对单词索引进行编码,但是编码的维度等于字典的维度,这样导致了向量的稀疏。另一个问题是,我们是试图预测单词之间的相关性,这种编码难以表征单词间的相关性,因为他们的L1距离(曼哈顿距离)都是一样的。
为了解决这个问题,深度学习中采用了embedding层,将one-hot编码映射到较小的维度向量中,而且向量中的每个元素都是连续的,而且该层的参数是可训练的。虽然对于每个输入都取了embedding,但是这4层的参数都是共享的。
first_word = fluid.layers.data(name='firstw', shape=[1], dtype='int64')
embed_first = fluid.layers.embedding(
input=first_word,
size=[dict_size, EMBED_SIZE],
dtype='float32',
is_sparse=is_sparse,
param_attr='shared_w')
3. 构建训练网络
该网络比较简单,经过word embedding后,直接采用两层的全连接层。由于是分类问题,后面采用了softmax的输出字典长度的向量,查找几率最大的单词。
def inference_program(is_sparse):
first_word = fluid.layers.data(name='firstw', shape=[1], dtype='int64')
second_word = fluid.layers.data(name='secondw', shape=[1], dtype='int64')
third_word = fluid.layers.data(name='thirdw', shape=[1], dtype='int64')
fourth_word = fluid.layers.data(name='fourthw', shape=[1], dtype='int64') embed_first = fluid.layers.embedding(
input=first_word,
size=[dict_size, EMBED_SIZE],
dtype='float32',
is_sparse=is_sparse,
param_attr='shared_w')
embed_second = fluid.layers.embedding(
input=second_word,
size=[dict_size, EMBED_SIZE],
dtype='float32',
is_sparse=is_sparse,
param_attr='shared_w')
embed_third = fluid.layers.embedding(
input=third_word,
size=[dict_size, EMBED_SIZE],
dtype='float32',
is_sparse=is_sparse,
param_attr='shared_w')
embed_fourth = fluid.layers.embedding(
input=fourth_word,
size=[dict_size, EMBED_SIZE],
dtype='float32',
is_sparse=is_sparse,
param_attr='shared_w') concat_embed = fluid.layers.concat(
input=[embed_first, embed_second, embed_third, embed_fourth], axis=1)
hidden1 = fluid.layers.fc(
input=concat_embed, size=HIDDEN_SIZE, act='sigmoid')
predict_word = fluid.layers.fc(input=hidden1, size=dict_size, act='softmax')
return predict_word
4、训练以及结果
分类问题,故采用交叉熵作为损失函数即可:
def train_program(is_sparse):
predict_word = inference_program(is_sparse)
next_word = fluid.layers.data(name='nextw', shape=[1], dtype='int64')
cost = fluid.layers.cross_entropy(input=predict_word, label=next_word)
avg_cost = fluid.layers.mean(cost)
return avg_cost
我们输入among a group of得到的结果为
Step : Average Cost 7.323672
Step : Average Cost 6.127039
softmax result=
[[0.03509435 0.03092922 0.00015478 ... 0.00019624 0.00020122 0.02606127]]
amog a group of :
the
对于4个embedding layer,输入[20 20 20 20]获取前两个单词的映射结果如下,可见这4个embedding layerd的参数是共享的。所做的映射都是相同的。
first word embeding result:
[[-0.03654227 0.03615221 -0.00636815 0.04953869 0.00659253 -0.03805562
-0.03781673 -0.00323956 0.04304311 -0.02775818 -0.02895659 -0.02973305
0.03278778 0.02302501 0.03120029 0.01132151 -0.03574367 -0.03974182
0.00527415 -0.02988834 -0.04431479 -0.03779307 -0.00829562 0.02014677
0.01256767 0.04155278 0.0176531 0.03231385 0.02013639 0.01016513
-0.01383959 -0.00534514]]
second word embeding result:
[[-0.03654227 0.03615221 -0.00636815 0.04953869 0.00659253 -0.03805562
-0.03781673 -0.00323956 0.04304311 -0.02775818 -0.02895659 -0.02973305
0.03278778 0.02302501 0.03120029 0.01132151 -0.03574367 -0.03974182
0.00527415 -0.02988834 -0.04431479 -0.03779307 -0.00829562 0.02014677
0.01256767 0.04155278 0.0176531 0.03231385 0.02013639 0.01016513
-0.01383959 -0.00534514]]
结语
该示例看似简单,但是embeding layer仍不知如何操作,或者甚至再训练过程中,参数如何得到优化,有待以后学习。
本文源码:Github
【PaddlePaddle】自然语言处理:句词预测的更多相关文章
- 【NLP】自然语言处理:词向量和语言模型
声明: 这是转载自LICSTAR博士的牛文,原文载于此:http://licstar.net/archives/328 这篇博客是我看了半年的论文后,自己对 Deep Learning 在 NLP 领 ...
- NLP之Bi-LSTM(在长句中预测下一个单词)
Bi-LSTM @ 目录 Bi-LSTM 1.理论 1.1 基本模型 1.2 Bi-LSTM的特点 2.实验 2.1 实验步骤 2.2 实验模型 1.理论 1.1 基本模型 Bi-LSTM模型分为2个 ...
- 吴恩达《深度学习》-课后测验-第五门课 序列模型(Sequence Models)-Week 2: Natural Language Processing and Word Embeddings (第二周测验:自然语言处理与词嵌入)
Week 2 Quiz: Natural Language Processing and Word Embeddings (第二周测验:自然语言处理与词嵌入) 1.Suppose you learn ...
- 吴恩达《深度学习》-第五门课 序列模型(Sequence Models)-第二周 自然语言处理与词嵌入(Natural Language Processing and Word Embeddings)-课程笔记
第二周 自然语言处理与词嵌入(Natural Language Processing and Word Embeddings) 2.1 词汇表征(Word Representation) 词汇表示,目 ...
- DeepLearning.ai学习笔记(五)序列模型 -- week2 自然语言处理与词嵌入
一.词汇表征 首先回顾一下之前介绍的单词表示方法,即one hot表示法. 如下图示,"Man"这个单词可以用 \(O_{5391}\) 表示,其中O表示One_hot.其他单词同 ...
- rnn-nlp-单词预测
import reader import numpy as np import tensorflow as tf # 数据参数 DATA_PATH = 'simple-examples/data/' ...
- Coursera Deep Learning笔记 序列模型(二)NLP & Word Embeddings(自然语言处理与词嵌入)
参考 1. Word Representation 之前介绍用词汇表表示单词,使用one-hot 向量表示词,缺点:它使每个词孤立起来,使得算法对相关词的泛化能力不强. 从上图可以看出相似的单词分布距 ...
- ng-深度学习-课程笔记-16: 自然语言处理与词嵌入(Week2)
1 词汇表征(Word representation) 用one-hot表示单词的一个缺点就是它把每个词孤立起来,这使得算法对词语的相关性泛化不强. 可以使用词嵌入(word embedding)来解 ...
- 95、自然语言处理svd词向量
import numpy as np import matplotlib.pyplot as plt la = np.linalg words = ["I","like& ...
随机推荐
- IIS上配置单页面404
问题 因为我们的应用是单页客户端应用,当用户在浏览器直接访问http://www.xxx.com/user时,刷新页面的时候,会返回404错误. 问题原因 服务端URL匹配不到相应的路由资源 解决方案 ...
- node.js中stream流中可读流和可写流的使用
node.js中的流 stream 是处理流式数据的抽象接口.node.js 提供了很多流对象,像http中的request和response,和 process.stdout 都是流的实例. 流可以 ...
- jquery 表单校验
<link type="text/css" href="<%=basepath%>css/form/validate.css" rel=&qu ...
- trinitycore 魔兽服务器源码分析(二) 网络
书接上文 继续分析Socket.h SocketMgr.h template<class T>class Socket : public std::enable_shared_from_t ...
- 为docker配置HTTP代理服务器
背景: node1不能访问外网, node2可以访问外网,node1通过node2的代理服务来访问外网. 1. node1不能访问外网 vim /etc/resolv.conf 注释掉DNS配置文件 ...
- Linux下设置快捷键
以设置终端为例,进入Settings>>Keyboard>>Custom Shortcuts,点左下脚的+号,Name栏填入Treminal,command栏填入gnome-t ...
- MFC开发中添加自定义消息和消息响应函数
(1)在.h或.cpp文件定义一个消息 #define CLICK_MESSAGE_BOX WM_USER+1001 //add by 20180612 给主窗口ctrl.cpp发送消息 //自定义消 ...
- WCF双工通信单工通信
1.单工模式 单向通信,指通信只有一个方向进行,即从客户端流向服务,服务不会发送响应,而客户端也不会期望会有响应.这种情况下,客户端发送消息,然后继续执行 运行后报错: 2.双工模式 双工模式的特点是 ...
- RabbitMQ 常用操作
RabbitMQ简介 1.首先安装erlang rpm -Uvh https://www.rabbitmq.com/releases/erlang/erlang-19.0.4-1.el7.centos ...
- Microsoft在8月7号发布的帮助文档更新中,HelpLibrary2安装Cab文档包出现签名问题
在VS 2017 8月2号发布15.7.6版本后,在8月7号推送了helpview程序中的绝大部分更新文档,在本次推送中多数Cab文件出现了无法进行安装的签名问题, 不论是单个下载,还是删除本地所有已 ...