[NLP][Python]基于keras和LSTM的文本生成

RNN and LSTM

学习如何使用RNN来预测和序列处理。
循环神经网络除了用于预测模型(做出预测)之外,他们还可以学习问题的序列,然后为问题域生成全新的合理序列。
初次尝试将问题分解为三个子问题。
- 1.下载一个免费的文本语料库,您可以使用它来训练文本生成模型
- 2.如何将文本序列的问题构建成循环神经网络生成模型
- 3.如何开发一个LSTM来为给定的问题生成合理的文本序列


实验利用[爱丽丝梦游仙境]全书作为实验数据,没有测试数据。(https://www.gutenberg.org/ebooks/11)

导入数据

load ascii text and covert to lowercase
filename = "wonderland.txt"
raw_text = open(filename).read()
raw_text = raw_text.lower()`

插入说一下read(),readline(),readlines()三个函数的区别

  • read 一次性读取所有文件,将所有文件放到一个字符串变量里
  • readline 每次讲一行读入内存,速度较慢(未比较)
  • readlines 读取时将所有文件一次性读取,然后按行解析成列表,一般读取时用这个

    导入数据之后首先lower()一下,因为后面生成的时候我们没有在意英文的首字母语法,这个有待改进。

数据预处理

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))

n_chars = len(raw_text)
n_vocab = len(chars)
  • 首先获取全部字符的set,然后做两个dict方便后面向量化,一个char2int,一个int2char,这个之后每个字符对应一个整数。
  • 接着获取全文字符数和set后的字符数,大约一个在15W一个在50左右。
  • 之后,做字符的向量化过程,因为字符是不能够之间拉入LSTM中训练的,我们预设序列长度为100,前100个数据没有输出,则有15W减去100个训练数据,将他们用char2int转换成向量形式。

首先,我们必须将输入序列列表变换为LSTM网络预期的[样本,时间步长,特征]。接下来,我们需要将整数重新缩放到0到1的范围,以使缺省情况下使用Sigmoid激活功能的LSTM网络更容易学习模式。
reshape()dataX为预期的张量形式,用utils中的to_categorical将labelY从类别向量(从0到nb_classes的整数向量)映射为二值类别矩阵

# prepare the dataset of input to output pairs encoded as integers
seq_length = 100
dataX = []
dataY = []
for i in range(0, n_chars - seq_length, 1):
    seq_in = raw_text[i:i + seq_length]
    seq_out = raw_text[i + seq_length]
    dataX.append([char_to_int[char] for char in seq_in])
    dataY.append(char_to_int[seq_out])
n_patterns = len(dataX)
print "Total Patterns: ", n_patterns

# reshape X to be [samples, time steps, features]
X = numpy.reshape(dataX, (n_patterns, seq_length, 1))

搭建网络

  • LSTM(input_shape=(100,1) ,output = 256)
  • DropOut(0.2)
  • Dense(256,vocabNum(大约在50))

编译之后把最好的weight用该回调函数将在每个epoch后保存模型到filepath。误差用的交叉熵,adam优化方法。误差大约在1.9-2.9之间


模型代码

model = Sequential()
model.add(LSTM(256, 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')
filepath="weights-improvement-{epoch:02d}-{loss:.4f}.hdf5"
checkpoint = ModelCheckpoint(filepath, monitor='loss', verbose=1, save_best_only=True, mode='min')
callbacks_list = [checkpoint]

model.fit(X, y, nb_epoch=20, batch_size=128, callbacks=callbacks_list)

生成预测文本
首先给一个种子序列作为输入,可以random随机给种子。然后把序列转化为[样本,时间步长,特征]形式,这点非常重要!非常重要!非常重要!下面是生成代码:

# generate characters
for i in range(1000):
    x = numpy.reshape(pattern, (1, len(pattern), 1))
    x = x / float(n_vocab)
    prediction = model.predict(x, verbose=0)
    index = numpy.argmax(prediction)
    result = int_to_char[index]
    seq_in = [int_to_char[value] for value in pattern]
    sys.stdout.write(result)
    pattern.append(index)
    pattern = pattern[1:len(pattern)]
print "\nDone."

总结一下,LSTM的初次尝试,一开始在网络输入上摸不到头脑,把序列问题当成了一般的分类做了处理,没有考虑到张量的问题。每个数据都有固定的序列。估计程序还是要跑好久。下面说下问题:

  • 生成的文本学习不到语法
  • 有大量单词没有无效单词
  • 有没有可能做成中文文本生成
  • 时间效率太低

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值