目錄
- 目錄
- 一,濾波器與卷積核
- 二,卷積層和池化輸出大小計算
- 2.1,CNN 中術語解釋
- 2.2,卷積輸出大小計算(簡化型)
- 2.3,理解邊界效應與填充 padding
- 參考資料
- 三,深度學習框架的張量形狀格式
- 四,Pytorch 、Keras 的池化層函式理解
- 4.1,torch.nn.MaxPool2d
- 4.2,keras.layers.MaxPooling2D
- 五,Pytorch 和 Keras 的卷積層函式理解
- 5.1,torch.nn.Conv2d
- 5.2,keras.layers.Conv2D
- 5.3,總結
- 六,softmax 回歸
- 七,交叉熵損失函式
- 7.1,為什么交叉熵可以用作代價函式
- 7.2,優化演算法理解
- 八,感受野理解
- 8.1,感受野大小計算
- 九,卷積和池化操作的作用
- 參考資料
- 十,卷積層與全連接層的區別
- 十一,CNN 權值共享問題
- 十二,CNN 結構特點
- Reference
- 十三,深度特征的層次性
- 十四,什么樣的資料集不適合深度學習
- 十五,什么造成梯度消失問題
- 十六,Overfitting 和 Underfitting 問題
- 16.1,過擬合問題怎么解決
- 16.2,如何判斷深度學習模型是否過擬合
- 16.3,欠擬合怎么解決
- 16.4,如何判斷模型是否欠擬合
- 十七,L1 和 L2 范數區別
- 參考資料學習
- 十八,TensorFlow計算圖概念
- 十九,BN(批歸一化)的作用
- 二十,什么是梯度消失和爆炸
- 梯度消失和梯度爆炸產生的原因
- 如何解決梯度消失和梯度爆炸問題
- 二十一,RNN回圈神經網路理解
- 二十二,訓練程序中模型不收斂,是否說明這個模型無效,導致模型不收斂的原因
- 二十三,VGG 使用 2 個 3*3 卷積的優勢
- 23.1,1*1 卷積的主要作用
- 二十四,Relu比Sigmoid效果好在哪里?
- 參考鏈接
- 二十五,神經網路中權值共享的理解
- 參考資料
- 二十六,對 fine-tuning(微調模型的理解),為什么要修改最后幾層神經網路權值?
- 參考資料
- 二十七,什么是 dropout?
- 27.1,dropout具體作業流程
- 27.2,dropout在神經網路中的應用
- 27.3,如何選擇dropout 的概率
- 參考資料
- 二十八,HOG 演算法原理描述
- HOG特征原理
- HOG特征檢測步驟
- 參考資料
- 二十九,激活函式
- 29.1,激活函式的作用
- 29.2,常見的激活函式
- 29.3,激活函式理解及函式梯度圖
- 三十,卷積層和池化層有什么區別
- 三十一,卷積層和池化層引數量計算
- 三十二,神經網路為什么用交叉熵損失函式
- 三十三,資料增強方法有哪些
- 33.1,離線資料增強和在線資料增強有什么區別?
- Reference
- 三十四,ROI Pooling替換為ROI Align的效果,及各自原理
- ROI Pooling原理
- ROI Align原理
- RoiPooling 和 RoiAlign 總結
- Reference
- 三十五,CNN的反向傳播演算法推導
- 三十六,Focal Loss 公式
- 三十七,快速回答
- 37.1,為什么 Faster RCNN、Mask RCNN 需要使用 ROI Pooling、ROI Align?
- 37.2,softmax公式
- 37.3,上采樣方法總結
- 37.4,移動端深度學習框架知道哪些,用過哪些?
- 37.5,如何提升網路的泛化能力
- 37.6,BN演算法,為什么要在后面加伽馬和貝塔,不加可以嗎?
- 37.7,驗證集和測驗集的作用
- 三十八,交叉驗證的理解和作用
- 三十九,介紹一下NMS和IOU的原理
- Reference
一,濾波器與卷積核
在只有一個通道的情況下,“卷積核”(“kernel”)就相當于濾波器(“filter”),這兩個概念是可以互換的,一個 “Kernel” 更傾向于是 2D 的權重矩陣,而 “filter” 則是指多個 kernel 堆疊的 3D 結構,如果是一個 2D 的 filter,那么兩者就是一樣的,但是一個3D filter,在大多數深度學習的卷積中,它是包含 kernel 的,每個卷積核都是獨一無二的,主要在于強調輸入通道的不同方面,
二,卷積層和池化輸出大小計算
不管是
TensorFlow、Keras、Caffe還是Pytorch,其卷積層和池化層的引數默認值可能有所不同,但是最終的卷積輸出大小計算公式是一樣的,
2.1,CNN 中術語解釋
卷積層主要引數有下面這么幾個:
- 卷積核
Kernal大小(在Tensorflow/keras框架中也稱為filter); - 填充
Padding; - 滑動步長
Stride; - 輸出通道數
Channels,
2.2,卷積輸出大小計算(簡化型)
1,在 Pytorch 框架中,圖片(feature map)經卷積 Conv2D 后輸出大小計算公式如下:\(\left \lfloor N = \frac{W-F+2P}{S}+1 \right \rfloor\),其中 \(\lfloor \rfloor\) 是向下取整符號,用于結果不是整數時進行向下取整(Pytorch 的 Conv2d 卷積函式的默認引數 ceil_mode = False,即默認向下取整, dilation = 1),
- 輸入圖片大小
W×W(默認輸入尺寸為正方形) Filter大小F×F- 步長
S - padding的像素數
P - 輸出特征圖大小
N×N
2,特征圖經反卷積(也叫轉置卷積) keras-Conv2DTranspose(pytorch-ConvTranspose2d) 后得到的特征圖大小計算方式:\(out = (in - 1) *s -2p + k\),還有另外一個寫法:\(W = (N - 1)*S - 2P + F\),可由卷積輸出大小計算公式反推得到,\(in\) 是輸入大小, \(k\) 是卷積核大小, \(s\) 是滑動步長, padding 的像素數 \(p\),\(out\) 是輸出大小,
反卷積也稱為轉置卷積,一般主要用來還原 feature map 的尺寸大小,在 cnn 可視化,fcn 中達到 pixel classification,以及 gan 中從特征生成影像都需要用到反卷積的操作,反卷積輸出結果計算實體,例如,輸入:2x2, 卷積核大小:4x4, 滑動步長:3,填充像素為 0, 輸出:7x7 ,其計算程序就是, (2 - 1) * 3 + 4 = 7,
3,池化層如果設定為不填充像素(對于 Pytorch,設定引數padding = 0,對于 Keras/TensorFlow,設定引數padding="valid"),池化得到的特征圖大小計算方式: \(N=(W-F)/S+1\),這里公式表示的是除法結果向下取整再加 1,
總結:對于Pytorch 和 tensorflow 的卷積和池化函式,卷積函式 padding 引數值默認為 0/"valid"(即不填充),但在實際設計的卷積神經網路中,卷積層一般會填充像素(same),池化層一般不填充像素(valid),輸出 shape 計算是向下取整,注意:當 stride為 1 的時候,kernel為 3、padding為 1 或者 kernel為 5、padding為 2,這兩種情況可直接得出卷積前后特征圖尺寸不變,
注意不同的深度學習框架,卷積/池化函式的輸出
shape計算會有和上述公式有所不同,我給出的公式是簡化版,適合面試題計算,實際框架的計算比這復雜,因為引數更多,
2.3,理解邊界效應與填充 padding
如果希望輸出特征圖的空間維度Keras/TensorFlow 設定卷積層的程序中可以設定 padding 引數值為 “valid” 或 “same”,“valid” 代表只進行有效的卷積,對邊界資料不處理,“same” 代表 TensorFlow 會自動對原影像進行補零(表示卷積核可以停留在影像邊緣),也就是自動設定 padding 值讓輸出與輸入形狀相同,
參考資料
- CNN中的引數解釋及計算
- CNN基礎知識——卷積(Convolution)、填充(Padding)、步長(Stride)
三,深度學習框架的張量形狀格式
-
影像張量的形狀有兩種約定,通道在前(
channel-first)和通道在后(channel-last)的約定,常用深度學習框架使用的資料張量形狀總結如下:Pytorch/Caffe: (N, C, H, W);TensorFlow/Keras: (N, H, W, C),
-
舉例理解就是
Pytorch的卷積層和池化層的輸入shape格式為(N, C, H, W),Keras的卷積層和池化層的輸入shape格式為(N, H, W, C),
值得注意的是 OpenCV 讀取影像后回傳的矩陣 shape 的格式是 (H, W, C)格式,當 OpenCV 讀取的影像為彩色影像時,回傳的多通道的 BGR 格式的矩陣(HWC),在記憶體中的存盤如下圖:

四,Pytorch 、Keras 的池化層函式理解
注意:對于
Pytorch、Keras的卷積層和池化層函式,其padding引數值都默認為不填充像素,默認值為0和valid,
4.1,torch.nn.MaxPool2d
class torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)
二維池化層,默認輸入的尺度是(N, C_in,H,W),輸出尺度(N,C_out,H_out,W_out),池化層輸出尺度的 Width 默認計算公式如下(ceil_mode= True 時是向上取整,Height 計算同理):
主要引數解釋:
kernel_size(int or tuple):max pooling的視窗大小,stride(int or tuple,optional):max pooling的視窗移動的步長,默認值是kernel_size`,padding(int or tuple,optional):默認值為0,即不填充像素,輸入的每一條邊補充0的層數,dilation:滑動窗中各元素之間的距離,ceil_mode:默認值為False,即上述公式默認向下取整,如果設為True,計算輸出信號大小的時候,公式會使用向上取整,
Pytorch中池化層默認ceil mode = false,而Caffe只實作了ceil mode= true的計算方式,
示例代碼:
import torch
import torch.nn as nn
import torch.autograd as autograd
# 大小為3,步幅為2的正方形視窗池
m = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
# pool of non-square window
input = autograd.Variable(torch.randn(20, 16, 50, 32))
output = m(input)
print(output.shape) # torch.Size([20, 16, 25, 16])
4.2,keras.layers.MaxPooling2D
keras.layers.MaxPooling2D(pool_size=(2, 2), strides=None, padding='valid', data_format=None)
對于 2D 空間資料的最大池化,默認輸入尺寸是 (batch_size, rows, cols, channels)/(N, H, W, C_in) 的 4D 張量,默認輸出尺寸是 (batch_size, pooled_rows, pooled_cols, channels) 的 4D 張量,
padding = valid:池化層輸出的特征圖大小為:\(N=(W-F)/S+1\),這里表示的是向下取整再加 1,padding = same: 池化層輸出的特征圖大小為 \(N = W/S\),這里表示向上取整,
主要引數解釋:
pool_size: 整數,或者2個整數表示的元組, 沿(垂直,水平)方向縮小比例的因數,(2,2)會把輸入張量的兩個維度都縮小一半, 如果只使用一個整數,那么兩個維度都會使用同樣的視窗長度,strides: 整數,2個整數表示的元組,或者是None, 表示步長值, 如果是None,那么默認值是pool_size,padding:"valid"或者"same"(區分大小寫),data_format: 字串,channels_last(默認)或channels_first之一, 表示輸入各維度的順序,channels_last代表尺寸是(batch, height, width, channels)的輸入張量, 而channels_first代表尺寸是(batch, channels, height, width)的輸入張量, 默認值根據Keras組態檔~/.keras/keras.json中的image_data_format值來設定,如果還沒有設定過,那么默認值就是"channels_last",
五,Pytorch 和 Keras 的卷積層函式理解
5.1,torch.nn.Conv2d
class torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)
二維卷積層, 輸入的尺度是(N, C_in, H, W),輸出尺度(N,C_out,H_out,W_out),卷積層輸出尺度的 Weight 計算公式如下(Height 同理):
Pytorch/Caffe框架輸入輸出資料的尺寸都是 ((N, C, H, W)),常規卷積的卷積核權重shape都為(C_out, C_in, kernel_height, kernel_width),常規卷積是這樣,但是分組卷積的卷積核權重shape為(C_out, C_in/g, kernel_height, kernel_width)和DW卷積的卷積核 權重shape為(C_in, 1, kernel_height, kernel_width),
kernel_size, stride, padding, dilation 引數可以是以下兩種形式( Maxpool2D 也一樣):
a single int:同樣的引數值被應用與height和width兩個維度,a tuple of two ints:第一個int值應用于height維度,第二個int值應用于width維度,也就是說卷積輸出后的height和width值是不同的,要分別計算,
主要引數解釋:
in_channels(int) – 輸入信號的通道,out_channels(int) – 卷積產生的通道,kerner_size(int or tuple) - 卷積核的尺寸,stride(int or tuple,optional) - 卷積步長,默認值為1,padding(int or tuple,optional) - 輸入的每一條邊補充0的層數,默認不填充,dilation(int or tuple,optional) – 卷積核元素之間的間距,默認取值1,groups(int,optional) – 從輸入通道到輸出通道的阻塞連接數,bias(bool,optional) - 如果bias=True,添加偏置,
示例代碼:
###### Pytorch卷積層輸出大小驗證
import torch
import torch.nn as nn
import torch.autograd as autograd
# With square kernels and equal stride
# output_shape: height = (50-3)/2+1 = 24.5,卷積向下取整,所以 height=24.
m = nn.Conv2d(16, 33, 3, stride=2)
# # non-square kernels and unequal stride and with padding
# m = nn.Conv2d(16, 33, (3, 5), stride=(2, 1), padding=(4, 2)) # 輸出shape: torch.Size([20, 33, 28, 100])
# # non-square kernels and unequal stride and with padding and dilation
# m = nn.Conv2d(16, 33, (3, 5), stride=(2, 1), padding=(4, 2), dilation=(3, 1)) # 輸出shape: torch.Size([20, 33, 26, 100])
input = autograd.Variable(torch.randn(20, 16, 50, 100))
output = m(input)
print(output.shape) # 輸出shape: torch.Size([20, 16, 24, 49])
5.2,keras.layers.Conv2D
keras.layers.Conv2D(filters, kernel_size, strides=(1, 1), padding='valid', data_format=None, dilation_rate=(1, 1), activation=None, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None)
2D 卷積層 (例如對影像的空間卷積),輸入輸出尺寸格式要求和池化層函式一樣,輸入尺寸:(N, H, W, C),卷積核尺寸:(K, K, C_in, C_out),
當使用該層作為模型第一層時,需要提供 input_shape 引數(整數元組,不包含 batch 軸),例如,input_shape=(128, 128, 3) 表示 128x128 的 RGB 影像,在 data_format="channels_last" 時,
主要引數解釋:
filters: 整數,輸出空間的維度 (即卷積中濾波器的輸出數量),kernel_size: 一個整數,或者2個整數表示的元組或串列,指明2D卷積視窗的寬度和高度, 可以是一個整數,為所有空間維度指定相同的值,strides: 一個整數,或者2個整數表示的元組或串列,指明卷積核模板沿寬度和高度方向的移動步長, 可以是一個整數,為所有空間維度指定相同的值, 指定任何 stride 值 != 1 與指定 dilation_rate 值 != 1 兩者不兼容,默認取值 1,即代表會不遺漏的滑過輸入圖片(Feature Map)的每一個點,padding:"valid"或"same"(大小寫敏感),默認valid,這里的"same"代表給邊界加上Padding讓卷積的輸出和輸入保持同樣("same")的尺寸(即填充像素),data_format: 字串,channels_last (默認)或channels_first之一,表示輸入中維度的順序,channels_last對應輸入尺寸為(batch_size, height, width, channels), channels_first 對應輸入尺寸為(batch_size, channels, height, width), 它默認為從Keras組態檔~/.keras/keras.json中 找到的image_data_format值, 如果你從未設定它,將使用channels_last,dilation_rate: 一個整數或2個整數的元組或串列, 指定膨脹卷積(空洞卷積dilated convolution)的膨脹率, 可以是一個整數,為所有空間維度指定相同的值, 當前,指定任何 dilation_rate 值 != 1 與 指定 stride 值 != 1 兩者不兼容,
5.3,總結
Pytorch 的 Conv2d 函式不要求提供 輸入資料的大小 (H,W),但是要提供輸入深度,Keras 的 Conv2d 函式第一層要求提供 input_shape 引數 (H,W, C),其他層不需要,
六,softmax 回歸
分類問題中,直接使用輸出層的輸出有兩個問題:
- 神經網路輸出層的輸出值的范圍不確定,我們難以直觀上判斷這些值的意義
- 由于真實標簽是離散值,這些離散值與不確定范圍的輸出值之間的誤差難以衡量
softmax 回歸解決了以上兩個問題,它將輸出值變換為值為正且和為 1 的概率分布,公式如下:
七,交叉熵損失函式
交叉熵刻畫了兩個概率分布之間的距離,它是分類問題中使用比較廣泛的一種損失函式,交叉熵一般會與 softmax 回歸一起使用,公式如下:
- \(p\) ——代表正確答案;
- \(q\) ——代表預測值;
- \(M\) ——類別的數量;
- \(y_{c}\) ——指示變數(
0或1),如果該類別和樣本的類別相同就是1,否則是0; - \(p_{c}\) ——對于觀測樣本屬于類別 \(c\) 的預測概率,
7.1,為什么交叉熵可以用作代價函式
從數學上來理解就是,為了讓學到的模型分布更接近真實資料的分布,我們需要最小化模型資料分布與訓練資料之間的 KL 散度,而因為訓練資料的分布是固定的,因此最小化 KL 散度等價于最小化交叉熵,而且交叉熵計算更簡單,所以機器/深度學習中常用交叉熵 cross-entroy 作為分類問題的損失函式,
7.2,優化演算法理解
Adam、AdaGrad、RMSProp優化演算法具有自適應性,
八,感受野理解
感受野理解(Receptive Field)是指后一層神經元在前一層神經元的感受空間,也可以定義為卷積神經網路中每層的特征圖(Feature Map)上的像素點在原始影像中映射的區域大小,即如下圖所示:

注意:感受野在 CNN 中是呈指數級增加的,小卷積核(如 3*3)通過多層疊加可取得與大卷積核(如 7*7)同等規模的感受野,此外采用小卷積核有兩個優勢:
- 小卷積核需多層疊加,加深了網路深度進而增強了網路容量(
model capacity)和復雜度(model complexity), - 增強了網路容量的同時減少了引數個數,
8.1,感受野大小計算
計算感受野時,我們需要知道:
參考 感受野(receptive file)計算
- 第一層卷積層的輸出特征影像素的感受野的大小等于濾波器的大小;
- 深層卷積層的感受野大小和它之前所有層的濾波器大小和步長有關系;
- 計算感受野大小時,忽略了影像邊緣的影響,
感受野的計算方式有兩種:自底向上和自頂向下(top to down),這里只講解后者,正常卷積(且不帶 padding)感受野計算公式如下:
其中 \(F(i, j)\) 表示第 i 層對第 j 層的區域感受野,所以這個公式是從上層向下層計算感受野的,仔細看這個公式會發現和反卷積輸出大小計算公式一模一樣,實際上感受野計算公式就是 feature_map 計算公式的反向推導,
以下 Python 代碼可以實作計算 Alexnet zf-5 和 VGG16 網路每層輸出 feature map 的感受野大小,卷積核大小和輸入影像尺寸默認定義好了,代碼如下:
# !/usr/bin/env python
# [filter size, stride, padding]
net_struct = {'alexnet': {'net':[[11,4,0],[3,2,0],[5,1,2],[3,2,0],[3,1,1],[3,1,1],[3,1,1],[3,2,0]],
'name':['conv1','pool1','conv2','pool2','conv3','conv4','conv5','pool5']},
'vgg16': {'net':[[3,1,1],[3,1,1],[2,2,0],[3,1,1],[3,1,1],[2,2,0],[3,1,1],[3,1,1],[3,1,1],
[2,2,0],[3,1,1],[3,1,1],[3,1,1],[2,2,0],[3,1,1],[3,1,1],[3,1,1],[2,2,0]],
'name':['conv1_1','conv1_2','pool1','conv2_1','conv2_2','pool2','conv3_1','conv3_2',
'conv3_3', 'pool3','conv4_1','conv4_2','conv4_3','pool4','conv5_1','conv5_2','conv5_3','pool5']},
'zf-5':{'net': [[7,2,3],[3,2,1],[5,2,2],[3,2,1],[3,1,1],[3,1,1],[3,1,1]],
'name': ['conv1','pool1','conv2','pool2','conv3','conv4','conv5']}}
def outFromIn(isz, net, layernum):
"""
計算feature map大小
"""
totstride = 1
insize = isz
# for layer in range(layernum):
fsize, stride, pad = net[layernum]
outsize = (insize - fsize + 2*pad) / stride + 1
insize = outsize
totstride = totstride * stride
return outsize, totstride
def inFromOut(net, layernum):
"""
計算感受野receptive file大小
"""
RF = 1
for layer in reversed(range(layernum)): # reversed 函式回傳一個反向的迭代器
fsize, stride, pad = net[layer]
RF = ((RF -1)* stride) + fsize
return RF
if __name__ == '__main__':
imsize = 224
feature_size = imsize
print ("layer output sizes given image = %dx%d" % (imsize, imsize))
for net in net_struct.keys():
feature_size = imsize
print ('************net structrue name is %s**************'% net)
for i in range(len(net_struct[net]['net'])):
feature_size, stride = outFromIn(feature_size, net_struct[net]['net'], i)
rf = inFromOut(net_struct[net]['net'], i+1)
print ("Layer Name = %s, Output size = %3d, Stride = % 3d, RF size = %3d" % (net_struct[net]['name'][i], feature_size, stride, rf))
程式輸出結果如下:
layer output sizes given image = 224x224
************net structrue name is alexnet**************
Layer Name = conv1, Output size = 54, Stride = 4, RF size = 11
Layer Name = pool1, Output size = 26, Stride = 2, RF size = 19
Layer Name = conv2, Output size = 26, Stride = 1, RF size = 51
Layer Name = pool2, Output size = 12, Stride = 2, RF size = 67
Layer Name = conv3, Output size = 12, Stride = 1, RF size = 99
Layer Name = conv4, Output size = 12, Stride = 1, RF size = 131
Layer Name = conv5, Output size = 12, Stride = 1, RF size = 163
Layer Name = pool5, Output size = 5, Stride = 2, RF size = 195
************net structrue name is vgg16**************
Layer Name = conv1_1, Output size = 224, Stride = 1, RF size = 3
Layer Name = conv1_2, Output size = 224, Stride = 1, RF size = 5
Layer Name = pool1, Output size = 112, Stride = 2, RF size = 6
Layer Name = conv2_1, Output size = 112, Stride = 1, RF size = 10
Layer Name = conv2_2, Output size = 112, Stride = 1, RF size = 14
Layer Name = pool2, Output size = 56, Stride = 2, RF size = 16
Layer Name = conv3_1, Output size = 56, Stride = 1, RF size = 24
Layer Name = conv3_2, Output size = 56, Stride = 1, RF size = 32
Layer Name = conv3_3, Output size = 56, Stride = 1, RF size = 40
Layer Name = pool3, Output size = 28, Stride = 2, RF size = 44
Layer Name = conv4_1, Output size = 28, Stride = 1, RF size = 60
Layer Name = conv4_2, Output size = 28, Stride = 1, RF size = 76
Layer Name = conv4_3, Output size = 28, Stride = 1, RF size = 92
Layer Name = pool4, Output size = 14, Stride = 2, RF size = 100
Layer Name = conv5_1, Output size = 14, Stride = 1, RF size = 132
Layer Name = conv5_2, Output size = 14, Stride = 1, RF size = 164
Layer Name = conv5_3, Output size = 14, Stride = 1, RF size = 196
Layer Name = pool5, Output size = 7, Stride = 2, RF size = 212
************net structrue name is zf-5**************
Layer Name = conv1, Output size = 112, Stride = 2, RF size = 7
Layer Name = pool1, Output size = 56, Stride = 2, RF size = 11
Layer Name = conv2, Output size = 28, Stride = 2, RF size = 27
Layer Name = pool2, Output size = 14, Stride = 2, RF size = 43
Layer Name = conv3, Output size = 14, Stride = 1, RF size = 75
Layer Name = conv4, Output size = 14, Stride = 1, RF size = 107
Layer Name = conv5, Output size = 14, Stride = 1, RF size = 139
九,卷積和池化操作的作用
卷積核池化的定義核程序理解是不難的,但是其作用卻沒有一個標準的答案,我在網上看了眾多博客和魏秀參博士的書籍,總結了以下答案,
卷積層和池化層的理解可參考魏秀參的《決議卷積神經網路》書籍,卷積(convolution )操作的作用如下:
區域感知,引數共享的特點大大降低了網路引數,保證了網路的稀疏性,- 通過卷積核的組合以及隨著網路后續操作的進行,卷積操作可獲取影像不同區域的不同型別特征;模型靠近底部的層提取的是區域的、高度通用的特征圖,而更靠近頂部的層提取的是更加抽象的語意特征,
池化/匯合(pooling )操作作用如下:
- 特征不變性(feature invariant),匯合操作使模型更關注是否存在某些特征而不是特征具體的位置可看作是一種很強的先驗,使特征學習包含某種程度自由度,能容忍一些特征微小的位移,
- 特征降維,由于匯合操作的降采樣作用,匯合結果中的一個元素對應于原輸入資料的一個子區域(sub-region),因此匯合相當于在空間范圍內做了維度約減(spatially dimension reduction),從而使模型可以抽取更廣范圍的特征,同時減小了下一層輸入大小,進而減小計算量和引數個數,
- 在一定程度上能防止過擬合(overfitting),更方便優化,
參考資料
魏秀參-《決議卷積神經網路》
十,卷積層與全連接層的區別
- 卷積層學習到的是區域模式(對于影像,學到的就是在輸入影像的二維小視窗中發現的模式)
- 全連接層學習到的是全域模式(全域模式就算設計所有像素)
十一,CNN 權值共享問題
首先權值共享就是濾波器共享,濾波器的引數是固定的,即是用相同的濾波器去掃一遍影像,提取一次特征特征,得到feature map,在卷積網路中,學好了一個濾波器,就相當于掌握了一種特征,這個濾波器在影像中滑動,進行特征提取,然后所有進行這樣操作的區域都會被采集到這種特征,就好比上面的水平線,
十二,CNN 結構特點
典型的用于分類的CNN主要由卷積層+激活函式+池化層組成,最后用全連接層輸出,卷積層負責提取影像中的區域特征;池化層用來大幅降低引數量級(降維);全連接層類似傳統神經網路的部分,用來輸出想要的結果,
CNN 具有區域連接、權值共享、池化操作(簡單說就是下采樣)和多層次結構的特點,
- 區域連接使網路可以提取資料的區域特征,
- 權值共享大大降低了網路的訓練難度,一個Filter只提取一個特征,在整個圖片(或者語音/文本) 中進行卷積,
- 池化操作與多層次結構一起,實作了資料的降維,將低層次的區域特征組合成為較高層次的特征,從而對整個圖片進行表示,
- 卷積神經網路學到的模式具有平移不變性(
translation invariant),且可以學到模式的空間層次結構,
Reference
(二)計算機視覺四大基本任務(分類、定位、檢測、分割
十三,深度特征的層次性
卷積操作可獲取影像區域不同型別特征,而匯合等操作可對這些特征進行融合和抽象,隨著若干卷積、匯合等操作的堆疊,各層得到的深度特征逐漸從泛化特征(如邊緣、紋理等)過渡到高層語意表示(軀干、頭部等模式),
十四,什么樣的資料集不適合深度學習
- 資料集太小,資料樣本不足時,深度學習相對其它機器學習演算法,沒有明顯優勢,
- 資料集沒有區域相關特性,目前深度學習表現比較好的領域主要是影像/語音/自然語言處理等領域,這些領域的一個共性是區域相關性,影像中像素組成物體,語音信號中音位組合成單詞,文本資料中單詞組合成句子,這些特征元素的組合一旦被打亂,表示的含義同時也被改變,對于沒有這樣的區域相關性的資料集,不適于使用深度學習演算法進行處理,舉個例子:預測一個人的健康狀況,相關的引數會有年齡、職業、收入、家庭狀況等各種元素,將這些元素打亂,并不會影響相關的結果,
十五,什么造成梯度消失問題
- 神經網路的訓練中,通過改變神經元的權重,使網路的輸出值盡可能逼近標簽以降低誤差值,訓練普遍使用BP演算法,核心思想是,計算出輸出與標簽間的損失函式值,然后計算其相對于每個神經元的梯度,進行權值的迭代,
- 梯度消失會造成權值更新緩慢,模型訓練難度增加,造成梯度消失的一個原因是,許多激活函式將輸出值擠壓在很小的區間內,在激活函式兩端較大范圍的定義域內梯度為0,造成學習停止,
十六,Overfitting 和 Underfitting 問題
16.1,過擬合問題怎么解決
首先所謂過擬合,指的是一個模型過于復雜之后,它可以很好地“記憶”每一個訓練資料中隨機噪音的部分而忘記了去“訓練”資料中的通用趨勢,訓練好后的模型過擬合具體表現在:模型在訓練資料上損失函式較小,預測準確率較高;但是在測驗資料上損失函式比較大,預測準確率較低,解決辦法如下:
資料增強, 增加資料多樣性;- 正則化策略:如 Parameter Norm Penalties(引數范數懲罰),
L1, L2正則化; dropout;- 模型融合, 比如Bagging 和其他集成方法;
BN,batch normalization;- Early Stopping(提前終止訓練),
16.2,如何判斷深度學習模型是否過擬合
- 首先將訓練資料劃分為訓練集和驗證集,
80%用于訓練集,20%用于驗證集(訓練集和驗證集一定不能相交);訓練都時候每隔一定Epoch比較驗證集但指標和訓練集是否一致,如果不一致,并且變壞了,那么意味著過擬合, - 用學習曲線
learning curve來判別過擬合,參考此博客,
16.3,欠擬合怎么解決
underfitting 欠擬合的表現就是模型不收斂,原因有很多種,這里以神經網路擬合能力不足問題給出以下參考解決方法:
- 尋找最優的權重初始化方案:如 He正態分布初始化
he_normal,深度學習框架都內置了很多權重初始化方法; - 使用適當的激活函式:卷積層的輸出使用的激活函式一般為
ReLu,回圈神經網路中的回圈層使用的激活函式一般為tanh,或者ReLu; - 選擇合適的優化器和學習速率:
SGD優化器速度慢但是會達到最優.
16.4,如何判斷模型是否欠擬合
神級網路欠擬合的特征就是模型訓練了足夠長但時間后, loss 值依然很大甚至與初始值沒有太大區別,且精度很低,測驗集亦如此,根據我的總結,原因一般有以下幾種:
- 神經網路的擬合能力不足;
- 網路配置的問題;
- 資料集配置的問題;
- 訓練方法出錯(初學者經常碰到,原因千奇百怪),
十七,L1 和 L2 范數區別
\(L1\) 范數(L1 norm)是指向量中各個元素絕對值之和,也有個美稱叫“稀疏規則算子”(Lasso regularization), 比如 向量 \(A=[1,-1,3]\), 那么 A 的 \(L1\) 范數為 \(|1|+|-1|+|3|\),簡單總結一下就是:
- \(L1\) 范數: 為向量 \(x\) 各個元素絕對值之和,
- \(L2\) 范數: 為向量 \(x\) 各個元素平方和的 \(\frac{1}{2}\) 次方,\(L2\) 范數又稱 Euclidean 范數或 Frobenius 范數
- \(L_{p}\) 范數: 為向量 \(x\) 各個元素絕對值 \(p\) 次方和的 \(1/p\) 次方,\(L_{p}\) 范數定義為: \(||x||_{p} = (\sum_{i=1}^{n} |x_i|^{p})^\frac{1}{p}\)
在支持向量機學習程序中,\(L1\) 范數實際是一種對于成本函式求解最優的程序,因此,\(L1\) 范數正則化通過向成本函式中添加 \(L1\) 范數,使得學習得到的結果滿足稀疏化,從而方便人類提取特征,
\(L1\) 范數可以使權值引數稀疏,方便特征提取, \(L2\) 范數可以防止過擬合,提升模型的泛化能力,
參考資料學習
- 淺談L0,L1,L2范數及其應用
- L1和L2 詳解(范數、損失函式、正則化)
十八,TensorFlow計算圖概念
Tensorflow 是一個通過計算圖的形式來表述計算的編程系統,計算圖也叫資料流圖,可以把計算圖看做是一種有向圖,Tensorflow 中的每一個計算都是計算圖上的一個節點,而節點之間的邊描述了計算之間的依賴關系,
十九,BN(批歸一化)的作用
在神經網路中間層也進行歸一化處理,使訓練效果更好的方法,就是批歸一化Batch Normalization(BN),
(1). 可以使用更高的學習率,如果每層的 scale 不一致,實際上每層需要的學習率是不一樣的,同一層不同維度的 scale 往往也需要不同大小的學習率,通常需要使用最小的那個學習率才能保證損失函式有效下降,Batch Normalization 將每層、每維的 scale 保持一致,那么我們就可以直接使用較高的學習率進行優化,
(2). 移除或使用較低的 dropout, dropout 是常用的防止 overfitting 的方法,而導致 overfitting 的位置往往在資料邊界處,如果初始化權重就已經落在資料內部,overfitting現象就可以得到一定的緩解,論文中最后的模型分別使用10%、5%和0%的dropout訓練模型,與之前的 40%-50% 相比,可以大大提高訓練速度,
(3). 降低 L2 權重衰減系數, 還是一樣的問題,邊界處的區域最優往往有幾維的權重(斜率)較大,使用 L2 衰減可以緩解這一問題,現在用了 Batch Normalization,就可以把這個值降低了,論文中降低為原來的 5 倍,
(4). 代替Local Response Normalization層, 由于使用了一種 Normalization,再使用 LRN 就顯得沒那么必要了,而且 LRN 實際上也沒那么 work,
(5). Batch Normalization調整了資料的分布,不考慮激活函式,它讓每一層的輸出歸一化到了均值為0方差為1的分布,這保證了梯度的有效性,可以解決反向傳播程序中的梯度問題,目前大部分資料都這樣解釋,比如 BN 的原始論文認為的緩解了 Internal Covariate Shift(ICS) 問題,
關于訓練階段和推理階段 BN 的不同可以參考 Batch Normalization詳解 ,
二十,什么是梯度消失和爆炸
- 梯度消失是指在深度學習訓練的程序中,梯度隨著
BP演算法中的鏈式求導逐層傳遞逐層減小,最后趨近于0,導致對某些層的訓練失效; - 梯度爆炸與梯度消失相反,梯度隨著
BP演算法中的鏈式求導逐層傳遞逐層增大,最后趨于無窮,導致某些層無法收斂;
在反向傳播程序中需要對激活函式進行求導,如果導數大于 1,那么隨著網路層數的增加,梯度更新將會朝著指數爆炸的方式增加這就是梯度爆炸,同樣如果導數小于 1,那么隨著網路層數的增加梯度更新資訊會朝著指數衰減的方式減少這就是梯度消失,
梯度消失和梯度爆炸產生的原因
出現梯度消失和梯度爆炸的問題主要是因為引數初始化不當以及激活函式選擇不當造成的,其根本原因在于反向傳播訓練法則,屬于先天不足,當訓練較多層數的模型時,一般會出現梯度消失問題(gradient vanishing problem)和梯度爆炸問題(gradient exploding problem),注意在反向傳播中,當網路模型層數較多時,梯度消失和梯度爆炸是不可避免的,
深度神經網路中的梯度不穩定性,根本原因在于前面層上的梯度是來自于后面層上梯度的乘積,當存在過多的層次時,就出現了內在本質上的不穩定場景,前面的層比后面的層梯度變化更小,故變化更慢,故引起了梯度消失問題,前面層比后面層梯度變化更快,故引起梯度爆炸問題,
如何解決梯度消失和梯度爆炸問題
常用的有以下幾個方案:
- 預訓練模型 + 微調
- 梯度剪切 + 正則化
relu、leakrelu等激活函式BN批歸一化- 引數標準初始化函式如
xavier CNN中的殘差結構LSTM結構
二十一,RNN回圈神經網路理解
回圈神經網路(recurrent neural network, RNN), 主要應用在語音識別、語言模型、機器翻譯以及時序分析等問題上,
在經典應用中,卷積神經網路在不同的空間位置共享引數,回圈神經網路是在不同的時間位置共享引數,從而能夠使用有限的引數處理任意長度的序列,
RNN 可以看做作是同一神經網路結構在時間序列上被復制多次的結果,這個被復制多次的結構稱為回圈體,如何設計回圈體的網路結構是 RNN 解決實際問題的關鍵,RNN 的輸入有兩個部分,一部分為上一時刻的狀態,另一部分為當前時刻的輸入樣本,
二十二,訓練程序中模型不收斂,是否說明這個模型無效,導致模型不收斂的原因
不一定,導致模型不收斂的原因有很多種可能,常見的有以下幾種:
- 沒有對資料做歸一化,
- 沒有檢查過你的結果,這里的結果包括預處理結果和最終的訓練測驗結果,
- 忘了做資料預處理,
- 忘了使用正則化,
- Batch Size 設的太大,
- 學習率設的不對,
- 最后一層的激活函式用的不對,
- 網路存在壞梯度,比如 ReLu 對負值的梯度為 0,反向傳播時,0 梯度就是不傳播,
- 引數初始化錯誤,
- 網路太深,隱藏層神經元數量錯誤,
- 更多回答,參考此鏈接,
二十三,VGG 使用 2 個 3*3 卷積的優勢
(1). 減少網路層引數,用兩個 3*3 卷積比用 1 個 5*5 卷積擁有更少的引數量,只有后者的 2?3?3/5?5=0.72,但是起到的效果是一樣的,兩個 3×3 的卷積層串聯相當于一個 5×5 的卷積層,感受野的大小都是 5×5,即 1 個像素會跟周圍 5×5 的像素產生關聯,把下圖當成動態圖看,很容易看到兩個 3×3 卷積層堆疊(沒有空間池化)有 5×5 的有效感受野,

(2). 更多的非線性變換,2 個 3×3 卷積層擁有比 1 個 5×5 卷積層更多的非線性變換(前者可以使用兩次 ReLU 激活函式,而后者只有一次),使得卷積神經網路對特征的學習能力更強,
paper中給出的相關解釋:三個這樣的層具有 7×7 的有效感受野,那么我們獲得了什么?例如通過使用三個 3×3 卷積層的堆疊來替換單個 7×7 層,首先,我們結合了三個非線性修正層,而不是單一的,這使得決策函式更具判別性,其次,我們減少引數的數量:假設三層 3×3 卷積堆疊的輸入和輸出有 C 個通道,堆疊卷積層的引數為 3×(3×3C) = 27C 個權重;同時,單個 7×7 卷積層將需要 7×7×C = 49C 個引數,即引數多 81%,這可以看作是對 7×7 卷積濾波器進行正則化,迫使它們通過 3×3 濾波器(在它們之間注入非線性)進行分解,
此回答可以參考 TensorFlow 實戰 p110,網上很多回答都說的不全,
23.1,1*1 卷積的主要作用
- 降維( dimension reductionality ),比如,一張500 * 500且厚度depth為100 的圖片在20個filter上做1*1的卷積,那么結果的大小為500*500*20,
- 加入非線性,卷積層之后經過激勵層,1*1的卷積在前一層的學習表示上添加了非線性激勵( non-linear activation ),提升網路的表達能力;
二十四,Relu比Sigmoid效果好在哪里?
Sigmoid 函式公式如下:
\(\sigma (x)=\frac{1}{1+exp(-x)}\)
ReLU激活函式公式如下:
\[f(x) = max(x, 0) = \begin{cases} x, & \text{if $x$ $\geq$ 0} \\ 0, & \text{if $x$ < 0} \end{cases}\]ReLU 的輸出要么是 0, 要么是輸入本身,雖然方程簡單,但實際上效果更好,在網上看了很多版本的解釋,有從程式實體分析也有從數學上分析,我找了個相對比較直白的回答,如下:
ReLU函式計算簡單,可以減少很多計算量,反向傳播求誤差梯度時,涉及除法,計算量相對較大,采用ReLU激活函式,可以節省很多計算量;- 避免梯度消失問題,對于深層網路,
sigmoid函式反向傳播時,很容易就會出現梯度消失問題(在sigmoid接近飽和區時,變換太緩慢,導數趨于 0,這種情況會造成資訊丟失),從而無法完成深層網路的訓練, - 可以緩解過擬合問題的發生,
ReLU會使一部分神經元的輸出為 0,這樣就造成了網路的稀疏性,并且減少了引數的相互依存關系,緩解了過擬合問題的發生, - 相比
sigmoid型函式,ReLU函式有助于隨機梯度下降方法收斂,
參考鏈接
ReLU為什么比Sigmoid效果好
二十五,神經網路中權值共享的理解
權值(權重)共享這個詞是由 LeNet5 模型提出來的,以 CNN 為例,在對一張圖偏進行卷積的程序中,使用的是同一個卷積核的引數,
比如一個 3×3×1 的卷積核,這個卷積核內 9 個的引數被整張圖共享,而不會因為影像內位置的不同而改變卷積核內的權系數,說的再直白一些,就是用一個卷積核不改變其內權系數的情況下卷積處理整張圖片(當然CNN中每一層不會只有一個卷積核的,這樣說只是為了方便解釋而已),
參考資料
如何理解CNN中的權值共享
二十六,對 fine-tuning(微調模型的理解),為什么要修改最后幾層神經網路權值?
使用預訓練模型的好處,在于利用訓練好的SOTA模型權重去做特征提取,可以節省我們訓練模型和調參的時間,
至于為什么只微調最后幾層神經網路權重,是因為:
(1). CNN 中更靠近底部的層(定義模型時先添加到模型中的層)編碼的是更加通用的可復用特征,而更靠近頂部的層(最后添加到模型中的層)編碼的是更專業業化的特征,微調這些更專業化的特征更加有用,它更代表了新資料集上的有用特征,
(2). 訓練的引數越多,過擬合的風險越大,很多SOTA模型擁有超過千萬的引數,在一個不大的資料集上訓練這么多引數是有過擬合風險的,除非你的資料集像Imagenet那樣大,
參考資料
Python深度學習p127.
二十七,什么是 dropout?
- dropout可以防止過擬合,dropout簡單來說就是:我們在前向傳播的時候,讓某個神經元的激活值以一定的概率 p 停止作業,這樣可以使模型的泛化性更強,因為它不會依賴某些區域的特征,
dropout效果跟bagging效果類似(bagging是減少方差variance,而boosting是減少偏差bias)- 加入dropout會使神經網路訓練時間邊長,模型預測時不需要dropout,記得關掉,

27.1,dropout具體作業流程
以 標準神經網路為例,正常的流程是:我們首先把輸入資料x通過網路前向傳播,然后把誤差反向傳播一決定如何更新引數讓網路進行學習,使用dropout之后,程序變成如下:
1,首先隨機(臨時)刪掉網路中一半的隱藏神經元,輸入輸出神經元保持不變(圖3中虛線為部分臨時被洗掉的神經元);
2,然后把輸入x通過修改后的網路進行前向傳播計算,然后把得到的損失結果通過修改的網路反向傳播,一小批訓練樣本執行完這個程序后,在沒有被洗掉的神經元上按照隨機梯度下降法更新對應的引數(w,b);
3,然后重復這一程序:
- 恢復被刪掉的神經元(此時被洗掉的神經元保持原樣沒有更新w引數,而沒有被洗掉的神經元已經有所更新);
- 從隱藏層神經元中隨機選擇一個一半大小的子集臨時洗掉掉(同時備份被洗掉神經元的引數);
- 對一小批訓練樣本,先前向傳播然后反向傳播損失并根據隨機梯度下降法更新引數(w,b) (沒有被洗掉的那一部分引數得到更新,洗掉的神經元引數保持被洗掉前的結果),
27.2,dropout在神經網路中的應用
(1). 在訓練模型階段
不可避免的,在訓練網路中的每個單元都要添加一道概率流程,標準網路和帶有dropout網路的比較圖如下所示:

(2). 在測驗模型階段
預測模型的時候,輸入是當前輸入,每個神經單元的權重引數要乘以概率p,

27.3,如何選擇dropout 的概率
input 的 dropout 概率推薦是 0.8, hidden layer 推薦是0.5, 但是也可以在一定的區間上取值,(All dropout nets use p = 0.5 for hidden units and p = 0.8 for input units.)
參考資料
- [Dropout:A Simple Way to Prevent Neural Networks from Overfitting]
- 深度學習中Dropout原理決議
二十八,HOG 演算法原理描述
方向梯度直方圖(Histogram of Oriented Gradient, HOG)特征是一種在計算機視覺和影像處理中用來進行物體檢測的特征描述子,它通過計算和統計影像區域區域的梯度方向直方圖來構成特征,在深度學習取得成功之前,Hog特征結合SVM分類器被廣泛應用于影像識別中,在行人檢測中獲得了較大的成功,
HOG特征原理
HOG 的核心思想是所檢測的區域物體外形能夠被光強梯度或邊緣方向的分布所描述,通過將整幅影像分割成小的連接區域(稱為cells),每個 cell 生成一個方向梯度直方圖或者 cell 中pixel 的邊緣方向,這些直方圖的組合可表示(所檢測目標的目標)描述子,
為改善準確率,區域直方圖可以通過計算影像中一個較大區域(稱為block)的光強作為 measure 被對比標準化,然后用這個值(measure)歸一化這個 block 中的所有 cells ,這個歸一化程序完成了更好的照射/陰影不變性,與其他描述子相比,HOG 得到的描述子保持了幾何和光學轉化不變性(除非物體方向改變),因此HOG描述子尤其適合人的檢測,
HOG 特征提取方法就是將一個image:
- 灰度化(將影像看做一個x,y,z(灰度)的三維影像)
- 劃分成小
cells(2*2) - 計算每個 cell 中每個 pixel 的 gradient(即 orientation)
- 統計每個 cell 的梯度直方圖(不同梯度的個數),即可形成每個 cell 的 descriptor,
HOG特征檢測步驟

總結:顏色空間歸一化——>梯度計算——>梯度方向直方圖——>重疊塊直方圖歸一化———>HOG特征
參考資料
HOG特征檢測-簡述
二十九,激活函式
29.1,激活函式的作用
- 激活函式實作去線性化,激活函式的引入是為了增加整個網路的表達能力(引入非線性因素),否則若干線形層的堆疊仍然只能起到線性映射的作用,無法形成復雜的函式,如果將每一個神經元(也就是神經網路的節點)的輸出通過一個非線性函式,那么整個神經網路的模型也就不再是線性的了,這個非線性函式就是激活函式,
- 激活函式可以把當前特征空間通過一定的線性映射轉換到另一個空間,讓資料能夠更好的被分類,
- 激活函式對模型學習、理解非常復雜和非線性的函式具有重要作用,
29.2,常見的激活函式
激活函式也稱非線性映射函式,常見的激活函式有:ReLU 函式、sigmoid 函式、tanh 函式等,其計算公式如下:
- ReLU函式:\(f(x)=max(x,0)\)
- sigmoid函式:\(f(x)=\frac{1}{1+e^{-x}}\)
- tanh函式:\(f(x)=\frac{1+e^{-2x}}{1+e^{-2x}}=\frac{2}{1+e^{-2x}}-1 = 2sigmoid(2x)-1\)
29.3,激活函式理解及函式梯度圖
Sigmoid激活函式,可用作分類任務的輸出層,可以看出經過sigmoid激活函式后,模型輸出的值域被壓縮到0到1區間(這和概率的取值范圍一致),這正是分類任務中sigmoid很受歡迎的原因,

tanh(x)型函式是在sigmoid型函式基礎上為解決均值問題提出的激活函式,tanh 的形狀和 sigmoid 類似,只不過tanh將“擠壓”輸入至區間(-1, 1),至于梯度,它有一個大得多的峰值1.0(同樣位于z = 0處),但它下降得更快,當|x|的值到達 3 時就已經接近零了,這是所謂梯度消失(vanishing gradients)問題背后的原因,會導致網路的訓練進展變慢,

ReLU處理了sigmoid、tanh中常見的梯度消失問題,同時也是計算梯度最快的激勵函式,但是,ReLU函式也有自身缺陷,即在 x < 0 時,梯度便為 y,換句話說,對于小于 y 的這部分卷積結果回應,它們一旦變為負值將再無法影響網路訓練——這種現象被稱作“死區",

三十,卷積層和池化層有什么區別
- 卷積層有引數,池化層沒有引數;
- 經過卷積層節點矩陣深度會改變,池化層不會改變節點矩陣的深度,但是它可以縮小節點矩陣的大小,
三十一,卷積層和池化層引數量計算
參考 神經網路模型復雜度分析 文章,
三十二,神經網路為什么用交叉熵損失函式
判斷一個輸出向量和期望的向量有多接近,交叉熵(cross entroy)是常用的評判方法之一,交叉熵刻畫了兩個概率分布之間的距離,是分類問題中使用比較廣泛的一種損失函式,給定兩個概率分布 p 和 q ,通過 q 來表示 p 的交叉熵公式為:\(H(p,q)=?∑p(x)logq(x)\)
三十三,資料增強方法有哪些
常用資料增強方法:
- 翻轉:
Fliplr,Flipud,不同于旋轉180度,這是類似鏡面的翻折,跟人在鏡子中的映射類似,常用水平、上下鏡面翻轉, - 旋轉:
rotate,順時針/逆時針旋轉,最好旋轉90-180度,否則會出現邊緣缺失或者超出問題,如旋轉45度, - 縮放:
zoom,影像可以被放大或縮小,imgaug庫可用Scal函式實作, - 裁剪:
crop,一般叫隨機裁剪,操作步驟是:隨機從影像中選擇一部分,然后降這部分影像裁剪出來,然后調整為原影像的大小,根本上理解,影像crop就是指從影像中移除不需要的資訊,只保留需要的部分 - 平移:
translation,平移是將影像沿著x或者y方向(或者兩個方向)移動,我們在平移的時候需對背景進行假設,比如說假設為黑色等等,因為平移的時候有一部分影像是空的,由于圖片中的物體可能出現在任意的位置,所以說平移增強方法十分有用, - 放射變換:
Affine,包含:平移(Translation)、旋轉(Rotation)、放縮(zoom)、錯切(shear), - 添加噪聲:過擬合通常發生在神經網路學習高頻特征的時候,為消除高頻特征的過擬合,可以隨機加入噪聲資料來消除這些高頻特征,
imgaug影像增強庫使用GaussianBlur函式, - 亮度、對比度增強:這是影像色彩進行增強的操作
- 銳化:
Sharpen,imgaug庫使用Sharpen函式,
33.1,離線資料增強和在線資料增強有什么區別?
資料增強分兩類,一類是離線增強,一類是在線增強:
- 離線增強 : 直接對硬碟上的資料集進行處理,并保存增強后的資料集檔案,資料的數目會變成增強因子 x 原資料集的數目 ,這種方法常常用于資料集很小的時候
- 在線增強 : 這種增強的方法用于,獲得 batch 資料之后,然后對這個batch的資料進行增強,如旋轉、平移、翻折等相應的變化,由于有些資料集不能接受線性級別的增長,這種方法長用于大的資料集,很多機器學習框架已經支持了這種資料增強方式,并且可以使用GPU優化計算,
`
Reference
深度學習中的資料增強
三十四,ROI Pooling替換為ROI Align的效果,及各自原理
faster rcnn 將 roi pooling 替換為 roi align 效果有所提升,
ROI Pooling原理
RPN 生成的 ROI 區域大小是對應與輸入影像大小(每個roi區域大小各不相同),為了能夠共享權重,所以需要將這些 ROI 映射回特征圖上,并固定大小,ROI Pooling操作程序如下圖:

ROI Pooling 具體操作如下:
Conv layers使用的是VGG16,feat_stride=32(即表示,經過網路層后圖片縮小為原圖的 1/32),原圖 \(800\times 800\),最后一層特征圖feature map大小: \(25\times 25\)- 假定原圖中有一
region proposal,大小為 \(665\times 665\),這樣,映射到特征圖中的大小:\(665/32=20.78\),即大小為 \(20.78\times 20.78\),原始碼中,在計算的時候會進行取整操作,于是,進行所謂的第一次量化,即映射的特征圖大小為20*20; - 假定
pooled_w=7、pooled_h=7,即pooling后固定成 \(7\times 7\) 大小的特征圖,所以,將上面在feature map上映射的 \(20\times 20\) 的region proposal劃分成49個同等大小的小區域,每個小區域的大小 \(20/7=2.86\),,即 \(2.86\times 2.86\),此時,進行第二次量化,故小區域大小變成 \(2\times 2\); - 每個 \(2\times 2\) 的小區域里,取出其中最大的像素值,作為這一個區域的‘代表’,這樣,49 個小區域就輸出 49 個像素值,組成 \(7\times 7\) 大小的
feature map,
所以,通過上面可以看出,經過兩次量化,即將浮點數取整,原本在特征圖上映射的 \(20\times 20\) 大小的 region proposal,偏差成大小為 \(7\times 7\) 的,這樣的像素偏差勢必會對后層的回歸定位產生影響,所以,產生了后面的替代方案: RoiAlign,
ROI Align原理
ROI Align 的作業原理如下圖,

ROI Align 是在 Mask RCNN 中使用以便使生成的候選框region proposal 映射產生固定大小的 feature map 時提出的,根據上圖,有著類似的映射:
Conv layers使用的是VGG16,feat_stride=32(即表示,經過網路層后圖片縮小為原圖的1/32),原圖 \(800\times 800\),最后一層特征圖feature map大小: \(25*\times 25\);- 假定原圖中有一region proposal,大小為 \(665*\times 665\),這樣,映射到特征圖中的大小:\(665/32=20.78\),即大小為 \(20.78\times 20.78\),此時,沒有像
RoiPooling那樣就行取整操作,保留浮點數; - 假定
pooled_w=7,pooled_h=7,即pooling后固定成 \(7\times 7\) 大小的特征圖,所以,將在feature map上映射的 \(20.78\times 20.78\) 的region proposal劃分成 49 個同等大小的小區域,每個小區域的大小 \(20.78/7=2.97\),即 \(2.97\times 2.97\); - 假定采樣點數為
4,即表示,對于每個 \(2.97\times 2.97\) 的小區域,平分四份,每一份取其中心點位置,而中心點位置的像素,采用雙線性插值法進行計算,這樣,就會得到四個點的像素值,如下圖:

上圖中,四個紅色叉叉‘×’的像素值是通過雙線性插值演算法計算得到的,
最后,取四個像素值中最大值作為這個小區域(即:\(2.97\times 2.97\) 大小的區域)的像素值,如此類推,同樣是 49 個小區域得到 49 個像素值,組成 \(7\times 7\) 大小的 feature map,
RoiPooling 和 RoiAlign 總結
總結:知道了 RoiPooling 和 RoiAlign 實作原理,在以后的專案中可以根據實際情況進行方案的選擇;對于檢測圖片中大目標物體時,兩種方案的差別不大,而如果是圖片中有較多小目標物體需要檢測,則優先選擇 RoiAlign,更精準些,
Reference
RoIPooling、RoIAlign筆記
三十五,CNN的反向傳播演算法推導
- 四張圖徹底搞懂CNN反向傳播演算法(通俗易懂)
- 反向傳播演算法推導程序(非常詳細)
三十六,Focal Loss 公式
為了解決正負樣本不平衡的問題,我們通常會在交叉熵損失的前面加上一個引數 \(\alpha\) ,即:
\[CE = \left\{\begin{matrix} -\alpha log(p), & if \quad y=1\\ -(1-\alpha)log(1-p), & if\quad y=0 \end{matrix}\right. \]盡管 \(\alpha\) 平衡了正負樣本,但對難易樣本的不平衡沒有任何幫助,因此,Focal Loss 被提出來了,即:
實驗表明 \(\gamma\) 取 2, \(\alpha\) 取 0.25 的時候效果最佳,
Focal loss成功地解決了在單階段目標檢測時,正負樣本區域極不平衡而目標檢測loss易被大批量負樣本所左右的問題,RetinaNet達到更高的精度的原因不是網路結構的創新,而是損失函式的創新!
三十七,快速回答
37.1,為什么 Faster RCNN、Mask RCNN 需要使用 ROI Pooling、ROI Align?
為了使得最后面的兩個全連接層能夠共享 conv layers(VGG/ResNet) 權重,在所有的 RoIs 都被 pooling 成(512×7×7)的feature map后,將它 reshape 成一個一維的向量,就可以利用 VGG16 的預訓練的權重來初始化前兩層全連接,
37.2,softmax公式
\[softmax(y)_{i} = \frac{e^{y_{i}}}{\sum_{j=1}^{n}e^{y_j}} \]
37.3,上采樣方法總結
上采樣大致被總結成了三個類別:
- 基于線性插值的上采樣:最近鄰演算法(
nearest)、雙線性插值演算法(bilinear)、雙三次插值演算法(bicubic)等,這是傳統影像處理方法, - 基于深度學習的上采樣(轉置卷積,也叫反卷積
Conv2dTranspose2d等) Unpooling的方法(簡單的補零或者擴充操作)
計算效果:最近鄰插值演算法 < 雙線性插值 < 雙三次插值,計算速度:最近鄰插值演算法 > 雙線性插值 > 雙三次插值
37.4,移動端深度學習框架知道哪些,用過哪些?
知名的有TensorFlow Lite、小米MACE、騰訊的 ncnn 等,目前都沒有用過,
37.5,如何提升網路的泛化能力
和防止模型過擬合的方法類似,另外還有模型融合方法,
37.6,BN演算法,為什么要在后面加伽馬和貝塔,不加可以嗎?
最后的 scale and shift 操作則是為了讓因訓練所需而“刻意”加入的BN能夠有可能還原最初的輸入,不加也可以,
37.7,驗證集和測驗集的作用
- 驗證集是在訓練程序中用于檢驗模型的訓練情況,從而確定合適的超引數;
- 測驗集是在模型訓練結束之后,測驗模型的泛化能力,
三十八,交叉驗證的理解和作用
參考知乎文章 N折交叉驗證的作用(如何使用交叉驗證),我的理解之后補充,
三十九,介紹一下NMS和IOU的原理
NMS全稱是非極大值抑制,顧名思義就是抑制不是極大值的元素,在目標檢測任務中,通常在決議模型輸出的預測框時,預測目標框會非常的多,其中有很多重復的框定位到了同一個目標,NMS 的作用就是用來除去這些重復框,從而獲得真正的目標框,而 NMS 的程序則用到了 IOU,IOU 是一種用于衡量真實和預測之間相關度的標準,相關度越高,該值就越高,IOU 的計算是兩個區域重疊的部分除以兩個區域的集合部分,簡單的來說就是交集除以并集,
在 NMS 中,首先對預測框的置信度進行排序,依次取置信度最大的預測框與后面的框進行 IOU 比較,當 IOU 大于某個閾值時,可以認為兩個預測框框到了同一個目標,而置信度較低的那個將會被剔除,依次進行比較,最終得到所有的預測框,
Reference
- 《Batch Normalization Accelerating Deep Network Training by Reducing Internal Covariate Shift》閱讀筆記與實作
- 詳解機器學習中的梯度消失、爆炸原因及其解決方法
- N折交叉驗證的作用(如何使用交叉驗證)
- 5分鐘理解Focal Loss與GHM——解決樣本不平衡利器
- 深度學習CV崗位面試問題總結(目標檢測篇)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/538044.html
標籤:其他
