深度学习-tensorflow2:03 - AI写诗

简介:利用tensorflow2框架,基于循环神经网络(RNN)的长短期记忆神经网络(LSTM)的生成算法,可以让AI生成诗歌,功能可以根据用户输入的起始字、意境等自定义参数生成诗歌。生成的每一首诗歌都是独一无二的,当然内容有些狗屁不通。

原作者github项目地址:

https://github.com/Stevengz/Poem_compose

历史攻略:

深度学习:win10安装TensorFlow

项目目录结构:

data.npy
ix2word.npy
tang.zip:唐诗数据集
test.py:测试运行最终结果
train.py:训练主体程序
training_checkpoints:训练结果
word2ix.npy

案例源码:请参考原作者github项目地址

训练执行:python train.py

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras import losses
import numpy as np
import os

# 导入数据集
data = np.load('data.npy', allow_pickle=True).tolist()
data_line = np.array([word for poem in data for word in poem])
ix2word = np.load('ix2word.npy', allow_pickle=True).item()
word2ix = np.load('word2ix.npy', allow_pickle=True).item()


# 构建模型的函数
def GRU_model(vocab_size, embedding_dim, units, batch_size):
    model = keras.Sequential([
        layers.Embedding(vocab_size,
                         embedding_dim,
                         batch_input_shape=[batch_size, None]),
        layers.GRU(units,
                   return_sequences=True,
                   stateful=True,
                   recurrent_initializer='glorot_uniform'),
        layers.Dense(vocab_size)
    ])
    return model


# 切分成输入和输出
def split_input_target(chunk):
    input_text = chunk[:-1]
    target_text = chunk[1:]
    return input_text, target_text


# 损失函数
def loss(labels, logits):
    return tf.keras.losses.sparse_categorical_crossentropy(labels, logits, from_logits=True)


# 每批大小
BATCH_SIZE = 64
# 缓冲区大小
BUFFER_SIZE = 10000
# 训练周期
EPOCHS = 40
# 诗的长度
poem_size = 125
# 嵌入的维度
embedding_dim = 64
# RNN 的单元数量
units = 128

# 创建训练样本
poem_dataset = tf.data.Dataset.from_tensor_slices(data_line)
# 将每首诗提取出来并切分成输入输出
poems = poem_dataset.batch(poem_size + 1, drop_remainder=True)
dataset = poems.map(split_input_target)
# 分批并随机打乱
dataset = dataset.shuffle(BUFFER_SIZE).batch(BATCH_SIZE, drop_remainder=True)

# 创建模型
model = GRU_model(vocab_size=len(ix2word),
                  embedding_dim=embedding_dim,
                  units=units,
                  batch_size=BATCH_SIZE)
model.summary()
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)

history = model.fit(dataset, epochs=EPOCHS, callbacks=[checkpoint_callback])

训练中的运行结果:

图片

测试和生成诗句:test.py

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import numpy as np


def GRU_model(vocab_size, embedding_dim, units, batch_size):
    model = keras.Sequential([
        layers.Embedding(vocab_size,
                         embedding_dim,
                         batch_input_shape=[batch_size, None]),
        layers.GRU(units,
                   return_sequences=True,
                   stateful=True,
                   recurrent_initializer='glorot_uniform'),
        # layers.GRU(units),
        layers.Dense(vocab_size)
    ])
    return model


# poem_type 为 0 表示整体生成,为 1 表示生成藏头诗
def generate_text(model, start_string, poem_type):
    # 控制诗句意境
    prefix_words = '白日依山尽,黄河入海流。欲穷千里目,更上一层楼。'
    num_generate = 20  # 要生成的字符个数
    poem_generated = []  # 空字符串用于存储结果
    temperature = 1.0

    # 以开头正常生成
    if poem_type == 0:
        # 将整个输入直接导入
        input_eval = [word2ix[s] for s in prefix_words + start_string]
        # 添加开始标识
        input_eval.insert(0, word2ix['<START>'])
        input_eval = tf.expand_dims(input_eval, 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)
            poem_generated.append(ix2word[predicted_id])
        # 删除多余的字
        del poem_generated[poem_generated.index('<EOP>'):]
        return (start_string + ''.join(poem_generated))
    # 藏头诗
    if poem_type == 1:
        for i in range(len(start_string)):
            # 藏头诗以每个字分别生成诗句
            input_eval = [word2ix[s] for s in prefix_words + start_string[i]]
            input_eval.insert(0, word2ix['<START>'])
            input_eval = tf.expand_dims(input_eval, 0)
            model.reset_states()
            poem_one = [start_string[i]]
            for j 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)
                poem_one.append(ix2word[predicted_id])
            # 删除多余的字
            del poem_one[poem_one.index('。') + 1:]
            poem_generated.append(''.join(poem_one) + '\n')
        return ''.join(poem_generated)


ix2word = np.load('ix2word.npy', allow_pickle=True).item()
word2ix = np.load('word2ix.npy', allow_pickle=True).item()

embedding_dim = 64  # 嵌入的维度
units = 128  # RNN 的单元数量
model = GRU_model(len(ix2word), embedding_dim, units=units, batch_size=1)

checkpoint_dir = './training_checkpoints'
model.load_weights(tf.train.latest_checkpoint(checkpoint_dir))
model.build(tf.TensorShape([1, None]))
model.summary()
for i in range(5):
    print(generate_text(model, start_string="新冠速退", poem_type=1))

运行结果:

图片

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值