Introduction
Sequence prediction problem has been around long time. データサイエンス業界で最も解決が難しい問題の1つとされています。 売上の予測から株式市場のデータのパターンの発見、映画のプロットの理解から話し方の認識、言語翻訳から iPhone のキーボードでの次の単語の予測まで、さまざまな問題が含まれます。
データサイエンスにおける最近のブレークスルーにより、これらのシーケンス予測問題のほとんどすべてにおいて、Long Short Term Memory ネットワーク、別名 LSTM が最も効果的なソリューションとして観察されていることが分かりました。 これは、長い時間にわたってパターンを選択的に記憶する性質があるからです。 この記事の目的は、LSTMを説明し、実際の問題で使用できるようにすることです。 それでは、見ていきましょう!
注意: 記事を読み進めるには、ニューラルネットワークと Keras (深層学習ライブラリ) の仕組みに関する基本的な知識が必要です。 これらの概念を理解するために、以下の記事を参照することができます:
- Understanding Neural Network From Scratch
- Fundamentals of Deep Learning – Introduction to Recurrent Neural Networks
- Tutorial: Kerasを使ったニューラルネットワークの最適化(画像認識事例あり)
目次
- Flashback: RNN(Recurrent Neural Networks)への考察
- RNNの限界
- RNNに対する改善点: Long Short Term Memory (LSTM)
- LSTMのアーキテクチャ
- Forget Gate
- Input Gate
- Output Gate
- LSTMによるテキスト生成。
フラッシュバック。 RNN(Recurrent Neural Networks)を見てみる
逐次データを例にとると、特定の銘柄の株式市場のデータであることがあります。 単純な機械学習モデルや人工ニューラルネットワークは、株価の出来高、始値など、いくつかの特徴に基づいて株価を予測することを学習します。 株価はこれらの特徴に依存しますが、前日の株価にも大きく依存します。 実際、トレーダーにとって、前日の値(またはトレンド)は予測のための1つの大きな決定要因です。
従来のフィードフォワードニューラルネットワークでは、すべてのテストケースは独立していると見なされます。 つまり、ある日のモデルを当てはめるとき、前の日の株価は考慮されない。
この時間に対する依存性は、リカレントニューラルネットワークによって達成される。 典型的な RNN は次のようになります:
これは一見すると威圧的ですが、一度展開するとずっとシンプルに見えます:
ここで、これらのネットワークが今日の株価を予測する前に株価のトレンドをどのように考慮しているかを視覚化することが容易になります。 ここで、時間tにおけるすべての予測(h_t)は、以前のすべての予測とそれらから学習された情報に依存している。
RNNは我々の目的であるシーケンス処理をかなりの程度解決してくれるが、完全ではない。 私たちはコンピュータがシェイクスピアのソネットを書くのに十分な性能を持つことを望んでいます。 RNNは短い文脈に関しては素晴らしいが、物語を構築し、それを記憶するためには、人間の脳のように、シーケンスの背後にある文脈を理解し記憶できるモデルが必要である。 これは単純なRNNでは不可能です。
なぜでしょうか。
Limitations of RNNs
Recurrent Neural Networks は、短期的な依存関係を扱う場合にうまく機能します。 それは、次のような問題に適用した場合です:
RNN はかなり効果的であることが判明しています。 というのは、この問題は文の文脈とは関係ないからである。 RNNはこの前に何が言われたのか、その意味は何だったのかを覚えている必要はなく、ほとんどの場合、空は青いということだけを知っていればいいのです。 したがって、予測は次のようになる。
しかし、バニラRNNは入力の背後にある文脈を理解することができない。 ずっと前に言われたことを、現在の予測をするときに思い出すことができないのです。 例として、
ここで、著者はスペインで20年間働いていたので、スペイン語に長けている可能性が高いと理解することができます。 しかし、適切な予測をするために、RNNはこの文脈を覚えておく必要があります。 しかし、RNNが適切な予測を行うためには、この文脈を記憶しておく必要があります。 これがリカレントニューラルネットワークの失敗です!
この背景には、Vanishing Gradientという問題があります。 これを理解するためには、フィードフォワードニューラルネットワークがどのように学習するのかについて、ある程度の知識が必要になります。 従来のフィードフォワードニューラルネットワークでは、特定の層で適用される重みの更新は、学習率、前の層からの誤差項、その層への入力の倍数であることが分かっています。 したがって、特定の層の誤差項は、どこか以前のすべての層の誤差の積である。 シグモイド関数のような活性化関数を扱う場合、その微分値(誤差関数に含まれる)は、開始層に向かうにつれて何倍にもなっていく。 その結果、開始層に向かうにつれて勾配がほとんどなくなり、これらの層の学習が困難になります。
同様のケースはRecurrent Neural Networksでも見られます。 RNNはわずかな時間だけ物事を記憶する。つまり、わずかな時間後に情報が必要になった場合は再現可能かもしれないが、多くの単語が入力されると、この情報はどこかで失われてしまうのである。 この問題は、RNNに少し手を加えたLong Short-Term Memory Networksを適用することで解決できます。
RNNに対する改善点 LSTM (Long Short-Term Memory) Networks
私たちが1日のカレンダーをアレンジするとき、予定に優先順位をつけますよね? もし、何か重要なことのためにスペースを確保する必要がある場合、可能な会議を収容するためにどの会議がキャンセルされる可能性があるか知っています。
RNNはそうしないことがわかりました。 新しい情報を追加するために、関数を適用することによって既存の情報を完全に変換するのです。 このため、情報全体が全体的に変更される。つまり、「重要な情報」と「そうでない情報」の区別が考慮されない。
LSTMは、乗算や加算によって情報を小さく修正する。 LSTMでは、情報はセルステートと呼ばれる仕組みで流れます。 こうすることで、LSTMは選択的に物事を記憶したり、忘れたりすることができる。 あるセル状態での情報は、3つの異なる依存性を持っている。
これを例で可視化します。 ある銘柄の株価を予測することを例にしてみよう。 今日の株価は、以下のように依存します。
- 前日までの株価のトレンド(下降トレンドか上昇トレンドか)
- 前日の株価(多くのトレーダーは買う前に前日の株価を比較するから)
- 今日の株価に影響を与える可能性がある要因。 それは、会社の新しい方針が大きく批判されることであったり、会社の利益が減少することであったり、あるいは会社の上層部が予想外に変化することであったりします。
これらの依存関係は、以下のように任意の問題に一般化できます:
- 前のセルの状態(すなわち、前の時間ステップの後にメモリに存在していた情報)
- 前の隠された状態(すなわち、前の時間ステップの後にメモリに存在していた情報)。 これは前のセルの出力と同じ)
- 現在の時間ステップでの入力(すなわち、その瞬間に投入される新しい情報)
LSTMのもう一つの大きな特徴は、ベルトコンベアと類似していることです
その通りです!
産業界では、工程ごとに製品を移動させるために使用されています。 LSTMはこの仕組みを利用して、情報を移動させるのです。
製品がベルトコンベアに乗っている間に成形されたり、塗装されたり、梱包されたりするように、異なる層を流れている間に、情報の追加、変更、削除があるかもしれません。
次の図は、LSTM とコンベヤベルトの密接な関係を説明しています。
Source
この図は実際の LSTM のアーキテクチャに近くもありませんが、今のところはこれで目的を達成できます。
ちょうどこの、情報全体を操作せずわずかに変更するという LSTM の特性のおかげで、物事を忘れたり記憶したり選択的にできるようになったのです。
LSTMのアーキテクチャ
LSTMの機能は、ある殺人事件を取材するニュースチャンネルのチームの機能を理解することで視覚化することができます。 さて、ニュース記事は事実、証拠、多くの人の発言で成り立っている。 新しいイベントが発生するたびに、3つのステップのいずれかを踏みます。
例えば、私たちは殺人が被害者に「毒」を飲ませて行われたと仮定していましたが、ちょうど入ってきた検死報告によると、死因は「頭部への衝撃」であったとします。 この報道チームの一員であるあなたはどうするか? 前の死因も、その事実の周りに織り込まれていたストーリーも、すぐに忘れてしまいます。
もし、まったく新しい容疑者が登場したらどうでしょう。 被害者に恨みを持つ人物が犯人である可能性は? この情報をニュースフィードに入力しますよね。
さて、これらの壊れた情報のすべては、主流メディアに提供することはできないのです。 そこで、ある時間間隔をおいて、この情報を要約し、関連するものを視聴者に出力する必要があります。
では、LSTM ネットワークのアーキテクチャの詳細について説明します:
Source
さて、これは前に見た簡易版に近いですが、説明しましょう。 典型的なLSTMネットワークはセル
(画像に見える長方形)と呼ばれる異なるメモリブロックで構成されている。 次のセルに転送される状態は、セルの状態と隠れた状態の2つである。 メモリブロックは物事を記憶する役割を担っており、このメモリに対する操作は、ゲートと呼ばれる大きく3つの機構で行われる。
4.1 Forget Gate
テキスト予測問題を例にとると、以下のようになります。 LSTMに次の文が入力されたとする。
「人」の後の最初のフルストップに遭遇するとすぐに、忘れ物ゲートは次の文に文脈の変化があるかもしれないと認識する。 その結果、その文の主語は忘れられ、主語の場所が空く。 そして、「ダン」について話し始めると、この主語の位置は「ダン」に割り当てられる。 この主語を忘れるプロセスは、忘却ゲートによってもたらされる。
忘却ゲートは、細胞の状態から情報を除去する役割を担っている。 LSTMが物事を理解するために不要になった情報や重要度の低い情報は、フィルタの掛け算によって取り除かれる。 これは、LSTMネットワークの性能を最適化するために必要である。
このゲートはh_t-1とx_tの2つの入力を受け取る。
h_t-1は前のセルからの隠れ状態または前のセルの出力、x_tはその特定の時間ステップの入力である。 与えられた入力は重み行列に掛けられ、バイアスが加えられる。 これに続いて、シグモイド関数がこの値に適用される。 シグモイド関数はセル状態の各数値に対応する 0 から 1 までの値を持つベクトルを出力する。 基本的にシグモイド関数は、どの値を残し、どの値を捨てるかを決定する役割を担っている。 もしセル状態の特定の値に対して「0」が出力されたら、それは忘却ゲートがセル状態にその情報を完全に忘れさせたいことを意味する。 同様に、「1」は、忘却ゲートがその情報全体を記憶しておきたいことを意味する。 このシグモイド関数から出力されるベクトルはセルの状態に乗算される。
4.2 Input Gate
さて、LSTMが文章を分析する別の例を見てみよう。
ここで重要な情報は、「ボブ」は水泳を知っており、4年間海軍に所属していることである。 これはセルの状態に追加することができますが、しかし、彼が電話でこのすべてを話したという事実はあまり重要でない事実であり、無視することができます。
入力ゲートはセル状態に情報を追加する役割を担っています。
- シグモイド関数を用いて、どのような値をセルの状態に追加する必要があるかを調整する。 これは基本的に忘却ゲートに非常に似ており、h_t-1とx_tからのすべての情報に対するフィルタとして機能する。
- セル状態に追加できる(h_t-1とx_tから知覚される)すべての可能な値を含むベクトルを作成すること。 これはtanh関数を用いて行われ、-1から+1までの値を出力する。
- 作成したベクトル(tanh関数)に調節フィルタ(シグモイドゲート)の値を乗算し、この有用な情報を加算操作によって細胞の状態に加える。
この3段階のプロセスが行われると、重要で冗長ではない情報だけが細胞の状態に加えられることを保証します。
4.3 出力ゲート
細胞の状態に沿って流れる情報のすべてが、ある時点で出力されるのに適しているとは限りません。
このフレーズでは、空いたスペースにいくつかのオプションがある可能性があることを視覚化する。 しかし、現在の入力である「勇敢な」は、名詞を説明するために使用される形容詞であることが分かっています。 したがって、どのような単語が続いても、名詞になる傾向が強くなります。
このように、現在の細胞の状態から有用な情報を選択し、出力として示すという仕事は、出力ゲートを介して行われます。 その構造は次の通りです。
出力ゲートの機能は、再び3つのステップに分解することができます:
- セル状態にtanh関数を適用してベクトルを作成し、それによって値を-1〜+1の範囲にスケーリングします。
- h_t-1とx_tの値を用いて、上記で作成したベクトルから出力すべき値を調整するようなフィルタを作成する。 このフィルタもシグモイド関数を用いる。
- この調節フィルタの値を手順1で作成したベクトルに乗算し、出力として送り出すとともに、次のセルの隠れ状態にも送る。
上の例のフィルタは、「ボブ」以外の値を必ず減少させるようにする。
LSTMを用いたテキスト生成
ここまでで、LSTMの理論的な概念と機能については十分理解できたと思います。 今度は、マクベスの原文の後に、あるn個の文字を予測できるモデルを構築しようとすることになる。 古典のテキストのほとんどは著作権で保護されなくなったので、こちらで見ることができます。
私たちは Keras ライブラリを使用します。これは、ニューラルネットワーク用の高レベル API であり、TensorFlow または Theano の上で機能します。 そのため、このコードに飛び込む前に、Keras がインストールされ、機能していることを確認してください。
それでは、テキストを生成しましょう!
-
Importing dependencies
# Importing dependencies numpy and kerasimport numpyfrom keras.models import Sequentialfrom keras.layers import Densefrom keras.layers import Dropoutfrom keras.layers import LSTMfrom keras.utils import np_utils
We import all the required dependencies and this is pretty much self-explanately.
-
テキスト ファイルの読み込みと、文字と整数のマッピングの作成
# load textfilename = "/macbeth.txt"text = (open(filename).read()).lower()# mapping characters with integersunique_chars = sorted(list(set(text)))char_to_int = {}int_to_char = {}for i, c in enumerate (unique_chars): char_to_int.update({c: i}) int_to_char.update({i: c})
テキスト ファイルを開き、すべての文字を小文字に変換しています。 次のステップを容易にするために、各文字をそれぞれの数値に対応させることにする。 これは、LSTM の計算部分を簡単にするために行います。
-
Preparing dataset
# preparing input and output datasetX = Y = for i in range(0, len(text) - 50, 1): sequence = text label =text X.append( for char in sequence]) Y.append(char_to_int)
データは、LSTM に ‘HELLO’ の ‘O’ を予測したい場合、入力としてフィードイン、予想出力として出力するフォーマットで準備されています。 同様に、ここでは必要なシーケンスの長さ(例では50に設定)を固定し、最初の49文字のエンコーディングをXに、期待される出力、つまり50文字目をYに保存します。
-
Reshaping of X
# reshaping, normalizing and one hot encodingX_modified = numpy.reshape(X, (len(X), 50, 1))X_modified = X_modified / float(len(unique_chars))Y_modified = np_utils.to_categorical(Y)
LSTM ネットワークは、入力が samples はデータ ポイント数、time steps は単一のデータ ポイントにある時間依存のステップ数、 features は Y で対応する真値に対して持つ変数の数という形式であることを期待する。
-
LSTM モデルの定義
# defining the LSTM modelmodel = Sequential()model.add(LSTM(300, input_shape=(X_modified.shape, X_modified.shape), return_sequences=True))model.add(Dropout(0.2))model.add(LSTM(300))model.add(Dropout(0.2))model.add(Dense(Y_modified.shape, activation='softmax'))model.compile(loss='categorical_crossentropy', optimizer='adam')
階層の線形スタックである逐次モデルが使用されます。 最初の層は300のメモリユニットを持つLSTM層で、シーケンスを返す。 これは、次のLSTM層がランダムに散らばったデータではなく、シーケンスを受け取ることを保証するために行われます。 各LSTM層の後にドロップアウト層が適用され、モデルのオーバーフィッティングを回避する。 最後に、最後の層は「ソフトマックス」活性化、ユニークな文字の数と同じニューロンを持つ完全連結層としています。これは、ホットエンコードされた結果を1つ出力する必要があるからです。
-
モデルのフィットと文字の生成
# fitting the modelmodel.fit(X_modified, Y_modified, epochs=1, batch_size=30)# picking a random seedstart_index = numpy.random.randint(0, len(X)-1)new_string = X# generating charactersfor i in range(50): x = numpy.reshape(new_string, (1, len(new_string), 1)) x = x / float(len(unique_chars)) #predicting pred_index = numpy.argmax(model.predict(x, verbose=0)) char_out = int_to_char seq_in = for value in new_string] print(char_out) new_string.append(pred_index) new_string = new_string
モデルはバッチサイズ30で100エポックにわたってフィットされる。 その後、ランダムな種を固定し(再現性を高めるため)、文字の生成を開始する。 モデルからの予測は、予測された文字の文字エンコーディングを出し、それを文字値にデコードしてパターンに付加します。
ネットワークの出力はこのようになります。
最終的には、十分な学習エポックを経て、時間とともにより良い結果を得られるようになります。 これは、シーケンス予測タスクを解決するために LSTM を使用する方法です。
End Notes
LSTM はシーケンスおよび時系列関連の問題に対する非常に有望な解決策です。 しかし、私が見つけた欠点は、それらを訓練するのが難しいということである。 単純なモデルの学習でさえ、多くの時間とシステムリソースが費やされます。 しかし、これはあくまでもハードウェアの制約なのです このようなネットワークについて、基本的な理解を深めていただければ幸いです。
学んで、取り組んで、ハックして、採用されよう!
。