主要内容

使用注意的顺序翻译

这个示例演示了如何使用循环序列到序列编码器-解码器模型将十进制字符串转换为罗马数字。

在抽象文本摘要和神经机器翻译等任务中,循环编码器-解码器模型已被证明是成功的。模型由一个编码器它通常使用循环层(如LSTM)处理输入数据,并使用译码器它将编码后的输入映射到所需的输出,通常使用第二个循环层。模型,结合注意机制在模型中允许解码器在生成翻译时关注编码输入的部分。

对于编码器模型,本示例使用一个简单的网络,由一个嵌入和两个LSTM操作组成。嵌入是一种将分类标记转换为数字向量的方法。

对于解码器模型,本示例使用一个非常类似于包含两个lstm的编码器的网络。然而,一个重要的区别是,解码器包含注意机制。注意机制允许解码器参加到编码器输出的特定部分。

负荷训练数据

从下面下载小数-罗马数字对“romanNumerals.csv”

文件名= fullfile (“romanNumerals.csv”);选择= detectImportOptions(文件名,...“TextType”“字符串”...“ReadVariableNames”、假);选项。VariableNames = [“源”“目标”];选项。VariableTypes = [“字符串”“字符串”];data = readtable(文件名,选择);

将数据分成训练和测试分区,每个分区包含50%的数据。

idx = randperm(大小(数据,1),500);dataTrain =数据(idx:);人数(=数据;人数((idx:) = [];

查看一些小数-罗马数字对。

头(dataTrain)
ans =8×2表源目标  ______ ________ " 492年”“CDXCII”“911”“CMXI”“965年”“CMLXV”“951年”“CMLI”“160年”“CLX”“662年”“DCLXII”“102年”“人民共和国”“440年”“CDXL”

数据进行预处理

属性对文本数据进行预处理transformText函数,列在示例的最后。的transformText函数通过将文本分割为字符并添加开始和停止标记对输入文本进行预处理和标记,以便进行翻译。如果要通过将文本分割成单词而不是字符来翻译文本,请跳过第一步。

startToken =“<开始>”;stopToken =“<停止>”;你要= dataTrain.Source;documentsSource = transformText(你要startToken stopToken);

创建一个wordEncoding对象,该对象使用词汇表将标记映射为数字索引,反之亦然。

encSource = wordEncoding (documentsSource);

使用字编码,将源文本数据转换为数字序列。

sequencesSource = doc2sequence(encSource, documentsSource,“PaddingDirection”“没有”);

使用相同的步骤将目标数据转换为序列。

strTarget = dataTrain.Target;documentsTarget = transformText (strTarget startToken stopToken);encTarget = wordEncoding (documentsTarget);sequencesTarget = doc2sequence(encTarget, documentsTarget,“PaddingDirection”“没有”);

按长度对序列排序。使用递增序列长度排序的序列进行训练,可以得到序列长度近似相同的批次,并确保在较长序列批次之前使用较小的批次更新模型。

sequenceLengths = cellfun(@(sequence) size(sequence,2),sequencesSource);[~, idx] = (sequenceLengths)进行排序;sequencesSource = sequencesSource (idx);sequencesTarget = sequencesTarget (idx);

创建arrayDatastore对象包含源数据和目标数据,并使用结合函数。

sequencesSourceDs = arrayDatastore (sequencesSource,“OutputType”“相同”);sequencesTargetDs = arrayDatastore (sequencesTarget,“OutputType”“相同”);sequencesDs =结合(sequencesSourceDs sequencesTargetDs);

初始化模型参数

初始化模型参数。对于编码器和解码器,指定嵌入维数为128,两个LSTM层包含200个隐藏单元,退出层具有0.05的随机退出概率。

embeddingDimension = 128;numHiddenUnits = 200;辍学= 0.05;

初始化编码器模型参数

使用高斯函数初始化编码嵌入的权值initializeGaussian函数,该函数作为支持文件附加到本示例中。金宝app指定平均值为0,标准偏差为0.01。想要了解更多,请看高斯函数初始化(深度学习工具箱)

inputSize = encSource。NumWords + 1;sz = [embeddingDimension inputSize]; / /设置尺寸μ= 0;σ= 0.01;parameters.encoder.emb.Weights = initializeGaussian (sz、μ、σ);

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

  • 属性使用gloria初始化器初始化输入权重initializeGlorot函数,该函数作为支持文件附加到本示例中。金宝app想要了解更多,请看Glorot初始化(深度学习工具箱)

  • 用正交初始化器初始化递归权值initializeOrthogonal函数,该函数作为支持文件附加到本示例中。金宝app想要了解更多,请看正交初始化(深度学习工具箱)

  • 使用单元遗忘门初始化器初始化偏差initializeUnitForgetGate函数,该函数作为支持文件附加到本示例中。金宝app想要了解更多,请看单元遗忘门初始化(深度学习工具箱)

初始化第一个编码器LSTM操作的可学习参数。

sz = [4*numHiddenUnits embedingdimension]; / /隐藏尺寸numOut = 4 * numHiddenUnits;numIn = embeddingDimension;parameters.encoder.lstm1。InputWeights = initializeGlorot(深圳、numOut numIn);parameters.encoder.lstm1。recurrentwights = initialize正交([4*numHiddenUnits numHiddenUnits]);parameters.encoder.lstm1。偏见= initializeUnitForgetGate (numHiddenUnits);

初始化第二个编码器LSTM操作的可学习参数。

sz = [4*numHiddenUnits numHiddenUnits];numOut = 4 * numHiddenUnits;numIn = numHiddenUnits;parameters.encoder.lstm2。InputWeights = initializeGlorot(深圳、numOut numIn);parameters.encoder.lstm2。recurrentwights = initialize正交([4*numHiddenUnits numHiddenUnits]);parameters.encoder.lstm2。偏见= initializeUnitForgetGate (numHiddenUnits);

初始化解码器模型参数

使用高斯函数初始化编码嵌入的权值initializeGaussian函数。指定平均值为0,标准偏差为0.01。

outputSize = encTarget。NumWords + 1;sz = [embedingdimension outputSize]; / /显示当前位置μ= 0;σ= 0.01;parameters.decoder.emb.Weights = initializeGaussian (sz、μ、σ);

属性使用gloria初始化器初始化注意机制的权值initializeGlorot函数。

sz = [numHiddenUnits numHiddenUnits]; / /numOut = numHiddenUnits;numIn = numHiddenUnits;parameters.decoder.attn.Weights = initializeGlorot(深圳、numOut numIn);

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

  • 属性使用gloria初始化器初始化输入权重initializeGlorot函数。

  • 用正交初始化器初始化递归权值initializeOrthogonal函数。

  • 使用单元遗忘门初始化器初始化偏差initializeUnitForgetGate函数。

初始化第一个解码器LSTM操作的可学习参数。

sz = [4*numHiddenUnits embedingdimension +numHiddenUnits];numOut = 4 * numHiddenUnits;numIn = embedingdimension + numHiddenUnits;parameters.decoder.lstm1.InputWeights = initializeGlorot(深圳、numOut numIn);parameters.decoder.lstm1. recurrentwights = initialize正交([4*numHiddenUnits numHiddenUnits]);parameters.decoder.lstm1.Bias = initializeUnitForgetGate (numHiddenUnits);

初始化第二个译码器LSTM操作的可学习参数。

sz = [4*numHiddenUnits numHiddenUnits];numOut = 4 * numHiddenUnits;numIn = numHiddenUnits;parameters.decoder.lstm2.InputWeights = initializeGlorot(深圳、numOut numIn);parameters.decoder. lst2m . recurrentwights = initialize正交([4*numHiddenUnits numHiddenUnits]);parameters.decoder.lstm2.Bias = initializeUnitForgetGate (numHiddenUnits);

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

  • 用gloria初始化器初始化权重。

  • 属性用零初始化偏差initializeZeros函数,该函数作为支持文件附加到本示例中。金宝app想要了解更多,请看零初始化(深度学习工具箱)

sz = [outputSize 2*numHiddenUnits]; / /输出numOut = outputSize;numIn = 2 * numHiddenUnits;parameters.decoder.fc.Weights = initializeGlorot(深圳、numOut numIn);parameters.decoder.fc.Bias = initializeZeros([outputSize 1]);

定义模型函数

创建函数modelEncodermodelDecoder,分别计算编码器和解码器模型的输出。

modelEncoder函数中列出的编码器模型函数部分,获取输入数据、模型参数、用于确定训练的正确输出的可选掩码,并返回模型输出和LSTM隐藏状态。

modelDecoder函数中列出的译码器模型函数段,取输入数据、模型参数、上下文向量、LSTM初始隐藏状态、编码器输出、退出概率、解码器输出、更新的上下文向量、更新的LSTM状态、注意分数。

定义模型梯度函数

创建函数modelGradients,列于模型梯度函数示例的一部分,该部分取编码器和解码器模型参数、一小批输入数据和与输入数据相对应的填充掩模,以及退出概率并返回相对于模型中可学习参数的损耗梯度和相应的损耗。

指定培训选项

训练的小批量大小为32为75个时期,学习率为0.002。

miniBatchSize = 32;numEpochs = 75;learnRate = 0.002;

初始化亚当的选项。

gradientDecayFactor = 0.9;squaredGradientDecayFactor = 0.999;

火车模型

使用自定义训练循环训练模型。使用minibatchqueue在培训过程中处理和管理小批量的图像。为每个mini-batch:

  • 使用自定义小批量预处理功能preprocessMiniBatch(在本例的最后定义)来查找mini-batch中所有序列的长度,并分别将源序列和目标序列填充到与最长序列相同的长度。

  • 排列填充序列的第二和第三维度。

  • 返回未格式化的迷你批处理变量dlarray具有底层数据类型的对象.所有其他输出都是数据类型的数组

  • 在可用的GPU上进行训练。返回GPU上的所有小批量变量(如果有的话)。使用GPU需要并行计算工具箱™和支持的GPU设备。金宝app有关支持的设备信息,请参见GPU版本支金宝app持。

minibatchqueue对象为每个迷你批处理返回4个输出参数:源序列、目标序列、迷你批处理中所有源序列的长度以及目标序列的序列掩码。

numMiniBatchOutputs = 4;兆贝可= minibatchqueue (sequencesDs numMiniBatchOutputs,...“MiniBatchSize”miniBatchSize,...“MiniBatchFcn”@ (x, t) preprocessMiniBatch (x, t, inputSize outputSize));

初始化培训进度图。

figure lineosstrain = animatedline(“颜色”[0.85 0.325 0.098]);ylim([0正])包含(“迭代”) ylabel (“损失”网格)

对象的值初始化adamupdate函数。

trailingAvg = [];trailingAvgSq = [];

火车模型。为每个mini-batch:

  • 读取填充序列的迷你批处理。

  • 计算损失和梯度。

  • 控件更新编码器和解码器模型参数adamupdate函数。

  • 更新培训进度图。

迭代= 0;开始=抽搐;%循环纪元。epoch = 1:numEpochs reset(mbq);%循环小批。Hasdata (mbq) iteration = iteration + 1;[dlX T, sequenceLengthsSource maskSequenceTarget] =下一个(兆贝可);%计算损失和梯度。(渐变,亏损)= dlfeval (@modelGradients、参数dlX T sequenceLengthsSource,...maskSequenceTarget,辍学);%使用adamupdate更新参数。(参数、trailingAvg trailingAvgSq) = adamupdate(参数、渐变trailingAvg trailingAvgSq,...迭代,learnRate、gradientDecayFactor squaredGradientDecayFactor);%显示训练进度。D =持续时间(0,0,toc(开始),“格式”“hh: mm: ss”);addpoints (lineLossTrain、迭代、双(收集(损失)))标题(”时代:“+时代+”,过去:“+ drawnow字符串(D))结束结束

生成翻译

要使用训练模型生成新数据的翻译,请使用与训练并将序列输入编码器-解码器模型相同的步骤将文本数据转换为数字序列,并使用令牌索引将结果序列转换回文本。

使用与训练相同的步骤对文本数据进行预处理。使用transformText函数,用于将文本分割为字符并添加开始和停止标记。

你要= dataTest.Source;strTarget = dataTest.Target;

翻译文本使用modelPredictions函数。

maxSequenceLength = 10;分隔符="";strTranslated = translateText(参数、你要maxSequenceLength miniBatchSize,...encSource、encTarget startToken stopToken,分隔符);

创建一个包含测试源文本、目标文本和翻译的表。

台=表;资源描述。源=你要;资源描述。目标= strTarget;资源描述。翻译= strTranslated;

查看随机选择的翻译。

idx = randperm(规模(人数(1)miniBatchSize);台(idx:)
ans =32×3表来源目标译______ ___________ __________“108”“CVIII”“CVIII”“651”“DCLI”“DCI”“147”“CXLVII”“CCLXVII”“850”“DCCCL”“DCCCDCC”“468”“CDLXVIII”“CCLXVIII”“168”“CLXVIII”“CDLXVIII”“220”“CCXX”“CCC”“832”“DCCCXXXII”“DCCCXXII”“162”“CLXII”“659”“DCLIX”“DCXIX”“224”“CCXXIV”“CCXXIV”“760”“DCCLX”“DCCLDC”“304”“ccciv”“ccciv”“65”“lxv”“dclv”“647”“dcxlvii”“dcxlvii”“596”“dxcvi”“dcxvi”⋮

文本转换功能

transformText函数通过将文本分割为字符并添加开始和停止标记对输入文本进行预处理和标记,以便进行翻译。如果要通过将文本分割成单词而不是字符来翻译文本,请跳过第一步。

函数str = text (str,startToken,stopToken)""”“));str = startToken + str + stopToken;文件= tokenizedDocument (str,“CustomTokens”, (startToken stopToken]);结束

Mini-Batch预处理功能

preprocessMiniBatch函数,在示例的“训练模型”一节中描述,对训练数据进行预处理。该函数使用以下步骤对数据进行预处理:

  1. 确定所有源和目标序列的长度在小批

  2. 将序列填充到与迷你批处理中最长序列相同的长度padsequences函数。

  3. 置换序列的最后两个维度

函数[X,T,sequenceLengthsSource,maskTarget] = preprocessMiniBatch(sequencesSource,sequencesTarget,inputSize,outputSize) sequenceLengthsSource = cellfun(@(X) size(X, 2),sequencesSource);X = padsequences (sequencesSource 2“PaddingValue”, inputSize);X = permute(X,[1 3 2]);[T, maskTarget] = padsequences (sequencesTarget 2“PaddingValue”, outputSize);T = permute(T,[1 3 2]);maskTarget = permute(maskTarget,[1 3 2]);结束

模型梯度函数

modelGradients函数取编码器和解码器模型参数、一小批输入数据和与输入数据相对应的填充掩模,以及退出概率和返回损失相对于模型中可学习参数和相应损失的梯度。

函数(渐变,亏损)= modelGradients(参数、dlX T,...sequenceLengthsSource maskTarget,辍学)%通过编码器前进。[dlZ, hiddenState] = modelEncoder (parameters.encoder、dlX sequenceLengthsSource);%解码器输出。doteacher强迫= rand < 0.5;sequenceLength =大小(T, 3);海底= decoderPredictions (hiddenState parameters.decoder, dlZ, T,辍学,...doTeacherForcing sequenceLength);%掩盖损失。海底=海底(::1:end-1);T = extractdata(收集(T(:,:, 2:结束)));T = onehotencode (T, 1“类名”1:尺寸(海底,1));maskTarget = maskTarget(:,:, 2:结束);maskTarget = repmat (maskTarget,大小(海底,1),1,1]);损失= crossentropy(海底T“面具”maskTarget,“Dataformat”“认知行为治疗”);%更新梯度。梯度= dlgradient(损失、参数);%作图时,回波损耗按序列长度归一化。loss = extractdata(loss) ./ sequenceLength;结束

编码器模型函数

这个函数modelEncoder获取输入数据、模型参数、用于确定训练的正确输出的可选掩码,并返回模型输出和LSTM隐藏状态。

如果sequenceLengths为空,则该函数不屏蔽输出。为指定空值sequenceLengths当使用modelEncoder函数的预测。

函数[dlZ, hiddenState] = modelEncoder(parametersEncoder, dlX, sequenceLengths)%嵌入。重量= parametersEncoder.emb.Weights;dlZ =嵌入(dlX,重量,“DataFormat”“认知行为治疗”);% LSTM 1。inputWeights = parametersEncoder.lstm1.InputWeights;recurrentWeights = parametersEncoder.lstm1.RecurrentWeights;偏见= parametersEncoder.lstm1.Bias;numHiddenUnits = size(recurrentwights, 2);initialHiddenState = dlarray(zeros([numHiddenUnits 1])); / /初始化initialCellState = dlarray(zeros([numHiddenUnits 1]));dlZ = lstm(dlZ, initialHiddenState, initialCellState, inputwights,...recurrentWeights,偏见,“DataFormat”“认知行为治疗”);% LSTM 2。inputWeights = parametersEncoder.lstm2.InputWeights;recurrentWeights = parametersEncoder.lstm2.RecurrentWeights;偏见= parametersEncoder.lstm2.Bias;[dlZ, hiddenState] = lstm(dlZ,initialHiddenState, initialCellState,...inputWeights recurrentWeights,偏见,“DataFormat”“认知行为治疗”);%掩蔽训练。如果~isempty(sequenceLengths) miniBatchSize = size(dlZ,2); / /排序n = 1:miniBatchSize hiddenState(:,n) = dlZ(:,n,sequenceLengths(n));结束结束结束

译码器模型函数

这个函数modelDecoder取输入数据、模型参数、上下文向量、LSTM初始隐藏状态、编码器输出、dropout概率、译码器输出、更新的上下文向量、更新的LSTM状态、注意分数。

函数[dlY, context, hiddenState, attentionScores] = modelDecoder(parametersDecoder, dlX, context,...hiddenState, dlZ辍学)%嵌入。重量= parametersDecoder.emb.Weights;dlX = embed(dlX,权重,“DataFormat”“认知行为治疗”);% RNN输入。sequenceLength =大小(dlX, 3);dlY = cat(1, dlX, repmat(context, [1 1 sequenceLength]));% LSTM 1。inputWeights = parametersDecoder.lstm1.InputWeights;recurrentWeights = parametersDecoder.lstm1.RecurrentWeights;偏见= parametersDecoder.lstm1.Bias;initialCellState = dlarray(0(大小(hiddenState)));dlY = lstm(dlY, hiddenState, initialCellState, inputwights, recurrentwights, bias,“DataFormat”“认知行为治疗”);%的辍学生。mask = (rand(size(dlY),“喜欢”, d) >辍学);海底=海底。*面具;% LSTM 2。inputWeights = parametersDecoder.lstm2.InputWeights;recurrentWeights = parametersDecoder.lstm2.RecurrentWeights;偏见= parametersDecoder.lstm2.Bias;[dlY, hiddenState] = lstm(dlY, hiddenState, initialCellState, inputwights, recurrentwights, bias,)“DataFormat”“认知行为治疗”);%的注意。重量= parametersDecoder.attn.Weights;[attentionScores, context] = attention(hiddenState, dlZ, weights);%连接。d = cat(1, d, repmat(context, [1 1 sequenceLength])); / /输入d%完全连接。重量= parametersDecoder.fc.Weights;偏见= parametersDecoder.fc.Bias;海底= fullyconnect(海底,重量、偏见,“DataFormat”“认知行为治疗”);% Softmax。海底= softmax(海底,“DataFormat”“认知行为治疗”);结束

注意函数

注意函数根据Luong的“一般”评分和更新的上下文向量返回注意力评分。每个时间步长的能量是隐藏状态和可学习的注意力权重乘以编码器输出的点积。

函数[attentionScores, context] = attention(hiddenState, encoderOutputs, weights)%初始化注意能量。[miniBatchSize, sequenceLength] = size(encoderOutputs, 2:3);attentionEnergies = 0 ([sequenceLength miniBatchSize],“喜欢”, hiddenState);%注意能量。hWX = hiddenState .* pagemtimes(weights,encoderOutputs);tt = 1:sequenceLength attentionEnergies(tt,:) = sum(hWX(:,:, tt), 1);结束%注意分数。attentionScores = softmax (attentionEnergies,“DataFormat”“CB”);%的上下文。encoderOutputs = permute(encoderOutputs, [1 3 2]);attentionScores = permute(attentionScores,[1 3 2]);上下文= pagemtimes (encoderOutputs attentionScores);上下文=挤压(上下文);结束

解码器模型预测函数

decoderModelPredictions函数返回预测的序列海底给定输入序列、目标序列、隐藏状态、退出概率、允许教师强制的标志和序列长度。

函数海底= decoderPredictions (hiddenState parametersDecoder, dlZ, T,辍学,...doTeacherForcing sequenceLength)%转换为美元。dlT = dlarray (T);%初始化上下文。miniBatchSize =大小(dlT, 2);numHiddenUnits =大小(dlZ, 1);context = 0 ([numHiddenUnits miniBatchSize],“喜欢”, dlZ);如果doTeacherForcing%通过解码器前进。dlY = modelDecoder(parametersDecoder, dlT, context, hiddenState, dlZ, dropout);其他的获得解码器的第一次步长。decoderInput = dlT (:: 1);%初始化输出。numClasses =元素个数(parametersDecoder.fc.Bias);dlY = 0 ([numClasses miniBatchSize sequencellength],“喜欢”, decoderInput);%循环时间步骤。t = 1: sequenceLength%通过解码器前进。[dlY(:,:,t), context, hiddenState] = modelDecoder(parametersDecoder, decoderInput, context,...hiddenState, dlZ辍学);%更新解码器输入。[~, decoderInput] = max(dlY(:,:,t),[],1);结束结束结束

文本翻译功能

translateText函数通过在小批上迭代转换文本数组。该函数将模型参数、输入字符串数组、最大序列长度、迷你批处理大小、源和目标字编码对象、开始和停止标记以及用于组装输出的分隔符作为输入。

函数strTranslated = translateText(参数、你要maxSequenceLength miniBatchSize,...encSource、encTarget startToken stopToken,分隔符)%转换文本。documentsSource = transformText(你要startToken stopToken);sequencesSource = doc2sequence (encSource documentsSource,...“PaddingDirection”“对”...“PaddingValue”, encSource。NumWords + 1);%转换为美元。X =猫(sequencesSource {:});X = permute(X,[1 3 2]);dlX = dlarray (X);%初始化输出。numObservations =元素个数(你要);strTranslated =字符串(numObservations, 1);%循环小批。numIterations = cell (nummobations / miniBatchSize);i = 1:numIterations idxMiniBatch = (i-1)*miniBatchSize+1:min(i*miniBatchSize,numObservations);miniBatchSize =元素个数(idxMiniBatch);使用模型编码器编码。sequenceLengths = [];[dlZ, hiddenState] = modelEncoder(参数。编码器,dlX(:,idxMiniBatch,:), sequenceLengths);%解码器的预测。doTeacherForcing = false;辍学= 0;decoderInput = repmat(word2ind(encTarget,startToken),[1 miniBatchSize]);decoderInput = dlarray (decoderInput);海底= decoderPredictions (parameters.decoder, dlZ、decoderInput hiddenState,辍学,...doTeacherForcing maxSequenceLength);[~, idxPred] = max(extractdata(dlY), [], 1);%保持翻译标志。idxStop = word2ind (encTarget stopToken);keeptranslation = idxPred ~= idxStop;%循环时间步骤。t = 1;t <= maxSequenceLength && any(keepTranslating(:,:,t))%更新输出。newWords = ind2word(encTarget, idxPred(:,:,t))';idxUpdate = idxMiniBatch (keepTranslating (:,:, t));strtranslate (idxUpdate) = strtranslate (idxUpdate) + delimiter + newWords(keepTranslating(:,:,t));T = T + 1;结束结束结束

另请参阅

|||(深度学习工具箱)|(深度学习工具箱)|(深度学习工具箱)|(深度学习工具箱)|(深度学习工具箱)|(深度学习工具箱)|(深度学习工具箱)|(深度学习工具箱)|

相关的话题