自回归模型(AutoregressiveModel)通过将生成问题视为一个序列过程来简化生成模型。自回归模型将预测条件建立在序列中的先前值上,而不是一个以随机潜变量为条件。因此,自回归模型尝试对数据生成分布进行显式建模,而不是尝试近似数据分布。在本节中,将介绍一类经典的自回归模型,长短期记忆网络(LongShort-TermMemoryNetwork,LSTM),并将LSTM应用于生成文本数据。
加载并过滤数据,以便只保留具有标题和描述的菜谱配方:
#加载并过滤数据withopen("./data/full_format_recipes.json")asjson_data:recipe_data=json.load(json_data)filtered_data=["Recipefor"+x["title"]+"|"+"".join(x["directions"])forxinrecipe_dataif"title"inxandx["title"]isnotNoneand"directions"inxandx["directions"]isnotNone]数据集中示例样本如下所示:
在使用Keras构建LSTM网络之前,我们首先需要了解文本数据的结构以及它与图像数据的不同之处。
文本和图像数据之间的差异性导致许多适用于图像数据的方法并不适用于文本数据:
接下来,我们介绍需要采取哪些步骤以使文本数据适合训练LSTM网络。
第一步是清理文本,并将文本转化为符号(token),分词(Tokenization)就是将文本分割成单独的符号(例如单词或字符)的过程。如何对文本进行分词取决于文本生成模型需要实现的目标。使用单词符号和字符符号都各有利弊,不同的选择选择会影响建模之前所需的文本清理方式以及模型输出。如果使用单词符号:
如果使用字符符号:
在本节中,我们使用小写单词分词,且不进行词干提取。我们还将标点符号转换为符号,因为我们希望模型能够预测句子的结束或使用逗号等标点符号:
在下图中,可以看到一部分符号的列表,并将它们映射到各自的索引,在本节中,填充符号同样使用0符号(即停止标记),并将不在词汇表(频率最高的前10,000个单词)中的未知单词标记为符号1。其他单词按频率顺序分配符号,词汇表中包含的单词数量也是训练过程的一个超参数,词汇表中包含的单词越多,文本中出现的未知符号越少,但模型规模也将更大以容纳更大规模的词汇表。
LSTM网络经过训练后,可以根据给定的单词序列预测序列中的下一个单词。例如,我们可以将“grilledchickenwithboiled”的对应的符号输入模型,模型应当能够输出恰当的下一个单词(例如potatoes,而不是bananas)。因此,我们只需将整个序列向后移动一个符号,就可以创建目标变量:
defprepare_inputs(text):text=tf.expand_dims(text,-1)tokenized_sentences=vectorize_layer(text)x=tokenized_sentences[:,:-1]y=tokenized_sentences[:,1:]returnx,y#创建训练集,其包含食谱符号(输入)和向后移动一个符号的相同食谱符号(目标变量)train_ds=text_ds.map(prepare_inputs)4.构建LSTM模型4.1模型架构LSTM模型的整体架构下图所示,模型的输入是整数符号序列,输出是词汇表中每个单词出现在序列下一个位置的概率。为了详细了解其工作原理,我们需要介绍两种新的层类型,Embedding和LSTM。
需要注意的是,输入层不需要提前指定序列长度。批大小和序列长度都是灵活的(因此形状为(None,None)),这是因为所有下游层与传递的序列长度是无关的。
嵌入层嵌入层(EmbeddingLayer)本质上是一个查找表,将每个符号转换为长度为embedding_size的向量,如下图所示。查找向量由模型作为权重进行学习。因此,该层学习的权重数量等于词汇表大小乘以嵌入向量的维度(即10,000×100=1,000,000)。
我们将每个符号嵌入到连续的向量中,使得模型能够学习每个单词的表示,且这个表示可以通过反向传播进行更新。我们也可以只对每个输入标记进行独热编码,但使用嵌入层效果更好,因为嵌入本身可训练,从而使模型更具灵活性。因此,输入层将形状为[batch_size,seq_length]的整数序列张量传递给嵌入层,嵌入层输出形状为[batch_size,seq_length,embedding_size]的张量,然后将其传递给LSTM层。
为了详细说明,我们继续深入此过程。观察序列通过该层的过程。
隐藏状态通过以下六个步骤进行更新:
构建、编译并训练LSTM:
编译并训练LSTM模型后,可以使用该模型生成长文本字符串:
神经网络会输出一组可供采样的每个单词的概率分布,并从中进行采样。因此,此文本生成过程是随机性的,而不是确定性。此外,我们还可以引入一个温度参数来调整采样过程的确定性程度。
温度参数当温度参数接近0时,采样过程更加确定性(即最高概率的单词最有可能被选择),而温度参数为1意味着每个单词都按模型输出的概率进行选择。
创建一个回调函数,以用于在每个训练epoch结束时生成文本:
关于这两个段落需要注意以下几点。首先,它们在风格上都与原始训练集中的食谱相似。它们都以一个食谱标题开头,并包含正确的语法结构。区别在于,在温度参数为1.0的情况下生成的文本更加大胆,因此比温度参数为0.2的生成结果准确性较差。使用温度参数为1.0生成多个样本会生成多个不同结果,因为模型是从具有更大方差的概率分布中进行采样。为了证明这一点,下图展示了对于各种序列来说,下一个出现概率最高的前5个单词。
该模型能够在多个上下文中生成下一个最可能出现的单词的分布。例如,即使我们从未告知模型有关名词、动词、形容词和介词等词性的信息,通常它也能够将单词按照词性分类,而且还能按照正确的语法使用这些单词。此外,模型能够根据给定标题选择一个合适的动词作为食谱说明的开头。对于烤蔬菜,它最有可能选择的动词可能是预热、准备、加热、放置或混合,而对于冰淇淋,它最有可能选择的动词可能是添加、混合、搅拌和混合。这表明模型具有一定能力的上下文理解能力,能够根据配料区分食谱之间的差异。同时还需要注意,在温度参数为0.2的生成示例中,更倾向于选择概率较高的单词,这就是为什么当温度参数较低时,生成的多样性通常较小的原因。虽然基本LSTM模型在生成逼真文本方面有较好性能,但显然它仍然难以理解所生成词汇的一些语义含义。例如,引入了不太可能搭配在一起的配料(例如,酸味的日式土豆、核桃屑和水果冰)。在某些情况下,这可能是有趣的,例如,希望LSTM生成有趣而独特的词语组合,但在大多数情况下,我们需要模型对单词的分组方式有更深入的理解。
在本节中,我们使用Keras构建了自回归模型——长短期记忆网络(LongShort-TermMemoryNetwork,LSTM),用于生成逼真的食谱文本,并了解如何通过调整采样过程的温度参数来增加或减少输出的随机性。
AIGC实战——生成模型简介AIGC实战——深度学习(DeepLearning,DL)AIGC实战——卷积神经网络(ConvolutionalNeuralNetwork,CNN)AIGC实战——自编码器(Autoencoder)AIGC实战——变分自编码器(VariationalAutoencoder,VAE)AIGC实战——使用变分自编码器生成面部图像AIGC实战——生成对抗网络(GenerativeAdversarialNetwork,GAN)AIGC实战——WGAN(WassersteinGAN)AIGC实战——条件生成对抗网络(ConditionalGenerativeAdversarialNet,CGAN)