10月から先輩&お客さんと Coursera の Deep Learning の講座を受講しています。
コース 1 Neural Networks and Deep Learning
の Week2 の受講が終ったのですが、DL初学者の自分にとってはなかなかに難解でした。
腹落ちさせるため&あとあとやりたいことに使えるように(とはいえネタバレにならない程度に)メモを残します。
課題設定
- 64px x 64px x 3(RGB) な画像が N + M 枚ある
- それぞれに猫かどうか(猫なら1, 猫でないなら0)のラベルが付いている
- N 枚を学習(train)用、M枚をテスト用途で使い、モデルの精度を上げる
課題の流れ
画像データを1次元配列に置き換える
画像データは、(N, 64, 64, 3)
の3次元の長さNの配列で与えられる。
train_set_x_org.shape = (209, 64, 64, 3) test_set_x_org.shape = (50, 64, 64, 3) train_set_y.shape = (1, 209) test_set_y.shape = (1, 50)
まずは、これを長さNの1次元の配列 (64 * 64 * 3, 209)
に変換する必要がある。
この変換は numpy の reshape
メソッドを用いる。
x.reshape(a, b)
とすることで、a x b の配列に変換できる。
また、 b を -1 とすることで、元のarray x と a からよしなに b の値を変換してくれる。
元々が、 x.shape = (2,6)
で a = 3
の場合は、 2 * 6 / 3 で b = 4
となる。
このメソッドを利用し、 (a, b, c, d)
を (b * c * d, a)
にするには、 x.reshape(x.shape[0], -1).T
とすればよい。
下記は reshape
メソッドの利用例。
> x = np.array([[[[11, 12, 13], [21, 22, 23]], [[31, 32, 33], [41, 42, 43]]], [[[11, 12, 13], [21, 22, 23]], [[31, 32, 33], [41, 42, 43]]], [[[11, 12, 13], [21, 22, 23]], [[31, 32, 33], [41, 42, 43]]], [[[11, 12, 13], [21, 22, 23]], [[31, 32, 33], [41, 42, 43]]], [[[11, 12, 13], [21, 22, 23]], [[31, 32, 33], [41, 42, 43]]]]) > x.reshape(x.shape[0], -1).T array([[11, 11, 11, 11, 11], [12, 12, 12, 12, 12], [13, 13, 13, 13, 13], [21, 21, 21, 21, 21], [22, 22, 22, 22, 22], [23, 23, 23, 23, 23], [31, 31, 31, 31, 31], [32, 32, 32, 32, 32], [33, 33, 33, 33, 33], [41, 41, 41, 41, 41], [42, 42, 42, 42, 42], [43, 43, 43, 43, 43]])
今回の例では、訓練データ、テストデータともに下記のように対応し、フラットなデータにする。
train_set_x_flatten = train_set_x_org.reshape(train_set_x_org.shpae[0], -1).T
RGB の平準化
0~255 を 0~1 に平準化します。単純に割るだけ。
train_set_x = train_set_x_org_flatten / 255
各種関数の作成
(ネタバレになるので詳細は省きます。)
- シグモイド関数、重みwとバイアスbの初期化関数の定義
- 伝播関数の定義
- シグモイド関数を用いて、コスト関数を定義する(expected と actual の差を
-y * log(a) - (1-y) * log(1-a)
で計算する) - コスト関数を w で偏微分
- コスト関数を b で偏微分
- シグモイド関数を用いて、コスト関数を定義する(expected と actual の差を
- 最適化関数の定義
- w, b の初期値を設定(0の配列と定数0)
- 伝播関数を利用し、コスト関数を w, b で偏微分した値 dw, db を取得
- w, b を 各偏微分の値に学習率を掛けた分だけ増やす(減らす)
- ↑2つの処理を何回もイテレーションする(最適な重みとバイアスが計算される!)
- 予測関数を作成する(今回はシグモイド関数を噛ませた結果が 0.5 より上なら cat とした)
※ assert(w.shape == (dim, 1))
のようなアサートを適宜入れると、コードの可読性もあがってよい。
モデルを作成
下記の流れ。
- w, b を初期化する
- 最適化関数を用いて w, b の最適な値を求める
- 正解率を出す
学習率による違い
ここまでの例題では、学習率を 0.5 として最適化を進めた。 学習率を 0.01, 0.001, 0.0001 とした場合にどうなるかの例が書いてあり、 今回のケースでは、
- 0.01 の場合、訓練データに対する正答率は上がるが、テストデータの正答率は下がる
- 0.001, 0.00001 の場合は、そもそも訓練が終わらない
という結果だった。
まとめ
- コスト関数の値を出す
- 重みとバイアスで偏微分し、傾きを求め、学習率分だけ w, b を変化させる(コスト関数が減る方向にいくはず)
- 繰り返して最適な(=イテレーションが終わる) w, b を求める
という流れだけをまずは理解するといいと思います。 何度か確認して、腹落ちしたらもう少し補足したいと思います。