CNN(畳み込みニューラルネットワーク)とは?

CNN(Convokution Neural Network)は、画像認識アルゴリズムとして定着した機械学習におけるモデルです。
CNNは「入力層」「隠れ層」「出力層」に大別されます。
入力層の役割は、画像の1ピクセル(画素)毎にニューロンを作成します。
隠れ層の役割は、画像の特徴パターンをを検知するニューロンを作成します。この層の中に「畳み込み層」と「プーリング層」が存在します。
本記事の主題は、この畳み込み層になります。
出力層の役割は、プーリング層からの情報を組み合わせて確信度を0から1までの数値で判定を行います。ここで気がついた方は賢いですね。
そう!出力層で使われるのがソフトマックス関数ですね。
畳み込み層のサンプルプログラム

畳み込み層について「0からDeepLearning」では”Convolutionレイヤ”として紹介されています。
下のプログラムが、「0からDeepLearning」に掲載されていた畳み込み層のサンプルプログラムになります。
im2col関数は、畳み込みを行う処理2重ループをなくしNumPyが効率的に処理できるように2次元配列に変換しているものです。col2im関数は、その逆のことを行っています。
畳み込み層の処理は、画像認識の処理で一番コストがかかる処理になりますので、このような最適化を行うことでパフォーマンス改善していくことが必要です。どういう処理を行ったらパフォーマンスが改善するか、処理スピードを追求していくのも面白いかもしれませんね。
最初からパフォーマンス改善済みでサンプルを提供するあたりが良書と思う理由の1つですね。プログラムの細かい説明は「0からDeepLearning」を買って確認してくださいね。
class Convolution:
def init(self, W, b, stride=1, pad=0):
self.W = W
self.b = b
self.stride = stride
self.pad = pad
# 中間データ(backward時に使用)
self.x = None
self.col = None
self.col_W = None
# 重み・バイアスパラメータの勾配
self.dW = None
self.db = None
def forward(self, x):
FN, C, FH, FW = self.W.shape
N, C, H, W = x.shape
out_h = 1 + int((H + 2*self.pad - FH) / self.stride)
out_w = 1 + int((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
out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2)
self.x = x
self.col = col
self.col_W = col_W
return out
def backward(self, dout):
FN, C, FH, FW = self.W.shape
dout = dout.transpose(0,2,3,1).reshape(-1, FN)
self.db = np.sum(dout, axis=0)
self.dW = np.dot(self.col.T, dout)
self.dW = self.dW.transpose(1, 0).reshape(FN, C, FH, FW)
dcol = np.dot(dout, self.col_W.T)
dx = col2im(dcol, self.x.shape, FH, FW, self.stride, self.pad)
return dxdef im2col(input_data, filter_h, filter_w, stride=1, pad=0):
N, C, H, W = input_data.shape
out_h = (H + 2*pad - filter_h)//stride + 1
out_w = (W + 2*pad - filter_w)//stride + 1
img = np.pad(input_data, [(0,0), (0,0), (pad, pad), (pad, pad)], 'constant')
col = np.zeros((N, C, filter_h, filter_w, out_h, out_w))
for y in range(filter_h):
y_max = y + stride*out_h
for x in range(filter_w):
x_max = x + stride*out_w
col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride]
col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N*out_h*out_w, -1)
return coldef col2im(col, input_shape, filter_h, filter_w, stride=1, pad=0):
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]オライリーJapan 斎藤康毅 著 「セロから作るDeep Learning」