テキスト符号化器モデル関数の定義
この例では、テキスト符号化器モデル関数の定義方法を示します。
深層学習のコンテキストでは、符号化器は、入力を何らかの潜在空間にマッピングする深層学習ネットワークの一部です。これらのベクトルは、さまざまなタスクに使用できます。次に例を示します。
ソフトマックス演算を符号化されたデータに適用し、クロス エントロピー損失を使用する分類。
符号化されたベクトルをコンテキスト ベクトルとして使用する sequence-to-sequence 変換。
データの読み込み
ファイル sonnets.txt
には、シェイクスピアのソネット全集が 1 つのテキスト ファイルとして格納されています。
ファイル "sonnets.txt"
からシェイクスピアのソネットのデータを読み取ります。
filename = "sonnets.txt";
textData = fileread(filename);
ソネットは、2 つの空白文字でインデントされています。replace
を使用してインデントを削除し、関数 split
を使用してテキストを個別の行に分割します。最初の 9 つの要素と短いソネット タイトルからヘッダーを削除します。
textData = replace(textData," ",""); textData = split(textData,newline); textData(1:9) = []; textData(strlength(textData)<5) = [];
データの準備
テキスト データをトークン化および前処理する関数を作成します。例の最後にリストされている関数 preprocessText
は以下のステップを実行します。
各入力ストリングの前後に、指定された開始トークンと停止トークンをそれぞれ付加する。
tokenizedDocument
を使用してテキストをトークン化する。
テキスト データを前処理し、開始トークン "<start>"
と停止トークン "<stop>"
をそれぞれ指定します。
startToken = "<start>"; stopToken = "<stop>"; documents = preprocessText(textData,startToken,stopToken);
トークン化されたドキュメントから単語符号化オブジェクトを作成します。
enc = wordEncoding(documents);
深層学習モデルの学習を行う際には、入力データは固定長のシーケンスを含む数値配列でなければなりません。ドキュメントの長さは異なるため、短いシーケンスはパディング値でパディングしなければなりません。
パディング トークンを含み、そのトークンのインデックスも決定するように、単語符号化を再作成します。
paddingToken = "<pad>";
newVocabulary = [enc.Vocabulary paddingToken];
enc = wordEncoding(newVocabulary);
paddingIdx = word2ind(enc,paddingToken)
paddingIdx = 3595
モデル パラメーターの初期化
符号化器の目的は、単語インデックスのシーケンスを何らかの潜在空間においてベクトルにマッピングすることです。
次のモデルのパラメーターを初期化します。
このモデルでは、次の 3 つの操作を行います。
埋め込みでは、範囲 1 ~
vocabularySize
で単語インデックスを次元embeddingDimension
のベクトルにマッピングします。ここで、vocabularySize
は符号化ボキャブラリの単語数、embeddingDimension
は埋め込みによって学習されたコンポーネントの数です。LSTM 演算では、単語ベクトルのシーケンスを入力として受け取り、1 x
numHiddenUnits
のベクトルを出力します。ここで、numHiddenUnits
は LSTM 演算での隠れユニットの数です。全結合演算では、入力と、バイアスを加算した重み行列を乗算し、サイズ
latentDimension
のベクトルを出力します。ここで、latentDimension
は潜在空間の次元です。
パラメーターの次元を指定します。
embeddingDimension = 100; numHiddenUnits = 150; latentDimension = 50; vocabularySize = enc.NumWords;
パラメーターの struct を作成します。
parameters = struct;
関数 initializeGaussian
を使用し、ガウスで埋め込みの重みを初期化します。この関数は、この例にサポート ファイルとして添付されています。平均値を 0、標準偏差を 0.01 に指定します。詳細については、ガウスによる初期化を参照してください。
mu = 0; sigma = 0.01; parameters.emb.Weights = initializeGaussian([embeddingDimension vocabularySize],mu,sigma);
符号化器の LSTM 演算に関する学習可能なパラメーターを初期化します。
関数
initializeGlorot
を使用し、Glorot 初期化子で入力の重みを初期化します。この関数は、この例にサポート ファイルとして添付されています。詳細については、Glorot の初期化を参照してください。関数
initializeOrthogonal
を使用し、直交初期化子で再帰重みを初期化します。この関数は、この例にサポート ファイルとして添付されています。詳細については、直交初期化を参照してください。関数
initializeUnitForgetGate
を使用し、ユニット忘却ゲート初期化子でバイアスを初期化します。この関数は、この例にサポート ファイルとして添付されています。詳細については、ユニット忘却ゲートによる初期化を参照してください。
学習可能なパラメーターのサイズは、入力のサイズによって異なります。LSTM 演算への入力は埋め込み演算からの単語ベクトルのシーケンスであるため、入力チャネルの数は embeddingDimension
になります。
入力重み行列のサイズは
4*numHiddenUnits
xinputSize
です。ここで、inputSize
は入力データの次元です。再帰重み行列のサイズは
4*numHiddenUnits
xnumHiddenUnits
です。バイアス ベクトルのサイズは
4*numHiddenUnits
x 1 です。
sz = [4*numHiddenUnits embeddingDimension]; numOut = 4*numHiddenUnits; numIn = embeddingDimension; parameters.lstmEncoder.InputWeights = initializeGlorot(sz,numOut,numIn); parameters.lstmEncoder.RecurrentWeights = initializeOrthogonal([4*numHiddenUnits numHiddenUnits]); parameters.lstmEncoder.Bias = initializeUnitForgetGate(numHiddenUnits);
符号化器の全結合演算に関する学習可能なパラメーターを初期化します。
Glorot 初期化子を使用して重みを初期化します。
関数
initializeZeros
を使用し、ゼロでバイアスを初期化します。この関数は、この例にサポート ファイルとして添付されています。詳細については、ゼロでの初期化を参照してください。
学習可能なパラメーターのサイズは、入力のサイズによって異なります。全結合演算への入力は LSTM 演算の出力であるため、入力チャネルの数は numHiddenUnits
になります。全結合演算でサイズ latentDimension
のベクトルを出力するには、出力サイズを latentDimension
に指定します。
重み行列のサイズは
outputSize
xinputSize
です。ここで、outputSize
とinputSize
は、出力と入力の次元にそれぞれ対応します。バイアス ベクトルのサイズは
outputSize
x 1 です。
sz = [latentDimension numHiddenUnits]; numOut = latentDimension; numIn = numHiddenUnits; parameters.fcEncoder.Weights = initializeGlorot(sz,numOut,numIn); parameters.fcEncoder.Bias = initializeZeros([latentDimension 1]);
モデル符号化器関数の定義
この例の符号化器モデル関数の節にリストされている関数 modelEncoder
を作成し、符号化器モデルの出力を計算します。関数 modelEncoder
は、モデル パラメーターおよびシーケンス長を単語インデックスの入力シーケンスとして受け取り、対応する潜在特徴ベクトルを返します。
データのミニバッチの準備
カスタム学習ループを使用してモデルの学習を行うには、データのミニバッチを反復処理し、それを符号化器モデル関数およびモデル勾配関数に必要な形式に変換しなければなりません。この例のこの節では、カスタム学習ループ内でデータのミニバッチを準備するのに必要な手順について説明します。
データのミニバッチ例を準備します。documents
から、32 件のドキュメントで構成されるミニバッチを選択します。これは、カスタム学習ループの反復処理で使用されるデータのミニバッチを表します。
miniBatchSize = 32; idx = 1:miniBatchSize; documentsBatch = documents(idx);
関数 doc2sequence
を使用してドキュメントをシーケンスに変換します。また、パディング トークンに対応する単語インデックスを使用し、そのシーケンスの右側をパディングするように指定します。
X = doc2sequence(enc,documentsBatch, ... PaddingDirection="right", ... PaddingValue=paddingIdx);
関数 doc2sequence
の出力は cell 配列です。ここで、その各要素は単語インデックスの行ベクトルです。符号化器モデル関数は数値入力を必要とするため、関数 cat
を使用してデータの行を連結し、最初の次元と連結するように指定します。出力のサイズは miniBatchSize
x sequenceLength
です。ここで、sequenceLength
はミニバッチ内の最長シーケンスの長さです。
X = cat(1,X{:}); size(X)
ans = 1×2
32 14
形式 "BTC"
(batch、time、channel) をもつ dlarray
にデータを変換します。ソフトウェアは、形式 "CTB"
に従って出力を自動的に再配置します。これにより、出力のサイズは 1
×miniBatchSize
×sequenceLength
になります。
X = dlarray(X,'BTC');
size(X)
ans = 1×3
1 32 14
マスクについては、ドキュメントのミニバッチを入力としてもつ関数 doclength
を使用し、パディングを削除した入力データのシーケンス長を計算します。
sequenceLengths = doclength(documentsBatch);
このコードの抜粋は、カスタム学習ループにおけるミニバッチの準備の例を示しています。
iteration = 0; % Loop over epochs. for epoch = 1:numEpochs % Loop over mini-batches. for i = 1:numIterationsPerEpoch iteration = iteration + 1; % Read mini-batch. idx = (i-1)*miniBatchSize+1:i*miniBatchSize; documentsBatch = documents(idx); % Convert to sequences. X = doc2sequence(enc,documentsBatch, ... PaddingDirection="right", ... PaddingValue=paddingIdx); X = cat(1,X{:}); % Convert to dlarray. X = dlarray(X,"BTC"); % Calculate sequence lengths. sequenceLengths = doclength(documentsBatch); % Evaluate model gradients. % ... % Update learnable parameters. % ... end end
モデル損失関数でのモデル関数の使用
カスタム学習ループを使用して深層学習モデルの学習を行う場合、学習可能なパラメーターについての損失および損失の勾配を計算しなければなりません。この計算は、モデル関数のフォワード パスの出力によって異なります。
符号化器のフォワード パスを実行するには、関数 modelEncoder
を、パラメーター、データ、シーケンス長を入力として直接使用します。出力は latentDimension
行 miniBatchSize
列の行列です。
Z = modelEncoder(parameters,X,sequenceLengths); size(Z)
ans = 1×2
50 32
このコードの抜粋は、モデル勾配関数内でモデル符号化器関数を使用する例を示しています。
function [loss,gradients] = modelLoss(parameters,X,sequenceLengths) Z = modelEncoder(parameters,X,sequenceLengths); % Calculate loss. % ... % Calculate gradients. % ... end
このコードの抜粋は、カスタム学習ループにおけるモデル勾配の評価の例を示しています。
iteration = 0; % Loop over epochs. for epoch = 1:numEpochs % Loop over mini-batches. for i = 1:numIterationsPerEpoch iteration = iteration + 1; % Prepare mini-batch. % ... % Evaluate model gradients. [loss,gradients] = dlfeval(@modelLoss, parameters, X, sequenceLengths); % Update learnable parameters. [parameters,trailingAvg,trailingAvgSq] = adamupdate(parameters,gradients, ... trailingAvg,trailingAvgSq,iteration); end end
符号化器モデル関数
関数 modelEncoder
は、モデル パラメーター、単語インデックスのシーケンス、シーケンス長を入力として受け取り、対応する潜在特徴ベクトルを返します。
入力データには長さの異なるパディング済みシーケンスが含まれるため、パディングによって損失計算に悪影響の及ぶ可能性があります。LSTM 演算について、シーケンスの最後のタイム ステップの出力 (多数のパディング値を処理した後の LSTM 状態に相当する可能性が高い) を返す代わりに、sequenceLengths
入力によって与えられた実際の最後のタイム ステップを決定します。
function Z = modelEncoder(parameters,X,sequenceLengths) % Embedding. weights = parameters.emb.Weights; Z = embed(X,weights); % LSTM. inputWeights = parameters.lstmEncoder.InputWeights; recurrentWeights = parameters.lstmEncoder.RecurrentWeights; bias = parameters.lstmEncoder.Bias; numHiddenUnits = size(recurrentWeights,2); hiddenState = zeros(numHiddenUnits,1,"like",X); cellState = zeros(numHiddenUnits,1,"like",X); Z1 = lstm(Z,hiddenState,cellState,inputWeights,recurrentWeights,bias); % Output mode "last" with masking. miniBatchSize = size(Z1,2); Z = zeros(numHiddenUnits,miniBatchSize,"like",Z1); Z = dlarray(Z,"CB"); for n = 1:miniBatchSize t = sequenceLengths(n); Z(:,n) = Z1(:,n,t); end % Fully connect. weights = parameters.fcEncoder.Weights; bias = parameters.fcEncoder.Bias; Z = fullyconnect(Z,weights,bias); end
前処理関数
関数 preprocessText
は以下のステップを実行します。
各入力ストリングの前後に、指定された開始トークンと停止トークンをそれぞれ付加する。
tokenizedDocument
を使用してテキストをトークン化する。
function documents = preprocessText(textData,startToken,stopToken) % Add start and stop tokens. textData = startToken + textData + stopToken; % Tokenize the text. documents = tokenizedDocument(textData,'CustomTokens',[startToken stopToken]); end
参考
dlfeval
| dlgradient
| dlarray