为你写诗,为你静止 ,为你做不可能的事。
为你写诗,你这不是为难我们直男直女的程序员们嘛。
虽然我写不出诗,但不代表我不能训练一个网络为你写诗,想要多少写多少!
所以今天的主题就是如何训练一个能自动写诗的LSTM模型。
废话不多说,代码如下:
爱情是一种怪事
我开始全身不受控制
爱情是一种本事
我开始连自己都不是
为你我做了太多的傻事
第一件就是为你写诗
为你写诗为你静止
为你做不可能的事
为你我学会弹琴写词
为你失去理智
为你写诗为你静止
为你做不可能的事
为你弹奏所有情歌的句子
我忘了说最美的是你的名字
呃呃呃好像不小心贴错代码了,重来:
# coding: utf-8
# In[1]:
import re
import random
import pandas as pd
import numpy as np
from keras.preprocessing import sequence
from keras.optimizers import SGD, RMSprop, Adagrad
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from keras.layers.embeddings import Embedding
from keras.layers.recurrent import LSTM, GRU
# In[2]:
# 读取数据, 生成汉字列表
with open('poetry.txt','r', encoding='UTF-8') as f:
raw_text = f.read()
lines = raw_text.split("\n")[:-1]
poem_text = [i.split(':')[1] for i in lines]
char_list = [re.findall('[\x80-\xff]{3}|[\w\W]', s) for s in poem_text]
# In[3]:
# 汉字 <-> 数字 映射
all_words = []
for i in char_list:
all_words.extend(i)
word_dataframe = pd.DataFrame(pd.Series(all_words).value_counts())
word_dataframe['id'] = list(range(1,len(word_dataframe)+1))
word_index_dict = word_dataframe['id'].to_dict()
index_dict = {}
for k in word_index_dict:
index_dict.update({word_index_dict[k]:k})
len(all_words), len(word_dataframe), len(index_dict)
# In[4]:
# 生成训练数据, x 为 前两个汉字, y 为 接下来的汉字
# 如: 明月几时有 会被整理成下面三条数据
# 明月 -> 几 月几 -> 时 几时 -> 有
seq_len = 2
dataX = []
dataY = []
for i in range(0, len(all_words) - seq_len, 1):
seq_in = all_words[i : i + seq_len]
seq_out = all_words[i + seq_len]
dataX.append([word_index_dict[x] for x in seq_in])
dataY.append(word_index_dict[seq_out])
len(dataY)
# In[5]:
X = np.array(dataX)
y = np_utils.to_categorical(np.array(dataY))
X.shape, y.shape
# In[6]:
model = Sequential()
# Embedding 层将正整数(下标)转换为具有固定大小的向量,如[[4],[20]]->[[0.25,0.1],[0.6,-0.2]]
# Embedding 层只能作为模型的第一层
# input_dim:大或等于0的整数,字典长度
# output_dim:大于0的整数,代表全连接嵌入的维度
model.add(Embedding(len(word_dataframe), 512))
# LSTM
model.add(LSTM(512))
# Dropout 防止过拟合
model.add(Dropout(0.5))
# output 为 y 的维度
model.add(Dense(y.shape[1]))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam')
model.summary()
# In[7]:
# 训练
model.fit(X, y, batch_size=64, epochs=40)
# In[8]:
def get_predict_array(seed_text):
chars = re.findall('[\x80-\xff]{3}|[\w\W]', seed_text)
x = np.array([word_index_dict[k] for k in chars])
proba = model.predict(x, verbose=0)
return proba
get_predict_array("明月")
# 可以看到预测出来的结果是两个列表, 下一个字是第二个列表
# In[9]:
def gen_poetry(model, seed_text, rows=4, cols=5):
'''
生成诗词的函数
输入: 两个汉字, 行数, 每行的字数 (默认为五言绝句)
'''
total_cols = cols + 1 # 加上标点符号
chars = re.findall('[\x80-\xff]{3}|[\w\W]', seed_text)
if len(chars) != seq_len: # seq_len = 2
return ""
arr = [word_index_dict[k] for k in chars]
for i in range(seq_len, rows * total_cols):
if (i+1) % total_cols == 0: # 逗号或句号
if (i+1) / total_cols == 2 or (i+1) / total_cols == 4: # 句号的情况
arr.append(2) # 句号在字典中的映射为 2
else:
arr.append(1) # 逗号在字典中的映射为 1
else:
proba = model.predict(np.array(arr[-seq_len:]), verbose=0)
predicted = np.argsort(proba[1])[-5:]
index = random.randint(0,len(predicted)-1) # 在前五个可能结果里随机取, 避免每次都是同样的结果
new_char = predicted[index]
while new_char == 1 or new_char == 2: # 如果是逗号或句号, 应该重新换一个
index = random.randint(0,len(predicted)-1)
new_char = predicted[index]
arr.append(new_char)
poem = [index_dict[i] for i in arr]
return "".join(poem)
# In[10]:
print(gen_poetry(model, '明月'))
print(gen_poetry(model, '悠然', rows=4, cols=7))
print(gen_poetry(model, '长河', rows=4, cols=7))
# In[11]:
model.save(filepath='lstm_poetry.hdf5')
# In[12]:
# 试下 GRU
gru = Sequential()
gru.add(Embedding(len(word_dataframe), 512))
gru.add(GRU(512))
# gru.add(Dropout(0.5))
gru.add(Dense(y.shape[1]))
gru.add(Activation('softmax'))
gru.compile(loss='categorical_crossentropy', optimizer='adam')
# In[13]:
gru.summary()
# In[14]:
gru.fit(X, y, batch_size=64, epochs=40)
# In[15]:
print(gen_poetry(gru, '明月'))
print(gen_poetry(gru, '悠然', rows=4, cols=7))
print(gen_poetry(gru, '长河', rows=4, cols=7))
# In[16]:
gru.save('gru_poetry.hdf5')
其中poetry.txt文件里是一些训练用到的诗句数据,代码文件和poetry.txt文件可以从我的github上下载:https://github.com/qq604395564/LSTM-Poetry
祝大家都能找到可以为她(他)写诗的人!
转载自原文链接, 如需删除请联系管理员。
原文链接:为你写诗(LSTM 诗歌生成器),转载请注明来源!