卷积神经网络的整体结构、卷积层、池化、python实现
卷積神經網絡的整體結構、卷積層、池化、python實現
- 一、整體結構
- 二、卷積層
- 三、池化層
- 四、python實現卷積層、池化層
一、整體結構
神經網絡相鄰層所有神經元之間都有連接,稱為全連接。前面用Affine層實現了全連接。
舉個例子
全連接神經網絡結構:
卷積神經網絡CNN的結構:
新增了Conv卷積層和Pooling池化層,之前的Affine-ReLU連接替換成了Conv-ReLU-Pooling連接。
CNN中,靠近輸出的層中使用之前Affine-ReLU組合,最后輸出層使用之前Affine-softmax組合,這是一種常見的CNN結構。
二、卷積層
全連接神經網絡存在的問題就是數據的形狀被忽視了,輸入三維圖像,但是向全連接層輸入時,需將三維拉成一維,這導致忽視了形狀中含有的空間信息,也就是說全連接,無法利用與形狀相關的信息。
卷積神經網絡為了解決這一問題,向各層中傳遞的數據是有形狀的數據,比如三維數據。
卷積層進行卷積運算,就像是圖像處理的濾波。
對于輸入數據,卷積運算以一定間隔滑動濾波器的窗口并將各個位置上濾波器的元素和輸入的對應元素相乘再求和,進行所謂乘積累加運算。
全連接神經網絡中,參數有權重和偏置等。
CNN中濾波器里面的數就是參數,濾波器里面數據的偏置也是參數。要通過cnn網絡對數據的學習,把這些參數給找到,從而達到優異的學習效果。
有時候進行卷積處理前要進行填充,也就是向輸入數據周圍填入固定的數據,填充主要是為了調整輸出的大小。(4,4)的輸入數據應用(3,3)濾波器時,輸出為(2,2),輸出比輸入縮小兩個元素就導致一個問題,如果每次進行卷積運算都縮小輸出,那么某時刻就無法再對輸出進行卷積運算,網絡就傳不下去了。如果說這個例子填充幅度是1,那么卷積運算輸出也是(4,4),卷積運算就可以在保持空間大小不變的情況下傳遞數據給下一層。
增大步幅,輸出大小會變小,增大填充輸出大小會變大。
假設輸入大小為(H,W),濾波器大小為(FH,FW),輸出大小為(OH,OW),填充為P,步幅為S。
有下面這個公式。
多維數據的卷積運算:
通道數為C、高度為H、長度為W的數據形狀,(C,H,W)
濾波器通道數為C、高度為FH、長度為FW,(C,FH,FW)
卷積后輸出的是一張特征圖。可以這樣理解,一個小方塊在大方塊里面移動,由于大方塊的C和小方塊一樣,所以卷積后是二維的。
如果想在通道上也有多個卷積運算,就需要用到多個濾波器如下圖。輸出將以方塊的形式傳給下一層。
如果增加偏置,如下圖:小長方體,也就是FN個偏置值。
如果增加批處理,也就是一次性處理N個數據,那么各層傳遞數據保存維度將增加一維,如下圖。
三、池化層
池化是縮小高、長方向上的空間運算。Max池化層是獲取目標區域最大值,然后把最大值放到輸出數據的其中一個元素里。池化層沒有要學習的參數,通道數不發生變化。池化對輸入數據微小偏差具有魯棒性,也就是說,輸入數據發生微小偏差時,池化層返回(與輸入數據沒發生微小偏差時)相同的輸出結果。
四、python實現卷積層、池化層
對于卷積來說,im2col這個函數能夠把大方塊的小方塊展開一行,這樣的話能和濾波器的小方塊 進行矩陣乘積運算,如下圖所示。
對于池化來說,im2col依然可以這么展開,就是把大正方形里面的小正方形展成一行,這里就不放圖了。
im2col實現代碼:
def im2col(input_data, filter_h, filter_w, stride=1, pad=0):"""Parameters----------input_data : 由(數據量, 通道, 高, 長)的4維數組構成的輸入數據filter_h : 濾波器的高filter_w : 濾波器的長stride : 步幅pad : 填充Returns-------col : 2維數組"""N, C, H, W = input_data.shapeout_h = (H + 2*pad - filter_h)//stride + 1out_w = (W + 2*pad - filter_w)//stride + 1img = 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_hfor x in range(filter_w):x_max = x + stride*out_wcol[:, :, 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 col反向傳播時候,要進行im2col逆處理,用的是col2im函數。
def col2im(col, input_shape, filter_h, filter_w, stride=1, pad=0):"""Parameters----------col :input_shape : 輸入數據的形狀(例:(10, 1, 28, 28))filter_h :filter_wstridepadReturns-------"""N, C, H, W = input_shapeout_h = (H + 2*pad - filter_h)//stride + 1out_w = (W + 2*pad - filter_w)//stride + 1col = 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_hfor x in range(filter_w):x_max = x + stride*out_wimg[:, :, y:y_max:stride, x:x_max:stride] += col[:, :, y, x, :, :]return img[:, :, pad:H + pad, pad:W + pad]卷積層、池化層實現代碼:
class Convolution:def __init__(self, W, b, stride=1, pad=0):self.W = Wself.b = bself.stride = strideself.pad = pad# 中間數據(backward時使用)self.x = None self.col = Noneself.col_W = None# 權重和偏置參數的梯度self.dW = Noneself.db = Nonedef forward(self, x):FN, C, FH, FW = self.W.shapeN, C, H, W = x.shapeout_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).Tout = np.dot(col, col_W) + self.bout = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2)self.x = xself.col = colself.col_W = col_Wreturn outdef backward(self, dout):FN, C, FH, FW = self.W.shapedout = 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 dxclass Pooling:def __init__(self, pool_h, pool_w, stride=1, pad=0):self.pool_h = pool_hself.pool_w = pool_wself.stride = strideself.pad = padself.x = Noneself.arg_max = Nonedef forward(self, x):N, C, H, W = x.shapeout_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)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)self.x = xself.arg_max = arg_maxreturn outdef backward(self, dout):dout = dout.transpose(0, 2, 3, 1)pool_size = self.pool_h * self.pool_wdmax = np.zeros((dout.size, pool_size))dmax[np.arange(self.arg_max.size), self.arg_max.flatten()] = dout.flatten()dmax = dmax.reshape(dout.shape + (pool_size,)) dcol = dmax.reshape(dmax.shape[0] * dmax.shape[1] * dmax.shape[2], -1)dx = col2im(dcol, self.x.shape, self.pool_h, self.pool_w, self.stride, self.pad)return dx總結
以上是生活随笔為你收集整理的卷积神经网络的整体结构、卷积层、池化、python实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: delphi 执行长时间存储过程 显示进
- 下一篇: java eav_动态自定义字段属性–M