使用 paddle来进行文本生成
paddle 简单介绍
paddle 是百度在2016年9月份开源的深度学习框架。
就我最近体验的感受来说的它具有几大优点:
1. 本身内嵌了许多和实际业务非常贴近的模型比如个性化推荐,情感分析,词向量,语义角色标注等模型还有更多实际已经内嵌了但是目前还没有出现在官方文档上的模型比如物体检测,文本生成,图像分类,ctr预估等等,可以快速应用到项目中去
2. 就实际体验来看,训练的速度相比于调用keras,在同等数据集上和相同网络架构上要快上不少。当然也是因为keras本身也是基于在tensorflow或者theano上面的,二次调用的速度不如paddle直接调用底层迅速。
缺点也有很多:
1. 一开始的安装对新手极其的不友好,使用docker安装感觉这个开源框架走不长久,所幸这个问题已经解决。
2. 目前很多的文档并不完善,也许百度系的工程师目前对这方面其实并不是很重视,新手教程看起来并非那么易懂。
3. 层的封装并不到位,很多神经网络层得自己去写,感觉非常的不方便。
最后希望借由本文,可以让你快速上手paddle。
一分钟安装paddle
docker 安装
之前paddle的安装方式是使用docker安装,感觉非常的反人类。
安装命令:
docker pull paddlepaddle/paddle:latest
pip 安装
现在已经支持pip 安装了。对(OS: centos 7, ubuntu 16.04, macos 10.12, python: python 2.7.x) 可以直接使用
pip install paddlepaddle 安装cpu 版本。
pip install paddlepaddle-gpu 安装gpu 版本。
安装完以后,测试的代码
import paddle.v2 as paddle
x = paddle.layer.data(name='x', type=paddle.data_type.dense_vector(13))
y = paddle.layer.fc(input=x, size=1, param_attr=paddle.attr.Param(name="fc.w"))
params = paddle.parameters.create(y)
print params["fc.w"].shape
当输出 [13,1],那么恭喜你,已经成功安装了paddle.
遇到的问题
当我在使用pip 安装方式安装了gpu版本的paddle以后,遇到了numpy 版本不兼容的问题。解决的办法是:在把本地的numpy卸载以后,我首先把安装的paddle卸载了,然后重新再安装了一遍paddle。这样在安装的过程当中,可以借由paddle的安装过程来检测你系统的其他python包是否符合paddle需要的环境。其他类似的python包的问题,都可以借由这个办法帮忙解决。
使用paddle中的循环神经网络来生成文本
背景简介
首先paddle实际上已经内嵌了这个项目:
https://github.com/PaddlePaddle/models/tree/develop/generate_sequence_by_rnn_lm
文本生成有很多的应用,比如根据上文生成下一个词,递归下去可以生成整个句子,段落,篇章。目前主流生成文本的方式是使用rnn来生成文本。
主要有两个原因:
1. 因为RNN 是将一个结构反复使用,即使输入的文本很长,所需的network的参数都是一样的。
2. 因为RNN 是共用一个结构的,共用参数的。可以用比较少的参数来训练模型。这样会比较难训练,但是一旦训练好以后,模型会比较难overfitting,效果也会比较好。
对于RNN使用的这个结构,由于原生的RNN的这个结构本身无法解决长程依赖的问题,目前主要使用Lstm 和GRU来进行代替。但是具体到LSTM 和GRU,因为LSTM需要使用三个门结构也就是通常所说的遗忘门,更新门,输出门。而GRU的表现和LSTM类似,却只需要两个门结构。训练速度更快,对内存的占用更小,目前看起来使用GRU是更好的选择。
项目实战
- 首先
git clone https://github.com/PaddlePaddle/models/tree/develop/generate_sequence_by_rnn_lm
到本地model 目录下
- 代码结构如下
.
├── data
│ └── train_data_examples.txt # 示例数据,可参考示例数据的格式,提供自己的数据
├── config.py # 配置文件,包括data、train、infer相关配置
├── generate.py # 预测任务脚本,即生成文本
├── beam_search.py # beam search 算法实现
├── network_conf.py # 本例中涉及的各种网络结构均定义在此文件中,希望进一步修改模型结构,请修改此文件
├── reader.py # 读取数据接口
├── README.md
├── train.py # 训练任务脚本
└── utils.py # 定义通用的函数,例如:构建字典、加载字典等
运行说明
- 首先执行python train.py 开始训练模型,待模型训练完毕以后。
- 执行python generate.py 开始运行文本生成代码。(默认的文本输入为data/train_data_example.txt,生成文本保存为data/gen_result.txt)
代码解析
- paddle 的使用有几个固定需要遵守的流程。
- 大致需要4步。1:初始化,2:定义网络结构,3:训练,4:预测。
- 其中定义网络结构具体需要定义 1:定义具体的网络结构,2:定义所需要的参数,3:定义优化的方法,4:定义event_handler 打印训练信息。
- 总体来说,paddle 的代码上手难度其实对新手挺大的,但思路非常的清晰,耐心阅读应该可以明白。下面我们具体介绍:
1.首先需要加载paddle 进行初始化:
import paddle.v2 as paddle
import numpy as np
paddle.init(use_gpu=False)
2.定义网络结构
# 变量说明
# vocab_dim: 输入变量的维度数.
# type vocab_dim: int
# emb_dim: embedding vector的维度数
# type emb_dim: int
# rnn_type: RNN cell的类型.
# type rnn_type: int
# hidden_size: hidden unit的个数.
# type hidden_size: int
# stacked_rnn_num: 堆叠的rnn cell的个数.
# type stacked_rnn_num: int
# 定义输入层
input = paddle.layer.data(
name="input", type=paddle.data_type.integer_value_sequence(vocab_dim))
if not is_infer:
target = paddle.layer.data(
name="target",
type=paddle.data_type.integer_value_sequence(vocab_dim)) # 定义embedding层
# 该层将上层的输出变量input 做为本层的输入灌入embedding层,将输入input 向量化,方便后续处理
input_emb = paddle.layer.embedding(input=input, size=emb_dim) # 定义rnn层
# 如果 rnn_type 是lstm,则堆叠lstm层
# 如果rnn_type 是gru,则堆叠gru层
# 如果 i = 0的话,先将 input_emb做为输入,其余时刻则将上一时刻的rnn_cell作为输入进行堆叠
# stack_rnn_num 等于多少就堆叠多少个 rnn层
if rnn_type == "lstm":
for i in range(stacked_rnn_num):
rnn_cell = paddle.networks.simple_lstm(
input=rnn_cell if i else input_emb, size=hidden_size)
elif rnn_type == "gru":
for i in range(stacked_rnn_num):
rnn_cell = paddle.networks.simple_gru(
input=rnn_cell if i else input_emb, size=hidden_size)
else:
raise Exception("rnn_type error!") # 定义全联接层
# 将上层最终定义得到的输出rnn_cell 做为输入灌入该全联接层
output = paddle.layer.fc(
input=[rnn_cell], size=vocab_dim, act=paddle.activation.Softmax()) # 最后一层cost中记录了神经网络的所有拓扑结构,通过组合不同的layer,我们即可完成神经网络的搭建。
cost = paddle.layer.classification_cost(input=output, label=target)
paddle的网络结构从这里可以看出其实定义起来需要自己写非常多的代码,感觉非常的冗余,虽然同样也是搭建积木自上而下一层层来写,代码开发的工作量其实蛮大的。
3.训练模型
在完成神经网络的搭建之后,我们首先需要根据神经网络结构来创建所需要优化的parameters(也就是网络结构的参数),并创建optimizer(求解网络结构参数的优化方法比如Sgd,Adam,Rmstrop)之后,我们可以创建trainer来对网络进行训练。在这里我们使用adam算法来作为我们优化的算法,L2正则项来作为正则项。并根据cost 中记录的网络拓扑结构来创建神经网络所需要的参数。
# create optimizer
adam_optimizer = paddle.optimizer.Adam(
learning_rate=1e-3,
regularization=paddle.optimizer.L2Regularization(rate=1e-3),
model_average=paddle.optimizer.ModelAverage(
average_window=0.5, max_average_window=10000)) # create parameters
parameters = paddle.parameters.create(cost)
# create trainer
trainer = paddle.trainer.SGD(
cost=cost, parameters=parameters, update_equation=adam_optimizer)
其中,trainer接收三个参数,包括神经网络拓扑结构 cost、神经网络参数 parameters以及迭代方程 adam_optimizer。在搭建神经网络的过程中,我们仅仅对神经网络的输入进行了描述。而trainer需要读取训练数据进行训练,PaddlePaddle中通过reader来加载数据。
# define reader
reader_args = {
"file_name": conf.train_file,
"word_dict": word_dict,
}
# 读取训练数据
train_reader = paddle.batch(
paddle.reader.shuffle(
reader.rnn_reader(**reader_args), buf_size=102400),
batch_size=conf.batch_size)
# 读取测试数据
test_reader = None
if os.path.exists(conf.test_file) and os.path.getsize(conf.test_file):
test_reader = paddle.batch(
paddle.reader.shuffle(
reader.rnn_reader(**reader_args), buf_size=65536),
batch_size=conf.batch_size)
最终我们可以调用trainer的train方法启动训练:
# define the event_handler callback
# event_handler 主要负责打印训练的进度信息,训练的损失值,这里可以自己定制
def event_handler(event):
if isinstance(event, paddle.event.EndIteration):
if not event.batch_id % conf.log_period:
logger.info("Pass %d, Batch %d, Cost %f, %s" % (
event.pass_id, event.batch_id, event.cost, event.metrics)) if (not event.batch_id %
conf.save_period_by_batches) and event.batch_id:
save_name = os.path.join(model_save_dir,
"rnn_lm_pass_%05d_batch_%03d.tar.gz" %
(event.pass_id, event.batch_id))
with gzip.open(save_name, "w") as f:
parameters.to_tar(f) if isinstance(event, paddle.event.EndPass):
if test_reader is not None:
result = trainer.test(reader=test_reader)
logger.info("Test with Pass %d, %s" %
(event.pass_id, result.metrics))
save_name = os.path.join(model_save_dir, "rnn_lm_pass_%05d.tar.gz" %
(event.pass_id))
with gzip.open(save_name, "w") as f:
parameters.to_tar(f) # 开始训练
trainer.train(
reader=train_reader, event_handler=event_handler, num_passes=num_passes)
至此,我们的训练代码定义结束,开始进行训练
python train.py
pass 相当于我们平常所使用的 epoch(即一次迭代), batch是我们每次训练加载的输入变量的个数,cost 是衡量我们的网络结构损失函数大小的具体值,越小越好,最后一项 classification_error_evaluator 是表明我们目前的分类误差的损失率,也是越小越好。
4.生成文本
当等待若干时间以后,训练完毕以后。开始进行文本生成。
python generate.py
生成文本展示
81 若隐若现 地像 幽灵 , 像 死神
-12.2542 一样 。 他 是 个 怪物 <e>
-12.6889 一样 。 他 是 个 英雄 <e>
-13.9877 一样 。 他 是 我 的 敌人 <e>
-14.2741 一样 。 他 是 我 的 <e>
-14.6250 一样 。 他 是 我 的 朋友 <e>
其中:
- 第一行
81 若隐若现 地像 幽灵 , 像 死神
以\t
为分隔,共有两列:- 第一列是输入前缀在训练样本集中的序号。
- 第二列是输入的前缀。
- 第二 ~
beam_size + 1
行是生成结果,同样以\t
分隔为两列:- 第一列是该生成序列的对数概率(log probability)。
- 第二列是生成的文本序列,正常的生成结果会以符号
<e>
结尾,如果没有以<e>
结尾,意味着超过了最大序列长度,生成强制终止
总结:
我们这次说明了如何安装paddle。如何使用paddle开始一段项目。总体来说paddle 的文档目前是非常的不规范,阅读的体验也不是很好,需要开发者耐心细致的阅读源代码来掌握paddle的使用方法。第二很多层的封装感觉写法非常的冗余,比如一定要用paddle作为前缀,把python写出了java的感觉。但是瑕不掩瑜,从使用的角度来看,一旦掌握了其使用方法以后,自己定义网络结构感觉非常的方便。训练的速度也是挺快的。
使用 paddle来进行文本生成的更多相关文章
- Python将文本生成二维码
#coding:utf-8 ''' Python生成二维码 v1.0 主要将文本生成二维码图片 测试一:将文本生成白底黑字的二维码图片 测试二:将文本生成带logo的二维码图片 ''' __autho ...
- GANs用于文本生成
上学期期末老师给了我本杂志让我好好看看里面的Gans网络是如何应用在文本生成上的,文章里面也没有介绍原理性的东西,只是说了加入这个Gans模型后效果有多好,给出了模型架构图和训练时所用的语料例子,也没 ...
- 实现nlp文本生成中的beam search解码器
自然语言处理任务,比如caption generation(图片描述文本生成).机器翻译中,都需要进行词或者字符序列的生成.常见于seq2seq模型或者RNNLM模型中. 这篇博文主要介绍文本生成解码 ...
- Texygen文本生成,交大计算机系14级的朱耀明
文本生成哪家强?上交大提出基准测试新平台 Texygen 2018-02-12 13:11测评 新智元报道 来源:arxiv 编译:Marvin [新智元导读]上海交通大学.伦敦大学学院朱耀明, 卢思 ...
- python根据文本生成词云图
python根据文本生成词云图 效果 代码 from wordcloud import WordCloud import codecs import jieba #import jieba.analy ...
- 学习笔记(21)- texar 文本生成
今天试了文本生成框架texar https://github.com/asyml/texar 这个texar框架里面,也有端到端的实现 pwd /Users/huihui/git/ git clone ...
- 自己动手实现深度学习框架-8 RNN文本分类和文本生成模型
代码仓库: https://github.com/brandonlyg/cute-dl 目标 上阶段cute-dl已经可以构建基础的RNN模型.但对文本相模型的支持不够友好, 这个阶段 ...
- 斯坦福NLP课程 | 第15讲 - NLP文本生成任务
作者:韩信子@ShowMeAI,路遥@ShowMeAI,奇异果@ShowMeAI 教程地址:http://www.showmeai.tech/tutorials/36 本文地址:http://www. ...
- paddle&蜜度 文本智能较对大赛经验分享(17/685)
引言 我之前参加了一个中文文本智能校对大赛,拿了17名,虽然没什么奖金但好歹也是自己solo拿的第一个比较好的名次吧,期间也学到了一些BERT应用的新视角和新的预训练方法,感觉还挺有趣的,所以在这里记 ...
随机推荐
- java课程设计---计算器(201521123020 邱伟达)
1.团队课程设计博客链接 http://www.cnblogs.com/br0823/p/7064407.html 2.个人负责模板或任务说明 1.初始化按键 2.实现加减乘除开方乘方等运算 3.每个 ...
- 201521123102 《Java程序设计》第11周学习总结
1. 本周学习总结 2.书面作业 1.互斥访问与同步访问 完成题集4-4(互斥访问)与4-5(同步访问)## 1.1 除了使用synchronized修饰方法实现互斥同步访问,还有什么办法实现互斥同步 ...
- Maven第三篇【Maven术语、pom.xml介绍】
maven术语 在我们上一篇中已经知道了在Intellij idea下是如何使用Maven的了,创建出来的目录结构是这样子的: 上面的目录结构就是Maven所谓的"约定",我们使用 ...
- java基础知识6-- 抽象类,抽象方法,接口,构造方法,类方法等易混淆的知识点
一.抽象类和抽象方法 (B 继承 抽象类A) 抽象类:有抽象方法的一定是抽象类 抽象方法:方法名前有abstract修饰,且方法没有方法体,即{},不需要实现任何功能,只是声明 1.抽象类中的方法有 ...
- python实例编写(2)--等待,一组对象,层级元素,frame对象处理
一.设置等待 #coding=utf-8 from selenium import webdriver from selenium.webdriver.support.ui import WebDri ...
- Srping - bean的依赖注入(Dependency injection)
目录 1 概述 2 两种基本的依赖注入方式 2.1 构造函数方式 2.2Setter方式 3 其他依赖注入功能 3.1 <ref/>标签引用不同范围的bean 3.2 内部bean 3.3 ...
- Java实现MD5加密_字符串加密_文件加密
Java实现MD5加密,具体代码如下: package com.bstek.tools; import java.io.FileInputStream; import java.io.IOExcept ...
- webservice07#契约优先#webservice实现简单的动态web项目
1, 用户管理 User{username,password,nickname} 属性. 2,契约优先[ 先用schema做标准来写wsdl.再生成服务器端的接口,再编写接口的类] 在src下创建目录 ...
- firebug离线安装方法-拖入法
这里介绍的是如何在Firefox中离线安装firebug插件. 1, 下载firebug离线包, 一般就是一个*.xpi文件; 2, 打开Firefox浏览器,直接将*.xpi文件拖入Firefox浏 ...
- Spring Security研究(1)
1, 获取Spring Security的Jar包 :从Spring网站下载页下载或者从Maven中央仓库下载.一个好办法是参考实例应用中包含的依赖库. 2,项目模块: Core - spring ...