主要内容

使用注意的顺序翻译

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

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

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

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

负荷训练数据

下载十进制罗马数字对“romanNumerals.csv”

文件名= fullfile (“romanNumerals.csv”);选择= detectImportOptions(文件名,...“TextType”“字符串”...“ReadVariableNames”,错误的);options.variablenames = [“源”“目标”];options.variabletypes = [“细绳”“细绳”];data = readtable(文件名,选择);

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

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

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

头(dataTrain)
ans =8×2表源目标  ______ ____________ " 437年”“CDXXXVII”“431”“CDXXXI”“102年”“人民共和国”“862年”“DCCCLXII”“738年”“DCCXXXVIII”“527年”“DXXVII”“401年”“CDI”“184年”“CLXXXIV”

数据进行预处理

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

startToken =“<开始>”;停止=;strsource = dataTrain {:,1};documentsource = transformtext(strsource,starttoken,stowtoken);

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

encSource = wordEncoding (documentsSource);

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

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

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

strtarget = dataTrain {:,2};DocumentStarget = TransformText(strtarget,starttoken,stowtoken);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的嵌入尺寸,具有200个隐藏单元的两个LSTM层,以及随机丢失的丢弃层,概率0.05。

embeddingDimension = 128;numhidendunits = 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 = [numhidendunits numhidentunits];numout = numhidendunits;numIn = numHiddenUnits;参数.decoder.attn.weights = initializeglorot(sz,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在培训期间处理和管理迷你批次图像。对于每个迷你批处理:

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

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

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

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

minibatchqueue对象返回每个迷你批处理的四个输出参数:源序列,目标序列,小批次中的所有源序列的长度以及目标序列的序列掩模。

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 = [];

火车模型。对于每个迷你批处理:

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

  • 计算损失和梯度。

  • 控件更新编码器和解码器模型参数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、迭代、双(收集(损失)))标题(”时代:“+ epoch +“,经过:”+ drawnow字符串(D))结束结束

生成翻译

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

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

你要=人数({:1};strTarget =人数({:2};

使用该文本翻译modelPredictions函数。

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

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

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

查看翻译的随机选择。

IDX = RANDPERM(大小(DataTest,1),小匹匹匹匹配);tbl(idx,:)
ans =32×3表来源翻译______ ___________ ___________“8”“VIII”“CCCXXVII”“595”“DXCV”“DCCV”“523”“DXXIII”“CDXXII”“675”“DCLXXV”“DCCLXV”“818”“DCCCXVIII”“DCCCXVIII”“265”“CCLXV”“CCLXV”“770”“DCCLXX”“DCCCL”“904”“CMIV”“CMVII”“121”“CXXI”“CCXI”“333”“CCCXXXIII”“817”“DCCCXVII”“DCCCXVII”“37”“XXXVII”“CCCXXXIV”“335”"CCCXXXV" "CCCXXXV" "902" "CMII" "CMIII" "995" "CMXCV" "CMXCV" "334" "CCCXXXIV" "CCCXXXIV" ⋮

文本转换功能

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)sequencelengssource = cellfun(@(x)大小(x,2),sequencessource);X = PAD序列(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:尺寸(dly,1));masktarget = masktarget(:,:,2:结束);masktarget = repmat(masktarget,[大小(dly,1),1,1]);损失=联语(DLY,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;refurrentweights = parametersencoder.lstm2.recurrentweights;bias = parametersencoder.lstm2.bias;[dlz,hiddenstate] = lstm(dlz,initialhiddentstate,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.inputpuights;refurrentweights = parametersdecoder.lstm1.recurrentweights;bias = parametersdecoder.lstm1.bias;initialcellstate = dlarray(zeros(zeros(size(hiddenstate)));dly = lstm(dly,hiddenstate,initialcellstate,输入重量,经常性重量,偏见,“DataFormat”“认知行为治疗”);%的辍学生。mask = (rand(size(dlY),“喜欢”,dly)>辍学);dly = dly。*面具;% LSTM 2。Inputweights = parametersdecoder.lstm2.inputpuights;refurrentweights = parametersdecoder.lstm2.recurrentweights;bias = parametersdecoder.lstm2.bias;[dly,hiddenstate] = lstm(dly,hiddentate,initialcellstate,输入重量,经常性重量,偏见,“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。dly = softmax(dly,“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 Imprefernenergies(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);上下文=挤压(上下文);结束

解码器模型预测函数

Decodermodelprections.函数返回预测的序列海底给定输入序列,目标序列,隐藏状态,丢弃概率,标志,以使教师强迫,以及序列长度。

函数dly = decoder预期(parametersdecoder,dlz,t,hiddenstate,丢弃,...doteacherforcing,sequencelength)%转换为美元。dlT = dlarray (T);%初始化上下文。miniBatchSize =大小(dlT, 2);numHiddenUnits =大小(dlZ, 1);context = 0 ([numHiddenUnits miniBatchSize],“喜欢”,dlz);如果doTeacherForcing%通过解码器前进。dly = modeldecoder(parametersdecoder,dlt,context,hiddenstate,dlz,辍学);其他的获得解码器的第一次步长。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 = ceil(numobservations / 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;结束结束结束

也可以看看

||||||||(文本分析工具箱)|(文本分析工具箱)|(文本分析工具箱)|(文本分析工具箱)

相关的话题