主要内容

定义文本编码器模型函数

这个例子展示了如何定义一个文本编码器模型函数。

在深度学习的背景下,编码器是深度学习网络的一部分,它将输入映射到一些潜在的空间。您可以将这些向量用于各种任务。例如,

  • 通过对编码数据应用软最大操作并使用交叉熵损失进行分类。

  • 使用编码的向量作为上下文向量的序列到序列的转换。

加载数据

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

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

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

十四行诗由两个空格缩进。删除缩进使用取代控件将文本拆分为单独的行分裂函数。删除头九个元素和短十四行诗标题。

textData = replace(textData,”“"");textData = split(textData,换行符);textData(1:9) = [];textData(strlength(textData)<5) = [];

准备数据

创建一个对文本数据进行标记和预处理的函数。这个函数preprocessText,在示例末尾列出,执行以下步骤:

  1. 分别使用指定的开始和停止令牌对每个输入字符串进行前置和追加。

  2. 使用标记化文本tokenizedDocument

预处理文本数据并指定开始和停止令牌“<开始>”而且“<停止>”,分别。

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

从标记化的文档创建单词编码对象。

enc = worddencoding(文档);

在训练深度学习模型时,输入数据必须是包含固定长度序列的数字数组。因为文档有不同的长度,所以必须用填充值填充较短的序列。

重新创建单词编码以包括填充标记并确定该标记的索引。

paddingToken =“<垫>”;newVocabulary = [c. vocabulary paddingToken];enc = worddencoding (newVocabulary);paddingIdx = word2ind(enc,paddingToken)
paddingIdx = 3595

初始化模型参数

编码器的目标是将字索引序列映射到某个潜在空间中的向量。

初始化以下模型的参数。

这个模型使用了三个操作:

  • 嵌入将单词索引映射到范围1vocabularySize对维数向量embeddingDimension,在那里vocabularySize编码词汇和中的单词数是多少embeddingDimension是嵌入学习到的组件的数量。

  • LSTM操作以字向量序列作为输入,输出为1 × -numHiddenUnits向量,numHiddenUnits为LSTM操作中隐藏单元的数量。

  • 全连接操作将输入乘以一个权重矩阵,加上偏置和输出大小的向量latentDimension,在那里latentDimension是潜空间的维数。

指定参数的尺寸。

embeddingDimension = 100;numHiddenUnits = 150;latentDimension = 50;vocabularySize = c. numwords;

为参数创建一个结构。

参数= struct;

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

Mu = 0;σ = 0.01;parameters.emb.Weights = initializ高斯([embeddingDimension vocabularySize],mu,sigma);

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

  • 类的gloot初始化器初始化输入权重initializeGlorot函数,该函数作为支持文件附加到本示例中。金宝app要了解更多信息,请参见Glorot初始化(深度学习工具箱)

  • 类的正交初始化式初始化循环权重initializeOrthogonal函数,该函数作为支持文件附加到本示例中。金宝app要了解更多信息,请参见正交初始化(深度学习工具箱)

  • 的单元忘记门初始化器初始化偏置initializeUnitForgetGate函数,该函数作为支持文件附加到本示例中。金宝app要了解更多信息,请参见单元忘记门初始化(深度学习工具箱)

可学习参数的大小取决于输入的大小。由于LSTM操作的输入是来自嵌入操作的字向量序列,因此输入通道的数量为embeddingDimension

  • 输入权重矩阵有大小4 * numHiddenUnits——- - - - - -inputSize,在那里inputSize输入数据的维数。

  • 递归权矩阵有大小4 * numHiddenUnits——- - - - - -numHiddenUnits

  • 偏差向量有大小4 * numHiddenUnits1。

sz = [4*numHiddenUnits embeddingDimension];numOut = 4*numHiddenUnits;numIn = embeddingDimension;parameters. lstmencode . inputwights = initializeGlorot(sz,numOut,numIn);parameters. lstmencode . recurrentwights = initializeOrthogonal([4*numHiddenUnits numHiddenUnits]);parameters. lstmencode . bias = initializeunit健忘门(numHiddenUnits);

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

  • 使用gloriot初始化器初始化权重。

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

可学习参数的大小取决于输入的大小。由于全连接操作的输入是LSTM操作的输出,因此输入通道的数量为numHiddenUnits.使全连通操作输出向量与大小一致latentDimension,指定输出大小为latentDimension

  • 权重矩阵有大小outputSize——- - - - - -inputSize,在那里outputSize而且inputSize分别对应于输出和输入维度。

  • 偏差向量有大小outputSize1。

sz = [latentDimension numHiddenUnits];numOut = latentDimension;numIn = numHiddenUnits;parameters. fcencode . weights = initializeGlorot(sz,numOut,numIn);parameters. fcencode . bias = initializeZeros([latentDimension 1]);

定义模型编码器函数

创建函数modelEncoder,列于编码器模型函数部分,该部分计算编码器模型的输出。的modelEncoder函数,将单词索引、模型参数和序列长度作为输入序列,返回相应的潜在特征向量。

准备小批量数据

要使用自定义训练循环训练模型,必须迭代小批量数据,并将其转换为编码器模型和模型梯度函数所需的格式。本节示例说明了在自定义训练循环中准备小批数据所需的步骤。

准备一个小批量数据示例。从中选择32个文档的小批文档.这表示自定义训练循环迭代中使用的小批数据。

miniBatchSize = 32;idx = 1:miniBatchSize;documentsBatch = documents(idx);

方法将文档转换为序列doc2sequence函数并指定使用与填充标记对应的单词索引右填充序列。

X = doc2sequence(enc,documentsBatch,...PaddingDirection =“正确”...PaddingValue = paddingIdx);

的输出。doc2sequence函数是一个单元格数组,其中每个元素都是单词索引的行向量。编码器模型函数需要数值输入,因此使用函数并指定沿第一个维度进行连接。输出有大小miniBatchSize——- - - - - -sequenceLength,在那里sequenceLength是迷你批处理中最长序列的长度。

X = cat(1,X{:});大小(X)
ans =1×232 14

将数据转换为adlarray带格式的“BTC”(批次,时间,通道)。软件自动重新排列输出的格式“施”所以输出有大小1——- - - - - -miniBatchSize——- - - - - -sequenceLength

X = dlarray(X,“BTC”);大小(X)
ans =1×332 14

方法计算输入数据的未填充序列长度doclength以小批量文档作为输入的函数。

sequenceLengths = doclength(documentsBatch);

此代码片段显示了在自定义训练循环中准备小批处理的示例。

迭代= 0;%遍历epoch。epoch = 1:numEpochs在小批上循环。i = 1:numIterationsPerEpoch迭代=迭代+ 1;读取小批。idx = (i-1)*miniBatchSize+1:i*miniBatchSize;documentsBatch = documents(idx);转换为序列。X = doc2sequence(enc,documentsBatch,...PaddingDirection =“正确”...PaddingValue = paddingIdx);X = cat(1,X{:});%转换为darray。X = dlarray(X,“BTC”);计算序列长度。sequenceLengths = doclength(documentsBatch);评估模型梯度。%……更新可学习参数。%……结束结束

在模型损失函数中使用模型函数

当使用自定义训练循环训练深度学习模型时,必须计算损失和损失相对于可学习参数的梯度。这个计算依赖于模型函数的前向传递的输出。

若要执行编码器的前向传递,请使用modelEncoder函数直接与参数,数据和序列长度作为输入。输出为latentDimension——- - - - - -miniBatchSize矩阵。

Z = modelEncoder(参数,X,sequenceLengths);大小(Z)
ans =1×250 32

这段代码片段展示了在模型梯度函数中使用模型编码器函数的示例。

函数[loss,gradients] = modelLoss(parameters,X,sequenceLengths) Z = modelEncoder(parameters,X,sequenceLengths);%计算损失。%……计算梯度。%……结束

这段代码片段显示了在自定义训练循环中评估模型梯度的示例。

迭代= 0;%遍历epoch。epoch = 1:numEpochs在小批上循环。i = 1:numIterationsPerEpoch迭代=迭代+ 1;准备小批量。%……评估模型梯度。[loss,gradients] = dlfeval(@modelLoss, parameters, X, sequenceLengths);更新可学习参数。[parameters,trailingAvg,trailingAvgSq] = adamupdate(参数,梯度,...trailingAvg trailingAvgSq,迭代);结束结束

编码器模型函数

modelEncoder函数,将模型参数、单词索引序列和序列长度作为输入,返回相应的潜在特征向量。

由于输入数据包含不同长度的填充序列,因此填充会对损失计算产生不利影响。对于LSTM操作,不是返回序列的最后一个时间步骤的输出(这可能对应于处理大量填充值后的LSTM状态),而是确定函数给出的实际最后一个时间步骤sequenceLengths输入。

函数Z = modelEncoder(参数,X,sequenceLengths)%嵌入。weights = parameters.emb.Weights;Z = embed(X,weights);% LSTM。inputwights = parameters. lstmencode . inputwights;recurrentwights = parameters. lstmencode . recurrentwights;bias = parameters. lstmencode . bias;numHiddenUnits = size(recurrentwights,2);hiddenState = 0 (numHiddenUnits,1,“喜欢”, X);cellState = 0 (numHiddenUnits,1,“喜欢”, X);Z1 = lstm(Z,hiddenState,cellState, inputwights, recurrentwights,bias);输出模式为“last”,带屏蔽。miniBatchSize = size(Z1,2);Z = 0 (numHiddenUnits,miniBatchSize,“喜欢”Z1);Z = dlarray(Z,“CB”);n = 1:miniBatchSize t = sequenceLengths(n);Z(:,n) = Z1(:,n,t);结束%完全连接。weights = parameters. fcencode . weights;bias = parameters. fcencode . bias;Z =完全连接(Z,权重,偏差);结束

预处理功能

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

  1. 分别使用指定的开始和停止令牌对每个输入字符串进行前置和追加。

  2. 使用标记化文本tokenizedDocument

函数documents = preprocessText(textData,startToken,stopToken)添加开始和停止令牌。textData = startToken + textData + stopToken;标记文本。文档= tokenizedDocument(文本数据,“CustomTokens”, (startToken stopToken]);结束

另请参阅

|||

相关的话题