最近看了不少关于写诗的博客,在前人的基础上做了一些小的改动,因比较喜欢一次输入很长的开头句,所以让机器人输出压缩为一个开头字生成两个诗句,写五言和七言诗,当然如果你想写更长的诗句是可以继续改动的。

在输入做了些改动,去除误输入的标点符号,例如输入下面词句:

怒发冲冠,凭栏处,潇潇雨歇。抬望眼,仰天长啸,壮怀激烈。

机器人写出如下:

怒漠多无度袍小,巡管山明恰见偷。
发杵共鸿莼散暮,家山曾住上阳台。
冲钩麻衣隐步障,楼舟复别赤轮楼。
冠盘一线倾中令,音信长思两足阴。
凭栏十字送月沈,莫待长筵韦与兵。
栏湿地闲鱼脚吠,匣中虚伴虎前羊。
处向梅香千万里,石城心中明碧簟。
潇湘夜塘独思不,几处深笼不尽迟。
潇湘十二海云天,五月今留报主人。
雨后青青沧练过,月明南渡雁来新。
歇鞭千里知贤哭,清镜草浮麋没繁。
抬吾谢安犹带减,醉来赤此不才齐。
望台已待隋家咏,楼上不能犹扫成。
眼看药炉香岭上,比惟无言旧青春。
仰归安得衰无事,三笑出师湘水春。
天初碧玉衣襟淡,国药满川霞彩寒。
长叹榆关家已远,从来父子屈襄郎。
啸花青石速望尽,宛逐汀洲随并年。
壮时天下还如旧,生计孤吟去杀无。
怀哉却寄终拘束,莫道人来有也才。
激眼剑旗喧并髻,新菰麦落破门骄。
烈灵不识槛西间,芳草青天有五禽。
怒搜温液切,若近太阳香。
发欲奔宾影,争得频人怜。
冲腾临缺曙,谢豹出红残。
冠盖若移在,想得绛皇皇。
凭高晋家雨,才不寄黄金。
栏落临巨浸,根孔恨仙桃。
处世愿越游,飘扬共行之。
潇湘南北洞,蜀国湘江湄。
潇湘弦管绝,上月洞庭时。
雨历道中朔,不起列仙风。
歇毂须江道,家歌住忽依。
抬山弄弓寞,装束岛霞裙。
望闻拜天子,幸有窦金狐。
眼看尽无些,香雨不兴天。
仰阮子不笔,不敢相思逸。
天与十二胆,彩笔取时七。
长安陇波归,银没乌方地。
啸作胡人船,大作康庄匠。
壮何时七两,隐括为匡庐。
怀君青纪肥,常带牺胆圣。
激逐鸱子子,人来儆此处。
烈太仓毛黄,家长受德吉。

代码如下:

main.py

import collections
import os
import sys
import re
import numpy as np
import tensorflow as tf
from model import rnn_model
from poems import process_poems, generate_batch os.environ['TF_CPP_MIN_LOG_LEVEL']='' tf.flags.DEFINE_integer('batch_size', 64, 'batch size.')
tf.flags.DEFINE_float('learning_rate', 0.01, 'learning rate.')
# set this to 'main.py' relative path
tf.flags.DEFINE_string('checkpoints_dir', './checkpoints/', 'checkpoints save path.')
tf.flags.DEFINE_string('file_path', './data/poetry.txt', 'file name of poems.') tf.flags.DEFINE_integer('epochs', 50, 'train how many epochs.') FLAGS = tf.flags.FLAGS start_token = 'G'
end_token = 'E' #开始训练
def run_training():
if not os.path.exists(os.path.dirname(FLAGS.checkpoints_dir)):
os.mkdir(os.path.dirname(FLAGS.checkpoints_dir))
if not os.path.exists(FLAGS.checkpoints_dir):
os.mkdir(FLAGS.checkpoints_dir)
# 单词转化的数字:向量,单词和数字一一对应的字典,单词
poems_vector, word_to_int, vocabularies = process_poems(FLAGS.file_path)
# 真实值和目标值
batches_inputs, batches_outputs = generate_batch(FLAGS.batch_size, poems_vector, word_to_int)
# 数据占位符
input_data = tf.placeholder(tf.int32, [FLAGS.batch_size, None])
output_targets = tf.placeholder(tf.int32, [FLAGS.batch_size, None]) end_points = rnn_model(model='lstm', input_data=input_data, output_data=output_targets, vocab_size=len(
vocabularies), rnn_size=128, num_layers=2, batch_size=64, learning_rate=FLAGS.learning_rate)
# 实例化保存模型
saver = tf.train.Saver(tf.global_variables())
# 全局变量进行初始化
init_op = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer())
with tf.Session() as sess:
# sess = tf_debug.LocalCLIDebugWrapperSession(sess=sess)
# sess.add_tensor_filter("has_inf_or_nan", tf_debug.has_inf_or_nan)
# 先执行,全局变量初始化
sess.run(init_op) start_epoch = 0
# 把之前训练过的checkpoint拿出来
checkpoint = tf.train.latest_checkpoint(FLAGS.checkpoints_dir)
if checkpoint:
# 拿出训练保存模型
saver.restore(sess, checkpoint)
print("[INFO] restore from the checkpoint {0}".format(checkpoint))
start_epoch += int(checkpoint.split('-')[-1])
print('[INFO] start training...')
try:
for epoch in range(start_epoch, FLAGS.epochs):
n = 0
# 多少行唐诗//每次训练的个数
n_chunk = len(poems_vector) // FLAGS.batch_size
for batch in range(n_chunk):
loss, _, _ = sess.run([
end_points['total_loss'], # 损失
end_points['last_state'], # 最后一次输出
end_points['train_op'] # 训练优化损失
], feed_dict={input_data: batches_inputs[n], output_targets: batches_outputs[n]})
n += 1
print('[INFO] Epoch: %d , batch: %d , training loss: %.6f' % (epoch, batch, loss))
if epoch % 6 == 0: # 每隔多少次保存
saver.save(sess, FLAGS.checkpoints_dir, global_step=epoch)
except KeyboardInterrupt:
print('[INFO] Interrupt manually, try saving checkpoint for now...')
saver.save(sess, FLAGS.checkpoints_dir, global_step=epoch)
print('[INFO] Last epoch were saved, next time will start from epoch {}.'.format(epoch)) def to_word(predict, vocabs):
t = np.cumsum(predict)
s = np.sum(predict)
# searchsorted 在前面查找后面的
sample = int(np.searchsorted(t, np.random.rand(1) * s))
# sample = np.argmax(predict)
if sample > len(vocabs):
sample = len(vocabs) - 1
return vocabs[sample] #调用模型生成诗句
def gen_poem(begin_words, num):
batch_size = 1
print('[INFO] loading corpus from %s' % FLAGS.file_path)
# 单词转化的数字:向量,单词和数字一一对应的字典,单词
poems_vector, word_int_map, vocabularies = process_poems(FLAGS.file_path)
# 此时输入为1个
input_data = tf.placeholder(tf.int32, [batch_size, None])
# 损失等
end_points = rnn_model(model='lstm', input_data=input_data, output_data=None, vocab_size=len(
vocabularies), rnn_size=128, num_layers=2, batch_size=64, learning_rate=FLAGS.learning_rate) saver = tf.train.Saver(tf.global_variables())
init_op = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer())
with tf.Session() as sess:
sess.run(init_op)
# 保存模型的位置,拿回sess
checkpoint = tf.train.latest_checkpoint(FLAGS.checkpoints_dir)
# checkpoint = tf.train.latest_checkpoint('./model/') saver.restore(sess, checkpoint)
# saver.restore(sess,'./model/-24')
# 从字典里面获取到的开始值
x = np.array([list(map(word_int_map.get, start_token))]) [predict, last_state] = sess.run([end_points['prediction'], end_points['last_state']],
feed_dict={input_data: x})
poem = ''
for begin_word in begin_words: while True:
if begin_word:
word = begin_word
else:
word = to_word(predict, vocabularies)
sentence = ''
while word != end_token: sentence += word
x = np.zeros((1, 1))
x[0, 0] = word_int_map[word]
[predict, last_state] = sess.run([end_points['prediction'], end_points['last_state']],
feed_dict={input_data: x, end_points['initial_state']: last_state})
word = to_word(predict, vocabularies)
# word = words[np.argmax(probs_)]
if len(sentence) == 2 + 2 * num and (',' or '?') not in sentence[:num] and (',' or '?') not in sentence[num+1:-1] and sentence[num] == ',' and '□' not in sentence:
poem += sentence
# sentence = ''
break
else:
print("我正在写诗呢") return poem #这里将生成的诗句,按照中文诗词的格式输出
#同时方便接入应用
def pretty_print_poem(poem):
poem_sentences = poem.split('。')
# print(poem_sentences)
for s in poem_sentences:
if s != '' and len(s) > 10:
# if s != '': print(s + '。') def main():
if len(sys.argv) == 2:
if sys.argv[1] == '':
print('[INFO] train tang poem...')
run_training()
elif sys.argv[1] == '':
num = int(input("请输入训练诗句(5:五言,7:七言):"))
if num == 5 or num == 7:
print('[INFO] write tang poem...')
begin_word = input('开始作诗,请输入起始字:')
if len(begin_word) == 0:
print("请输入词句")
return
r1 = '[a-zA-Z0-9’!"#$%&\'()*+,-./:;<=>?@,。?★、…【】《》?“”‘’![\\]^_`{|}~]+'
begin_word = re.sub(r1, '', begin_word)
poem2 = gen_poem(begin_word, num)
pretty_print_poem(poem2)
else:
print('输入有误') else:
print('a',sys.argv[1])
print("请按照以下方式执行:")
print("python xxxx.py 1(1:训练,2:写诗)")
else:
print(len(sys.argv))
print("请按照以下方式执行:")
print("python xxxx.py 1(1:训练,2:写诗)") if __name__ == '__main__':
main()

将诗歌和单词转换为一一对应的数字:

def process_poems(file_name):
# 诗集
poems = []
with open(file_name, "r", encoding='utf-8', ) as f:
for line in f.readlines():
try:
title, content = line.strip().split(':')
content = content.replace(' ', '')
if '_' in content or '(' in content or '《' in content or '[' in content or \
start_token in content or end_token in content:
continue
if len(content) < 5 or len(content) > 79:
continue
content = start_token + content + end_token
poems.append(content)
except ValueError as e:
pass
# 按诗的字数排序
poems = sorted(poems, key=lambda l: len(line)) # 统计每个字出现次数
all_words = []
for poem in poems:
all_words += [word for word in poem]
# 这里根据包含了每个字对应的频率 Counter({'我': 3, '你': 2, '他': 1})
counter = collections.Counter(all_words) # items转化为列表,里面为元组 [('他', 1), ('你', 2), ('我', 3)]
count_pairs = sorted(counter.items(), key=lambda x: x[-1])
# ('他', '你', '我'),(1, 2, 3)
words, _ = zip(*count_pairs) # 取前多少个常用字
words = words[:len(words)] + (' ',)
# words = words[:len(words)]
# 每个字映射为一个数字ID {'他': 0, '你': 1, '我': 2}
word_int_map = dict(zip(words, range(len(words))))
# 将诗歌中每个字转换成一一对应的数字,输入poem中的每个字,转化成对应数字返回
# 没有获得word对应数字Id,就返回len(words)
poems_vector = [list(map(lambda word: word_int_map.get(word, len(words)), poem)) for poem in poems] return poems_vector, word_int_map, words

定义真实值和目标值:

def generate_batch(batch_size, poems_vec, word_to_int):
# 每次取64首诗进行训练
# 计算有多少个batch_size
n_chunk = len(poems_vec) // batch_size
x_batches = []
y_batches = []
for i in range(n_chunk):
start_index = i * batch_size
end_index = start_index + batch_size batches = poems_vec[start_index:end_index]
# 找到这个batch的所有poem中最长的poem的长度
length = max(map(len, batches))
# 填充一个这么大小的空batch,空的地方放空格进行填充
x_data = np.full((batch_size, length), word_to_int[' '], np.int32)
for row in range(batch_size):
# 每一行就是一首诗,在原本的长度上把诗还原上去
x_data[row, :len(batches[row])] = batches[row]
y_data = np.copy(x_data)
# y的话就是x向左边也就是前面移动一个
y_data[:, :-1] = x_data[:, 1:]
"""
x_data y_data
[6,2,4,6,9] [2,4,6,9,9]
[1,4,2,8,5] [4,2,8,5,5]
"""
x_batches.append(x_data)
y_batches.append(y_data)
return x_batches, y_batches

定义训练模型:

# -*- coding: utf-8 -*-
import os
import tensorflow as tf
import numpy as np
os.environ['TF_CPP_MIN_LOG_LEVEL']='' #不显示一些提示警告信息 def rnn_model(model, input_data, output_data, vocab_size, rnn_size=128, num_layers=2, batch_size=64,
learning_rate=0.01):
"""
construct rnn seq2seq model.
:param model: model class 模型种类
:param input_data: input data placeholder 输入
:param output_data: output data placeholder 输出
:param vocab_size: 词长度
:param rnn_size: 一个RNN单元的大小
:param num_layers: RNN层数,神经元
:param batch_size: 步长
:param learning_rate: 学习速率
:return:
"""
end_points = {} def rnn_cell():
if model == 'rnn':
cell_fun = tf.contrib.rnn.BasicRNNCell
elif model == 'gru':
cell_fun = tf.contrib.rnn.GRUCell
elif model == 'lstm':
# 基础模型
cell_fun = tf.contrib.rnn.BasicLSTMCell
# 指定rnn_size大小,H,C,控制值和输出值,是否当做元组返回,默认为True
cell = cell_fun(rnn_size, state_is_tuple=True)
return cell
# 基本单元
cell = tf.contrib.rnn.MultiRNNCell([rnn_cell() for _ in range(num_layers)], state_is_tuple=True)
# cell = tf.contrib.rnn.MultiRNNCell([rnn_cell()] * num_layers, state_is_tuple=True) if output_data is not None:
# 初始化
initial_state = cell.zero_state(batch_size, tf.float32)
else:
initial_state = cell.zero_state(1, tf.float32)
# 指定用cpu运行
with tf.device("/cpu:0"):
# 输入的向量转化为128维向量,所以先构建隐层,指定值为+1 到-1区间
embedding = tf.get_variable('embedding', initializer=tf.random_uniform(
[vocab_size + 1, rnn_size], -1.0, 1.0))
# embedding = tf.Variable(tf.random_uniform([vocab_size + 1,rnn_size],-1.0,1.0))
# 输入的不是所有的词,是所有词的一部分,寻找属于哪个词
inputs = tf.nn.embedding_lookup(embedding, input_data) # [batch_size, ?, rnn_size] = [64, ?, 128]
# 输出,和最后一次的输出
outputs, last_state = tf.nn.dynamic_rnn(cell, inputs, initial_state=initial_state)
# 转换为128列的输出,output相当于中间一个128维隐层结果,向量
output = tf.reshape(outputs, [-1, rnn_size])
# 128维的权重,和词汇量
weights = tf.Variable(tf.truncated_normal([rnn_size, vocab_size + 1]))
# 偏置
bias = tf.Variable(tf.zeros(shape=[vocab_size + 1]))
# bias加到前面没一行,预测值
logits = tf.nn.bias_add(tf.matmul(output, weights), bias=bias)
# [?, vocab_size+1] if output_data is not None:
# output_data must be one-hot encode 指定深度为,词汇量深度+1,真实值
labels = tf.one_hot(tf.reshape(output_data, [-1]), depth=vocab_size + 1)
# should be [?, vocab_size+1]
# 计算损失,真实值和预测值
loss = tf.nn.softmax_cross_entropy_with_logits(labels=labels, logits=logits)
# loss shape should be [?, vocab_size+1]
# 对损失求平均
total_loss = tf.reduce_mean(loss)
# 训练,优化损失
train_op = tf.train.AdamOptimizer(learning_rate).minimize(total_loss) end_points['initial_state'] = initial_state
end_points['output'] = output
end_points['train_op'] = train_op
end_points['total_loss'] = total_loss
end_points['loss'] = loss
end_points['last_state'] = last_state
else:
# 预测值
prediction = tf.nn.softmax(logits) end_points['initial_state'] = initial_state
end_points['last_state'] = last_state
end_points['prediction'] = prediction return end_points

训练的时候大概训练了半天吧,基于cpu,loss降到2到3之间就没训练了。古诗里面有些宋词,所以可能会写出一些宋词来。因此当写出宋词的时候,统统过滤了,让机器人从新写一次。

怒浩叛奴风入襄,相思犹记浇秋木。
发夜在关江伯均,屏帏倾酒醺醺时。
冲棱出与征轮钓,北阙朱门注胜囚。
冠子弄衣诗句苦,雁归羊祜得行戎。
凭仗眼巡分一已,拂眉下枕风吹鬓。
栏畔秋风听别情,无将日月悲卮花。
处飞更醉紫骝出,莫怕黄芽头孤酒。
潇湘似人风共恶,月影湿金横向波。
潇湘湘水涵红团,拖蜡桐花过酒楼。
雨丰寒鸟没疏角,雨过嵩门逐几层。
歇山地在秦栖狎,借问纯山色色微。
抬普高花量且白,也遭纱帽却离歌。
望华衔泥不复相,时时避缴如红兰。
眼眼南天南岳畔,十年章岸一何当。
仰头忽要天台绿,九没街边雪里临。
天下别容兵起力,怀王过写复何人。
长江九泽分明月,应逐征帆转汉阳。
啸骨立亡何所赠,别时身去坦云中。
壮时烟雨分雪发,战马翩翩一千尺。
怀乡生抛怀甲得,终竟颠应年子人。
激尔饷于无一事,岛层明月上高台。
烈士不能还续竹,应经此去虽迷定。

Tensorflow之基于LSTM神经网络写唐诗的更多相关文章

  1. 在TensorFlow中基于lstm构建分词系统笔记

    在TensorFlow中基于lstm构建分词系统笔记(一) https://www.jianshu.com/p/ccb805b9f014 前言 我打算基于lstm构建一个分词系统,通过这个例子来学习下 ...

  2. tensorflow实现基于LSTM的文本分类方法

    tensorflow实现基于LSTM的文本分类方法 作者:u010223750 引言 学习一段时间的tensor flow之后,想找个项目试试手,然后想起了之前在看Theano教程中的一个文本分类的实 ...

  3. 一文详解如何用 TensorFlow 实现基于 LSTM 的文本分类(附源码)

    雷锋网按:本文作者陆池,原文载于作者个人博客,雷锋网已获授权. 引言 学习一段时间的tensor flow之后,想找个项目试试手,然后想起了之前在看Theano教程中的一个文本分类的实例,这个星期就用 ...

  4. Tensorflow之基于MNIST手写识别的入门介绍

    Tensorflow是当下AI热潮下,最为受欢迎的开源框架.无论是从Github上的fork数量还是star数量,还是从支持的语音,开发资料,社区活跃度等多方面,他当之为superstar. 在前面介 ...

  5. 用tensorflow搭建RNN(LSTM)进行MNIST 手写数字辨识

    用tensorflow搭建RNN(LSTM)进行MNIST 手写数字辨识 循环神经网络RNN相比传统的神经网络在处理序列化数据时更有优势,因为RNN能够将加入上(下)文信息进行考虑.一个简单的RNN如 ...

  6. 基于卷积神经网络的人脸识别项目_使用Tensorflow-gpu+dilib+sklearn

    https://www.cnblogs.com/31415926535x/p/11001669.html 基于卷积神经网络的人脸识别项目_使用Tensorflow-gpu+dilib+sklearn ...

  7. 基于卷积神经网络的面部表情识别(Pytorch实现)----台大李宏毅机器学习作业3(HW3)

    一.项目说明 给定数据集train.csv,要求使用卷积神经网络CNN,根据每个样本的面部图片判断出其表情.在本项目中,表情共分7类,分别为:(0)生气,(1)厌恶,(2)恐惧,(3)高兴,(4)难过 ...

  8. TensorFlow(九):卷积神经网络

    一:传统神经网络存在的问题 权值太多,计算量太大 权值太多,需要大量样本进行训练 二:卷积神经网络(CNN) CNN通过感受野和权值共享减少了神经网络需要训练的参数个数. 三:池化 四:卷积操作 五: ...

  9. LSTM 神经网络输入输出层

    今天终于弄明白,TensorFlow和Keras中LSTM神经网络的输入输出层到底应该怎么设置和连接了.写个备忘. https://machinelearningmastery.com/how-to- ...

随机推荐

  1. 从MVC和三层架构说到SSH整合开发

    相信很多人都认同JavaWeb开发是遵从MVC开发模式的,遵从三层架构进行开发的,是的,大家都这么认同.但是相信大家都会有过这样一个疑问,if(MVC三层模式==三层架构思想)out.println( ...

  2. Matlab实现画柱状图坐标标签旋转

    引言: 在用matlab画柱状图或者其他图的时候,你是否碰到下图这种情况: 乍一看这个柱状图画的有馍有洋的,but,仔细一看你会发现,横坐标标签如果再长一点就不好看啦,甚至会重叠,就像这样: 这样的图 ...

  3. YAML基础教程

    一.YAML介绍YAML参考了其他多种语言,包括:XML.C语言.Python.Perl以及电子邮件格式RFC2822.Clark Evans在2001年5月在首次发表了这种语言,另外Ingy döt ...

  4. 基于promtheus的监控解决方案

    一.前言 鄙人就职于某安全公司,团队的定位是研发安全产品云汇聚平台,为用户提供弹性伸缩的云安全能力.前段时间产品组提出了一个监控需求,大致要求:平台对vm实行动态实时监控,输出相应图表界面,并提供警报 ...

  5. OpenLayer实现路径运动

    近期由于业务的需求,让我这从未想过要碰Web Gis的业余前端开发者,走了Web Gis的开发道路.功能需求很简单,但却也是让自己难为了好几天.如,应该选择那个Gis框架,Gis框架的兼容性如何,直接 ...

  6. kolla 多节点部署 openstack

    kolla 介绍 简介 kolla 的使命是为 openstack 云平台提供生产级别的.开箱即用的交付能力.kolla 的基本思想是一切皆容器,将所有服务基于 Docker 运行,并且保证一个容器只 ...

  7. API 测试的具体实现

    目录 API 测试的具体实现 基于 Spring Boot 构建的 API 使用 cURL 命令行工具进行测试 使用图形界面工具 Postman 进行测试 如何应对复杂场景的 API 测试? 总结 A ...

  8. Spring Boot 定义系统启动任务,你会几种方式?

    在 Servlet/Jsp 项目中,如果涉及到系统任务,例如在项目启动阶段要做一些数据初始化操作,这些操作有一个共同的特点,只在项目启动时进行,以后都不再执行,这里,容易想到web基础中的三大组件( ...

  9. .net core 程序退出事件

    平滑关闭,关闭事件 //捕获Ctrl+C事件 Console.CancelKeyPress += Console_CancelKeyPress; //进程退出事件 AppDomain.CurrentD ...

  10. Android Gradle 依赖配置:implementation & api

    背景: Android Gradle plugin 3.0开始(对应Gradle版本 4.1及以上),原有的依赖配置类型compile已经被废弃,开始使用implementation.api和anno ...