主要内容

使用注意的顺序翻译

此示例显示如何使用重复序列 - 序列编码器 - 解码器模型将十进制字符串转换为罗马数字。

在抽象文本摘要和神经机器翻译等任务中,循环编码器-解码器模型已被证明是成功的。模型由一个编码器它通常使用循环层(如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表源目标______ ____________“437”“cdxxxvii”“431”“cdxxxi”“102”“cii”862“”dccclxii“”738“”dccxxxviii“”527“”dxxvii“”401“”cdi“184”“clxx​​xiv“

数据进行预处理

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

startToken =“<开始>”;stopToken =“<停止>”;你要= dataTrain {: 1};documentsSource = transformText(你要startToken stopToken);

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

encSource = wordEncoding (documentsSource);

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

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

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

strTarget = dataTrain {: 2};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”“相同”);sequencess =组合(Sequencessourceds,Sequencestargetds);

初始化模型参数

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

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

初始化编码器模型参数

使用高斯函数初始化编码嵌入的权值initializeGaussian函数,该函数作为支持文件附加到本示例中。万博1manbetx指定0的平均值和0.01的标准偏差。想要了解更多,请看高斯函数初始化

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

初始化Encoder LSTM操作的可读参数:

  • 使用Glorot Initializer初始化输入权重使用initializeGlorot函数,该函数作为支持文件附加到本示例中。万博1manbetx想要了解更多,请看Glorot初始化

  • 使用正交初始化器初始化复制权重initializeOrthogonal函数,该函数作为支持文件附加到本示例中。万博1manbetx想要了解更多,请看正交初始化

  • 使用单元遗忘门初始化器初始化偏差InitializeUnitForgetgate.函数,该函数作为支持文件附加到本示例中。万博1manbetx想要了解更多,请看单元遗忘门初始化

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

sz = [4 * numhidentunits embeddingdimensile];numOut = 4 * numHiddenUnits;numin = embeddingdimension;parameters.encoder.lstm1.inputweights = initializeglorot(sz,numout,numin);parameters.encoder.lstm1.recurrentweights = initialize正常([4 * numhidentunits numhidentunits]);parameters.encoder.lstm1.bias = initializeUnitForgetgate(numhidentunits);

初始化第二个编码器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 = [embeddingdimension输出];μ= 0;σ= 0.01;参数.decoder.emb.weights = initializegaussian(sz,mu,sigma);

使用Glorot Initializer使用Glorot Initializer初始化注意机制的权重initializeGlorot功能。

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

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

  • 使用Glorot Initializer初始化输入权重使用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(sz,numout,numin);参数.decoder.lstm2.recurrentweights = initialize正常([4 * numhidentunits numhidentunits]);参数.decoder.lstm2.bias = initializeUnitForgetgate(numhidentunits);

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

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

  • 属性用零初始化偏差initializeZeros函数,该函数作为支持文件附加到本示例中。万博1manbetx想要了解更多,请看零初始化

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状态,和注意得分。

定义模型渐变功能

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

指定培训选项

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

minibatchsize = 32;numepochs = 75;学习= 0.002;

初始化亚当的选项。

gradientDecayFactor = 0.9;squaredGradientDecayFactor = 0.999;

火车模型

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

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

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

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

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

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

numminibatchoutputs = 4;MBQ = minibatchqueue(序列规定,numminibatchouts,...“MiniBatchSize”,小匹马,...“MiniBatchFcn”@ (x, t) preprocessMiniBatch (x, t, inputSize outputSize));

初始化培训进度图。

figure lineosstrain = animatedline('颜色',[0.85 0.325 0.098]);ylim([0 inf])xlabel(“迭代”) ylabel (“损失”) 网格

初始化值的adamupdate.功能。

trailingAvg = [];trailingAvgSq = [];

训练模型。为每个mini-batch:

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

  • 计算损失和梯度。

  • 使用该更新编码器和解码器模型参数adamupdate.功能。

  • 更新培训进度图。

迭代= 0;start = tic;%循环纪元。为了epoch = 1:numepochs复位(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(start),“格式”“hh: mm: ss”);Addpoints(LineLoStrain,迭代,双(收集(丢失)))标题(”时代:“+时代+”,过去:“+字符串(d))绘制结尾结尾

生成翻译

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

使用与训练相同的步骤对文本数据进行预处理。使用transformText函数,在示例结束时列出,将文本拆分为字符并添加启动和停止令牌。

strsource = dataTest {:,1};strtarget = dataTest {:,2};

翻译文本使用模特预分规功能。

maxSequenceLength = 10;分隔符="";strtranslated = translateText(参数,strsource,max sequencelength,minibatchsize,...encsource,enctarget,starttoken,streptoken,delimiter);

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

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

查看随机选择的翻译。

idx = randperm(规模(人数(1)miniBatchSize);台(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函数通过将文本分割为字符并添加开始和停止标记对输入文本进行预处理和标记,以便进行翻译。如果要通过将文本分割成单词而不是字符来翻译文本,请跳过第一步。

功能文档= TransformText(str,starttoken,stowtoken)str = strip(替换(str,""));str = starttoken + str + stowtoken;文档=令人畏缩的document(str,'CustomTokens', (startToken stopToken]);结尾

迷你批处理预处理功能

preprocessMiniBatch在示例的列车模型部分中描述的功能,预处理培训数据。该函数使用以下步骤预处理数据:

  1. 确定迷你批处理中所有源和目标序列的长度

  2. 填充序列与使用迷你批量中最长序列相同的长度拼图序列功能。

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

功能[X,T,sequenceLengthsSource,maskTarget] = preprocessMiniBatch(sequencesSource,sequencesTarget,inputSize,outputSize) sequenceLengthsSource = cellfun(@(X) size(X, 2),sequencesSource);X = padsequences (sequencesSource 2“paddingsvalue”,输入);x = y yute(x,[1 3 2]);[t,masktarget] = pad sequences(sequencestarget,2,“paddingsvalue”,输出);t =换算(t,[1 3 2]);masktarget = permute(masktarget,[1 3 2]);结尾

模型梯度函数

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

功能(渐变,亏损)= modelGradients(参数、dlX T,...sequenceLengthsSource maskTarget,辍学)通过编码器转发%。[dlZ, hiddenState] = modelEncoder (parameters.encoder、dlX sequenceLengthsSource);%解码器输出。doteacherforcing = rand <0.5;sequencelength = size(t,3);dly = decoder预期(参数.decoder,dlz,t,hiddenstate,丢弃,...doTeacherForcing sequenceLength);%掩蔽损失。海底=海底(::1:end-1);T = extractdata(收集(T(:,:, 2:结束)));T = onehotencode (T, 1'classnames'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,重量,'datomformat'“认知行为治疗”);%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,偏见,'datomformat'“认知行为治疗”);%LSTM 2。inputWeights = parametersEncoder.lstm2.InputWeights;recurrentWeights = parametersEncoder.lstm2.RecurrentWeights;偏见= parametersEncoder.lstm2.Bias;[dlZ, hiddenState] = lstm(dlZ,initialHiddenState, initialCellState,...inputWeights recurrentWeights,偏见,'datomformat'“认知行为治疗”);%掩蔽训练。如果〜isempty(序列)minibatchsize =尺寸(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 =嵌入(DLX,权重,'datomformat'“认知行为治疗”);% 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,'datomformat'“认知行为治疗”);%的辍学生。面具=(兰特(尺寸(dly),“喜欢”, d) >辍学);海底=海底。*面具;%LSTM 2。inputWeights = parametersDecoder.lstm2.InputWeights;recurrentWeights = parametersDecoder.lstm2.RecurrentWeights;偏见= parametersDecoder.lstm2.Bias;[dlY, hiddenState] = lstm(dlY, hiddenState, initialCellState, inputwights, recurrentwights, bias,)'datomformat'“认知行为治疗”);% 注意力。重量= parametersDecoder.attn.Weights;[attentionScores, context] = attention(hiddenState, dlZ, weights);%连接。dly = cat(1,dly,repmat(上下文,[1 1 sequencelength]));%完全连接。重量= parametersDecoder.fc.Weights;偏见= parametersDecoder.fc.Bias;海底= fullyconnect(海底,重量、偏见,'datomformat'“认知行为治疗”);%softmax。海底= softmax(海底,'datomformat'“认知行为治疗”);结尾

注意力功能

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

功能[上下文] =注意(隐藏器,ercoderoutputs,权重)%初始化注意能量。[Minibatchsize,Sequencelength] =大小(EncoderOutputs,2:3);Ippectionenergies = zeros([sequencelength minibatchsize],“喜欢”, hiddenState);%注意能量。hWX = hiddenState .* pagemtimes(weights,encoderOutputs);为了tt = 1:sequenceLength attentionEnergies(tt,:) = sum(hWX(:,:, tt), 1);结尾%注意分数。actentionscores = softmax(注意力,'datomformat'“CB”);% 语境。EncoderOutputs = permute(ercoderoutputs,[1 3 2]);actentionscores =换算(诊断核,[1 3 2]);context = pagemtimes(encoderoutputs,interentionscores);上下文=挤压(上下文);结尾

解码器模型预测函数

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

功能海底= decoderPredictions (hiddenState parametersDecoder, dlZ, T,辍学,...doTeacherForcing sequenceLength)%转换为dlarray。dlt = dlarray(t);%初始化上下文。minibatchsize =尺寸(dlt,2);numhidendunits = size(dlz,1);context = zeros([numhidendunits minibatchsize],“喜欢”, dlZ);如果doTeacherForcing通过解码器的%前进。dlY = modelDecoder(parametersDecoder, dlT, context, hiddenState, dlZ, dropout);别的%获得解码器的第一次步骤。decoderInput = dlT (:: 1);%初始化输出。numclasses = numel(parametersdecoder.fc.bias);dly = zeros([numcrasses minibatchsize sequencelength],“喜欢”, decoderInput);%循环时间步骤。为了t = 1:Sequencelength通过解码器的%前进。[dly(:,:,t),context,hiddenstate] = modeldecoder(parametersdecoder,decoderinput,context,...HiddenState,DLZ,辍学);%更新解码器输入。[〜,decoderinput] = max(dly(:,:,t),[],1);结尾结尾结尾

文本翻译功能

翻译函数通过迭代迷你批量来翻译一系列文本。该函数作为输入的模型参数,输入字符串阵列,最大序列长度,迷你批量大小,源和目标字编码对象,启动和停止令牌,以及用于组装输出的分隔符​​。

功能strtranslated = translateText(参数,strsource,max sequencelength,minibatchsize,...EncSource,Enctarget,StartToken,StopToken,Delimiter)%转换文本。documentsSource = transformText(你要startToken stopToken);sequencessource = doc2sequence(encsource,documentSource,...“PaddingDirection”'对'...“PaddingValue”,encsource.numwords + 1);%转换为dlarray。X = CAT(3,Sequencessource {:});x = y yute(x,[1 3 2]);dlx = dlarray(x);%初始化输出。numobservations = numel(strsource);strtranslated = strings(numobservations,1);%循环小批。numIterations = cell (nummobations / miniBatchSize);为了i = 1:numiterations idxminibatch =(i-1)* minibatchsize + 1:min(i * minibatchsize,numobservations);minibatchsize = numel(idxminibatch);使用模型编码器编码。Sequencelengths = [];[dlz,hiddenstate] = modelencoder(parameters.encoder,dlx(:,idxminibatch,:),sequencelengs);%解码器预测。doteacherforcing = false;辍学= 0;DecoderInput = Repmat(Word2ind(Enctarget,StartToken),[1 minibatchsize]);DecoderInput = DlArray(DecoderInput);dly = decoder预期(参数.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;结尾结尾结尾

另请参阅

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

相关的话题