hirohirohirohirosのブログ

地方国立大学に通う情報系学部4年

ゼロから作るDeep Learning 3 ステップ52~ステップ54 まとめ

hirohirohirohiros.hatenablog.com

ステップ53

モデルの保存

 機械学習の学習には数時間以上かかる事がザラにあります.そのようなモデルを利用するたびに学習させるのはあまりに時間の無駄です.よって,一度学習させたモデルはどこかに保存しておいて,利用したり,再度学習させたりすることで,無駄な時間をかけずに済みます.しかし,モデルを保存するには何を保存すれば良いのでしょうか.Pytorchにはモデルその物を保存する方法と,モデルのパラメータを保存する方法があります.
 dezeroでは,モデルのパラメータをParameterクラスとして実装しています.よって,モデルのParameterクラスから,パラメータの情報(ndarrayインスタンス)を抜き出し,numpyの機能を使って保存することでモデルの保存とします.よって,dezeroのモデルの保存はモデルのパラメータの保存と言うことになります.

ndarrayの保存と読み込み

 numpyの保存機能と読み込み機能を確認します.

import numpy as np
x = np.array([[1, 2, 3], [4, 5, 6]])
np.save("test", x)
y = np.load("test.npy")
print(y)
>>[[1 2 3]
     [4 5 6]]

 一つのndarrayを保存するにはnp.save関数を使います.一つ目の引数にファイル名,二つ目の引数にndarrayを指定します.このとき,拡張子は書かなくても自動で.npyが付きます.読み込むときはnp.load関数を使います.読み込むファイルの名前を引数に指定します.このときは,ちゃんと拡張子.npzを記述しないと読み込んでくれません.

import numpy as np
x = np.array([[1, 2, 3], [4, 5, 6]])
y = np.array([[7, 8, 9], [10, 11, 12]])
dic = {"x":x, "y":y}
np.savez("test", **dic)
w = np.load("test.npz")
print(w)
x_ = w["x"]
y_ = w["y"]
print(x_)
print(y_)
>><numpy.lib.npyio.NpzFile object at 0x000002937579FF28>
      [[1 2 3]
       [4 5 6]]
      [[ 7  8  9]
       [10 11 12]]

 複数のndarrayを保存するときはディクショナリに格納して保存します.関数はsavezという関数を使います.使い方はsave関数と同じで,第一引数にファイル名,第二引数にndarrayを指定します.保存されるファイルは拡張子が.npzになることに注意します.第二引数には,ディクショナリのアンパック**を付ける事で,ディクショナリの中身を開封することが出来ます.読み込むときは同様にnp.load関数を使います.
 np.loadで読み込んでも,そのまますぐ使えるわけではありません.読み込んだwを表示させるとndarrayの中身が表示されずオブジェクトが表示されてしまいます.ndarrayの中身を表示させるためには,読み込むときに指定したkeyを使う必要があります.w["x"]やw["y"]とすることで正しくndarrayを取り出す事が出来ました.
 最後に,np.savez_compressed関数があります.これはnp.savez関数と同じですが,ファイルを圧縮して保存することで,ファイルサイズが小さくなります.実際にどれほど変わるのかを実験してみようと思います.大きなndarrayを用意して保存させます.

import numpy as np
dic = {}
for i in range(10**3):
    dic[str(i)] = np.random.rand(10**4)
np.savez_compressed("savez_compressed", **dic)

 使ったコードはこれで,合計10**7個の値をもつndarrayを保存します.そして,保存する関数をsavezとsavez_compressedの二つで保存してみます.結果が下の画像です.

savez_compressedの方が4500kbほどサイズが小さくなっていることが分かります.使い方や実行時間はほとんど変わらないのでsavez_compressedを使う方がよいことが分かります.

ステップ54

Dropout

 Dropoutとは,モデルの汎化性能を上げるために行うテクニックです.学習時にニューロンの一部を無効化し,学習させないようにします.ランダムにどのニューロンを消去するかを選択しながら学習を進めます.なぜDropoutがモデルの汎化性能を上げることに効果があるのかというと,Dropoutがアンサンブルに近い関係を持つからです.
 アンサンブルとは,複数のモデルの出力の平均を取って,全体の出力とする手法のことです.データ分析コンペでも,LightGBMとXgboostとCatboostの出力の平均を取ったり,全体の特徴量の中からランダムに一部選んで学習させた複数モデルの平均を取ったり,ランダムシード値を複数変えて学習させたモデルの平均を取ったりすると,一つのモデルの結果よりスコアが良くなることが多いです.
 アンサンブルはモデルの性能を上げる効果があり,Dropoutはアンサンブルに近い関係にあるため,Dropoutもモデルの性能を上げる効果があるという訳です.なぜDropoutがアンサンブルに近い関係を持つかというと,Dropoutのニューロンを一部ランダムに消去し学習させるという工程が,毎回異なるモデルで学習していると解釈できるためです.一つのモデルで,ニューロンを消去することで,複数のモデルによるアンサンブル効果を得ていると考えられます.

Direct DropoutとInverted Dropout

 例えば,学習時に消去率60%のニューロンを消去し学習させた場合,推論時に全てのニューロンで推論するには出力を0.4倍しないといけません.学習時より多いニューロンで推論させたら,その分出力の値も大きくなるからです.このように,学習時にニューロンを消去する割合を決め,推論時にその分出力を小さくする手法を直接のDropout, Direct Dropoutと呼びます.
 逆に,学習時に出力を小さくする手法をInverted Dropoutと言います.この手法だと学習時には小さくしたりせずそのまま出力することが出来ます.さらに,学習時に消去率分の出力調整をすることで,消去率を学習時に変化させる事が出来ます.一回目の学習は消去率50%,二回目の学習では消去率40%というように変更することが出来ます.Direct Dropoutでは,推論時に出力を調整するため,このようなことはできません.
 現在多くのディープラーニングフレームワークはInverted Dropoutで実装されています.