打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
文本生成:双层RNN(LSTM)生成金庸小说里人物的名字

传统的机器学习,还有深度学习,最简单的形式,就是输出N个向量,对应N个结果,即所谓的“有监督”学习。然后再给定一个新的向量,就知道对应的分类。

那有没有可能学习一堆数据之后,按照学习到的规律,生成一些数据呢?是可能的,在图像识别中,就是所谓的GAN图片生成,因为图片包含了所有信息,生成的效果是很好的。

本文想讨论文本的生成,这里先提供一种比较简单的形式。

用tensorflow的话,模板代码太多,所有细节都需要自己处理。本文仍然使用tflearn来做。

首先是素材准备,把金庸小说里的人名汇总起来,做个简单的预处理,变成如下格式(一行一个),这里包含了所有金庸小说里的人名。我们要学习这些名字,然后按规律模型自己生成一些名字。

自然语言都是需要预处理成计算机可以识别的格式,在深度学习中一般不提取特征,就直接用下标,可以是词(word)或字(char)。本文是取名字,所以使用字(char)。

tflearn已经提供了一个预处理的函数:string_to_semi_redundant_sequences,按字面意思是就是“字符串转为半冗余的序列”。什么意思呢?

string_utf8是输入的字符串,格式为“皇太极\n祖大寿\n倪哑巴\n胡桂南\n胡老三崔秋山\n黄真\n崔希敏\n黄二毛子\n曹化淳\n黄须人”,注意\n也是一个字符。

seq_maxlen是生成的序列的长度,这里取20。

redun_step是步长,就是每隔几个字取一次,这里取2。

比如,取[0:20)个字,就是“皇太极\n祖大寿\n倪哑巴\n胡桂南\n胡老三崔秋”,输出要预测的”下一个字“就是第20个字,在这个例子中是“山”。然后跳redun_step步,也就是从“极\n祖大寿\n倪哑巴\n胡桂南\n胡老三崔秋山\n”,对就的输出是“崔”。

但我们不能直接使用文字 ,而是输出下标,我们会构建一个char_idx,也就是

输出:{'真': 649, '赫': 854, '笔': 691, '翰': 724, '侍': 72, '丝': 18, '纪': 705, '身': 860, '修': 80...}这样的格式。X=(5387, 20, 1017),Y=(5387,1017), 这就构建了(X,Y)的对应关系,就可以进行训练了。

import os
import requests
import tflearn
from tflearn.data_utils import *

path = "jy2.txt"
maxlen = 20
string_utf8 = open(path, "r",encoding='utf-8').read()
#char_idx是得到文本序列里,每个char(字)的坐标,英文序列就是每个字母。
#如果是英文,就是26个字母,中文字比较多
#这里步长为3,取序列长度=20,比如[0-19]个字做input,20个字做output
X, Y, char_idx = \
string_to_semi_redundant_sequences(string_utf8, seq_maxlen=maxlen, redun_step=1)

这里使用双层的LSTM,SequenceGenerator,仍然是一个DNN的model,只不过把predict封装成了可以预测产生序列。

g = tflearn.input_data(shape=[None, maxlen, len(char_idx)])
g = tflearn.lstm(g, 512, return_seq=True)#这里有一个return_seq
g = tflearn.dropout(g, 0.5)
g = tflearn.lstm(g, 512)
g = tflearn.dropout(g, 0.5)
g = tflearn.fully_connected(g, len(char_idx), activation='softmax')#1022
g = tflearn.regression(g, optimizer='adam', loss='categorical_crossentropy',
learning_rate=0.001)

m = tflearn.SequenceGenerator(g, dictionary=char_idx,
seq_maxlen=maxlen,
clip_gradients=5.0,
checkpoint_path='model_us_cities')
epoch = 40
for i in range(epoch):
seed = random_sequence_from_string(string_utf8, maxlen)
m.fit(X, Y, validation_set=0.1, batch_size=128,
n_epoch=1, run_id='us_cities')
print("-- TESTING...")
print("-- Test with temperature of 1.2 --")
out1 = m.generate(30, temperature=1.2, seq_seed=seed)
print(type(out1),out1)
print("-- Test with temperature of 1.0 --")
print(m.generate(30, temperature=1.0, seq_seed=seed))
print("-- Test with temperature of 0.5 --")
print(m.generate(30, temperature=0.5, seq_seed=seed))

第一个epoch之后的输出还比较乱:

第8个epoch之后,好一些了:

第28个epoch,基本上能识别出常用的姓了。

第35个epoch:

lstm的训练计算量比较大,双层lstm就更慢了,但效果还是不错的。统计到了文本里很多信息。这里可以扩展比如整本射雕英雄传,四大名著都可以。然后计算机就可以”创作“了。

关于作者:魏佳斌,互联网产品/技术总监,北京大学光华管理学院(MBA),特许金融分析师(CFA),资深产品经理/码农。偏爱python,深度关注互联网趋势,人工智能,AI金融量化。致力于使用最前沿的认知技术去理解这个复杂的世界。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
正确理解UNICODE UTF
资源 | 数十种TensorFlow实现案例汇集:代码 笔记
目前网上嵌入式最好的printf,用起来!
找出字符串中最长的数字字符串
python用于NLP的seq2seq模型实例:用Keras实现神经机器翻译
C#中文乱码解决:UTF8 转 UNICODE
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服