PyTorch を使用した文字ベースの再帰型ニューラル ネットワークの実装

PyTorch を使用した文字ベースの再帰型ニューラル ネットワークの実装

ここ数週間、私は PyTorch で char-rnn のバージョンを実装することに多くの時間を費やしてきました。これまでニューラル ネットワークをトレーニングしたことがないので、ここから始めるのが面白いかもしれません。

このアイデア (The Unreasonable Effects of RNNs より) を使用すると、文字ベースのリカレント ニューラル ネットワーク (RNN) をテキストでトレーニングし、驚くほど優れた結果を得ることができます。

[[358756]]

しかし、望んでいた結果は得られなかったものの、PyTorch と RNN の実験を始めようとしている他の人たちに役立つことを願って、いくつかのサンプル コードと結果を共有したいと思いました。

以下は Jupyter ノートブック形式のコードです: PyTorch.ipynb の char-rnn 。この Web ページの上部にある [Colab で開く] ボタンをクリックすると、Google の Colab サービスで開き、トレーニングに無料の GPU を使用できます。全部で約 75 行のコードですが、このブログ投稿でできる限り詳しく説明します。

ステップ1: データを準備する

まず、データをダウンロードする必要があります。私はプロジェクト・グーテンベルクのハンス・クリスチャン・アンデルセン童話のデータを使用しました。

  1. !wget -O 童話.txt

これはデータを準備するためのコードです。データ処理には fastai ライブラリの Vocab クラスを使用しました。このクラスは、一連の文字を「語彙」に変換し、この「語彙」を使用して文字を数字に変換します。

次に、モデルのトレーニングに使用できる大きな数値配列 ( training_set ) を作成します。

  1. fastai.text からインポート *
  2. テキスト= unidecode.unidecode (open('fairy-tales.txt').read())
  3. v = Vocab .create((テキスト内の x に対して x ), max_vocab = 400 , min_freq = 1 )
  4. トレーニングセット= torch.Tensor (v.numericalize([x for x in text])).type(torch.LongTensor).cuda()
  5. num_letters =長さ(v.itos)

ステップ2: モデルを定義する

これは、PyTorch の LSTM クラスのラッパーです。 LSTM クラスをカプセル化するだけでなく、次の 3 つのことを行います。

  • 入力ベクトルをワンホットエンコードして、正しい次元になるようにします。
  • LSTM の出力は長さ hidden_​​size のベクトルであり、それを文字に変換するには長さ input_size のベクトルが必要なので、LSTM レイヤーの後に線形変換を追加します。
  • LSTM 隠し層の出力ベクトル (実際には 2 つのベクトルがあります) をインスタンス変数として保存し、実行の各ラウンドの後に .detach() 関数を実行します。 (.detach() が何をするのかを説明するのは難しいのですが、ある意味でモデルの微分計算を「終了」させるものだと理解しています。)
  1. クラス MyLSTM(nn.Module):
  2. def __init__(self, input_size, hidden_​​size):
  3. スーパー().__init__()
  4. self.lstm = nn.LSTM (入力サイズ、隠しサイズ、 batch_first = True )
  5. self.h2o = nn.Linear (隠しサイズ、入力サイズ)
  6. 自己入力サイズ= 入力サイズ
  7. self.hidden =なし 
  8.  
  9. def forward(自分自身、入力):
  10. 入力= torch.nn. functional.one_hot (入力、 num_classes = self.input_size ).type(torch.FloatTensor).cuda().unsqueeze(0)
  11. self.hidden が None の場合:
  12. l_output、 self self.hidden = self.lstm(入力)
  13. それ以外:
  14. l_output、 self self.hidden = self.lstm(input、self.hidden)
  15. self.hidden = (self.hidden[0].detach()、self.hidden[1].detach())
  16.  
  17. self.h2o(l_output) を返します。

このコードも魔法のようなことを行いますが、それほど明白ではありません。入力が 6 つの文字に対応するベクトル (例: [1,2,3,4,5,6]) である場合、nn.LSTM は時間の経過に伴うバックプロパゲーションを使用して内部的に隠しベクトルを 6 回更新するというのが私の理解です。

ステップ3: トレーニングコードを書く

モデルは自動的にトレーニングされません。

最初は fastai ライブラリ (PyTorch のラッパーでもある) のヘルパー クラスを使用してみました。何をしているのか全くわからなかったので少し混乱しましたが、結局モデルのトレーニング コードを自分で書くことになりました。

以下のコード (epoch() メソッド) は、1 ラウンドのトレーニング プロセスに関する基本情報です。基本的には、以下のことを繰り返します。

  • などの文字列を RNN モデルに渡します。これらは、お茶にはならないはずです。 (数値ベクトルとして渡されます)
  • 次の文字の予測結果を取得する
  • RNN モデルの予測と実際の次の文字 (tease という単語は e で終わるため、e) の間の損失関数を計算します。
  • 勾配を計算する(loss.backward() 関数を使用)
  • 勾配降下法の方向に沿ってモデル内のパラメータの重みを変更します(self.optimizer.step() 関数を使用)
  1. クラスTrainer():
  2. __init__(self)を定義します。
  3. self.rnn = MyLSTM (入力サイズ、隠しサイズ).cuda()
  4. self.optimizer = torch.optim.Adam (self.rnn.parameters(), amsgrad = True lr lr =lr)
  5. エポックを定義します。
  6. = 0  
  7. 私は<  長さ(トレーニングセット) - 40:
  8. seq_len =ランダム.randint (10, 40)
  9. 入力、ターゲット=トレーニングセット[i:i+seq_len]、トレーニングセット[i+1:i+1+seq_len]
  10. i += シーケンス長
  11. # フォワードパス
  12. 出力= self .rnn(入力)
  13. 損失= F .cross_entropy(output.squeeze()[-1:], target[-1:])
  14. # 勾配を計算し、最適化ステップを実行する
  15. 自己.オプティマイザ.zero_grad()
  16. 損失.後方()
  17. 自己オプティマイザステップ()

nn.LSTMを使用して時間経過に沿ってバックプロパゲートし、独自のコードを書かないでください。

まず、次のように、一度に 1 文字ずつ LSTM レイヤーに渡し、定期的に導関数を計算する独自のコードを書きました。

  1. iが範囲(20)内にある場合:
  2. 入力、ターゲット=(iter)
  3. 出力、非表示= self .lstm(入力、非表示)
  4. 損失= F .cross_entropy(出力、ターゲット)
  5. 非表示非表示= 非表示.detach()
  6. 自己.オプティマイザ.zero_grad()
  7. 損失.後方()
  8. 自己オプティマイザステップ()

このコードは 20 文字を 1 文字ずつ渡し、最後に 1 回トレーニングします。このステップは時間によるバックプロパゲーションと呼ばれ、Karpathy がブログ記事で使用しているものです。

この方法は、ある程度は役に立ちます。私が書いた損失関数は、最初はしばらく減少しますが、その後ピークに達します。なぜこのようなことが起こったのかは分かりませんが、LSTM に 20 文字ずつ (seq_len 次元に応じて) 渡してバックプロパゲーションするように変更したところ、状況は改善しました。

ステップ 4: モデルをトレーニングします。

モデルが英語のようなテキストを出力し始めるまで、同じデータに対してこのトレーニング コードを約 300 回繰り返しました。約1時間かかりました。

この場合、モデルが過剰適合しているかどうかは気にしませんが、実際のシナリオでモデルをトレーニングする場合は、検証セットでモデルを検証する必要があります。

ステップ 5: 出力を生成します。

最後に、このモデルを使用して出力を生成します。このトレーニング済みモデルからテキストを生成するヘルパー メソッド (make_preds と next_pred) を作成しました。ここで重要なのは、ベクトルの次元を揃えることです。重要な点は次のとおりです。

  1. 出力= rnn (入力)
  2. prediction_vector = F .softmax(出力/温度)
  3. 文字= v .textify(torch.multinomial(prediction_vector, 1).flatten(), sep = '' ).replace('_', ' ')

基本的に私たちが行うことは次のとおりです。

  • RNN レイヤーは、アルファベットの各文字または記号に対して数値ベクトル (出力) を出力します。
  • この出力ベクトルは確率ベクトルではないため、これを確率値(つまり、すべての値の合計が 1 になる値)に変換するには、F.softmax(出力/温度) 演算が必要です。温度は、制限内で、より高い確率に与えられる重みを何らかの方法で制御します。温度を 0.0000001 に設定すると、常に最も高い確率を持つ文字が選択されます。
  • torch.multinomial(prediction_vector) は確率のベクトルを取得し、これらの確率を使用してベクトル内のインデックス (12 など) を選択するために使用されます。
  • v.textify は 12 を文字に変換します。

処理するテキストの長さが 300 の場合、このプロセスを 300 回繰り返すだけで済みます。

結果!

予測関数のパラメータを温度 = 1 に設定し、モデルによって次の結果が生成されました。これは英語に少し似ていますが、モデルが英語を最初から「学習」し、文字シーケンスのレベルで学習していることを考えると、かなり良い結果です。

これらの単語には意味がありませんが、どのような出力が欲しいのかわかりません。

「あなたがコロタルだった人は、少しは犯罪的だったに違いないと言い、カブトムシを家に送りました。 「私は緑の森の頭にいるでしょう。牧師。 「私は皇帝のソルテスを子供に手渡しました。母親は意識のかなり下にあり、それは彼らが皇帝の最後の偉大なものを見た森のきらめきです。大きな家は消えていましたが、カブトムシの反対側で見た音は何も不思議ではありませんでした。 「私は彼に幸せを知るでしょう。これは彼女自身と緑の安全な羽毛の若いモンスの音の物語です。」

「それは牧師でした。水の音に手を置いて、美しさと家と木と顔を考えていました。いくつかはカエルと海に糸をひいて、黄色は意図的すぎました、彼は牧師に暖かくありませんでした。牧師は運命づけられ、鐘から世界に行く、なぜ本当に労働者の最もハンサムな背中は彼女がカペルベンであり、菓子と思考が座って素晴らしいものを作っていたのか

以下の結果は、temperature=0.1 の場合に生成されます。これは、「毎回最も高い確率の文字を選択する」方法に近い方法で文字を選択します。その結果、出力に多くの重複が生じます。

甲虫の美しさの音。 「彼女は海の偉大な皇帝であり、太陽は甲虫にとってとても暖かく、甘美な甲虫でした。 「私は甲虫のためにとても多くなります。 「私は世界のためにとても多くなります。 そして太陽は海にとってとても暖かく、太陽は海にとってとても暖かく、鐘から世界の音、甲虫は海でした。 そして鐘から世界の音、甲虫は海でした。 そして木の花の音、木の音、そして鐘から世界の音、木から世界の音、そして木の音

この出力には、甲虫、菓子職人、太陽、海という単語に対する奇妙な執着があります。

まとめます!

これまでのところ、私の結果は Karpathy ほど良くありませんが、おそらくいくつかの理由があります。

  • トレーニングデータが不十分です。
  • 1 時間のトレーニングの後、Colab ノートブックの情報を確認する忍耐力がありませんでした。
  • Karpathy は、より多くのパラメータを含む LSTM の 2 つのレイヤーを使用しましたが、私は 1 つのレイヤーのみを使用しました。
  • それは全く別のものです。

しかし、概ね合格点の結果が出ました! 悪くないですね!

<<:  人工知能はどれくらい怖いのでしょうか?アメリカはAI兵器を開発し、イランの科学者は死亡した

>>:  無料の Python 機械学習コース 1: 線形回帰アルゴリズム

ブログ    
ブログ    

推薦する

...

BEVFusionを超えて!高速かつシンプルなBEV統合展開ソリューション

この記事は、Heart of Autonomous Driving の公開アカウントから許可を得て転...

最新レビュー!拡散モデルと画像編集の愛憎関係

この記事は、Heart of Autonomous Driving の公開アカウントから許可を得て転...

自動運転開発ツールチェーンの現状と動向を20,000語で解説

要点: 1. 自動車会社が独自の自動運転システムを開発することがトレンドとなっている。 2. MBD...

テクノロジーの専門家が若者と対談、第1回JD全国大学生アルゴリズム設計・プログラミングエリート競技会セミナーが開催されました

最近、「2021 JD全国大学生アルゴリズム設計・プログラミングエリートコンテスト-コードの無限の想...

製造業におけるAI: インテリジェントロボットには次の4つの機能が必要です

インテリジェントロボットはインテリジェント製品の代表的なものです。知能ロボットには、少なくとも以下の...

ニューラルネットワークの層とノードの数を設定する方法

[51CTO.com クイック翻訳] 人工ニューラル ネットワークには、ネットワークのアーキテクチャ...

AIを活用したリアルタイムの脅威インテリジェンスでサイバー脅威に対抗する方法

多くの企業のセキュリティ運用センター チームにとって、サイバー攻撃に対する防御は、ますます高度化する...

AIでAIを守る、次世代のAIベースのサイバー脅威ソリューション

多くの関係者は、AI が「悪」の力にもなり得るという事実を受け入れ始めています。関連する海外メディア...

決済の未来は生体認証にかかっている

現在、生体認証技術は比較的成熟しており、さまざまな応用シナリオがあります。国内の生体認証市場全体は、...

モジュール式の機械学習システムで十分でしょうか?ベンジオの教師と生徒が答えを教えてくれます

ディープラーニングの研究者は、神経科学と認知科学からインスピレーションを得ています。隠れユニットや入...

...

...

CTOは「大きな衝撃を受けた」:GPT-4Vの自動運転テストを5回連続で実施

この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...

5つのリソースカテゴリー:大規模言語モデルのリソース効率を向上させる方法、超詳細なレビューはこちら

近年、OpenAI の GPT-3 などの大規模言語モデル (LLM) は、人工知能の分野で大きな進...