ニューラルネットワークを使った列学習と自然言語処理

「列学習」とは,ニューラルネットを訓練して実行させることのできるさまざまな関連タスクを指す.これらのタスクに共通なのは,ネットへの入力がある種の列となっていることである.この入力は通常可変長である.つまり,ネットは短い列でも長い列でも同様にうまく動作するということである.
さまざまな列学習タスクを分けるのは,ネットの出力の形式である.出力の形式に従って,多様な方法がある.
このチュートリアルではこれらの手法のほとんどについて簡単な例を示す.
列の回帰

整数の加算

ここの例では,ネットは2桁の整数2つを足すよう訓練される.入力が数値ではなく数列であるのに対して出力は数値という点が難しいところである.例えば,ネットは入力"25+33"を取り,58に近い実数を返す必要がある.訓練データには長さ3 ("5+5"),長さ4 ("5+10"),長さ5 ("10+10")の例が含まれているので,入力は可変長である.
2桁の数の加算とそれに対応する数値結果を記述する列に基づいた訓練データを作成する:
入力列を読み込み数値結果を予測す一連の再帰層からなるネットを作成する:
ネットワークを訓練する:
入力のリストに,訓練されたネットワークを適用する:
列の分類

感情分析

映画評論記事の抜粋を"positive"あるいは"negative"として分類する分類子を訓練する.
まず訓練データと検証データを取得する:
入力として文字列を取り,"positive""negative"を返すネットを定義する:
2回の訓練ラウンドでネットを訓練する:
訓練されたネットを訓練集合からの例で評価して,その確率を得る:
Sequence-to-Sequence学習
Sequence-to-sequence学習は,入力と予測される出力の両方が列である学習タスクである.例えばドイツ語から英語への翻訳,音声ファイルからの書出し,数のリストの並べ替え等がこのタスクに当たる.

固定長の出力を伴う整数の加算

この例では入力として可変長の数列を取り,出力として固定長の数列を予測するネットの訓練方法を示す."250+123"等の総和を記述する文字列を取り,"373 "等の答を記述する文字列を生成する.
3桁の数の加算と,それに対応する結果の数列を記述する列に基づいた訓練データを作成する.出力が固定長になるために,すべての出力は最大で長さ4(999+999=1998であるため)になるよう充填される:
入力として列を取り,長さ4の別の列を返すネットを定義する:
40回の訓練ラウンドでネットを訓練する:
ネットを別の例に適用する:
訓練集合でネットの確度を求める:

可変長の出力を伴う整数の加算

ここでは,入出力が両方とも可変長の数列であり,それらが同一ではない文字列でネットを訓練する方法を説明する.このタスクの高度な例として,英語をドイツ語に翻訳するというものがあるが,ここではもっと単純に,"250+123"等の総和を記述する数列を取り,"373"等の答を記述する出力数列を生成するというものにする.使用されるメソッドはI. Sutskeverその他による2014年の論文「Sequence to Sequence Learning with Neural Networks」を基にしている.
3桁の加算とそれに対応する列としての結果を記述する列に基づく訓練データを作成する:
列の最初と最後に特別なコードを使うNetEncoderを作成する.これは出力列の最初と最後を示すのに使われる:
エンコーダを入力列で評価する:
「+」を含む入力について同様のエンコーダを作成する:
入力列を取り,出力としてサイズ150の単独のベクトルを返すネットを定義する:
入力としてサイズ150の入力ベクトルおよびベクトルの列を取り,出力としてベクトルの列を返すネットを定義する:
CrossEntropyLossLayerおよびエンコーダネットとデコーダネットを持つネットを定義する:
ネットを訓練する(この手順は「教師強制」と言われることもよくある):
このような3桁の整数の加算の場合,可能な出力は1999通りしかない.それぞれの可能な出力に対する損失を計算し,損失を最小限にする出力を見付けることが可能である:
入力の数と訓練されたネットが与えられた場合の出力を予測する:
入力が与えられたときの各出力に対する損失を可視化することもできる:
より効率的に予測を求めるには,EndOfString仮想文字に達するまで出力を生成し続ける.
まず訓練されたNetGraphから,訓練された「エンコーダ」と「デコーダ」のサブネットを抽出し,適切なエンコーダとデコーダを加える:
SequenceLastLayerを使って,前の文字が与えられたときに答の最後の文字だけを予測するデコーダのバージョンを作成する.「ターゲット」入力と同じアルファベットを使って,確率ベクトルの文字デコーダが追加される:
部分的な答にデコーダを適用する:
デコーダがターゲットの列の最後を予測すると,空の列が生成される:
ここで「エンコーダ」ネット,「デコーダ」ネット,入力列を取る予測関数を定義する.デコーダが終了するまで,関数は継続してより長い結果を計算する:
この予測関数を入力データで評価する:
これは,厳密な最尤推定を求める最初の方法の近似値である:
次の文字を得るためにそれぞれの部分的な答をデコーダに渡すことによって生成する初歩的な方法には,n2の時間的コストがある.ここでn は出力の長さであるため,長い列の生成には適さない.NetStateObjectを使うと n の時間的コストを伴って生成することができる.
まず,1文字を取り次の文字を予測するデコーダを生成する.GatedRecurrentLayerの回帰状態は,後の時点でNetStateObjectによって処理される.
訓練されたネットから,訓練されたGatedRecurrentLayerLinearLayerを取得する:
列の最初と最後を示す特殊クラスだけでなく,各文字を符号化および復号化する「クラス」エンコーダおよびデコーダを定義する:
1文字を取り,GatedRecurrentLayerを1ステップ実行し,1つのsoftmax予測を生成するネットを定義する:
この予測子は,Informationで分かるように,内部的な回帰状態を持っている:
訓練されたエンコーダによって生成されるコードから種を播かれるNetStateObjectを使って内部的な再帰状態を記憶する関数を生成する:
いくつかの入力にこの関数を適用し,予測される列を得る:
テスト集合での訓練されたネットの確度を求める:

整数の並べ替え

この例では,ネットを訓練して整数のリストを並べ替える.例えば,ネットは入力{3,2,4}を取って{2,3,4}を返さなければならないのである.この例は,多数の数列学習タスクにおけるニューラルネットの性能を大きく向上させるAttentionLayerの使い方も示す.
1から6までの整数のリストからなる訓練集合と検証集合を作成する:
訓練集合から無作為抽出された3つのサンプルを表示する:
AttentionLayerを持つNetGraphを定義する:
ネットを訓練する:
ネットを使って整数のリストを並べ替える:

Toyデータセットの光学文字認識(OCR)

光学文字認識問題では,文字列を含む画像を取り,文字のリストを返す.その方法の例として,1つの文字だけを含む画像を生成するために画像を前処理し,分類を行うというものがある.これは不安定な方法であり,文字がくっついている筆記体等では全くうまくいかない.
まず文字の画像とそれに対応する文字列からなる訓練データと検証データを生成する:
データ集合を検証集合と訓練集合に分ける:
訓練集合のRandomSampleを取る:
使用される文字のリスト:
このデコーダは,ビームサイズが50のビームサーチデコーダである:
1つの画像を取り,幅の次元を列の次元とするネットを定義する.幅の次元上の確率ベクトルの列が生成される:
ターゲットポートに文字のNetEncoderが加わったCTCLossLayerを定義する:
CTC損失を使ってネットを訓練する:
訓練されたネットを検証集合の画像で評価する:
画像のデコーディングのトップから5つと,それぞれのデコーディングに対する負の対数尤度を求める:
質問応答

bAbI QAデータセットで訓練された回帰型ニューラルネットワークのサンプル

再帰型ネットワークを使って,bAbI QAデータセットの最初のタスク(Single Supporting Fact)で質問応答ネットを訓練する.
まず訓練データと検証データを取得する:
使用されるクラスのリストと,質問およびコンテキストに使われる辞書を取得する:
質問の列とコンテキストの列を取り,応答を返すネットを定義する:
ネットワークを三回の訓練ラウンドで訓練する.NetTrainはデコーダに提供されたのと同じクラスを使って自動的にCrossEntropyLossLayerを追加する:
訓練されたネットを使って予測を行う:
検証集合での訓練されたネットの確度を求める:

bAbI QAデータセットで訓練されたメモリネットワーク

Sukhbaatarらによる2015年の論文「End-to-End Memory Networks」に基づいたメモリネットワークを使って,bAbI QAデータセットの最初のタスク(Single Supporting Fact)で質問応答ネットを訓練する.
まず訓練データと検証データを取得する:
メモリネットには可変長の例を現在サポートしない層(TransposeLayer等)がある.
すべての列をトークンのリストに変換し,これらのリストが同じ長さになるように左充填(この例では右充填より性能がよい)を行う:
"Context"入力はPaddingシンボルで充填された,長さ68のリストになった.
使用されるクラスのリスト,および質問とコンテキストに使われる辞書を取得する:
ネットを定義する:
この例の学習性能を向上させる"RMSProp"最適化法を使ってネットを訓練する:
検証データにおけるネットの確度を求める:
言語モデル

文字レベルの言語モデル

英語の文字レベルの言語モデルを訓練する.
まず2つの小説それぞれから25文字の訓練例題30万個を作成する:
このデータは,文字列が与えられると次の文字を予測するという分類問題の形式である.以下はデータのサンプルである:
テキスト中のすべての文字のリストを得る:
文字列を取り,次の文字の予測を返すネットを定義する:
ネットを訓練する.これはCPUでは最大1時間かかるので,NVIDIAグラフィックスカードが利用できる場合はTargetDevice->"GPU"を使う.最近のGPUではこの例は訳7分で完了する:
文字列が与えられたときに次の文字を予測する:
最初のテキストが与えられたときに,次のテキスト100文字を生成する.この方法では,長い文字列を効率よく生成するためにNetStateObjectを使っている:
予測の確率分布から抽出することで,もっとおもしろいテキストが得られることがある:
入力として1つの文字列だけを必要とするこの学習問題の別の形式として,ネット内部の残りの文字列から最後の文字を分離させるというものがある.
グラフでSequenceMostLayerSequenceLastLayerを使って,最後の文字を他から切り離す:
もとの訓練データの入力文字列でこのネットを訓練する(つまり,ネットをわずかに短い列で訓練するということである):
言語モデルをより効率的に訓練するためには,「教師強制」を使う.この方法では,ネットは最後の文字ではなく,文字列全体を同時に予測する.
まず文字列全体を同時に予測するネットを構築する.このネットは,最後の要素を取って通常のベクトルソフトマックスを実行する代りに,LinearLayerがマップされ,行列のソフトマックスが実行されるという点で,先ほどの予測ネットと異なる:
ターゲットの文を取り,それをずらしてネットワークに提示する強制ネットワークを構築する.長さ26の文の場合,1から25までの文字をネットに提示し,ネットが文字2から26までの予測を行うようにするのである.この予測はCrossEntropyLossLayerを使って実際の文字と比較され損失が計算される:
もとのデータの入力列でネットを訓練する.通常のCPUでは15分程度かかるが,最近のGPUでは2分しかかからない.教師強制はより効率的な方法なので,訓練ラウンドの回数は少なくてもよい:
結果から一連の予測を抽出する:
それから一連の1文字予測を構築する:
予測子を検証する:
最初のテキストが与えられたときに,テキスト100文字を生成する.この方法では,長いテキスト列を効率的に生成するためにNetStateObjectが使われる:
予測の確率分布から抽出すると,もっとおもしろいテキストを得ることができる: