举个小小的例子,来看看LSTM是怎么玩的
我们这里用温斯顿丘吉尔的人物传记作为我们的学习语料。
(各种中文语料可以自行网上查找,英文的小说语料可以从古登堡计划网站下载txt平文本:https://www.gutenberg.org/wiki/Category:Bookshelf)
第一步,一样,先导入各种库
import numpy
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import LSTM
from keras.callbacks import ModelCheckpoint
from keras.utils import np_utils
接下来,我们把文本读入
raw_text = open('../input/Winston_Churchil.txt').read()
raw_text = raw_text.lower()
既然我们是以每个字母为层级,字母总共才26个,所以我们可以很方便的用One-Hot来编码出所有的字母(当然,可能还有些标点符号和其他noise)
chars = sorted(list(set(raw_text)))
char_to_int = dict((c, i) for i, c in enumerate(chars))
int_to_char = dict((i, c) for i, c in enumerate(chars))
我们看到,全部的chars:
chars
一共有:
len(chars)
同时,我们的原文本一共有:
len(raw_text)
我们这里简单的文本预测就是,给了前置的字母以后,下一个字母是谁?
比如,Winsto, 给出 nBritai 给出 n
我们需要把我们的raw text变成可以用来训练的x,y:
x 是前置字母们y 是后一个字母
seq_length = 100
x = []
y = []
for i in range(0, len(raw_text) - seq_length):
given = raw_text[i:i + seq_length]
predict = raw_text[i + seq_length]
x.append([char_to_int[char] for char in given])
y.append(char_to_int[predict])
我们可以看看我们做好的数据集的长相:
print(x[:3])
print(y[:3])
此刻,楼上这些表达方式,类似就是一个词袋,或者说 index。
接下来我们做两件事:
我们已经有了一个input的数字表达(index),我们要把它变成LSTM需要的数组格式: [样本数,时间步伐,特征]
第二,对于output,我们在Word2Vec里学过,用one-hot做output的预测可以给我们更好的效果,相对于直接预测一个准确的y数值的话。
n_patterns = len(x)
n_vocab = len(chars)
# 把x变成LSTM需要的样子
x = numpy.reshape(x, (n_patterns, seq_length, 1))
# 简单normal到0-1之间
x = x / float(n_vocab)
# output变成one-hot
y = np_utils.to_categorical(y)
print(x[11])
print(y[11])
LSTM模型构建
model = Sequential()
model.add(LSTM(128, input_shape=(x.shape[1], x.shape[2])))
model.add(Dropout(0.2))
model.add(Dense(y.shape[1], activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam')
model.fit(x, y, nb_epoch=10, batch_size=32)
我们来写个程序,看看我们训练出来的LSTM的效果:
def predict_next(input_array):
x = numpy.reshape(input_array, (1, seq_length, 1))
x = x / float(n_vocab)
y = model.predict(x)
return y
def string_to_index(raw_input):
res = []
for c in raw_input[(len(raw_input)-seq_length):]:
res.append(char_to_int[c])
return res
def y_to_char(y):
largest_index = y.argmax()
c = int_to_char[largest_index]
return c
好,写成一个大程序:
def generate_article(init, rounds=500):
in_string = init.lower()
for i in range(rounds):
n = y_to_char(predict_next(string_to_index(in_string)))
in_string += n
return in_string
init = 'Professor Michael S. Hart is the originator of the Project'
article = generate_article(init)
print(article)