サイトアイコン マサムネの部屋

Pythonによるディープラーニングの実装➂

機械学習

pythonで1から作るディープラーニング第三弾です。前回は、ニューラルネットワークで使われる全結合層では、画像の持つ位置情報を保つことが出来ないという事から始まり、それを克服するために畳み込み層を使いました。
前回の記事はこちらからどうぞ。

Pythonによるディープラーニングの実装➁
pythonによるディープラーニング実装記事第二弾です。画像認識の問題では、ニューラルネットワークを考えても微妙な事が多いです。行列そのものに操作を加える畳み込みの解説と実装をします。畳み込み層とアファイン層それぞれに画像を通してみて、畳み込み層が画像を図形として捉えている事を確認します。

畳み込み層によって画像の情報を保存しながらパラメーターの学習が出来ますが、大事な情報をさらに絞るための層を用意します。それが今回実装するプーリング層1です。

記事で使っているソースコードはgithub に置いてあります。
https://github.com/msamunetogetoge

スポンサーリンク

プーリングとは?

分類問題を解くためのモデルを考えているとしましょう。出力でsoftmax 関数を考えているとすると、入力の数字が大きければ大きい程出力される値は1に近付きます。つまり、出力層においては、値が大きい\( \simeq \) 出力結果となるのです。
値の小さい数字は、出力の結果にほとんど影響を与えないという意味で、いらない存在です。そのような数字を消してしまおうというのがプーリングです。
前の記事の言葉を使うと、\( n \times n\)の大きさのフィルター を用意して、フィルター内の行列から最大値を取るのがMax Pooling です。 \( 2\times 2\)、ストライド2 のプーリングをMで表して、例を計算してみましょう。
$$\begin{eqnarray}
M\left(
\begin{pmatrix}
1 & 2 & 3 & 4 \\
3 & 0 & 1 & 6 \\
1 & 5 & 2 & 3 \\
3 & 1 & 2 & 4
\end{pmatrix}
\right)
= \begin{pmatrix}
3 & 6 \\
5 & 4
\end{pmatrix}
\end{eqnarray}$$
例えば、動物の写真があって、象か否かを区別したいとします。訓練されたモデルでは、長い鼻や大きな耳に対応する部分の行列に大きな数字が出てくるはずです。プーリング層があると、大事な情報だけを抽出することが出来るのです。
特色として、プーリングには学習すべきパラメーターがありません。また、入力より出力がデータ数が少なくなります。プーリング層を入れておくことで計算が軽くなったりします。

プーリング層の実装

プーリング層の実装をしましょう。im2col を使って、1フィルター分が1行に並ぶように変形すれば行ごとに最大値を取るだけです。イメージは次のような感じです。\( 2 \times 2 \)のプーリングを考えます。
$$\begin{eqnarray}
\begin{pmatrix}
1 & 2 & 3 & 4 \\
3 & 0 & 1 & 6 \\
1 & 5 & 2 & 3 \\
3 & 1 & 2 & 4
\end{pmatrix}
\rightarrow \begin{bmatrix}
1& 2 & 3 & 0 \\
3 & 4 & 1 & 6 \\
1 & 5 & 3 & 1 \\
2 & 3 & 2 & 4
\end{bmatrix}
\end{eqnarray}$$
画像がカラーだとチャンネルがRGBの3種類あり、データの数と合わせて、基本的に入力は4次元のベクトルです。しかし、チャンネルとデータ数の部分には手を加えないので実装は簡単なものになります。

class Pooling:
    def __init__(self, pool_h, pool_w, stride=1, pad=0):
        self.pool_h = pool_h
        self.pool_w = pool_w
        self.stride = stride
        self.pad = pad

    def forward(self, x):
        N, C, H, W = x.shape
        out_h = int(1 + (H - self.pool_h) / self.stride) #畳み込み層と同じ出力結果
        out_w = int(1 + (W - self.pool_w) / self.stride)

        col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad)
        col = col.reshape(-1, self.pool_h*self.pool_w) #1行に1フィルター分を格納

        arg_max = np.argmax(col, axis=1)
        out = np.max(col, axis=1)
        out = out.reshape(N, out_h, out_w, C).transpose(0, 3, 1, 2)

        return out

プーリングの実験

実際に写真をプーリング層に通してみましょう。画像認識で良く遊ばれるlena さんに実験台になってもらいます。本物の画像はカラーですが、白黒画像でやってみましょう。画像サイズは\(256 \times 256 \)です。

lenaさん

\(10 \times 10 \)、ストライド1でプーリング層に通してみます。

プーリングされたlenaさん

誰の写真かはハッキリと分からなくなりましたが輪郭は残っており、帽子を被った女性(?)であることは判別できます。生の画像をプーリング層に通すと、輪郭を抽出する効果があります。細かいパーツ部分はまとめられてしまうので、輪郭や大きな形の部分しか残らないのです。
次回は畳み込み層とプーリング層に何度も画像を通すとどうなるか実験してみます。

まとめ

・プーリング 層(Max Pooling) の解説をした。
・プーリング 層の実装をした。
・画像をプーリングすると、輪郭だけが残る

  1. プーリングと言ったらMax pooling を指します。