AIって結局何なのかよく分からないので、とりあえず100日間勉強してみた Day70
経緯についてはこちらをご参照ください。
■本日の進捗
- col2imを理解
■はじめに
今回も「ゼロから作るDeep Learning Pythonで学ぶディープラーニングの理論と実装(オライリー・ジャパン)」で、深層学習を学んでいきます。
今回はim2colで変換した行列を戻すcol2im関数を構築していきます。
■col2im
畳み込みニューラルネットワークは入力である画像データの空間的情報を保持することで、(主な層として)全結合層を用いた基本的なニューラルネットワークより上手く画像データの特徴を捉えられるのでした。
しかし、im2colの行った変換は一見その情報を失ったようにも見えます。実際にはフィルターで変換された形で空間的情報を保持するので欠損がある訳ではないのですが、そのためには変換した行列を元の形に戻せないといけません。
ここで活躍するのがcol2im関数です。
パディング以外を元に戻した高さをH’、幅をW’とすると、
$$ H’ = H_{out} +2P + S – 1 $$
$$ W’ = W_{out} + 2P + S – 1 $$
前回の結果からim2colで5×5の画像を変換した結果が下記のようになりました。
[[0, 0, 0, 0, 1, 2, 0, 6, 7],
[0, 0, 0, 1, 2, 3, 6, 7, 8],
[0, 0, 0, 2, 3, 4, 7, 8, 9],
[0, 0, 0, 3, 4, 5, 8, 9, 10],
[0, 0, 0, 4, 5, 0, 9, 10, 0]
[0, 1, 2, 0, 6, 7, 0, 11, 12],
[1, 2, 3, 6, 7, 8, 11, 12, 13],
[2, 3, 4, 7, 8, 9, 12, 13, 14],
[3, 4, 5, 8, 9, 10, 13, 14, 15],
[4, 5, 0, 9, 10, 0, 14, 15, 0],
[0, 6, 7, 0, 11, 12, 0, 16, 17],
[6, 7, 8, 11, 12, 13, 16, 17, 18],
[7, 8, 9, 12, 13, 14, 17, 18, 19],
[8, 9, 10, 13, 14, 15, 18, 19, 20],
[9, 10, 0, 14, 15, 0, 19, 20, 0],
[0, 11, 12, 0, 16, 17, 0, 21, 22],
[11, 12, 13, 16, 17, 18, 21, 22, 23],
[12, 13, 14, 17, 18, 19, 22, 23, 24],
[13, 14, 15, 18, 19, 20, 23, 24, 25],
[14, 15, 0, 19, 20, 0, 24, 25, 0],
[0, 16, 17, 0, 21, 22, 0, 0, 0],
[16, 17, 18, 21, 22, 23, 0, 0, 0],
[17, 18, 19, 22, 23, 24, 0, 0, 0],
[18, 19, 20, 23, 24, 25, 0, 0, 0],
[19, 20, 0, 24, 25, 0, 0, 0, 0]]
これをcol2im関数で変換すると下記のようにパディングも含めて元の行列に戻ります。
[[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20],
[21, 22, 23, 24, 25]]
■col2im関数の実装
col2im関数を実装していきます。
まずは、畳み込み演算を行った後の出力の高さと幅を算出します。
out_h = (H + 2*pad - filter_h) // stride + 1 out_w = (W + 2*pad - filter_w) // stride + 1
im2colで構築したcol行列を元に戻します。
col = col.reshape(N, out_h, out_w, C, filter_h, filter_w).transpose(0, 3, 4, 5, 1, 2)
先程の式で変換後の画像配列を初期化します。
img = np.zeros((N, C, H + 2*pad + stride - 1, W + 2*pad + stride - 1))
col配列を画像配列に足し合わせていき、これをフィルターの高さと幅の数だけループします。
for y in range(filter_h): y_max = y + stride * out_h for x in range(filter_w): x_max = x + stride * out_w img[:, :, y:y_max:stride, x:x_max:stride] += col[:, :, y, x, :, :]
最後にパディングを取り除いて元の画像サイズに戻します。
return img[:, :, pad:H + pad, pad:W + pad]
これをまとめると下記のように記述できます。
def col2im(col, input_shape, filter_h, filter_w, stride, pad): N, C, H, W = input_shape out_h = (H + 2*pad - filter_h)//stride + 1 out_w = (W + 2*pad - filter_w)//stride + 1 col = col.reshape(N, out_h, out_w, C, filter_h, filter_w).transpose(0, 3, 4, 5, 1, 2) img = np.zeros((N, C, H + 2*pad + stride - 1, W + 2*pad + stride - 1)) for y in range(filter_h): y_max = y + stride*out_h for x in range(filter_w): x_max = x + stride*out_w img[:, :, y:y_max:stride, x:x_max:stride] += col[:, :, y, x, :, :] return img[:, :, pad:H + pad, pad:W + pad]
■おわりに
今回はim2col関数によって変換された行列を元に戻すcol2im関数を構築しました。この関数を用いて、次回から畳み込み層を実行していきます。
■参考文献
- Andreas C. Muller, Sarah Guido. Pythonではじめる機械学習. 中田 秀基 訳. オライリー・ジャパン. 2017. 392p.
- 斎藤 康毅. ゼロから作るDeep Learning Pythonで学ぶディープラーニングの理論と実装. オライリー・ジャパン. 2016. 320p.
- ChatGPT. 4o mini. OpenAI. 2024. https://chatgpt.com/
- API Reference. scikit-learn.org. https://scikit-learn.org/stable/api/index.html
- PyTorch documentation. pytorch.org. https://pytorch.org/docs/stable/index.html