LSTM写仿造诗经作诗

"窈窕泥觼湿。方有娈君子,惄焉?其常则?今我不能今。天后之德,胡然国成?有自君子,归哉极哉!"

    这几句诗词看上去是不是有点诗经的味道,细看却是一窍不通,这个全都是LSTM学习了诗经后自动生成的。

import tensorflow as tf
import numpy as np
import os
import time
import textwrap
# 读取并为 py2 compat 解码
text = open("../poem_lstm_practice/poem.txt", 'rb').read().decode(encoding='utf-8')

# 文本长度是指文本中的字符个数
print ('Length of text: {} characters'.format(len(text)))
# 看一看文本中的前 250 个字符
print(text[:250])
Length of text: 37551 characters

关关雎鸠,在河之洲。窈窕淑女,君子好逑。参差荇菜,左右流之。窈窕淑女,寤寐求之。求之不得,寤寐思服。悠哉悠哉,辗转反侧。参差荇菜,左右采之。窈窕淑女,琴瑟友之。参差荇菜,左右芼之。窈窕淑女,钟鼓乐之。
葛之覃兮,施于中谷,维叶萋萋。黄鸟于飞,集于灌木,其鸣喈喈。葛之覃兮,施于中谷,维叶莫莫。是刈是濩,为絺为绤,服之无斁。言告师氏,言告言归。薄污我私,薄浣我衣。害浣害否,归宁父母。
采采卷耳,不盈顷筐。嗟我怀人,置彼周行。陟彼崔嵬,我马虺隤。我姑酌彼金罍,维以不永怀。陟彼高冈,我马玄黄。我
# 文本中的非重复字符
vocab = sorted(set(text))
print ('{} unique characters'.format(len(vocab)))
2798 unique characters
# 创建从非重复字符到索引的映射
char2idx = {u:i for i, u in enumerate(vocab)}
print(char2idx)
idx2char = np.array(vocab)

text_as_int = np.array([char2idx[c] for c in text])
# 设定每个输入句子长度的最大值
seq_length = 100
examples_per_epoch = len(text)//seq_length
# 创建训练样本 / 目标
char_dataset = tf.data.Dataset.from_tensor_slices(text_as_int)
for i in char_dataset.take(5):
    print(idx2char[i.numpy()])


关 关 雎

sequences = char_dataset.batch(seq_length+1, drop_remainder=True)

for item in sequences.take(5):
  print(repr(''.join(idx2char[item.numpy()])))
'\r\n关关雎鸠,在河之洲。窈窕淑女,君子好逑。参差荇菜,左右流之。窈窕淑女,寤寐求之。求之不得,寤寐思服。悠哉悠哉,辗转反侧。参差荇菜,左右采之。窈窕淑女,琴瑟友之。参差荇菜,左右芼之。窈窕淑女,钟鼓乐之'
'。\r\n葛之覃兮,施于中谷,维叶萋萋。黄鸟于飞,集于灌木,其鸣喈喈。葛之覃兮,施于中谷,维叶莫莫。是刈是濩,为絺为绤,服之无斁。言告师氏,言告言归。薄污我私,薄浣我衣。害浣害否,归宁父母。\r\n采采卷耳,不'
'盈顷筐。嗟我怀人,置彼周行。陟彼崔嵬,我马虺隤。我姑酌彼金罍,维以不永怀。陟彼高冈,我马玄黄。我姑酌彼兕觥,维以不永伤。陟彼砠矣,我马瘏矣,我仆痡矣,云何吁矣。\r\n南有樛木,葛藟累之。乐只君子,福履绥之'
'。南有樛木,葛藟荒之。乐只君子,福履将之。南有樛木,葛藟萦之。乐只君子,福履成之。\r\n螽斯羽,诜诜兮。宜尔子孙,振振兮。螽斯羽,薨薨兮。宜尔子孙。绳绳兮。螽斯羽,揖揖兮。宜尔子孙,蛰蛰兮。\r\n桃之夭夭,'
'灼灼其华。之子于归,宜其室家。桃之夭夭,有蕡其实。之子于归,宜其家室。桃之夭夭,其叶蓁蓁。之子于归,宜其家人。\r\n肃肃兔罝,椓之丁丁。赳赳武夫,公侯干城。肃肃兔罝,施于中逵。赳赳武夫,公侯好仇。肃肃免罝'
def split_input_target(chunk):
    input_text = chunk[:-1]
    target_text = chunk[1:]
    return input_text, target_text

dataset = sequences.map(split_input_target)
for input_example, target_example in  dataset.take(1):
  print ('Input data: ', repr(''.join(idx2char[input_example.numpy()])))
  print ('Target data:', repr(''.join(idx2char[target_example.numpy()])))
Input data:  '\r\n关关雎鸠,在河之洲。窈窕淑女,君子好逑。参差荇菜,左右流之。窈窕淑女,寤寐求之。求之不得,寤寐思服。悠哉悠哉,辗转反侧。参差荇菜,左右采之。窈窕淑女,琴瑟友之。参差荇菜,左右芼之。窈窕淑女,钟鼓乐'
Target data: '\n关关雎鸠,在河之洲。窈窕淑女,君子好逑。参差荇菜,左右流之。窈窕淑女,寤寐求之。求之不得,寤寐思服。悠哉悠哉,辗转反侧。参差荇菜,左右采之。窈窕淑女,琴瑟友之。参差荇菜,左右芼之。窈窕淑女,钟鼓乐之'
for i, (input_idx, target_idx) in enumerate(zip(input_example[:5], target_example[:5])):
    print("Step {:4d}".format(i))
    print("  input: {} ({:s})".format(input_idx, repr(idx2char[input_idx])))
    print("  expected output: {} ({:s})".format(target_idx, repr(idx2char[target_idx])))
Step    0
  input: 1 ('\r')
  expected output: 0 ('\n')
Step    1
  input: 0 ('\n')
  expected output: 199 ('关')
Step    2
  input: 199 ('关')
  expected output: 199 ('关')
Step    3
  input: 199 ('关')
  expected output: 2561 ('雎')
Step    4
  input: 2561 ('雎')
  expected output: 2739 ('鸠')
# 批大小
BATCH_SIZE = 64

# 设定缓冲区大小,以重新排列数据集
# (TF 数据被设计为可以处理可能是无限的序列,
# 所以它不会试图在内存中重新排列整个序列。相反,
# 它维持一个缓冲区,在缓冲区重新排列元素。) 
BUFFER_SIZE = 10000

dataset = dataset.shuffle(BUFFER_SIZE).batch(BATCH_SIZE, drop_remainder=True)

dataset
<BatchDataset shapes: ((64, 100), (64, 100)), types: (tf.int32, tf.int32)>
# 词集的长度
vocab_size = len(vocab)

# 嵌入的维度
embedding_dim = 256

# RNN 的单元数量
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.LSTM(rnn_units,
                        return_sequences=True,
                        stateful=True,
                        recurrent_initializer='glorot_uniform'),
    tf.keras.layers.LSTM(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)
for input_example_batch, target_example_batch in dataset.take(1):
  example_batch_predictions = model(input_example_batch)
  print(example_batch_predictions.shape, "# (batch_size, sequence_length, vocab_size)")
(64, 100, 2798) # (batch_size, sequence_length, vocab_size)
def loss(labels, logits):
  return tf.keras.losses.sparse_categorical_crossentropy(labels, logits, from_logits=True)

example_batch_loss  = loss(target_example_batch, example_batch_predictions)
print("Prediction shape: ", example_batch_predictions.shape, " # (batch_size, sequence_length, vocab_size)")
print("scalar_loss:      ", example_batch_loss.numpy().mean())
Prediction shape:  (64, 100, 2798)  # (batch_size, sequence_length, vocab_size)
scalar_loss:       7.9366827
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=1000
history = model.fit(dataset, epochs=EPOCHS, callbacks=[checkpoint_callback])
Epoch 1/1000
5/5 [==============================] - 4s 439ms/step - loss: 7.3037
Epoch 2/1000
5/5 [==============================] - 2s 443ms/step - loss: 6.1857
Epoch 3/1000
5/5 [==============================] - 2s 443ms/step - loss: 6.0807
Epoch 4/1000
5/5 [==============================] - 2s 459ms/step - loss: 6.0250
tf.train.latest_checkpoint(checkpoint_dir)
'./training_checkpoints\\ckpt_368'
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]))
def generate_text(model, start_string):
  # 评估步骤(用学习过的模型生成文本)

  # 要生成的字符个数
    num_generate = 1000

  # 将起始字符串转换为数字(向量化)
    input_eval = [char2idx[s] for s in start_string]
    input_eval = tf.expand_dims(input_eval, 0)

  # 空字符串用于存储结果
    text_generated = []

  # 低温度会生成更可预测的文本
  # 较高温度会生成更令人惊讶的文本
  # 可以通过试验以找到最好的设定
    temperature = 1.0

  # 这里批大小为 1
    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))
# print(generate_text(model, start_string=u"关"))
# print(type(s))
s = generate_text(model, start_string=u"窈窕")
# s = '\n'.join(textwrap.wrap(s,8))
# s = ','.join(textwrap.wrap(s,4))


print(s)
窈窕泥觼湿。方有娈君子,惄焉?其常则?今我不能今。天后之德,胡然国成?有自君子,归哉极哉!
摽有梅,其实七兮。求我庶士,迨其怀兮。摽有梅,顷筐塈之。求我庶士,迨其谓之。
嘒彼小星,三五在东。肃肃宵征,夙夜在公。寔命不同!嘒彼小星,维参与昴。肃肃兔罝,椓之丁丁。赳赳武夫,公侯取:我园,无折我树檀。岂敢爱之?畏人之多言。仲可怀也,人之多言亦可畏也。
叔于田,巷无居人。岂不怀甚?子哉不死!虽则佩阻,以祈尔爵。籥舞笙鼓,乐既和奏。烝衎君子,俾尔弥尔性,饮酒来迩。
执竞武王,陟望之。燕婉之水,其叶箐蒲。六月采蓝,牖流采云。有肃鸨翼。君子有酒,嘉命式私。既见君子,其带一,乃陟南冈。乃觏于京,京师之野。于时处处,于时庐旅,于时言言,于时语语。笃公刘,于京斯依。跄跄济济,俾筵俾几。既登乃依,乃如西顾,亦孔冥。不可好也,维我愿音。冽彼泉桑,在彼中河。髧彼两髦,实维我仪。之死矢靡它。母也天只,无谅人只!泛彼柏舟,在彼中河。髧彼两髦,实维我心。之死矢靡慝。母也天只,不谅人只!
墙有茨,不可扫也。中冓之言,不可道也。所可道也,言之丑也。墙有茨,不可襄也。中冓之言,不可详也。所可详也,言之长也。墙有茨,不可束也。中冓之言,不可详也。所可详也,言之长也。墙有茨,不可束也。中冓之言,不可详也。所可详也,言之长也。墙有茨,不可束也。中冓之言,不可详也。所可详也,言之长也。墙有茨,不可束也。中冓之言,不可详也。所可详也,言之长也。墙有茨,不可襄也。中冓之言,不可详也。所可详也,言之长也。墙有茨,不可束也。中冓之言,不可详也。所可详也,言之长也。墙有茨,不可束也。中冓之言,不可详也。所可详也,言之长也。墙有茨,不可束也。中冓之好,不可错服。独。言旋言归,复我邦家。我奕与兮,敝予又改。今哉匪周,女予卿功。靡人靡生!
交采勿狐,不居无灾。出有旧乎驺虞!
泛彼飞隼,载飞载止。嗟我兄弟,莫远具尔。或四之筵,或授之几。四筵设席,出夫玄罦。我生尔迈,维周之方。四方其章,允王维。有兔爰爰,雉离于罦。我生之初,不日其皇。谋亦孔言,是授之光。四牡骙骙,八鸾喈喈。仲山甫徂齐,丧乱其声。乐乐右。天子是毗,俾民不承。受越众君梓,无鹿信也。忧心之云,念我无禄。何以我思?不敢也行。无父,庶不我好?胡逝我梁?不作我稷。我百不显,自我出思。终诞云知,我心孔黄。或已是嘉,不永寿弟。曾孙卿民,秉心宣疾。
衡维在奏,三民之野。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值