cha_kabuのNotebooks

個人的な機械学習関連勉強のアウトプット置き場です。素人の勉強録なので、こちらに辿り着いた稀有な方、情報はあまり信じない方が身のためです。

ゼロから作るDeep Learning3 フレームワーク編を読む その⑪ステップ52~54

はじめに

以下の記事シリーズの続きです。

cha-kabu.hatenablog.com

本編

ステップ52 GPU対応

このステップは…スルーします!他ライブラリ使う時はお決まりのお作法(GPU使用可能確認してオブジェクトをGPUに投げる)をしておけばとりあえずできますし、自分のPCが2012年頃?に買ったやつで、当時動画編集もしてたのでNVIDIAQuadro K600っていう確か当時はそれなりだったGPUが載ってるのですがこいつがどこまでやれるのかも分からないし、何よりそもそも自分の環境でcupyを使えるようにできませんでした…

こちらのサイト様を参考にCUDAもCuPyもインストールはできたのですが、いざimport cupyとすると、

'CUDA path could not be detected.'

と言われてしまい…全然意味は分かっていませんが環境変数PATHとやらもちゃんと設定されているんですけどね…軽く数日かかりそうなのでスルー!

それはそうと参考先サイトの充実度がすごい…設定関係がすべて図付でめちゃくちゃ分かりやすい…

ステップ53 モデルの保存と読み込み

コード自体は難しくないと思いますが、書籍の具体例で何が起こっているかを見てみます。まず、modelの構造とsave_weights()内で_fratten_params()メソッドがどのようなことを行っているかまとめます。

f:id:cha_kabu:20201122210057p:plain

Layer(あるいはそれを継承した)インスタンス_fratten_params()メソッドが実行されると、空の辞書にParameterインスタンスの値(Parameter.data)をParameterが存在する階層に関わらずすべて格納します。その時、辞書のkeyはParameter自身の名前と親のLayerの名前を"/"で繋げたものになります。

そうしてできた辞書に格納されている値はVariableでnumpyでは保存ができませんので、図では省略しましたがarray_dictというndarrayで値をもった別の辞書を作成し、それをnp.savez_compressed関数で保存します。

そして、load_weights()メソッドを新しく作成したModelインスタンス(各パラメータの値は初期化されてしまっているが、構造は保存したものと同じ)で呼び出すと、対応するkeyのデータを各パラメータに設定してくれます。

注意というほどでもありませんが、保存しているのは例えばmodel.l0.W.dataの値だけですので、これ以外の情報は読み込まれません。具体例として、modelで学習したパラメータを保存しておき(コードは省略)、model2に読み込んで各インスタンス変数を確認すると以下の様になっています。

# modelのインスタンス変数確認
print(model.l1.b.data) # [-0.00109223  0.00141618 -0.00185522 ...]
print(model.l1.b.grad) # variable([-0.01123966 -0.01110208  0.01427339 ...])

# 同じ構造のモデルをmodel2として作成、modelのパラメータ値をロード
model2 = MLP((1000, 10))
model2.load_weights("array.npz")

# model2のインスタンス変数確認
print(model2.l1.b.data) # [-0.00109223  0.00141618 -0.00185522 ...]
print(model2.l1.b.grad) # None

ステップ54 Dropoutとテストモード

なんだか…突然説明が雑では…書いてあることは分かるので先に進もうかと思いますが、DeZeroでどうやってDropout実装するのかの説明が今までと比べて急にあっさりで…関数としての実装なので、コンストラクタでは何もせずに活性化関数の様にforwardメソッドに書けば良いのでしょうか…?一応↓のクラスを作ったところ、動きはしました(正しい自信はないです…)。

class ThreeLayerNet(Model):
    def __init__(self, hidden_size, out_size):
        super().__init__()
        self.l1 = L.Linear(hidden_size)
        self.l2 = L.Linear(hidden_size)
        self.l3 = L.Linear(out_size)

    def forward(self, x):
        y = F.dropout(self.l1(x))
        y = F.relu(y)
        y = F.dropout(self.l2(y))
        y = F.relu(y)
        y = self.l3(y)
        return y

最後に

めちゃくちゃ短いですが先に進むとキリが悪いのでここまで!残すはCNNとRNN(+LSTM)です。書籍の説明はあっさりしていそう&今まで雰囲気で写経してしか使ってないので長くなりそうです…次回は~ステップ58を予定。