利用递归神经网络模型对输入序列进行处理。
概述
一些机器学习问题需要多于一组输入数据,并且随着时间推移处理一些列的输入数据。神经网络模型可以处理一系列输入,但需要在输入之间维护神经网络的某些状态。Core ML 提供了一种简单的方法来维护网络的状态并处理一些列输入。
了解神经网络工作流程
对于机器学习模型来说处理自然语言是一个困难的任务,因为可能的句子数量是无限的,因此无法将所有输入编码到模型中。一个常用的方法来减少输入的可能性的数量,通过使用字母或者单词作为模型的输入,而不是将整句话作为一次输入处理。然而,该模型需要一种方法来维持状态以“记住”先前在序列中呈现的字母或单词。
考虑训练一个神将网络模型去生成莎士比亚戏剧《罗密欧与朱丽叶》。神经网络在不实用明确规则的情况下,对单词及其相近的单词之间的关系进行编码。在热门话题中,“O, Romeo, Romeo, wherefore art thou Romeo?”罗密欧这个词出现了三次,但每次出现之后都有一个不同的词。模型需要一个区分用途的方法。递归神经网络是一类神经网络,通过在处理单词时将每个单词作为附加输入处理后使用模型的状态来解决该问题。
图一:三个输入字上的递归神经网络的输入和输出
图1显示了学习罗密欧与朱丽叶的网络示例工作流程。要启动短语,提供“O”和nil状态作为输入。预测下一个字,并且网络还为输入“O”生成其状态的表示,称为f(“O”)。下一个输入词“Romeo”与前一个状态f(“O”)组合,以创建下一个输入。鉴于该输入,该模型再次以高概率输出“罗密欧”。
下一个输入词“Romeo”与前一个输入词相同。但是,状态输入是不同的。状态输入现在是f(“O”,“Romeo”)。即使先前的输入字是相同的,不同的状态也允许网络输出预测“wherefore”。
揭示模型状态
在Xcode中添加一个基于递归神经网络模型,查看输入和输出特性公开的神经网络状态。
图二
图二展示了Xcode中ShakespeareLanguageModel视图,该模型具有一个递归神经网络层,列出了它的输入输出特性的状态。其他递归神经网络,例如
Short-Term Memory和Gated Recurrent networks,可以自动创建输入输出特性。这个网络接受两个输入:
Input word和State input,他们是可选的。word是一个String类型,名为stateIn的state是一个包含512个Double数值的一维数组。state input是一个可选值,因为序列开头没有之前的状态。网络有三个输出:
most probable next word,一个Dictionary与其概率配对的可能的下一个word,以及State output,他是一个512个Double类型值的一维数组,用这三个字段来表示处理输入后的网络状态。MLMultiArray输出表示网络内部节点激活水平的状态。为了使网络“记住”已处理的输入序列,先前的输出状态必须伴随下一个输入。实际上,你可能遇到具有默认状态feature名称的图层。例如,
Long Short-Term Memory networks会有lstm_h_in和lstm_c_in作为默认状态的参数名称用于输入,以及lstm_h_out和lsth_c_out用于输出。"h"表示隐藏状态,"c"表示LSTM网络使用的单元状态。这些输出状态必须作为输入状态进行传递,以便网络在输入序列中正常工作。
启动输入序列
这个网络是经过训练的,根据一个句子中的两个提示词,从剧中生成一个句子的其余部分。通过将提示符中的第一个单词和nil作为前一个状态传递进来,开始用这个模型处理一系列输入。
Listing 1 Initializing a network by using nil as the first state
// 创建要用作示例的提示符
let prompt = ["O", "Romeo"]
// 使用生成的输入API创建网络的输入,没有状态
let modelInput = ShakespeareLanguageModelInput(previousWord: prompt[0], stateIn: nil)
// 预测第二个单词,生成“O”的模型状态
var modelOutput = try model.prediction(input: modelInput)
在这个示例代码中,被Xcode生成的ShakespeareLanguageModelInput类,被用于存储预测调用的两个输入。
基于先前的状态作出预测
使用来自提示符的第二个单词和来自预测的输出状态作为输入状态创建输入。将该输入与模型一起使用以生成对句子的第三个单词的预测。
Listing 2 Predicting the third word by using the second word and the state after processing the first word
// 设置第二个单词的输入(忽略预测单词)
modelInput.previousWord = prompt[1]
// 使用输出模型状态作为下一个单词的输入模型状态
modelInput.stateIn = modelOutput.stateOut
// 预测第三个单词
modelOutput = try model.prediction(input: modelInput)
// 第三个单词现在在modelOutput.nextWord中
当你用头两个单词初始化网络的时候,需要保留输出状态来表示输入序列。预测的单词和概率被忽略。它们被忽略了,因为第二个单词Romeo来自实际文本,而不是模型的预测。
然而,一旦处理了两个单词提示,输出的下一个单词最可能是句子中的第三个单词。它会被用来作输入单词,来生成句子中的第四个单词。重复使用输出作为输入生成句子中的其余部分。
Listing 3 Using the next word prediction as the input word, to generate the rest of the sentence
// 当预测的单词不是句子的结尾时,将下一个单词和输出状态反馈回网络。
while modelOutput.nextWord != "</s>" {
// Update the inputs from the network's output
modelInput.previousWord = modelOutput.nextWord
modelInput.stateIn = modelOutput.stateOut
// Predict the next word
modelOutput = try model.prediction(input: modelInput)
}
Listing 3 重复使用预测的单词和状态作为输入单词和状态的过程,直到预测的单词</s>。这个网络使用字符串</s>表示句子的结尾。
验证输出并重置输入状态
此时,模型已经预测到了句子的结尾。nextWord值的序列表示模型对整个s句子的预测。可以将整个预测句子呈现给用户以进行验证或者以编程方式与实际文本进行比较。













网友评论