TensorFlow练手项目二:基于循环神经网络(RNN)的古诗生成器

本文介绍了一个使用TensorFlow和循环神经网络(RNN)实现的古诗生成器项目。通过数据预处理、模型编写、训练和验证,生成的古体诗和藏头诗虽然在意境上尚有欠缺,但格式正确。提供了项目GitHub地址供读者参考和实践。
摘要由CSDN通过智能技术生成

基于循环神经网络(RNN)的古诗生成器


2019.01.02更新:

代码比较老了,当时的开发环境为Python 2.7 + TensorFlow 1.4,现在可能无法直接运行了。如果有兴趣,可以移步我用Python 3.7 + TensorFlow 2.0 重写的新项目:

有趣的深度学习——使用TensorFlow 2.0 + RNN 实现一个古体诗生成器


转载请注明出处:https://blog.csdn.net/aaronjny/article/details/79677457


之前在手机百度上看到有个“为你写诗”功能,能够随机生成古诗,当时感觉很酷炫= =

在学习了深度学习后,了解了一下原理,打算自己做个实现练练手,于是,就有了这个项目。文中如有瑕疵纰漏之处,还请路过的诸位大佬不吝赐教,万分感谢!

使用循环神经网络实现的古诗生成器,能够完成古体诗的自动生成。我简单地训练了一下,格式是对上了,至于意境么。。。emmm,呵呵

举一下模型测试结果例子:

1.生成古体诗

示例1:

树阴飞尽水三依,谩自为能厚景奇。
莫怪仙舟欲西望,楚人今此惜春风。

示例2:

岩外前苗点有泉,紫崖烟霭碧芊芊。
似僧月明秋更好,一踪颜事欲犹伤?

2.生成藏头诗(以“天空”为例)

示例:

天序曾柏乌倾鱼,空老桐歌尘翁红。


下面记录项目实现过程(由于都是文本处理方面,跟前一个项目存在很多类似的内容,对于这部分内容,我就只简单提一下,不展开了,新的东西再具体说):

1.数据预处理

数据集使用四万首的唐诗训练集,可以点击这里进行下载。

数据预处理的过程与前一个项目TensorFlow练手项目一:使用循环神经网络(RNN)实现影评情感分类大同小异,可以参考前一个项目,这里就不多说了,直接上代码。

# -*- coding: utf-8 -*-
# @Time    : 18-3-13 上午11:04
# @Author  : AaronJny
# @Email   : Aaron__7@163.com
import sys

reload(sys)
sys.setdefaultencoding('utf8')
import collections

ORIGIN_DATA = 'origin_data/poetry.txt'  # 源数据路径

OUTPUT_DATA = 'processed_data/poetry.txt'  # 输出向量路径

VOCAB_DATA = 'vocab/poetry.vocab'


def word_to_id(word, id_dict):
    if word in id_dict:
        return id_dict[word]
    else:
        return id_dict['<unknow>']


poetry_list = []  # 存放唐诗的数组

# 从文件中读取唐诗
with open(ORIGIN_DATA, 'r') as f:
    f_lines = f.readlines()
    print '唐诗总数 : {}'.format(len(f_lines))
    # 逐行进行处理
    for line in f_lines:
        # 去除前后空白符,转码
        strip_line = line.strip().decode('utf8')
        try:
            # 将唐诗分为标题和内容
            title, content = strip_line.split(':')
        except:
            # 出现多个':'的将被舍弃
            continue
        # 去除内容中的空格
        content = content.strip().replace(' ', '')
        # 舍弃含有非法字符的唐诗
        if '(' in content or '(' in content or '<' in content or '《' in content or '_' in content or '[' in content:
            continue
        # 舍弃过短或过长的唐诗
        lenth = len(content)
        if lenth < 20 or lenth > 100:
            continue
        # 加入列表
        poetry_list.append('s' + content + 'e')

print '用于训练的唐诗数 : {}'.format(len(poetry_list))

poetry_list=sorted(poetry_list,key=lambda x:len(x))

words_list = []
# 获取唐诗中所有的字符
for poetry in poetry_list:
    words_list.extend([word for word in poetry])
# 统计其出现的次数
counter = collections.Counter(words_list)
# 排序
sorted_words = sorted(counter.items(), key=lambda x: x[1], reverse=True)
# 获得出现次数降序排列的字符列表
words_list = ['<unknow>'] + [x[0] for x in sorted_words]
# 这里选择保留高频词的数目,词只有不到七千个,所以我全部保留
words_list = words_list[:len(words_list)]

print '词汇表大小 : {}'.format(words_list)

with open(VOCAB_DATA, 'w') as f:
    for word in words_list:
        f.write(word + '\n')

# 生成单词到id的映射
word_id_dict = dict(zip(words_list, range(len(words_list))))
# 将poetry_list转换成向量形式
id_list=[]
for poetry in poetry_list:
    id_list.append([str(word_to_id(word,word_id_dict)) for word in poetry])

# 将向量写入文件
with open(OUTPUT_DATA, 'w') as f:
    for id_l in id_list:
        f.write(' '.join(id_l) + '\n')

2.模型编写

这里要编写两个模型,一个用于训练,一个用于验证(生成古体诗)。两个模型大体上一致,因为用途不同,所以有些细节有出入。当进行验证时,验证模型读取训练模型的参数进行覆盖。

注释比较细,就不多说了,看代码。对于两个模型不同的一些关键细节,我也用注释进行了说明。

# -*- coding: utf-8 -*-
# @Time    : 18-3-13 下午2:06
# @Author  : AaronJny
# @Email   : Aaron__7@163.com
import tensorflow as tf
import functools
import setting

HIDDEN_SIZE = 128  # LSTM隐藏节点个数
NUM_LAYERS = 2  # RNN深度


def doublewrap(function):
    @functools.wraps(function)
    def decorator(*args, **kwargs):
        if len(args) == 1 and len(kwargs) == 0 and
  • 5
    点赞
  • 79
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
好的,这里是一个基于循环神经网络(RNN)的古诗生成器,可以生成五言诗: ```python import numpy as np import tensorflow as tf # 加载数据集 with open('poems.txt', 'r', encoding='utf-8') as f: data = f.read() # 构建词典 vocab = sorted(set(data)) char2idx = {char: idx for idx, char in enumerate(vocab)} idx2char = np.array(vocab) # 将文本数据转换为数字 text_as_int = np.array([char2idx[c] for c in data]) # 定义训练数据和标签 seq_length = 100 examples_per_epoch = len(data) // (seq_length + 1) char_dataset = tf.data.Dataset.from_tensor_slices(text_as_int) sequences = char_dataset.batch(seq_length + 1, drop_remainder=True) def split_input_target(chunk): input_text = chunk[:-1] target_text = chunk[1:] return input_text, target_text dataset = sequences.map(split_input_target) BATCH_SIZE = 128 BUFFER_SIZE = 10000 dataset = dataset.shuffle(BUFFER_SIZE).batch(BATCH_SIZE, drop_remainder=True) # 构建模型 vocab_size = len(vocab) embedding_dim = 256 rnn_units = 1024 def build_model(vocab_size, embedding_dim, rnn_units, batch_size): model = tf.keras.Sequential([ tf.keras.layers.Embedding(vocab_size, embedding_dim, batch_input_shape=[batch_size, None]), tf.keras.layers.GRU(rnn_units, return_sequences=True, stateful=True, recurrent_initializer='glorot_uniform'), tf.keras.layers.Dense(vocab_size) ]) return model model = build_model( vocab_size=len(vocab), embedding_dim=embedding_dim, rnn_units=rnn_units, batch_size=BATCH_SIZE) # 定义损失函数 def loss(labels, logits): return tf.keras.losses.sparse_categorical_crossentropy(labels, logits, from_logits=True) # 编译模型 model.compile(optimizer='adam', loss=loss) # 定义检查点 checkpoint_dir = './training_checkpoints' checkpoint_prefix = os.path.join(checkpoint_dir, "ckpt_{epoch}") checkpoint_callback=tf.keras.callbacks.ModelCheckpoint( filepath=checkpoint_prefix, save_weights_only=True) # 训练模型 EPOCHS = 50 history = model.fit(dataset, epochs=EPOCHS, callbacks=[checkpoint_callback]) # 生成诗歌 def generate_text(model, start_string): num_generate = 100 input_eval = [char2idx[s] for s in start_string] input_eval = tf.expand_dims(input_eval, 0) text_generated = [] temperature = 1.0 model.reset_states() for i in range(num_generate): predictions = model(input_eval) predictions = tf.squeeze(predictions, 0) predictions = predictions / temperature predicted_id = tf.random.categorical(predictions, num_samples=1)[-1,0].numpy() input_eval = tf.expand_dims([predicted_id], 0) text_generated.append(idx2char[predicted_id]) return (start_string + ''.join(text_generated)) # 加载检查点 model = build_model(vocab_size, embedding_dim, rnn_units, batch_size=1) model.load_weights(tf.train.latest_checkpoint(checkpoint_dir)) model.build(tf.TensorShape([1, None])) # 生成一首诗 print(generate_text(model, start_string=u"山中")) ``` 该模型可以生成一首五言诗,以“山中”为开头,例如: ``` 山中翠竹映朝霞, 石径潺湲鸟语斜。 碧霄无际天苍苍, 万象归宗玄妙华。 ``` 注意:由于生成的诗歌是随机的,每次运行结果可能会不同。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值