这个例子展示了如何定义一个文本编码器模型函数。
在深度学习的背景下,编码器是深度学习网络的一部分,它将输入映射到某个潜在空间。您可以在各种任务中使用这些向量。例如,
通过对编码数据应用softmax运算和使用交叉熵损失进行分类。
使用编码向量作为上下文向量进行序列到序列的转换。
该文件sonnets.txt
在一个文本文件中包含了莎士比亚所有的十四行诗。
阅读文件中的莎士比亚十四行诗数据“sonnets.txt”
.
文件名=“sonnets.txt”;textData = fileread(文件名);
十四行诗用两个空格缩进。使用删除缩进取代
将文本分割成单独的行分裂
函数。删除头9个元素和短十四行诗标题的标题。
textData =取代(textData,”“,"");textData =分裂(textData、换行符);textData (1:9) = [];textData (strlength (textData) < 5) = [];
创建一个用于标记和预处理文本数据的函数。这个函数preprocessText
,执行以下步骤:
分别用指定的开始标记和停止标记添加和附加每个输入字符串。
使用标记文本tokenizedDocument
.
预处理文本数据并指定开始和停止标记“<开始>”
和“<停止>”
,分别。
startToken =“<开始>”;stopToken =“<停止>”;文件= preprocessText (textData startToken stopToken);
从标记化的文档创建单词编码对象。
内附= wordEncoding(文件);
在训练深度学习模型时,输入数据必须是一个包含固定长度序列的数字数组。因为文档有不同的长度,所以必须用填充值填充较短的序列。
重新创建单词编码以包括填充令牌并确定该令牌的索引。
paddingToken =“<垫>”;newVocabulary = [cn . vocabulary paddingToken];内附= wordEncoding (newVocabulary);paddingToken paddingIdx = word2ind (enc)
paddingIdx = 3595
编码器的目标是将单词索引序列映射到某个潜在空间中的向量。
初始化以下模型的参数。
该模型使用三种操作:
不过,这个嵌入映射的是范围为1的单词索引vocabularySize
到维数向量embeddingDimension
,在那里vocabularySize
编码词汇表中的单词数是多少embeddingDimension
为通过嵌入学到的组件数。
LSTM操作将单词向量作为输入序列,输出1-by-numHiddenUnits
向量,numHiddenUnits
为LSTM操作中隐藏单元的个数。
全连接操作将输入乘以一个添加偏差的权值矩阵,并输出大小向量latentDimension
,在那里latentDimension
是潜在空间的维度。
指定参数的尺寸。
embeddingDimension = 100;numHiddenUnits = 150;latentDimension = 50;vocabularySize = enc.NumWords;
为参数创建一个结构体。
参数=结构;
使用高斯函数初始化嵌入的权值initializeGaussian
函数,该函数作为支持文件附加到本示例中。万博1manbetx指定平均值为0,标准偏差为0.01。想要了解更多,请看高斯函数初始化.
μ= 0;σ= 0.01;parameters.em . weights = initializeGaussian([embedingdimension vocabularySize],mu,sigma);
初始化编码器LSTM操作的可学习参数:
可学习参数的大小取决于输入的大小。由于LSTM操作的输入是来自于嵌入操作的字向量序列,因此输入通道的数量为embeddingDimension
.
输入权值矩阵有大小4 * numHiddenUnits
——- - - - - -inputSize
,在那里inputSize
是输入数据的维度。
递归权矩阵有大小4 * numHiddenUnits
——- - - - - -numHiddenUnits
.
偏差向量有大小4 * numHiddenUnits
1。
sz = [4*numHiddenUnits embedingdimension]; / /隐藏尺寸numOut = 4 * numHiddenUnits;numIn = embeddingDimension;parameters.lstmEncoder.InputWeights = initializeGlorot(深圳、numOut numIn);parameters. lstmencoder . recurrentwights = initialize正交([4*numHiddenUnits numHiddenUnits]);parameters.lstmEncoder.Bias = initializeUnitForgetGate (numHiddenUnits);
初始化编码器全连接操作的可学习参数:
用gloria初始化器初始化权重。
属性用零初始化偏差initializeZeros
函数,该函数作为支持文件附加到本示例中。万博1manbetx想要了解更多,请看零初始化.
可学习参数的大小取决于输入的大小。因为全连接操作的输入是LSTM操作的输出,所以输入通道的数量为numHiddenUnits
.使全连接运算输出具有大小的向量latentDimension
,指定输出大小为latentDimension
.
权矩阵有大小outputSize
——- - - - - -inputSize
,在那里outputSize
和inputSize
分别对应输出维度和输入维度。
偏差向量有大小outputSize
1。
sz = [latentDimension numHiddenUnits];numOut = latentDimension;numIn = numHiddenUnits;parameters.fcEncoder.Weights = initializeGlorot(深圳、numOut numIn);parameters.fcEncoder.Bias = initializeZeros([latentDimension 1]);
创建函数modelEncoder
,列于编码器模型函数计算编码器模型的输出。的modelEncoder
函数,将单词索引、模型参数和序列长度作为输入序列,并返回相应的潜在特征向量。
要使用自定义训练循环训练模型,必须对小批量数据进行迭代,并将其转换为编码器模型和模型梯度函数所需的格式。本节示例演示了在自定义训练循环中准备一小批数据所需的步骤。
准备一个示例的小批数据。从中选择包含32个文档的小批处理文档
.这表示在自定义训练循环的迭代中使用的小批数据。
miniBatchSize = 32;idx = 1: miniBatchSize;documentsBatch =文档(idx);
属性将文档转换为序列doc2sequence
函数并指定用与填充标记相对应的单词索引右填充序列。
X = doc2sequence (enc documentsBatch,...“PaddingDirection”,“对”,...“PaddingValue”, paddingIdx);
输出doc2sequence
函数是一个单元格数组,其中每个元素是字索引的行向量。由于编码器模型函数需要数字输入,因此使用猫
函数并指定沿第一个维度连接。输出有尺寸miniBatchSize
——- - - - - -sequenceLength
,在那里sequenceLength
是最小批处理中最长序列的长度。
X =猫(1,X {:});大小(X)
ans =1×232 14
将数据转换为dlarray
带格式的“BTC”
(批量、时间、通道)。该软件自动重新安排输出有格式“施”
输出有大小1
——- - - - - -miniBatchSize
——- - - - - -sequenceLength
.
dlX = dlarray (X,“BTC”);大小(dlX)
ans =1×31 32 14
方法来计算输入数据的未填充序列长度doclength
功能与小批文件作为输入。
sequenceLengths = doclength (documentsBatch);
此代码片段显示了在自定义训练循环中准备迷你批处理的示例。
迭代= 0;%循环纪元。为时代= 1:numEpochs%循环小批。为i = 1:numIterationsPerEpoch iteration = iteration + 1;% mini-batch阅读。idx =(张)* miniBatchSize + 1:我* miniBatchSize;documentsBatch =文档(idx);%转换为序列。X = doc2sequence (enc documentsBatch,...“PaddingDirection”,“对”,...“PaddingValue”, paddingIdx);X =猫(1,X {:});%转换为美元。dlX = dlarray (X,“BTC”);%计算序列长度。sequenceLengths = doclength (documentsBatch);%评估模型梯度。%……%更新可学习参数。%……结束结束
当使用自定义训练循环训练深度学习模型时,必须计算损失相对于可学习参数的梯度。这个计算依赖于模型函数的前向传递的输出。
要执行编码器的前向传递,请使用modelEncoder
函数直接使用参数、数据和序列长度作为输入。输出为latentDimension
——- - - - - -miniBatchSize
矩阵。
dlZ = modelEncoder(参数、dlX sequenceLengths);大小(dlZ)
ans =1×250 32
此代码片段显示了在模型梯度函数中使用模型编码器函数的示例。
函数gradient = modelGradients(parameters,dlX,sequenceLengths) dlZ = modelEncoder(parameters,dlX,sequenceLengths);%计算损失。%……%计算梯度。%……结束
此代码片段显示了在自定义训练循环中评估模型梯度的示例。
迭代= 0;%循环纪元。为时代= 1:numEpochs%循环小批。为i = 1:numIterationsPerEpoch iteration = iteration + 1;% mini-batch做好准备。%……%评估模型梯度。gradient = dlfeval(@modelGradients, parameters, dlX, sequenceLengths);%更新可学习参数。(参数、trailingAvg trailingAvgSq) = adamupdate(参数、渐变...trailingAvg trailingAvgSq,迭代);结束结束
的modelEncoder
函数,将模型参数、词索引序列和序列长度作为输入,返回相应的潜在特征向量。
由于输入数据包含不同长度的填充序列,填充可能对损失计算产生不利影响。对于LSTM操作,不是返回序列的最后一个时间步骤的输出(很可能对应于处理大量填充值后的LSTM状态),而是确定由sequenceLengths
输入。
函数dlZ = modelEncoder(参数、dlX sequenceLengths)%嵌入。重量= parameters.emb.Weights;dlZ =嵌入(dlX、重量);% LSTM。inputWeights = parameters.lstmEncoder.InputWeights;recurrentWeights = parameters.lstmEncoder.RecurrentWeights;偏见= parameters.lstmEncoder.Bias;numHiddenUnits =大小(recurrentWeights, 2);hiddenState = 0 (numHiddenUnits 1“喜欢”dlX);cellState = 0 (numHiddenUnits 1“喜欢”dlX);dlZ1 = lstm (dlZ hiddenState、cellState inputWeights, recurrentWeights,偏差);%输出模式'last'与掩蔽。miniBatchSize =大小(dlZ1, 2);miniBatchSize, dlZ = 0 (numHiddenUnits“喜欢”dlZ1);dlZ = dlarray (dlZ,“CB”);为n = 1:miniBatchSize t = sequenceLengths(n);dlZ (:, n) = dlZ1 (:, n, t);结束%完全连接。重量= parameters.fcEncoder.Weights;偏见= parameters.fcEncoder.Bias;dlZ = fullyconnect(重量,dlZ偏差);结束
这个函数preprocessText
执行以下步骤:
分别用指定的开始标记和停止标记添加和附加每个输入字符串。
使用标记文本tokenizedDocument
.
函数文件= preprocessText (textData startToken stopToken)%添加开始和停止标记。textData = startToken + textData + stopToken;标记文本。文件= tokenizedDocument (textData,“CustomTokens”, (startToken stopToken]);结束