目录
有状态性
双向RNN
编码向量
如果有一个经过训练的模型,接下来就可以对其进行预测:
sample_1="""
I hate that the dismal weather had me down for so long,when will it break! Ugh,when does happiness return? The sun is blinding and the puffy clouds are too thin. I can't wait for the weekend.
"""
from keras.api.models import model_from_json
with open("simplernn_model1.json","r") as json_file:
json_string=json_file.read()
model=model_from_json(json_string)
model.load_weights('simplernn_weights1.h5')
vec_list=tokenize_and_vectorize([(1,sample_1)])
test_vec_list=pad_turnc(vec_list,maxlen)
test_vec=np.reshape(test_vec_list,(len(test_vec_list),maxlen,embedding_dims))
print(model.predict_classes(test_vec))
结果是负向的。
我们又有了一个可以添加到流水线中的工具,可以对可能的回复以及用户可能输入的问题或搜索进行分类。选择循环神经网络的原因之一是:与前馈网络或卷积神经网络相比,循环神经网络训练和传递新样本的成本相对较高。
对于使用RNN,要记住出现过的输入位(bit)的概念在NLP中是非常重要的。对循环神经网络来说,梯度消失通常是一个难以克服的问题,特别是在一个有如此多时刻的样本中。
有状态性
有时候,我们想要记住从一个输入样本到下一个输入样本的信息,而不仅仅是单个样本中的一个输入词条到下一个输入词条的一个时刻(词条)。在训练结束时,除了通过反向传播被编码在权重中的内容,最终的输出对网络没有影响,下一个输入将重新开始。Keras在基本RNN层提供了一个关键字参数stateful,它默认为False,如果在模型中添加sampleRNN层时将其设置为True,则最后一个样本的最后一个输出将在下一个时刻与第一个词条输入一起传递给它自己,就像在样本的中间一样。
当我们想要对一个大型的已被分割成段落或句子进行处理的文档建模时,将stateful设置为True不失为一个好主意。甚至可以使用它来对相关文档的整个语料库的含义建模。但是,我们并不希望在没有重置样本间模型状态的情况下,在不相关的文档或段落上训练有状态的RNN。同样的,如果经常打乱文本样本,则一个样本的最后几个词条与下一个样本的前几个词条没有任何关系。因此,对于打乱的文本,我们需要确保stateful参数设置为False,因为样本的顺序不能帮助模型找到合适的匹配关系。
如果传递给fit方法一个batch_size参数,则模型的有状态性将在一批中保存每个样本的输出,然后前一批中第一个样本的输出将会输入给下一批中的第一个样本,前一批中第二个样本的输出将会输入给下一批的第二个样本,以此类推。如果我们试图基于整体的某一小部分对较大的单个语料库进行建模,那么关注数据集的顺序就变得非常重要。
双向RNN
如果词之间的依存关系翻转,例如: They want to pet the dog whose fur was brown.
当读到词条“fur”时,已经遇到了“dog”,并且对它有所了解。但这个句子也包含了“狗有皮毛且毛皮是棕色的”这一信息。这些信息与之前的动作“pet”、“they”想要抚摸的事实有关、也许“they”只喜欢抚摸柔软的、棕色的东西。
人类阅读句子的方向是单向的,但当接收到新信息时,人类的大脑能够迅速回到文本前面的内容。人类可以处理那些没有按照最佳顺序呈现的信息。如果我们能允许模型在输入之间来回切换,这就是双向循环神经网络的用武之地。Keras添加了一个层包装器,它可以在必要时自动翻转输入和输出,为我们自动组装一个双向RNN:
from keras.api.models import Sequential
from keras.api.layers import SimpleRNN
from keras.api.layers import Bidirectional
num_neurons=10
maxlen=100
embedding_dims=300
model=Sequential()
model.add(Bidirectional(SimpleRNN(
num_neurons,return_sequences=True,input_shape=(maxlen,embedding_dims)
)))
其基本思想是将两个RNN并排在一起,将输入像普通单向RNN的输入一样传递到其中一个RNN中,并将同样的输入从反向传递到另一个RNN中(如下图)。然后,在每个时刻将这两个网络的输出拼接到一起作为另一个网络中对应(相同输入词条)时刻的输入。在获取输入最后一个时刻的输出后,将其与在反向网络的第一个时刻的由相同输入词条生成的输出拼接起来。
有了这些工具,不仅可以对文本进行预测和分类,还可以对语言本身及其使用方式进行建模。有了这种对算法的更深层次的理解,我们还可以生成全新的语句,而不仅仅是模仿模型之前见过的文本。
编码向量
在稠密层的前面有一个向量,它的形状(神经元数量*1)来自给定输入序列的循环层的最后一个时刻。这个向量与卷积神经网络中的思想向量是同等的概念。它是词条训练的编码表示。虽然它只能对与网络所训练的标签相关的序列的思想进行编码,但就NLP领域而言,这是惊人的成就,预示着在计算上能将更高阶的概念编码乘向量。