主要内容

生成文本使用Autoencoders

这个例子展示了如何使用autoencoders生成文本数据。

autoencoder是一种深度学习网络,训练有素的复制它的输入。一个autoencoder由两个小网络:编码器和译码器。编码器将输入数据映射到一个特征向量在一些潜在的空间。解码器使用向量重建数据的潜在空间。

无监督的训练过程。换句话说,该模型不需要带安全标签的数据。生成文本,您可以使用译码器来重建从任意输入文本。

这个例子火车autoencoder生成文本。编码器使用一个字嵌入和LSTM操作输入文本映射到潜在的向量。译码器使用一个LSTM操作和相同的嵌入重构文本潜在的向量。

加载数据

该文件sonnets.txt包含所有莎士比亚的十四行诗在一个文本文件。

读了莎士比亚的十四行诗的数据文件“sonnets.txt”

文件名=“sonnets.txt”;textData = fileread(文件名);

十四行诗是缩进两个空格字符。消除压痕使用取代并使用的文本分割成单独的行分裂函数。去除前九头元素和短诗的标题。

textData =取代(textData,”“,”“);textData =分裂(textData、换行符);textData (1:9) = [];textData (strlength (textData) < 5) = [];

准备数据

创建一个函数符和文本数据进行预处理。这个函数preprocessText上市的例子,执行以下步骤:

  1. 突出显示和附加每个输入字符串指定的启动和停止令牌,分别。

  2. 在标记文本使用tokenizedDocument

预处理文本数据和指定开始和结束标记“<开始>”“<停止>”,分别。

startToken =“<开始>”;stopToken =“<停止>”;文件= preprocessText (textData startToken stopToken);

创建一个词编码对象的标记化的文档。

内附= wordEncoding(文件);

当培训深入学习模型,输入数据必须包含固定长度的序列的数字数组。因为这些文件有不同的长度,必须垫填充的短序列值。

重新创建这个词编码包括填充令牌和确定的指数令牌。

paddingToken =“<垫>”;(内附newVocabulary =。词汇paddingToken];内附= wordEncoding (newVocabulary);paddingToken paddingIdx = word2ind (enc)
paddingIdx = 3595

初始化模型参数

初始化参数模型。

在这里, T 是序列长度, x 1 , , x T 是输入的单词序列指标,然后呢 y 1 , , y T 重建的序列。

编码器词指数序列映射到一个潜在的向量转换的输入序列的词用一个嵌入向量,输入向量序列这个词变成一个LSTM操作,并应用一个完全连接操作的最后一次一步LSTM输出。解码器可以使用LSTM初始化输入编码器的输出。对于每一个时间步,译码器预测下一个时间步长,并使用输出为下一个时间步的预测。编码器和解码器使用相同的嵌入。

指定的尺寸参数。

embeddingDimension = 100;numHiddenUnits = 150;latentDimension = 75;vocabularySize = enc.NumWords;

创建一个结构参数。

参数=结构;

初始化使用高斯使用嵌入的权重initializeGaussian函数附加到这个例子作为支持文件。金宝app指定一个意味着(0)和标准偏差为0.01。欲了解更多,请看高斯函数初始化

深圳= [embeddingDimension vocabularySize];μ= 0;σ= 0.01;parameters.emb。重量= initializeGaussian (sz、μ、σ);

初始化可学的参数编码器LSTM操作:

  • 初始化输入权重Glorot初始化器使用initializeGlorot函数附加到这个例子作为支持文件。金宝app欲了解更多,请看Glorot初始化

  • 初始化的权重与正交初始化器使用initializeOrthogonal函数附加到这个例子作为支持文件。金宝app欲了解更多,请看正交初始化

  • 初始化倾向与单位大门忘记初始化使用initializeUnitForgetGate函数附加到这个例子作为支持文件。金宝app欲了解更多,请看单位大门忘记初始化

深圳= [4 * numHiddenUnits embeddingDimension];numOut = 4 * numHiddenUnits;numIn = embeddingDimension;parameters.lstmEncoder。InputWeights = initializeGlorot(深圳、numOut numIn);parameters.lstmEncoder。RecurrentWeights = initializeOrthogonal ([4 * numHiddenUnits numHiddenUnits]);parameters.lstmEncoder。偏见= initializeUnitForgetGate (numHiddenUnits);

初始化可学的参数编码器完全连接操作:

  • 初始化权重Glorot初始值设定项。

  • 使用零使用初始化偏差initializeZeros函数附加到这个例子作为支持文件。金宝app欲了解更多,请看零初始化

深圳= [latentDimension numHiddenUnits];numOut = latentDimension;numIn = numHiddenUnits;parameters.fcEncoder。重量= initializeGlorot(深圳、numOut numIn);parameters.fcEncoder。偏见= initializeZeros ([latentDimension 1]);

初始化可学的参数解码器LSTM操作:

  • 初始化输入权重Glorot初始值设定项。

  • 初始化复发与正交初始化权重。

  • 初始化倾向与单位忘记门初始值设定项。

深圳= [4 * latentDimension embeddingDimension];numOut = 4 * latentDimension;numIn = embeddingDimension;parameters.lstmDecoder。InputWeights = initializeGlorot(深圳、numOut numIn);parameters.lstmDecoder。RecurrentWeights = initializeOrthogonal ([4 * latentDimension latentDimension]);parameters.lstmDecoder。偏见= initializeZeros ([4 * latentDimension 1]);

初始化可学的译码器的参数完全连接操作:

  • 初始化权重Glorot初始值设定项。

  • 初始化与零偏差。

深圳= [vocabularySize latentDimension];numOut = vocabularySize;numIn = latentDimension;parameters.fcDecoder。重量= initializeGlorot(深圳、numOut numIn);parameters.fcDecoder。偏见= initializeZeros ([vocabularySize 1]);

了解更多关于体重初始化,明白了初始化函数可学的参数模型

定义模型编码器功能

创建函数modelEncoder中列出,编码器模型函数部分的示例中,计算编码器的输出模型。的modelEncoder函数,取词序列作为输入指标,模型参数和序列长度,并返回相应的潜在特征向量。更多地了解编码器函数定义一个模型,明白了定义文本编码器模型函数

定义模型译码器函数

创建函数modelDecoder中列出,译码器模型函数部分的示例中,计算译码器的输出模型。的modelDecoder函数,取词序列作为输入指标,模型参数和序列长度,并返回相应的潜在特征向量。更多地了解译码器函数定义一个模型,明白了定义文本译码器模型的功能

定义模型损失函数

modelLoss函数,列出的损失函数模型部分的示例中,模型可学的参数作为输入,输入数据和一个向量序列长度的屏蔽,并返回损失,损失的梯度对可学的参数。更多地了解损失函数定义一个模型,明白了定义模型损失函数自定义训练循环

指定培训选项

指定的选项进行训练。

100年火车时代mini-batch大小为128。

miniBatchSize = 128;numEpochs = 100;

培训学习速率为0.01。

learnRate = 0.01;

列车网络的

列车网络使用自定义训练循环。

亚当优化器的初始化参数。

trailingAvg = [];trailingAvgSq = [];

初始化培训进展阴谋。创建一个动画线条,情节损失对相应的迭代。

图C = colororder;lineLossTrain = animatedline(颜色= C (2:));包含(“迭代”)ylabel (“损失”网格)ylim([0正])

火车模型。第一时代洗牌和遍历mini-batches数据的数据。

为每个mini-batch:

  • 将文本数据转换为序列的指数。

  • 将数据转换为dlarray

  • GPU培训,将数据转换为gpuArray对象。

  • 计算损失和梯度。

  • 更新可学的参数使用adamupdate函数。

  • 更新培训进展阴谋。

火车在GPU如果一个是可用的。使用GPU需要并行计算工具箱™和支持GPU设备。金宝app支持设备的信息,请参阅金宝appGPU计算的需求(并行计算工具箱)

培训可以花费一些时间来运行。

numObservations =元素个数(文件);numIterationsPerEpoch =地板(numObservations / miniBatchSize);迭代= 0;开始=抽搐;时代= 1:numEpochs%洗牌。idx = randperm (numObservations);文档(文档(idx);i = 1: numIterationsPerEpoch迭代=迭代+ 1;% mini-batch阅读。idx =(张)* miniBatchSize + 1:我* miniBatchSize;documentsBatch =文档(idx);%转换为序列。X = doc2sequence (enc documentsBatch,PaddingDirection =“正确”,PaddingValue = paddingIdx);X =猫(1,X {:});%转换为dlarray。X = dlarray (X,“BTC”);%如果训练在GPU,然后将数据转换成gpuArray。如果canUseGPU X = gpuArray (X);结束%计算序列的长度。sequenceLengths = doclength (documentsBatch);%损失评估模型和梯度。(损失,梯度)= dlfeval (@modelLoss、参数X, sequenceLengths);%更新可学的参数。(参数、trailingAvg trailingAvgSq) = adamupdate(参数、渐变trailingAvg trailingAvgSq,迭代,learnRate);%显示培训进展。D =持续时间(0,0,toc(开始),格式=“hh: mm: ss”);=双重损失(损失);addpoints (lineLossTrain、迭代、失去)标题(”时代:“+时代+”,过去:“+ drawnow字符串(D))结束结束

生成文本

生成文本初始化解码器使用闭环生成的不同的随机状态。闭环生成模型生成数据时一次一个时间步,使用前面的预测未来预测作为输入。

指定生成3序列长度16。

numGenerations = 3;sequenceLength = 16;

创建一个随机值数组初始化解码器状态。

Z = dlarray (randn (latentDimension numGenerations),“CB”);

如果预测在GPU上,然后将数据转换成gpuArray

如果canUseGPU Z = gpuArray (Z);结束

预测使用modelPredictions函数,列出的例子。的modelPredictions函数返回的输出分数译码器模型参数,译码器的初始状态,最大序列长度,词编码,开始令牌,mini-batch大小。

Y = modelDecoderPredictions(参数,Z, sequenceLength, enc、startToken miniBatchSize);

找到这个词指数最高的分数。

[~,idx] = max (Y, [], 1);idx =挤压(idx);

数字指标转换为使用的单词和加入他们加入函数。

strGenerated =加入(enc.Vocabulary (idx));

提取文本之前的第一站令牌使用extractBefore函数。防止函数返回失踪当没有停止令牌,将停止令牌附加到每个序列的结束。

strGenerated = extractBefore (strGenerated + stopToken stopToken);

删除填充令牌。

strGenerated =擦掉(strGenerated paddingToken);

生成过程介绍了空格字符之间的预测,这意味着一些标点符号出现不必要的空格之前和之后。重构生成的文本通过删除空格前后适当的标点符号。

删除指定的标点符号之前出现的空间。

punctuationCharacters = [“。””、““”“)””:“”;““?”“啊!”];strGenerated =取代(strGenerated,”“+ punctuationCharacters punctuationCharacters);

删除指定的标点符号后出现的空间。

punctuationCharacters = [”(““”];strGenerated =取代(strGenerated punctuationCharacters +”“,punctuationCharacters);

删除前导和尾随空白使用函数和视图生成的文本。

strGenerated =地带(strGenerated)
strGenerated =3×1的字符串“我的傻瓜黑色接地少减弱旅行松松唱酷善良这种“茁壮成长”perjur会向外一个看起来黑,可能在这里。”"birds him antique side his hours age,"

编码器模型函数

modelEncoder功能,使用模型作为输入参数,词指数序列,序列长度,并返回相应的潜在特征向量。

因为输入数据包含不同长度的序列进行填充,填充可以有负面影响损失计算。LSTM操作,而不是返回的输出序列的最后时间步(这可能对应于LSTM状态处理后大量填充的值),确定实际的上次给出的步骤sequenceLengths输入。

函数Z = modelEncoder(参数X, sequenceLengths)%嵌入。重量= parameters.emb.Weights;Z =嵌入(X,重量);% LSTM。inputWeights = parameters.lstmEncoder.InputWeights;recurrentWeights = parameters.lstmEncoder.RecurrentWeights;偏见= parameters.lstmEncoder.Bias;numHiddenUnits =大小(recurrentWeights, 2);hiddenState = 0 (numHiddenUnits 1“喜欢”,X);cellState = 0 (numHiddenUnits 1“喜欢”,X);Z1 = lstm (Z, hiddenState, cellState、inputWeights recurrentWeights,偏差);%输出模式与屏蔽“最后”。miniBatchSize =大小(Z1, 2);Z = 0 (numHiddenUnits miniBatchSize,“喜欢”Z1);n = 1: miniBatchSize t = sequenceLengths (n);Z (:, n) = Z1 (:, n, t);结束%完全连接。重量= parameters.fcEncoder.Weights;偏见= parameters.fcEncoder.Bias;Z = fullyconnect (Z,重量、偏见、DataFormat =“CB”);结束

译码器模型函数

modelDecoder函数,使用模型作为输入参数,序列的指数,和网络状态,并返回解码序列。

因为lstm函数是有状态(当给定一个时间序列作为输入,该函数在每个时间步)之间传播并更新状态,嵌入fullyconnect功能是当分布式默认情况下(当给定一个时间序列作为输入,功能独立操作每个时间步),modelDecoder功能支持序列和单一金宝app时间步输入。

函数[Y,状态]= modelDecoder(参数X,状态)%嵌入。重量= parameters.emb.Weights;X =嵌入(X,重量);% LSTM。inputWeights = parameters.lstmDecoder.InputWeights;recurrentWeights = parameters.lstmDecoder.RecurrentWeights;偏见= parameters.lstmDecoder.Bias;hiddenState = state.HiddenState;cellState = state.CellState;[Y, hiddenState, cellState] = lstm (X, hiddenState cellState,inputWeights recurrentWeights,偏差);状态。HiddenState = HiddenState;状态。CellState = CellState;%完全连接。重量= parameters.fcDecoder.Weights;偏见= parameters.fcDecoder.Bias;Y = fullyconnect (Y,重量,偏差);% Softmax。Y = softmax (Y);结束

损失函数模型

modelLoss函数作为输入模型可学的参数,输入数据X和一个向量序列长度的屏蔽,并返回损失和损失的梯度对可学的参数。

计算掩盖损失,损失函数使用的模型maskedCrossEntropy函数,列出的例子。训练序列的解码器来预测下一个时间步,指定目标被一个时间步输入序列移位。

更多地了解损失函数定义一个模型,明白了定义模型损失函数自定义训练循环

函数(损失,梯度)= modelLoss(参数X, sequenceLengths)%编码器模型。Z = modelEncoder(参数X, sequenceLengths);%初始化LSTM状态。状态=结构;状态。HiddenState = Z;状态。CellState = 0(大小(Z),“喜欢”,Z);%老师强迫。Y = modelDecoder(参数X,状态);%的损失。Y = Y (:: 1: end-1);T = X(:,:, 2:结束);损失=意味着(maskedCrossEntropy (Y, T, sequenceLengths));%梯度。梯度= dlgradient(损失、参数);%正常化损失策划。sequenceLength =大小(X, 3);损失= / sequenceLength损失;结束

模型的预测函数

modelPredictions函数返回的输出分数译码器模型参数,译码器的初始状态,最大序列长度,词编码,开始令牌,mini-batch大小。

函数Y = modelDecoderPredictions(参数,Z,最大长度,enc、startToken miniBatchSize) numObservations =大小(Z, 2);numIterations =装天花板(numObservations / miniBatchSize);startToken startTokenIdx = word2ind (enc);vocabularySize = enc.NumWords;Y = 0 (vocabularySize numObservations,最大长度,“喜欢”,Z);%在mini-batches循环。i = 1: numIterations idxMiniBatch =(张)* miniBatchSize + 1: min(我* miniBatchSize numObservations);miniBatchSize =元素个数(idxMiniBatch);%初始化状态。状态=结构;状态。HiddenState = Z (:, idxMiniBatch);状态。CellState = 0(大小(Z (:, idxMiniBatch)),“喜欢”,Z);%初始化译码器的输入。decoderInput = dlarray (repmat (startTokenIdx [1 miniBatchSize]),“认知行为治疗”);随着时间的推移%循环步骤。t = 1:最大长度%预测下一个时间步。[Y: idxMiniBatch t),状态]= modelDecoder(参数、decoderInput状态);%闭环的一代。[~,idx] = max (Y (:, idxMiniBatch t));decoderInput = dlarray (idx,“CB”);结束结束结束

戴面具的交叉熵损失函数

maskedCrossEntropy函数计算指定的输入序列和目标序列之间的损失忽略任何时间步骤包含填充使用指定的序列长度的向量。

函数maskedLoss = maskedCrossEntropy (Y, T, sequenceLengths) numClasses =大小(Y, 1);miniBatchSize =大小(Y, 2);sequenceLength =大小(Y, 3);maskedLoss = 0 (sequenceLength miniBatchSize,“喜欢”,Y);t = 1: sequenceLength T1 =单(oneHot (t (:,:, t), numClasses));掩码= (t < = sequenceLengths) ';:maskedLoss (t) =面具。* crossentropy (Y (:,:, t), T1);结束maskedLoss = (maskedLoss, 1)之和;结束

文本预处理功能

这个函数preprocessText执行以下步骤:

  1. 突出显示和附加每个输入字符串指定的启动和停止令牌,分别。

  2. 在标记文本使用tokenizedDocument

函数文件= preprocessText (textData startToken stopToken)%添加启动和停止令牌。textData = startToken + textData + stopToken;%在标记文本。文件= tokenizedDocument (textData,“CustomTokens”,(startToken stopToken]);结束

一个炎热的编码功能

oneHot将数字索引数组转换为一个炎热的编码向量。

函数哦= oneHot (idx outputSize) miniBatchSize =元素个数(idx);哦= 0 (outputSize miniBatchSize);c = n = 1: miniBatchSize idx (n);哦(c, n) = 1;结束结束

另请参阅

||

相关的话题