ゼロから作るDeep Learning2(その2)

「ゼロから作るDeep Learning2」の続きメモ。

 

「5章 リカレントニューラルネットワーク(RNN)」

参考動画

www.youtube.com

参考情報

deepage.net

RNNは、時系列データを扱う。文章は、分散表現された単語が並んでいるため時系列データとなる。ネットワークとしては、ニューラルネットを次から次へつなげていくだけのもになる。単語がつならりその結果が、文章の分散表現となる。

この章で出てくる「Truncated BPTT」という学習方法を覚えておくとよい。OpenNMT-pyの学習でも使用している。

順伝播のつながりは維持し、逆伝播のみ適当な長さで切り離して学習を行う。

 

「6章 ゲート付きRNN」

参考動画

www.youtube.com

単純なRNNだと学習時の勾配が消失してしまったり、爆発してしまったりしてしまう。

なかなかうまくいかないものだ。そこで、適当にゲートをつけて、次のニューラルネットに送ったり遅らせなかったりするゲートを入れる。電子回路のラッチのような構成になる。このゲートの開け閉めの塩梅を学習させる。

 

ゼロから作るDeep Learning2(その1)

ゼロから作るDeep Learning2」を読んだ時のメモ。

www.oreilly.co.jp

「1章 ニューラルネットワークの復習」

復習の章。特にコメントなし。

 

「2章 自然言語と単語の分散表現」と「3章 word2vec」

自然言語処理では、単語をベクトルとして表そうとしている。
ベクトルで表現できると何がよいかというと、ベクトルは方向を表しているので
例えば、車と自転車が同じような方向を持つことが表せるようになる。
さらにベクトルは足し算引き算ができるので、うまくモデルが作れれば以下のようなこともできるようになる。
「王様」- 「男」+ 「女」= 「女王」
このベクトルデータのことを分散表現と読んでいる。

 

よいベクトルを作るには、単語と単語の関連から作るとよいらしく
コーパス(学習元となる文章たち)を集めて、その文の単語毎の前後の出現確率からベクトルを作成する。

 

ベクトル作成の手法として2種類あり、カウントベースと推論ベースと呼ばれている。
カウントベースの手法では、周囲の単語の共起行列から単語の分散表現を作っていた。
大規模なコーパスを扱うのが大変という問題がある。
カウントベースの手法は、全データを一気にバッチで学習するが
推論ベースの手法は、ミニバッチでデータサンプルから繰り返し学習することができる。
単語の出現確率をニューラルネットワークで計算する。

 

「4章 word2vecの高速化」

3章で作成したword2vecの高速化のために「Embeddig」と「Negative Sampling」を行う。「Embeddig」は最初からこれでやった方がわかりやすい気もした。まぁ、ゼロから作る本だから一旦簡単なニューラルネットワークから作っているのだろう。

「Negative Sampling」は、正解ケースと失敗ケースの学習に分けて、失敗ケースはサンプリングで学習させることにより、計算量を少なくしている。

 

この辺りは、以下の動画も併せて見るとよい。

www.youtube.com

 

 更に参考情報

deepage.net

ニューラルネットワークの学習(その2)

「ゼロから作るDeep Learning」の続きの「6章 学習に関するテクニック」に関するメモ。

学習時の手法やハイパラメータについて書いてある。

取り敢えず、学習時のコードを読む時に覚えておいた方がよいものとして、

optimization(最適化)という単語とSGDという手法。あと似たものとして、Adamを覚えとけば何とかなる気がする。困った時に読み直せばよい。

過学習対策の正則化の手法として、weight decayが記載されているが、これはLINEの中の人が書いた以下の本がわかりやすかった。

www.amazon.co.jp

ディープラーニングのための数学の本はいろいろ出ているけれど、これが一番わかりやすい気がする。

数学は知っていた方がよいけど、まずは実際に使ってみて、ソースコードを読んでみてからもっと理論的に深堀したくなってから数学に触れた方が良い気がする。

しかし、その段になって、ある程度の数学の知識がないと積み上げるのが大変なので、準備はしておかないといけないのが辛い。

正則化の手法としてもうひとつ「Dropout」がでてくる。このパラメータもよく見かける。

またよく似たものとして、枝刈り(Pruning)という、モデルのサイズを圧縮する手法がある。この枝刈りは、学習済みモデルのネットワークを物理的に切断する手法である。

それに対して「Dropout」は、学習時にランダムにノードを消して学習させる論理的な手法である。

なんにしろ、実際に学習を動かしてみて、困らないとここら辺は身につかない気がする。

「7章 畳み込みニューラルネットワーク」画像関係の処理によく使われるCNNが登場する。しかし、CNNは画像処理だけではなく、セルの関連性を見たい場合に他でも使われる。後で、Attentionと対比して見ていきたい。

CNNの良いところは、説明に画像処理が使われるのでイメージしやすい所だと思う。

「7.6 CNNの可視化」がイメージしやすいので、取り敢えずここまで流し読みするのがオススメ。画像処理なので、フィルタを作成して、データと掛け合わせて反応具合をみて、特徴点を抽出する。フィルタには、縦方向に反応するエッジや横方向に反応するエッジがある。このフィルタは予め用意しているわけではなく、学習していくうちにたまたま縦や横に反応するフィルタができあがり、それが強く反応して、よい結果を得るからそのフィルタ構成がよい重みとなり、モデルとして残っていく。つまり、CNNの学習は、そのデータにあったフィルタを作ることである。

学習のために、微分で勾配を計算する仕組みは、他のニューラルネットワーク学習と同様。

https://github.com/oreilly-japan/deep-learning-from-scratch/blob/master/common/layers.py#L232

 

 

 

ニューラルネットワークの学習(その1)

ニューラル機械翻訳の理論的な所を見ていきたい。

まずは、Attentionを理解することを目標とする。

いきなりAttentionを理解することはできないので、まずニューラルネットワークから始める。

www.oreilly.co.jp

これを読めばいいんじゃねと思うが、あくまで目標はAttentionを理解することなので、ひとまず、端折って良い所をあげたいと思う。

あと、Sonyクラウドニューラルネットワークサービスの「Neural Network Console」の説明動画が参考になる。

結構数があるが、以下の3つぐらいを見ておくとよいと思う。

 

www.youtube.com

Deep Learningの概要がなんとなくわかればよい。

 

www.youtube.com

ニューラルネットワークの学習(誤差逆伝播法)の動作がイメージできるとよい。

 

www.youtube.com

Affine結合/Tanh(活性化関数)/Convolution(畳み込み)/Pooling/Softmaxとかの単語がそれぞれ何をさしているかが、何となくわかればよい。

使い分けは、以下のページがわかりやすい。

arakan-pgm-ai.hatenablog.com

 

「ゼロから作るDeep Learning」は、まずは細かい所は置いといて「5章 誤差逆伝播法」までを一気に読んでしまうのが良いと思う。

ニューラルネットワークの学習で何を行っているのかをまずイメージできることが重要だと思う。

ニューラルネットワークの最適な重みパラメータを見つけるのが学習である。そのために、評価関数を定義して、重みパラメータを調整していく。調整をバッチ処理的にできるように微分計算で勾配を求めてその方向に調整していく。なので、いろいろな層が微分可能であることが重要である。

ここら辺がイメージできて、後の細かい手法は必要に迫られた時に見ていけばよいのではないかと思う。

 

以下、目次毎のコメント

1章 Python入門

 流し読みでOK

2章 パーセプトロン

 なんとなくニューラルネットワークの構成物がこんな物だとわかればOK

 今の段階では、バイアスは無視しておいてよい。

3章 ニューラルネットワーク

 どんな種類の活性化関数があり(ReLu/Sigmoid/Tanh等)それが何をするのか?

 ニューラルネットワークでどんな計算をしているのか?(単なる行列計算)

 ※行列の内積は、後々「単語の分散表現」の比較等でよく出てくる。

 ソフトマックス関数とは何をしているのか?(結果を確率で表現している)

 (ニューラルネットワークとしては、INとOUTのサイズは固定でそれに併せたデータを入れれば、OUTのサイズの確率が出力される。)

4章 ニューラルネットワークの学習

 損失関数とは何か?

 (関数としては、2乗和誤差と交差エントロピー誤差を覚えておけばOK)

 勾配と学習処理のイメージがわけばOK

5章 誤差逆伝播

 計算グラフと合成関数がでてくるが、各レイヤとしては、foward()とbackward()を実装すればよい。

 https://github.com/oreilly-japan/deep-learning-from-scratch/blob/master/ch05/layer_naive.py

 実装する際にfoward()は、自分の通常の計算を行い、backward()は微分計算を実装すればよい。

 

 

ニューラル機械翻訳の実践と理論(その2)

いよいよGoogle ColaboratoryでOpenNMTを実行する。

qiita.com

翻訳させるためには、まず学習させる必要がある。学習のために対訳コーパスと呼ばれるデータを用意する必要がある。例えば、英日翻訳の場合、英語の原文とそれを日本語訳した文章(対訳)が必要となる。

インターネット上には、いろいろな対訳データがある。

phontron.com

Qiitaの例と同じように、KFTTという京都に関するWikipediaを人手で翻訳した対訳コーパスを使用する。(京都に関する文章のみなので結構バイアスがあるデータになってしまうのが難点。。)

forest1040.hatenadiary.org

の手順で、ssh接続する。

あとは以下を実行する。注意点としては、python2がデフォルトなので、必ずpython3を使用すること。

# OpenNMT-pyをgitクローン
git clone https://github.com/OpenNMT/OpenNMT-py.git
cd OpenNMT-py
# 依存ライブラリをインストール
sudo python3 setup.py install

# kfttデータを持ってくる
cd ~
mkdir data
cd data
wget http://www.phontron.com/kftt/download/kftt-data-1.0.tar.gz
tar xzf kftt-data-1.0.tar.gz
cp -r kftt-data-1.0/data/tok ../OpenNMT-py/kftt

# 前処理を実行
cd ~/OpenNMT-py
onmt_preprocess -train_src kftt/kyoto-train.en -train_tgt kftt/kyoto-train.ja -valid_src kftt/kyoto-dev.en -valid_tgt kftt/kyoto-dev.ja -save_data kftt/demo

# 学習を実行(10000ステップまで1000ステップごとにモデルを保存)
onmt_train -gpu_ranks 0 --train_steps 10000 -data kftt/demo -save_model demo-model -save_checkpoint_steps 1000

# 翻訳を実行
onmt_translate -model demo-model_step_10000.pt -src data/src-test.txt -output pred.txt -replace_unk -verbose

前処理の詳細はおいおい説明したい。フォーマット等も解析しないと。。

今回の学習では、デフォルトのニューラルネットワーク(RNNベース)を使用している。学習を実行すると最初に以下のように、ネットワーク構成が表示される。

[2020-06-27 01:53:57,310 INFO] NMTModel(
(encoder): RNNEncoder(
(embeddings): Embeddings(
(make_embedding): Sequential(
(emb_luts): Elementwise(
(0): Embedding(50002, 500, padding_idx=1)
)
)
)
(rnn): LSTM(500, 500, num_layers=2, dropout=0.3)
)
(decoder): InputFeedRNNDecoder(
(embeddings): Embeddings(
(make_embedding): Sequential(
(emb_luts): Elementwise(
(0): Embedding(50004, 500, padding_idx=1)
)
)
)
(dropout): Dropout(p=0.3, inplace=False)
(rnn): StackedLSTM(
(dropout): Dropout(p=0.3, inplace=False)
(layers): ModuleList(
(0): LSTMCell(1000, 500)
(1): LSTMCell(500, 500)
)
)
(attn): GlobalAttention(
(linear_in): Linear(in_features=500, out_features=500, bias=False)
(linear_out): Linear(in_features=1000, out_features=500, bias=False)
)
)
(generator): Sequential(
(0): Linear(in_features=500, out_features=50004, bias=True)
(1): Cast()
(2): LogSoftmax()
)
)

詳細説明はおいおいになるが、Encoder(RNNEncoder)+Decoder(InputFeedRNNDecoder)+ generatorの構造になっている。

また後々の説明となるが、このネットワークでは、AttentionをDecoderの箇所でGlobalAttentionとして使用している。

取り敢えず今の所は、単語だけ覚えておくとよい。

 

学習が進んでいくと以下のようなログが表示されていく。

[2020-06-27 01:54:14,418 INFO] Step 50/10000; acc: 3.32; ppl: 272219.62; xent: 12.51; lr: 1.00000; 3746/4081 tok/s; 17 sec
[2020-06-27 01:54:23,089 INFO] Step 100/10000; acc: 3.43; ppl: 112228.97; xent: 11.63; lr: 1.00000; 7270/7793 tok/s; 26 sec
[2020-06-27 01:54:30,885 INFO] Step 150/10000; acc: 3.71; ppl: 50100.14; xent: 10.82; lr: 1.00000; 6898/7620 tok/s; 34 sec
[2020-06-27 01:54:40,337 INFO] Step 200/10000; acc: 3.68; ppl: 4956.98; xent: 8.51; lr: 1.00000; 6913/7733 tok/s; 43 sec
[2020-06-27 01:54:49,264 INFO] Step 250/10000; acc: 5.61; ppl: 1799.82; xent: 7.50; lr: 1.00000; 7435/7848 tok/s; 52 sec
[2020-06-27 01:54:58,311 INFO] Step 300/10000; acc: 7.89; ppl: 1163.46; xent: 7.06; lr: 1.00000; 6855/7916 tok/s; 61 sec

各値の意味も説明しないといけないが、取り敢えず指標だけ。。

  • acc(accuracy): 100に出来るだけ近いほうが良い。
  • ppl(perplexity): 1に出来るだけ近いほうが良い。
  • xent(CrossEntropy): 出来るだけ小さい数字が良い。

何を持って計算しているのか?どのように計算しているのか?学習ってなんなのか?

ソースコードを見ないといけないが、そもそもニューラルネットワークとは何かというところから初めていこう。

 

学習がある程度できたら、翻訳を実行してみればよい。

「-model demo-model_step_10000.pt」で指定しているのが、学習時に生成されるモデルデータである。今、1000ステップ毎にモデルを保存しているので、それを指定すればよい。

 

これで取り敢えず、翻訳できるところまで来た。

さらなる発展としては、「翻訳精度の向上」と「翻訳速度の向上」の2方向が考えられる。

 

  • 翻訳精度の向上
  1.  ニューラルネットワークに「Transformer」を使用する。
  2. 学習に使う 対訳コーパスの工夫を行う。
  • 翻訳速度の向上
  1. モデルの変換を行う(蒸留/量子化等)
  2. TorchScriptへの変換
  3. CTranslate2を使用する
  4. TPU等のハードウェアを使用する

だが、その前に ニューラルネットワーク自体の学習を積み上げて行く必要がある。

 

 

ニューラル機械翻訳の実践と理論(その1:番外編)

無料GPUクラウドGoogle Colaboratoryだが、もちろん制限がある。

以下の場合にインスタンスが停止されてしまう。

  • 【12時間ルール】新しいインスタンスを起動してから12時間経過
  • 【90分ルール】ノートブックのセッションが切れてから90分経過

セッションタイムアウトは、15分程度で発生している気がする。

セッションタイムアウトしたあと、インスタンスはアイドル状態になり、再接続すれば復旧するらしいがよくわからない。

以下のコードを実行しておいて、何かやらせておけばよいみたい。

import datetime
import time
 
time_in_second = 60
 
start = time.time();
while True:
print(datetime.datetime.now())
print(time.time() - start)
time.sleep(time_in_second)

kunsen.net

あと、データや生成したモデルは、GoogleDriveをマウントしておき退避すればよい。

qiita.com

 

ニューラル機械翻訳の実践と理論(その1)

本当は、「ニューラル機械翻訳の理論と実装」という題にしたかったのだけど理論がついてこないだろうから、理論は後回し。。

そして、実装まで踏み込めればよいのだけれど、難しいからまずは実践ということでこの題にしてみました。

ということでは、まずは、ニューラル機械翻訳オープンソースである「OpenNMT」を動かしてみたいと思う。

opennmt.net

ニューラルネットワークを構築することになるので、行列計算をたくさん行う必要があり、GPUがあった方が都合がよい。ちょうどコロナで特別定額給付金が入ったから、グラボでも買うかと思ったが、Google様が無料で使えるGPUクラウドを用意してくれている。

UIが「jupyter notebook」ぽいので、食わず嫌いしていたが背に腹は変えられない。。

ということで、以下を参考にして動かしてみる。

qiita.com

しかし、UIでPythonを動かすのが気に食わない。。

コマンドも実行できるがめんどくさい。

学習データやモデルデータのパスを確認するのにいちいちUIからコマンド入れるのダルい。あぁ、黒い画面が欲しい。。

ということで、以下を参考にして、「Google Colaboratory」にssh接続してしまう。

qiita.com

 

まずは、「https://ngrok.com」でアカウントを作成しておく必要がある。

ngorkは、ローカルネットワーク上にあるサービスを外部公開できるようにするサービスである。最近テレワークとかで、会社のPCを自宅から触れるようにしている方が多いと思うがその類のサービスである。

これをGoogle Colaboratoryの無料GPUインスタンスに仕込んで、sshするのだ。

やり方は、さっきのページ通りでOKで、ngorkの

Your Authtoken

のページでアクセストークンを取得しておく。

そして、Google Colaboratoryにアクセスして、

colab.research.google.com

GPUインスタンスを起動しておく。

接続しただけでは、GPUインスタンスになっていない場合があるため、以下の要領で確認と設定をしておく。

www.tdi.co.jp

あとは、Google Colaboratoryのセルに以下をコピペして実行すればよい。

!pip install git+https://github.com/demotomohiro/remocolab.git
import remocolab
remocolab.setupSSHD()

ngrokのauthtokenをコピペするようメッセージが表示されるので、先程のアクセストークンとregionを入力する。regionは、jpを選んでおく。

しばらく待っていると(2分ぐらい)、sshサーバがインストールされipとパスワードを教えてくれる。

あとは、接続してやるだけだ。