Tensorflow框架循环神经网络实现文本生成

import numpy as np
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import SimpleRNN, Dense
import matplotlib.pyplot as plt

# 加载训练数据
text = open('chinese_text.txt', encoding='utf-8').read()
print(f'训练数据字符数: {len(text)}')

# 创建索引词典
chars = sorted(list(set(text)))
char_to_index = {c: i for i, c in enumerate(chars)} # 字符为键,下标为值的词典
index_to_char = {i: c for i, c in enumerate(chars)} # 下标为键,字符为值的词典
chars = [char_to_index[char] for char in text]

# 处理训练数据
maxlen = 10  # 序列长度
step = 1  # 每步移动的字符数
sentences = []
next_chars = []
for i in range(0, len(text) - maxlen, step):
    sentences.append(text[i: i + maxlen]) # 将文本分段,每段10个字符
    next_chars.append(text[i + maxlen])
print(f'句段总数: {len(sentences)}')

# 向量化输入和目标
X = np.zeros((len(sentences), maxlen, len(chars)), dtype=bool) # 第一维为总段数,第二维为每段的字符数,第三维为词典的长度
y = np.zeros((len(sentences), len(chars)), dtype=bool)
for i, sentence in enumerate(sentences):
    for t, char in enumerate(sentence):
        X[i, t, char_to_index[char]] = True # 以每段的每个字符在词典中的值为下标,给其下一维对应的位置置真
    y[i, char_to_index[next_chars[i]]] = True # 以其对应X中段的下一个字符在词典中的值为下标,给其下一维对应的位置置真

# 构建RNN模型
model = Sequential()
model.add(SimpleRNN(128)) # 增加简单RNN层
# model.add(SimpleRNN(128, input_shape=(maxlen, len(chars))))
model.add(Dense(len(chars), activation='softmax')) # 增加全连接层
model.compile(loss='categorical_crossentropy', optimizer='adam') # 指定损失函数及优化器

# 训练模型
history = model.fit(X, y, batch_size=128, epochs=100)


loss_values = history.history['loss'] # 获取损失函数
loss_values = list(loss_values)
plt.figure()
plt.plot(range(1, 100 + 1), loss_values, c = '#000000', label = 'train loss')
plt.title('Train Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.savefig('Train Loss.svg')
plt.show()


# 定义采样函数
def sample(preds, temperature): # 预测概率数组和温度参数
    preds = np.asarray(preds).astype('float64') # 将preds转换为NumPy数组,并确保其数据类型为float64
    preds = np.log(preds) / temperature # 当温度参数较低时,概率分布更确定,较高时,概率分布更随机
    exp_preds = np.exp(preds)
    preds = exp_preds / np.sum(exp_preds) # 归一化
    probas = np.random.multinomial(1, preds, 1)
    return np.argmax(probas)

# 测试
test_text = '人物风流往往非,空余' # 十个字符
print(f'测试输入为: {test_text}')
print(f'完整输出古诗为: {test_text}', end='')
for i in range(100):
    test = np.zeros((1, maxlen, len(chars)), dtype=bool)
    for i, char in enumerate(test_text):
        test[0, i, char_to_index[char]] = True

    preds = model.predict(test, verbose=0)[0] # 不输出任何日志
    next_index = sample(preds, temperature=0.5)
    next_char = index_to_char[next_index]

    test_text += next_char
    test_text = test_text[1:] # 将预测后的结果加入段,去除段首成员,将新的段作为新的输入

    print(next_char, end='')
    if(next_char=='\n'):break # 以换行符作为诗结束的标志

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值