ドキュメンテーション

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

深層学習を使用したテキストの生成

この例では、深層学習長短期記憶 (LSTM) ネットワークに学習させてテキストを生成する方法を説明します。

テキスト生成用の深層学習ネットワークに学習させるには、文字のシーケンスにおける次の文字を予測する sequence-to-sequence LSTM ネットワークに学習させます。次の文字を予測するネットワークに学習させるには、1 タイム ステップ分シフトした入力シーケンスを応答として指定します。

文字のシーケンスを LSTM ネットワークに入力するには、各学習観測値をベクトル で表される文字のシーケンスに変換します。ここで、D はボキャブラリに含まれる一意の文字の数です。各ベクトルについて、x が、与えられたボキャブラリ内のインデックス i の文字に対応する場合は であり、 の場合は です。

学習データの読み込み

テキスト データをテキスト ファイル sonnets.txt から抽出します。

filename = "sonnets.txt";
textData = fileread(filename);

ソネットは 2 つの空白文字でインデントされ、2 つの改行文字で区切られています。replace を使用してインデントを削除し、split を使用してテキストを個別のソネットに分割します。最初の 3 つの要素のメイン タイトルと、各ソネットの前に現れるソネット タイトルを削除します。

textData = replace(textData,"  ","");
textData = split(textData,[newline newline]);
textData = textData(5:2:end);

最初のいくつかの観測値を表示します。

textData(1:10)
ans = 10×1 cell array
    {'From fairest creatures we desire increase,↵That thereby beauty's rose might never die,↵But as the riper should by time decease,↵His tender heir might bear his memory:↵But thou, contracted to thine own bright eyes,↵Feed'st thy light's flame with self-substantial fuel,↵Making a famine where abundance lies,↵Thy self thy foe, to thy sweet self too cruel:↵Thou that art now the world's fresh ornament,↵And only herald to the gaudy spring,↵Within thine own bud buriest thy content,↵And tender churl mak'st waste in niggarding:↵Pity the world, or else this glutton be,↵To eat the world's due, by the grave and thee.'                                 }
    {'When forty winters shall besiege thy brow,↵And dig deep trenches in thy beauty's field,↵Thy youth's proud livery so gazed on now,↵Will be a tatter'd weed of small worth held:↵Then being asked, where all thy beauty lies,↵Where all the treasure of thy lusty days;↵To say, within thine own deep sunken eyes,↵Were an all-eating shame, and thriftless praise.↵How much more praise deserv'd thy beauty's use,↵If thou couldst answer 'This fair child of mine↵Shall sum my count, and make my old excuse,'↵Proving his beauty by succession thine!↵This were to be new made when thou art old,↵And see thy blood warm when thou feel'st it cold.'               }
    {'Look in thy glass and tell the face thou viewest↵Now is the time that face should form another;↵Whose fresh repair if now thou not renewest,↵Thou dost beguile the world, unbless some mother.↵For where is she so fair whose unear'd womb↵Disdains the tillage of thy husbandry?↵Or who is he so fond will be the tomb,↵Of his self-love to stop posterity?↵Thou art thy mother's glass and she in thee↵Calls back the lovely April of her prime;↵So thou through windows of thine age shalt see,↵Despite of wrinkles this thy golden time.↵But if thou live, remember'd not to be,↵Die single and thine image dies with thee.'                                    }
    {'Unthrifty loveliness, why dost thou spend↵Upon thy self thy beauty's legacy?↵Nature's bequest gives nothing, but doth lend,↵And being frank she lends to those are free:↵Then, beauteous niggard, why dost thou abuse↵The bounteous largess given thee to give?↵Profitless usurer, why dost thou use↵So great a sum of sums, yet canst not live?↵For having traffic with thy self alone,↵Thou of thy self thy sweet self dost deceive:↵Then how when nature calls thee to be gone,↵What acceptable audit canst thou leave?↵Thy unused beauty must be tombed with thee,↵Which, used, lives th' executor to be.'                                                      }
    {'Those hours, that with gentle work did frame↵The lovely gaze where every eye doth dwell,↵Will play the tyrants to the very same↵And that unfair which fairly doth excel;↵For never-resting time leads summer on↵To hideous winter, and confounds him there;↵Sap checked with frost, and lusty leaves quite gone,↵Beauty o'er-snowed and bareness every where:↵Then were not summer's distillation left,↵A liquid prisoner pent in walls of glass,↵Beauty's effect with beauty were bereft,↵Nor it, nor no remembrance what it was:↵But flowers distill'd, though they with winter meet,↵Leese but their show; their substance still lives sweet.'                   }
    {'Then let not winter's ragged hand deface,↵In thee thy summer, ere thou be distill'd:↵Make sweet some vial; treasure thou some place↵With beauty's treasure ere it be self-kill'd.↵That use is not forbidden usury,↵Which happies those that pay the willing loan;↵That's for thy self to breed another thee,↵Or ten times happier, be it ten for one;↵Ten times thy self were happier than thou art,↵If ten of thine ten times refigur'd thee:↵Then what could death do if thou shouldst depart,↵Leaving thee living in posterity?↵Be not self-will'd, for thou art much too fair↵To be death's conquest and make worms thine heir.'                                }
    {'Lo! in the orient when the gracious light↵Lifts up his burning head, each under eye↵Doth homage to his new-appearing sight,↵Serving with looks his sacred majesty;↵And having climb'd the steep-up heavenly hill,↵Resembling strong youth in his middle age,↵Yet mortal looks adore his beauty still,↵Attending on his golden pilgrimage:↵But when from highmost pitch, with weary car,↵Like feeble age, he reeleth from the day,↵The eyes, 'fore duteous, now converted are↵From his low tract, and look another way:↵So thou, thyself outgoing in thy noon:↵Unlook'd, on diest unless thou get a son.'                                                            }
    {'Music to hear, why hear'st thou music sadly?↵Sweets with sweets war not, joy delights in joy:↵Why lov'st thou that which thou receiv'st not gladly,↵Or else receiv'st with pleasure thine annoy?↵If the true concord of well-tuned sounds,↵By unions married, do offend thine ear,↵They do but sweetly chide thee, who confounds↵In singleness the parts that thou shouldst bear.↵Mark how one string, sweet husband to another,↵Strikes each in each by mutual ordering;↵Resembling sire and child and happy mother,↵Who, all in one, one pleasing note do sing:↵Whose speechless song being many, seeming one,↵Sings this to thee: 'Thou single wilt prove none.''}
    {'Is it for fear to wet a widow's eye,↵That thou consum'st thy self in single life?↵Ah! if thou issueless shalt hap to die,↵The world will wail thee like a makeless wife;↵The world will be thy widow and still weep↵That thou no form of thee hast left behind,↵When every private widow well may keep↵By children's eyes, her husband's shape in mind:↵Look! what an unthrift in the world doth spend↵Shifts but his place, for still the world enjoys it;↵But beauty's waste hath in the world an end,↵And kept unused the user so destroys it.↵No love toward others in that bosom sits↵That on himself such murd'rous shame commits.'                           }
    {'For shame! deny that thou bear'st love to any,↵Who for thy self art so unprovident.↵Grant, if thou wilt, thou art belov'd of many,↵But that thou none lov'st is most evident:↵For thou art so possess'd with murderous hate,↵That 'gainst thy self thou stick'st not to conspire,↵Seeking that beauteous roof to ruinate↵Which to repair should be thy chief desire.↵O! change thy thought, that I may change my mind:↵Shall hate be fairer lodg'd than gentle love?↵Be, as thy presence is, gracious and kind,↵Or to thyself at least kind-hearted prove:↵Make thee another self for love of me,↵That beauty still may live in thine or thee.'                     }

テキスト データのシーケンスへの変換

テキスト データを予測子用のベクトルのシーケンスと応答用の categorical シーケンスに変換します。

関数 categorical は、改行と空白のエントリを未定義として扱います。これらの文字の categorical 要素を作成するには、それぞれ特殊文字 "" (段落記号、"\x00B6") および "·" (中黒、"\x00B7") に置き換えます。あいまいさを避けるために、テキストに現れない特殊文字を選択しなければなりません。これらの文字は学習データに現れないため、この目的に使用できます。

newlineCharacter = compose("\x00B6");
whitespaceCharacter = compose("\x00B7");
textData = replace(textData,[newline " "],[newlineCharacter whitespaceCharacter]);

テキスト内の一意の文字から成るボキャブラリを作成します。

uniqueCharacters = unique([textData{:}]);
numUniqueCharacters = numel(uniqueCharacters);

テキスト データについてループし、各観測値の文字を表すベクトルのシーケンスと応答用の文字の categorical シーケンスを作成します。各観測値の終わりを表すために、特殊文字 "␃" (テキスト終結、"\x2403") を含めます。

endOfTextCharacter = compose("\x2403");
for i = 1:numel(textData)
    characters = textData{i};
    sequenceLength = numel(characters);
    
    % Get indices of characters.
    [~,idx] = ismember(characters,uniqueCharacters);
    
    % Convert characters to vectors.
    X = zeros(numUniqueCharacters,sequenceLength);
    for j = 1:sequenceLength
        X(idx(j),j) = 1;
    end
    
    % Create vector of categorical responses with end of text character.
    charactersShifted = [cellstr(characters(2:end)')' endOfTextCharacter];
    Y = categorical(charactersShifted);
    
    XTrain{i} = X;
    YTrain{i} = Y;
end

最初の観測値と、対応するシーケンスのサイズを表示します。シーケンスは DS 列の行列です。D は特徴次元 (一意の文字の数)、S はシーケンス長 (テキストの文字数) です。

textData{1}
ans = 
'From·fairest·creatures·we·desire·increase,¶That·thereby·beauty's·rose·might·never·die,¶But·as·the·riper·should·by·time·decease,¶His·tender·heir·might·bear·his·memory:¶But·thou,·contracted·to·thine·own·bright·eyes,¶Feed'st·thy·light's·flame·with·self-substantial·fuel,¶Making·a·famine·where·abundance·lies,¶Thy·self·thy·foe,·to·thy·sweet·self·too·cruel:¶Thou·that·art·now·the·world's·fresh·ornament,¶And·only·herald·to·the·gaudy·spring,¶Within·thine·own·bud·buriest·thy·content,¶And·tender·churl·mak'st·waste·in·niggarding:¶Pity·the·world,·or·else·this·glutton·be,¶To·eat·the·world's·due,·by·the·grave·and·thee.'
size(XTrain{1})
ans = 1×2

    61   610

対応する応答シーケンスを表示します。このシーケンスは、応答から成る 1 行 S 列の categorical ベクトルです。

YTrain{1}
ans = 1×610 categorical array
     r      o      m      ·      f      a      i      r      e      s      t      ·      c      r      e      a      t      u      r      e      s      ·      w      e      ·      d      e      s      i      r      e      ·      i      n      c      r      e      a      s      e      ,      ¶      T      h      a      t      ·      t      h      e      r      e      b      y      ·      b      e      a      u      t      y      '      s      ·      r      o      s      e      ·      m      i      g      h      t      ·      n      e      v      e      r      ·      d      i      e      ,      ¶      B      u      t      ·      a      s      ·      t      h      e      ·      r      i      p      e      r      ·      s      h      o      u      l      d      ·      b      y      ·      t      i      m      e      ·      d      e      c      e      a      s      e      ,      ¶      H      i      s      ·      t      e      n      d      e      r      ·      h      e      i      r      ·      m      i      g      h      t      ·      b      e      a      r      ·      h      i      s      ·      m      e      m      o      r      y      :      ¶      B      u      t      ·      t      h      o      u      ,      ·      c      o      n      t      r      a      c      t      e      d      ·      t      o      ·      t      h      i      n      e      ·      o      w      n      ·      b      r      i      g      h      t      ·      e      y      e      s      ,      ¶      F      e      e      d      '      s      t      ·      t      h      y      ·      l      i      g      h      t      '      s      ·      f      l      a      m      e      ·      w      i      t      h      ·      s      e      l      f      -      s      u      b      s      t      a      n      t      i      a      l      ·      f      u      e      l      ,      ¶      M      a      k      i      n      g      ·      a      ·      f      a      m      i      n      e      ·      w      h      e      r      e      ·      a      b      u      n      d      a      n      c      e      ·      l      i      e      s      ,      ¶      T      h      y      ·      s      e      l      f      ·      t      h      y      ·      f      o      e      ,      ·      t      o      ·      t      h      y      ·      s      w      e      e      t      ·      s      e      l      f      ·      t      o      o      ·      c      r      u      e      l      :      ¶      T      h      o      u      ·      t      h      a      t      ·      a      r      t      ·      n      o      w      ·      t      h      e      ·      w      o      r      l      d      '      s      ·      f      r      e      s      h      ·      o      r      n      a      m      e      n      t      ,      ¶      A      n      d      ·      o      n      l      y      ·      h      e      r      a      l      d      ·      t      o      ·      t      h      e      ·      g      a      u      d      y      ·      s      p      r      i      n      g      ,      ¶      W      i      t      h      i      n      ·      t      h      i      n      e      ·      o      w      n      ·      b      u      d      ·      b      u      r      i      e      s      t      ·      t      h      y      ·      c      o      n      t      e      n      t      ,      ¶      A      n      d      ·      t      e      n      d      e      r      ·      c      h      u      r      l      ·      m      a      k      '      s      t      ·      w      a      s      t      e      ·      i      n      ·      n      i      g      g      a      r      d      i      n      g      :      ¶      P      i      t      y      ·      t      h      e      ·      w      o      r      l      d      ,      ·      o      r      ·      e      l      s      e      ·      t      h      i      s      ·      g      l      u      t      t      o      n      ·      b      e      ,      ¶      T      o      ·      e      a      t      ·      t      h      e      ·      w      o      r      l      d      '      s      ·      d      u      e      ,      ·      b      y      ·      t      h      e      ·      g      r      a      v      e      ·      a      n      d      ·      t      h      e      e      .      ␃ 

LSTM ネットワークの作成と学習

LSTM アーキテクチャを定義します。隠れユニットが 200 個の sequence-to-sequence LSTM 分類ネットワークを指定します。学習データの特徴次元 (一意の文字の数) を入力サイズとして、応答に含まれるカテゴリの数を全結合層の出力サイズとして設定します。

inputSize = size(XTrain{1},1);
numHiddenUnits = 200;
numClasses = numel(categories([YTrain{:}]));

layers = [
    sequenceInputLayer(inputSize)
    lstmLayer(numHiddenUnits,'OutputMode','sequence')
    fullyConnectedLayer(numClasses)
    softmaxLayer
    classificationLayer];

学習オプションを指定します。学習エポックの回数を 500 に、初期学習率を 0.01 に指定します。勾配の発散を防ぐために、勾配のしきい値を 1 に設定します。

ミニバッチ サイズ オプションは、1 回の反復で処理する観測値の数を指定します。関数が学習のすべての観測値を確実に使用するように、データを均等に分割するミニバッチ サイズを指定します。そうでない場合、関数はミニバッチに収まっていない観測値を無視します。ミニバッチのサイズを 77 に設定します。

学習の進行状況を監視するには、'Plots' オプションを 'training-progress' に設定します。詳細出力を表示しないようにするには、'Verbose'false に設定します。

options = trainingOptions('adam', ...
    'MaxEpochs',500, ...
    'InitialLearnRate',0.01, ...
    'GradientThreshold',1, ...
    'MiniBatchSize',77,...
    'Plots','training-progress', ...
    'Verbose',false);

ネットワークに学習をさせます。

net = trainNetwork(XTrain,YTrain,layers,options);

新しいテキストの生成

学習データに含まれるテキストの最初の文字が従う確率分布から文字をサンプリングしてテキストの最初の文字を生成します。学習済み LSTM ネットワークを使用して、生成されたテキストの現在のシーケンスに基づいて次のシーケンスを予測し、残りの文字を生成します。ネットワークがテキスト終結文字を予測するまで、文字を 1 つずつ生成し続けます。

学習データに含まれる最初の文字の分布に従って、最初の文字をサンプリングします。関数 datasample には、Statistics and Machine Learning Toolbox™ が必要です。

initialCharacters = extractBefore(textData,2);
firstCharacter = datasample(initialCharacters,1);
generatedText = string(firstCharacter)
generatedText = 
"S"

ネットワークを使用して最初の予測を行うには、最初に生成された文字を表すベクトルを入力します。入力文字内にある生成された文字のインデックスを見つけて、ベクトルを作成します。

X = zeros(numUniqueCharacters,1);
idx = strfind(uniqueCharacters,firstCharacter);
X(idx) = 1;

残りの予測については、ネットワークの予測スコアに従って、次の文字をサンプリングします。予測スコアは次の文字の確率分布を表します。ネットワークの出力層のクラス名で与えられた文字のボキャブラリから文字をサンプリングします。

vocabulary = string(net.Layers(end).Classes);

predictAndUpdateState を使用して 1 文字ずつ予測します。

予測ごとに、前の文字のベクトルを入力します。ネットワークがテキスト終結文字を予測するか、生成されたテキストの長さが 500 文字になったら予測を停止します。データの大規模なコレクション、長いシーケンス、または大規模ネットワークの場合は、通常、GPU での予測の方が CPU での予測より計算時間が短縮されます。そうでない場合、通常、CPU での予測の計算の方が高速です。1 タイム ステップの予測には、CPU を使用します。予測に CPU を使用するには、predictAndUpdateState'ExecutionEnvironment' オプションを 'cpu' に設定します。

maxLength = 500;
while strlength(generatedText) < maxLength
    % Predict the next character scores.
    [net,characterScores] = predictAndUpdateState(net,X,'ExecutionEnvironment','cpu');
    
    % Sample the next character.
    newCharacter = datasample(vocabulary,1,'Weights',characterScores);
    
    % Stop predicting at the end of text.
    if newCharacter == endOfTextCharacter
        break
    end
    
    % Add the character to the generated text.
    generatedText = generatedText + newCharacter;
    
    % Create a new vector for the next input.
    X(:) = 0;
    idx = strfind(uniqueCharacters,newCharacter);
    X(idx) = 1;
end

特殊文字を対応する空白文字や改行文字に置き換えて、生成されたテキストを再構成します。

generatedText = replace(generatedText,[newlineCharacter whitespaceCharacter],[newline " "])
generatedText = 
    "Some way is their shadow that god;
     My moars thine engilsether! do not live:
     Hos noth now faith inseathed is on shane?
     That to thy me, thou desired tor better improasst,
     Which should I'le recoupt a thought
     enlessed ferb wretch to razed'
     That in my sube for Love's fire
     The world doth lie doth tile dost grow and heing;
     For then thou repard troush thy beauty of thy day;
     Then be of subslent fire by sin age's.
     How mised with manners when I to angermen'd no each,
     And that my expweriol, with me aftormmo"

複数のテキストを生成するには、resetState を使用して生成間のネットワークの状態をリセットします。

net = resetState(net);

参考

| | |

関連するトピック