官方文本解析以及调试
官方RNN链接:https://www.tensorflow.org/tutorials/text/text_generation
数据集来自莎士比亚作品集,资源链接:https://storage.googleapis.com/download.tensorflow.org/data/shakespeare.txt
基本配置环境:
Python3,Tensorflow, Keras。
库文件:
from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf
import numpy as np
import os
import time
下载数据集并读取:
path_to_file = tf.keras.utils.get_file('shakespeare.txt', 'https://storage.googleapis.com/download.tensorflow.org/data/shakespeare.txt')
# Read, then decode for py2 compat.
text = open(path_to_file, 'rb').read().decode(encoding='utf-8')
# length of text is the number of characters in it
print ('Length of text: {} characters'.format(len(text)))
# Take a look at the first 250 characters in text
print(text[:250])
# The unique characters in the file
vocab = sorted(set(text))
print ('{} unique characters'.format(len(vocab)))
由于数据集下载地址为https协议,官方文档这里会报错,
修改如下,在库文件添加ssl协议,并选择关闭
from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf
import ssl
import numpy as np
import os
import time
ssl._create_default_https_context = ssl._create_unverified_context
path_to_file = tf.keras.utils.get_file('shakespeare.txt', 'https://storage.googleapis.com/download.tensorflow.org/data/shakespeare.txt')
下载成功!
通常对于NLP文本测试来说,会首先删除文本中的特殊字符以及数字等等,
在官方文档中给出了一种不常使用的方法,这种方法可以有效转换特殊字符和文本中的关系,但是不适用于数据量较大的文本处理,并且一般不用。
官方给出的方法首先会创建两个检索表,即把字符映射到数字,把数字映射到字符。
处理过程中以全数字进行处理,,之后再用查找表还原。
#vocab中是已经处理过的数据并排序,其中set是将单词转化为字母表示,sorted是将set中的集合排序。
vocab = sorted(set(text))
#创建了char2idx字符到索引映射以及idx2char索引到字符的映射集
#Creating a mapping from unique characters to indices
char2idx = {u:i for i, u in enumerate(vocab)}
idx2char = np.array(vocab)
text_as_int = np.array([char2idx[c] for c in text])
首先来看看vocab中的东西是什么
我们可以从输出来看这种处理方法的问题,首先有可能破坏词与词之间的关系,但是语序关系会随之加强。
转化后的char2idx是以数字为表示,而idx2char只是矩阵化了字符形式。
接着我们来看官方文档中的预测任务。
在官方文本中,首先给出了一个预测任务,即输入一个字符序列后,训练模型以预测输出的每个时间步长后面的字符。
在各个过程中,由于RNN存在一个内部状态,这个状态取决于前置属性,后来的每个输出都需要结合每一个前置输入的属性进行预测。
为了能够实现这个RNN状态,首先需要创建一个训练模型
- 这个训练模型首先包含了所有文本,将所有文本都转化为序列,例如上面的索引模型
- 每个输入序列都会产生一个向右移动的偏置量,这个偏置的生成字符会作为目标文本对预测结果进行修正和判断。
- 例如限定一个长度为4的目标序列,以hallow为输入文本。在第一个阶段首先输入的是hall,与此同时产生一个向右偏移的序列“ello”,再通过RNN训练后产生一个结果,这个结果会与偏移序列比较并修正。在第二个阶段开始后,输入了ello的同时,会产生第二个偏移序列“llow”,并且在第二阶段的学习过程中会提取前面所有阶段的中间信息,可以称之为RNN的中间状态。
在官方给出的RNN模型我们可以看出,对于输入文本的语序分析来说,普通的RNN模型往往只是能够分析前置的规律,并不能提取出从后往前的特性,对于这一点会在以后的RNN-LSTM以及SEQ2SEQ模型中得到优化,这部分以后有缘再说。
好了,接下来我们来看看RNN如何阅读莎士比亚作品集并写出一段相似的文章。
# The maximum length sentence we want for a single input in characters
seq_length = 100
examples_per_epoch = len(text)//(seq_length+1)
# Create training examples / targets
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()])))
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()])))
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])))