RNNを使用した基本的な数学方程式の解法[コーディング例付き]
公開: 2020-12-07人生があなたにRNNを与えるなら、計算機を作ってください
リカレントニューラルネットワークは、ノード間の接続が順次有向グラフを形成する、古典的な人工ニューラルネットワークの1つです。 RNNは、可変長シーケンスを処理するための内部状態メモリがあるため、音声認識、手書き認識などのアプリケーションで有名です。
RNNはさらに2つのタイプに分類されます。 1つ目は有限インパルスであり、そのニューラルネットワークは有向非巡回グラフの形式であり、1つのノードを、ネットワーク内に目に見えるサイクルがなく、前方にある1つ以上のノードに接続できます。 もう1つは、ニューラルネットワークがフィードフォワードニューラルネットワークに展開できない有向非巡回グラフの形式である無限インパルスです。
目次
私たちは何をするつもりですか?
算術式の出力を予測するモデルを作成しましょう。 たとえば、入力に「11 + 88」を指定すると、モデルはシーケンス内の次の単語を「99」として予測する必要があります。 RNNはシーケンシャルデータを処理するため、入力と出力は文字のシーケンスです。
データセットコレクションと比較すると、モデルのアーキテクチャの設計は簡単な作業のように見えます。 データを必要とするAIモデルは、許容できる精度を得るためにかなりの量のデータを必要とするため、データの生成やデータセットの収集は大変な作業です。
したがって、このモデルは6つの基本的なステップで実装できます。

- データの生成
- モデルの構築
- データのベクトル化とベクトル化解除
- データセットの作成
- モデルのトレーニング
- モデルのテスト
モデルの実装に取り掛かる前に、必要なすべてのライブラリをインポートしましょう。
numpyをnpとしてインポートします tensorflowをtfとしてインポートします tensorflow.keras.modelsからインポートシーケンシャル tensorflow.keras.layersからDense、Dropout、SimpleRNN、RepeatVector、TimeDistributedをインポートします tensorflow.keras.callbacksからEarlyStopping 、 LambdaCallbackをインポートします termcolorからインポートカラー |
1.データの生成
基本的な算術方程式を書くために必要なすべての文字を含むchar文字列を定義しましょう。 したがって、文字列は0〜9のすべての文字と、/、*、+、-、。(10進数)などのすべての算術演算子で構成されます。
数値データをモデルに直接フィードすることはできません。データをテンソルの形式で渡す必要があります。 データ内の文字列をワンホットエンコードされたベクトルに変換すると、モデルのパフォーマンスが最適化されます。 ワンホットエンコードされたベクトルは、char文字列の長さと同じ長さの配列であり、各ワンホットベクトルには、各文字列に存在する文字のそれぞれのインデックスにのみ1つがあります。
たとえば、文字列が「0123456789」であり、「12」のような文字列をエンコードする場合、ワンホットベクトルは[[0,1,0,0,0,0,0,0 、0,0]、[0,0,1,0,0,0,0,0,0,0]]。 これを行うには、1つのインデックスをキーとして、もう1つを値として、もう1つをその逆として2つの辞書を作成する必要があります。
char_string = ' 0123456789 /*+-。 ' num_chars = len (char_string) character_to_index = dict ((c、i) for i、c in enumerate (char_string)) index_to_character = dict ((i、c) for i、c in enumerate (char_string)) |
次に、ランダムな算術方程式とその方程式の結果を返す関数を作成しましょう。
def Division (n、d): d != 0else0の場合はn / dを返します def datagen (): random1 = np.random.randint(low = 0 、high = 100 ) random2 = np.random.randint(low = 0 、high = 100 ) op = np.random.randint(low = 0 、high = 4 ) op == 1の場合: arith = str (random1) + ' + ' + str (random2) res = str ( random1 + random2) elif op == 1 : arith = str (random1) + ' – ' + str (random2) res = str ( random1 – random2) elif op == 2 : arith = str (random1) + ' * ' + str (random2) res = str ( random1 * random2) その他: arith = str (random1) + ' / ' + str (random2) res = str ( round (division(random1、random2)、 2 )) arith、resを返す |
また読む:興味深いニューラルネットワークプロジェクトのアイデア
2.モデルの構築
モデルには、エンコーダーとデコーダーがあります。 エンコーダーは、入力形状が(None、num_chars)で128の非表示ユニットを持つ単純なRNNモデルです。非表示ユニットを32、64、128などとして選択する理由は、非表示ユニットを次の累乗として使用するCPUまたはGPUのパフォーマンスが向上するためです。 2.2。
私たちのエンコーダーは完全に接続されたネットワークになり、これらの出力はネットワークにフィードバックされます。これがRNNの仕組みです。 RNNレイヤーはデフォルトで「tanh」アクティベーションを使用します。エンコーダーに最適であるため、変更しません。 このレイヤーの出力は単一のベクトルになり、出力全体の単一のベクトルを取得するには、パラメーターとして必要な回数だけRepeatVector()レイヤーを使用します。
これで、出力ベクトルは指定された入力のエッセンスを持ち、このベクトルはデコーダーに供給されます。
デコーダーは単純なRNNレイヤーで構成されており、予測されたシーケンスを返すためにRNNレイヤーが必要なため、これにより出力シーケンスが生成されます。「return_sequences」にTrueのフラグを立てます。 'return_sequences'をTrueとして割り当てることにより、RNNレイヤーは各タイムステップ(多対多のRNN)の予測シーケンスを返します。
このRNNレイヤーの出力は、「num_chars」個の非表示ユニットを持つDenseレイヤーに送られます。各文字の確率が必要なため、softmaxアクティベーションを使用します。 Denseレイヤーをデプロイする前に、このレイヤーをTimeDistributedレイヤーにブリッジする必要があります。これは、各タイムステップの出力用にDenseレイヤーをデプロイする必要があるためです。
hidden_units = 128 max_time_steps = 5 #出力を5文字にハードコーディングしています def model (): モデル= Sequential() model.add(SimpleRNN(hidden_units、input_shape = ( None 、num_chars))) model.add(RepeatVector(max_time_steps)) model.add(SimpleRNN(hidden_units、return_sequences = True )) model.add(TimeDistributed(Dense(num_chars、activation = ' softmax ' ))) リターンモデル model = model() model.summary() model.compile(loss = ' categorical_crossentropy ' 、optimizer = ' adam ' 、metrics = [ ' accuracy ' ]) |
モデルのアーキテクチャは上記のようになります
必読:ニューラルネットワークチュートリアル
3.データのベクトル化と非ベクトル化
データをベクトル化および非ベクトル化するための関数を定義しましょう。
算術式と結果を一緒にベクトル化する関数は次のとおりです。
def vectorize (arith、res): x = np.zeros((max_time_steps、num_chars)) y = np.zeros((max_time_steps、num_chars)) ![]() x_remaining = max_time_steps – len (arith) y_remaining = max_time_steps – len (res) for i、c in enumerate (arith): x [x_remaining + i、character_to_index [c]] = 1 範囲内のiの場合(x_remaining): x [i、character_to_index [ ' 0 ' ]] = 1 for i、c in enumerate (res): y [y_remaining + i、character_to_index [c]] = 1 範囲内のiの場合(y_remaining): y [i、character_to_index [ ' 0 ' ]] = 1 x、yを返す |
同様に、文字列を非ベクトル化するための関数があります。 受け取る出力は確率のベクトルであるため、np.argmax()を使用して最も確率の高い文字を選択します。 これで、index_to_characterディクショナリを使用して、そのインデックスの文字をさかのぼることができます。
def devectorize (入力): res = [index_to_character [np.argmax(vec)] for i、vec in enumerate ( input )] return ' ' .join(res) |
'devectorize'関数での制約は、末尾の文字をゼロで埋めることです。 たとえば、入力ベクトルが( '1-20'、'-19')の場合、ベクトル化解除された出力は(' 01-20'、' 00-19')になります。 これらの余分なパッド付きゼロを処理する必要があります。 文字列を削除する関数を書いてみましょう。
defストリッピング(入力): フラグ= False 出力= ' ' 入力のcの場合: フラグがなく、 c == ' 0 'の場合: 継続する if c == ' + 'またはc == ' – 'またはc == ' * 'またはc == ' / 'またはc == ' 。 ' : フラグ= False その他: フラグ= True 出力+= c 出力を返す |
4.データセットの作成
データを生成するための関数の定義が完了したので、その関数を使用して、そのような(算術式、結果)のペアが多数あるデータセットを作成しましょう。
def create_dataset (num_equations): x_train = np.zeros((num_equations、max_time_steps、num_chars)) y_train = np.zeros((num_equations、max_time_steps、num_chars)) 範囲内のiの場合(num_equations): e、l = datagen() x、y = vectorize(e、l) x_train [i] = x y_train [i] = y x_train、y_trainを返します |
5.モデルのトレーニング
データハンガーモデルをトレーニングするための適切な数である50,000サンプルのデータセットを作成しましょう。このデータの25%を検証に使用します。 また、精度が8エポックの間変わらない場合は、インテリジェントトレーニング中断のコールバックを作成しましょう。 これは、忍耐パラメータを8に設定することで実現できます。

x_train、y_train = create_dataset( 50000 ) simple_logger = LambdaCallback( on_epoch_end = lambda e、l: print ( ' {:.2f} ' .format(l [ ' val_accuracy ' ])、end = ' _ ' ) )。 Early_stopping = EarlyStopping(monitor = ' val_loss ' 、patience = 8 ) model.fit(x_train、y_train、epochs = 100 、validation_split = 0.25 、verbose = 0 、 コールバック= [simple_logger、early_stopping]) |
6.モデルのテスト
次に、サイズ30のデータセットを作成して、モデルをテストしましょう。
x_test、y_test = create_dataset(num_equations = 20 ) preds = model.predict(x_test) full_seq_acc = 0 for i、pred in enumerate (preds): pred_str = stripping(devectorize(pred)) y_test_str = stripping(devectorize(y_test [i])) x_test_str = stripping(devectorize(x_test [i])) col = '緑' ifpred_str == y_test_strelse '赤' _ _ full_seq_acc + = 1 / len (preds) * int (pred_str == y_test_str) outstring = '入力:{}、出力:{}、予測:{} ' .format(x_test_str、y_test_str、pred_str) 印刷(colored(outstring、col)) print ( ' \ n完全なシーケンス精度:{:.3f}% ' .format( 100 * full_seq_acc)) |
出力は次のようになります
ここでは精度が少し悪いことがわかります。とにかく、非表示のユニットの数、検証の分割、エポックの数など、いくつかのハイパーパラメータを調整することで精度を最適化できます。
結論
RNNの基本的なワークフローを理解し、RNNがシーケンシャルデータに最適であることを理解し、ランダムな算術方程式のデータセットを生成し、基本的な算術式の出力を予測するためのシーケンシャルモデルを開発し、そのモデルをデータセットでトレーニングしました。モデルを作成し、最終的に、モデルがこれまでに見たことのない小さなデータセットを使用してテストしました。
RNN、機械学習について詳しく知りたい場合は、IIIT-BとupGradの機械学習とAIのPGディプロマをご覧ください。これは、働く専門家向けに設計されており、450時間以上の厳格なトレーニング、30以上のケーススタディと課題を提供します。 IIIT-B卒業生のステータス、5つ以上の実践的な実践的なキャップストーンプロジェクト、トップ企業との雇用支援。
機械学習におけるニューラルネットワークの種類は何ですか?
機械学習では、人工ニューラルネットワークは基本的に人間の脳に似せて設計された計算モデルです。 達成する必要のある数学的計算に基づいて機械学習が採用するさまざまな種類の人工ニューラルネットワークがあります。 これらのニューラルネットワークは、さまざまな方法でデータから学習するさまざまな機械学習手法のサブセットです。 最も広く使用されているタイプのニューラルネットワークには、リカレントニューラルネットワーク–長期記憶、フィードフォワードニューラルネットワーク–人工ニューロン、放射状基底関数ニューラルネットワーク、Kohonen自己組織化ニューラルネットワーク、畳み込みニューラルネットワーク、モジュラーニューラルネットワークなどがあります。とりわけ。
リカレントニューラルネットワークの利点は何ですか?
リカレントニューラルネットワークは、深層学習と機械学習で最も一般的に使用される人工ニューラルネットワークの1つです。 このタイプのニューラルネットワークモデルでは、前のステップで得られた結果が次のステップへの入力として供給されます。 リカレントニューラルネットワークには、次のようないくつかの利点があります。以前の入力を含め、時間の経過とともにすべての情報を保持できるため、時系列予測に最適です。 このタイプは、長短記憶の最良のインスタンスです。 また、リカレントニューラルネットワークは、畳み込み層を使用して建設的なピクセル近傍を提供します。
ニューラルネットワークは実際のアプリケーションでどのように使用されていますか?
人工ニューラルネットワークはディープラーニングの不可欠な部分であり、これも機械学習と人工知能の超専門分野です。 ニューラルネットワークは、さまざまな重要な目的を達成するためにさまざまな業界で使用されています。 人工ニューラルネットワークの最も興味深い実際のアプリケーションには、株式市場の予測、顔の認識、航空宇宙産業における高性能の自動操縦と障害診断、防衛部門における武力攻撃と物体の位置の分析、画像処理、とりわけ、ヘルスケアセクターにおける薬物の発見と病気の検出、署名の検証、手書きの分析、天気予報、ソーシャルメディアの傾向予測。