ディープラーニングについてディープにラーニング。

思いっきり、自分が学んだことのアウトプットしていきますが、何分初心者。もし何かアドバイス等頂けましたら幸いです!

プーリングとコンボリューションの実装

今日もアウトプット。

今日はプーリング層について。

プーリング層

プーリングとは、各プーリング層で対応する値の最大値をとってくる演算のこと。
目的は、過学習の抑制や、位置変化に対しても対応ができるようになる点。
図のほうがわかりやすい。

f:id:kawam0t0:20191226220453p:plain

特徴はおよそ2点

・学習するパラメータがない。
 なぜなら、単純にプーリング層に沿って最大値を取るだけだから

チャンネル数は変化しない
 プーリングの演算によって、出力チャネルは変わらない
 →Convはフィルターの数で出力のチャネル数が変わった

Convolution / Pooling層の実装


畳み込み層やプーリング層の実装はとても複雑である。


なんせ、CNNにおいて、各層に流れるデータは4次元。
(10,2,30,30)で表される。
30×30サイズで2チャンネルのデータが10個あるってこと。


パイソンで実行。

import numpy as np

x = np.random.rand(10,2,30,30)

print(x.shape) #全チャネルの次元数
print(x[0]) #一つ目のデータの次元数 
print(x[0].shape) #(2,30,30) -> 1個目の次元数
print(x[1].shape) #(2,30,30) -> 2個目の次元数
im2colで4次元データを2次元データに

CNNでは、なんせ大量のデータを計算するので、

計算自体やたらめんどくさい。
そんな時は、im2colを使えば難なくクリア。

こいつは中々やり手なやつで、
入力データに対して、フィルターを適用するすべての領域を横方向に展開するって
言われても図で見たほうが早い。

f:id:kawam0t0:20191226221200p:plain

つまりは、3次元(バッチサイズが加わったら4次元)のでーたにたいして、まさかの2次元配列を実行してくれる。
こうすることで、多少のメモリは食うものの、
行列の計算ライブラリを使って、大きな掛け算ができたり、する。

f:id:kawam0t0:20191226221321p:plain

整理しておくと、im2colは3次元配列に対して、
横方向の配列に変換してくれる。
使われる場所は入力データからフィルター(カーネル)に行くときに行列の配列に変えて、更にそこから内積を求めてくれる。

そして、そのままでは全結合層ニューラルネットワークと同じになるので、
そこから4次元になんとリシェイプしてくれる。

パイソンでイメージをつかむためにコードでも記載する

class Convolution:
    #初期化
    def __init__(self,w,b,stride=1,pad=0):
        self.w = w
        self.b = b
        self.stride = stride
        self.pad = pad
    #順伝播    
    def forward(self , x):
        #重み
        fn , c , fh , fw = x.shape
        out_h = int(1 + (h + 2 * self.pad - fh) / self.stride)
        out_w = int(1 + (w + 2 * self.pad - fw) / self.stride)
        
        col = im2col(x , fh , fw ,self.stride , self.pad)
        #行列変換
        col_w = self.w.reshape(fn , -1).T
        #内積
        out = np.dot(col , col_w) + self.b
        #2次元の配列を4次元に変換
        out = out.reshape(n , out_h , out_w , -1).trainspose(0,3,1,2)
        
        return out
            
#プーリング層の実装
"""
パラメータを保持しない層で畳み込みを行わない。
その代わり、位置変化に対して対応可能になる。
過学習を抑えることができるのがメリット
"""

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)
        
        out = np.max(col,axis=1)
        out = out.reshape(n , out_h , out_w,c).transpose(0,3,1,2)
        return out

コメントとかそろってないけど、ご勘弁。
では、また。