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: 線形回帰アルゴリズム

ブログ    
ブログ    

推薦する

将来、人工知能は人間の意思決定に取って代わることができるでしょうか?

ほとんどの CIO は、AI に意思決定を任せることに消極的です。しかし、それは彼らがより優れた、よ...

ニューラルスタイル転送アルゴリズムで絵を描くことを学習する人間は、芸術分野で人工知能に負けるのでしょうか?

人工知能はますます多用途になり、すでに私たちの仕事のすべてを人工知能が引き継ぐことができるようです。...

AI を理解する: 人工知能システムで説明可能性を追求する理由

この記事は、公開アカウント「Reading the Core」(ID: AI_Discovery)か...

コンピュータビジョンがビジネス課題の解決に役立つ 5 つの方法

自動運転車、交通標識検出、顔認識、セルフサービスチェックアウト。 これらすべての高度なソリューション...

人工知能が教育に与える影響は技術サポートだけにとどまらない

統合と国境を越えた発展が進む今日の世界において、教育が象牙の塔に留まり、自己満足に浸っているだけでは...

ディープラーニングの最適化手法の簡単な紹介: 勾配降下法

実際、ディープラーニングは多くの厄介な最適化問題を解決しています。ニューラル ネットワークは、問題に...

...

AIが人間を支配するのではないかと心配ですか?人工知能の「怖さ」をどう克服するか?

この記事は公開アカウント「Reading Core Technique」(ID: AI_Discov...

雪の結晶がどのように形成されるかは、これまでずっと謎でした。この物理学者は、その謎を解明したいと考えています。

テクノロジートラベラー北京ニュース 1 月 3 日:ケネス・リブブレヒトは、この寒い冬に暖かく快適な...

...

AI研究者の邢波氏:機械学習には明確な理論的枠組みが欠けており、評価の目標と方法を再定義する必要がある

[[426278]] 2021年1月、コンピュータサイエンスと人工知能分野のトップ学者であるエリッ...

Golang GC についていくつか誤解がありますが、本当に Java アルゴリズムよりも高度なのでしょうか?

[[273650]]まず最初に強調しておきたいのは、この記事の発端は High Availabil...

中国は、インターネット、ビッグデータ、人工知能などの分野における知的財産保護に関する研究と実践を実施します。

[[432777]]中国新聞社、北京、11月1日(記者:孫子発)中国国家知識産権局の沈長宇局長は1...

フェデレーテッドラーニングも安全ではないのでしょうか? Nvidiaの研究は「プライバシーフリー」データを使用して元の画像を直接再構築します

フェデレーテッド ラーニングは、データがローカルの場所から出ないようにするプライバシー保護戦略により...

セキュリティ業界の大手企業はどのようにドローンを配備するのでしょうか?

ドローンは警報装置、検出器、カメラなどを搭載し、多くの機能を実現でき、セキュリティ監視、スマートビル...