定义文本编码器模型函数
这个例子展示了如何定义一个文本编码器模型函数。
在深度学习的背景下,编码器是深度学习网络的一部分,它将输入映射到一些潜在的空间。您可以将这些向量用于各种任务。例如,
通过对编码数据应用软最大操作并使用交叉熵损失进行分类。
使用编码的向量作为上下文向量的序列到序列的转换。
加载数据
该文件sonnets.txt
在一个文本文件中包含了莎士比亚所有的十四行诗。
阅读文件中的莎士比亚十四行诗数据“sonnets.txt”
.
文件名=“sonnets.txt”;textData = fileread(文件名);
十四行诗由两个空格缩进。删除缩进使用取代
控件将文本拆分为单独的行分裂
函数。删除头九个元素和短十四行诗标题。
textData = replace(textData,”“,"");textData = split(textData,换行符);textData(1:9) = [];textData(strlength(textData)<5) = [];
准备数据
创建一个对文本数据进行标记和预处理的函数。这个函数preprocessText
,在示例末尾列出,执行以下步骤:
分别使用指定的开始和停止令牌对每个输入字符串进行前置和追加。
使用标记化文本
tokenizedDocument
.
预处理文本数据并指定开始和停止令牌“<开始>”
而且“<停止>”
,分别。
startToken =“<开始>”;stopToken =“<停止>”;documents = preprocessText(textData,startToken,stopToken);
从标记化的文档创建单词编码对象。
enc = worddencoding(文档);
在训练深度学习模型时,输入数据必须是包含固定长度序列的数字数组。因为文档有不同的长度,所以必须用填充值填充较短的序列。
重新创建单词编码以包括填充标记并确定该标记的索引。
paddingToken =“<垫>”;newVocabulary = [c. vocabulary paddingToken];enc = worddencoding (newVocabulary);paddingIdx = word2ind(enc,paddingToken)
paddingIdx = 3595
初始化模型参数
编码器的目标是将字索引序列映射到某个潜在空间中的向量。
初始化以下模型的参数。
这个模型使用了三个操作:
嵌入将单词索引映射到范围1
vocabularySize
对维数向量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操作的可学习参数:
可学习参数的大小取决于输入的大小。由于LSTM操作的输入是来自嵌入操作的字向量序列,因此输入通道的数量为embeddingDimension
.
输入权重矩阵有大小
4 * numHiddenUnits
——- - - - - -inputSize
,在那里inputSize
输入数据的维数。递归权矩阵有大小
4 * numHiddenUnits
——- - - - - -numHiddenUnits
.偏差向量有大小
4 * numHiddenUnits
1。
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
分别对应于输出和输入维度。偏差向量有大小
outputSize
1。
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
执行以下步骤:
分别使用指定的开始和停止令牌对每个输入字符串进行前置和追加。
使用标记化文本
tokenizedDocument
.
函数documents = preprocessText(textData,startToken,stopToken)添加开始和停止令牌。textData = startToken + textData + stopToken;标记文本。文档= tokenizedDocument(文本数据,“CustomTokens”, (startToken stopToken]);结束
另请参阅
wordEncoding
|word2ind
|doc2sequence
|tokenizedDocument