捲積神經網路(convolutional neural network,CNN),權值共用(weight sharing)網路結構降低模型複雜度,減少權值數量,是語音分析、圖像識別熱點。無須人工特征提取、數據重建,直接把圖片作輸入,自動提取特征,對平移、比例縮放、傾斜等圖片變形具有高度不變形。捲積( ...
捲積神經網路(convolutional neural network,CNN),權值共用(weight sharing)網路結構降低模型複雜度,減少權值數量,是語音分析、圖像識別熱點。無須人工特征提取、數據重建,直接把圖片作輸入,自動提取特征,對平移、比例縮放、傾斜等圖片變形具有高度不變形。捲積(convolution),泛函數分析積分變換數學方法,兩個函數f和g生成第三個函數數學運算元,表徵函靈敏f與g翻轉、平移重疊部分面積。f(x)、g(x)為R1兩個可積函數。積分新函數為函數f與g捲積。∫-∞+∞f(τ)g(x-E)dτ。
神經網路(neural networks,NN)包括輸入層、隱藏層、輸出層。捲積神經網路隱藏層分為捲積層和池化層(pooling layer 下採樣層)。捲積層的捲積核(conventional kernel)在原始圖像平移提取特征,每個特征是特征映射。池化層匯聚特征稀疏參數減少學習參數數量,降低網路複雜度。最大值池化(max pooling)、平均值池化(average pooling)。捲積核提取特征映射動作padding,移動步長(Stride)不一定整除圖像素寬度,越邊邊緣取樣為SAME,不越過邊緣取樣為VALID。
Necognitron->LeCun->LeNet->AlexNet
->網路加深:VGG16->VGG19
->增強捲積層功能:NIN->GoogleNet->Incption V3 Incption V4 ->
二者結合ResNet
->分類任務到檢測任務:KCNN->FastRCNN->Faster-CNN
->增加新功能模塊:FCN->STNet->CNN+RM/LSTM
捲積神經網路起點神經認知機(neocognitron)模型,出現捲積結構。第一個捲積神經網路模型LeCun,1989年,發明人LeCun。論文 http://yann.lecun.com/exdb/publis/pdf/lecun-98.pdf。徑向基函數(radial basis function RBF)。1998年,LeCun,LeNet。http://vision.stanford.edu/cs598_spring07/papers/Lecun98.pdf。SVM 手工設計特征分類器。ReLU,Dropout ,GPU,大數據,2012年曆史性突破AlexNet。
網路加深。
LeNet。輸入層32x32,圖像預處理reshape,潛在明顯特征出現在最高層特征監測捲積核中心。捲積層3個(C1、C3、C5),增強原信號特征、降低噪音,線上演示: https://graphics.stanford.edu/courses/cs178/applets/convolution.html 不同捲積核輸出特征映射不同。降採樣層2個(S2、S4),降低網路訓練參數、模型過擬合程度,最大池化(max pooling)選中區域最大值,平均值池化(mean pooling)選中區域平均值。全連接層1個(F6),輸入向量和權重向量點積加偏置,傳給sigmoid函數,產生單元i狀態。輸出層(高斯連接),歐式徑向基函數(Euclidean radial basis funtion)單元,10個類別對應10個徑向基函數單元,每個單元84個輸入,輸出RBF單元計算輸入向量和類別標記向量歐式距離,越遠越大。
AlexNet,2012年,Geoffrey Hintion及學生Alex Krizhevsky、Ilya Sutskever,《ImageNet Classification with Deep Convolutional Neural Networks》。不同GPU處理圖像的不同部分,僅在部分層通信。5個捲積層,3個全連接層,5000萬個可調參數。最後全連接層輸出到1000維softmax層,產生覆蓋1000類標記分佈。防止過擬合,Dropout 0.5概率隱藏層神經元輸出置0,共用權值,降低互適應,收斂迭代次數增加一倍。數據增強(data augmentation)變形(水平翻轉圖像、反射變化flip,原始圖像隨機平移變換crop,隨機光照、彩色變換、顏色抖動)增加新數據。非線性激活函數,ReLU,收斂速度比sigmoid/tanh快。大數據訓練,120萬ImageNet圖像數據。GPU實現,直接從GPU記憶體讀出、寫入。LRN(local response normalization)規範化層。
增強捲積層功能。
VGGNet,Karen simonyan、Andrew Zisserman 《Very Deep Convolutional Networks for Large_Scale Visual Recognition》http://www.robots.ox.ac.uk/~vgg/research/very_deep/ 。5個捲積組(8-16層)、2層全連接層圖像特征,1層全連接分類特征。加深捲積層數達到準確率提升瓶頸。
GoogleNet。NIN(Network in Network)思想,Min Lin、Qiang Chen、Shuicheng Yan論文《Network In Network》https://arxiv.org/abs/1312.4400 。線性捲積層(linear convolution layer)變多層感知捲積層(multilayer perceptron),全連接層改為全局平均池化。2014年 GoogleNet(Inception V1),Christian Szegedy、Wei Liu論文《Going Deeper with Convolutions》https://arxiv.org/abs/1409.4842 。使用1x1捲積核降維,在全連接層連接1x1、3x3、5x5捲積結果。寬度、深度擴大,加速。層數更深,22層,不同深度增加兩上損失函數避免反向傳播梯度消失。增加多種大小捲積核,降維Inception模型,1x1捲積核降低特征映射厚度。
結合網路加深和增強捲積模塊功能。
ResNet。2015年,ILSVRC不依賴外部數據物體檢測、物體識別項目冠軍,MSRA 何凱明,152層。ImageNet 分類、檢測、定位、COCO數據集檢測(deteciton)、分隔(segmentation)冠軍。Kaiming He、Xiangyu Zhang、Shaoqing Ren、Jian Sun《Deep Residual Learning for Image Recognition》 https://arxiv.org/abs/1512.03385 。網路退化(network degradation),shortcut結構,輸入跳層傳遞加捲積結果。殘差(residual),複雜非線性映射H(x)預測圖片分類,殘差函數(residual function)F(x)=H(x)-x,優化殘差映射比直接優化H(x)簡單。
從分類任務到檢測任務。圖片目標檢測,視頻目標檢測(VID)。
R-CNN,Region Proposal Networks(RPN)和CNN結合。RPNs,任意尺寸圖片一系列帶識別物體概率分數建議區域。使用小網路在最後捲積特征映射滑動掃描,滑動網路每次與特征映射視窗全連接,映射到低維向量,送入兩個全連接層(box回歸層box-regression layer和box分類層box-classification layer)。重覆計算,幾千個建議區域(region)互相重疊,多次重覆提取特性。
Fast R-CNN,加速版本,最後建議區域映射CNN最後捲積層特征映射,一張圖片只提取一次特征,提高速度,瓶頸在RPN,支持多類物體同時檢測,行人車輛檢測技術。
Fater-R-CNN,RPN交給CNN做,達到實時。Shaoqing Ren、Kaiming He、Ross Girshick、Jian Sun論文《Faster R-CNN:Towards Real-Time Object Detection with Region Proposal Networks》 https://arxiv.org/abs/1506.01497 。
增加新功能模塊。
FCN(反捲積)、STNet、CNN與RNN/LSTM混合結構。
MNIST AlexNet實現。網路結構圖。
1、仔細研讀網路論文,理解每一層輸入、輸出值、網路結構。
2、按照載入數據、定義網路模型、訓練模型、評估模型步驟實現網路。
https://github.com/aymericdamien/TensorFlow-Examples/blob/master/examples/3_NeuralNetworks/convolutional_network.py 。
https://github.com/tensorflow/models/blob/master/tutorials/image/alexnet/alexnet_benchmark.py 。
#!/usr/bin/python
# -*- coding:utf8 -*-
# 輸入數據
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("/tmp/data/", one_hot=True)
import tensorflow as tf
# 定義網路超參數
learning_rate = 0.001
training_iters = 20000
batch_size = 128
display_step = 10
# 定義網路參數
n_input = 784 # 輸入的維度(img shape:28x28)
n_classes = 10 # 標記的維度(0-9 digits)
dropout = 0.75 # Dropout 的概率,輸出可能性
# 占位符輸入
x = tf.placeholder(tf.float32, [None, n_input])
y = tf.placeholder(tf.float32, [None, n_classes])
keep_prob = tf.placeholder(tf.float32) #dropout
# 捲積操作
def conv2d(name, x, W, b,strides=1):
x = tf.nn.conv2d(x, W, strides=[1, strides, strides, 1], padding='SAME')
x = tf.nn.bias_add(x, b)
return tf.nn.relu(x, name=name) #用relu激活函數
# 最大下採樣操作
def maxpool2d(name, x, k=2):
return tf.nn.max_pool(x, ksize=[1, k, k, 1], strides=[1, k, k, 1], padding='SAME', name=name)
# 規範化操作
def norm(name, l_input, lsize=4):
return tf.nn.lrn(l_input, lsize, bias=1.0, alpha=0.001 / 9.0, beta=0.75, name=name)
# 所有的網路參數
weights = {
'wc1': tf.Variable(tf.random_normal([11, 11, 1, 96])),
'wc2': tf.Variable(tf.random_normal([5, 5, 96, 256])),
'wc3': tf.Variable(tf.random_normal([3, 3, 256, 384])),
'wc4': tf.Variable(tf.random_normal([3, 3, 384, 384])),
'wc5': tf.Variable(tf.random_normal([3, 3, 384, 256])),
'wd1': tf.Variable(tf.random_normal([4*4*256, 4096])),
'wd2': tf.Variable(tf.random_normal([4096, 4096])),
'out': tf.Variable(tf.random_normal([4096, 10]))
}
biases = {
'bc1': tf.Variable(tf.random_normal([96])),
'bc2': tf.Variable(tf.random_normal([256])),
'bc3': tf.Variable(tf.random_normal([384])),
'bc4': tf.Variable(tf.random_normal([384])),
'bc5': tf.Variable(tf.random_normal([256])),
'bd1': tf.Variable(tf.random_normal([4096])),
'bd2': tf.Variable(tf.random_normal([4096])),
'out': tf.Variable(tf.random_normal([n_classes]))
}
# 定義AlexNet網路模型
def alex_net(x, weights, biases, dropout):
# 向量轉為矩陣
x = tf.reshape(x, shape=[-1, 28, 28, 1])
# 第一卷積層
# 捲積
conv1 = conv2d('conv1', x, weights['wc1'], biases['bc1'])
# 最大池化(向下採樣)
pool1 = max_pool('pool1', conv1, k=2)
# 規範化(歸一化)
norm1 = norm('norm1', pool1, lsize=4)
# 第二捲積層
# 捲積
conv2 = conv2d('conv2', conv1, weights['wc2'], biases['bc2'])
# 最大池化(向下採樣)
pool2 = max_pool('pool2', conv2, k=2)
# 規範化(歸一化)
norm2 = norm('norm2', pool2, lsize=4)
# 第三捲積層
# 捲積
conv3 = conv2d('conv3', conv2, weights['wc3'], biases['bc3'])
# 最大池化(向下採樣)
pool3 = max_pool('pool3', conv3, k=2)
# 規範化(歸一化)
norm3 = norm('norm3', pool3, lsize=4)
# 第四捲積層
conv4 = conv2d('conv4', conv3, weights['wc4'], biases['bc4'])
# 最大池化(向下採樣)
pool4 = max_pool('pool4', conv4, k=2)
# 規範化(歸一化)
norm4 = norm('norm4', pool4, lsize=4)
# 第五捲積層
conv5 = conv2d('conv5', conv4, weights['wc5'], biases['bc5'])
# 最大池化(向下採樣)
pool5 = max_pool('pool5', conv4, k=2)
# 規範化(歸一化)
norm5 = norm('norm5', pool5, lsize=4)
# 第一全連接層,先把特征圖轉為向量
fc1 = tf.reshape(norm5, [-1, weights['wd1'].get_shape().as_list()[0]])
fc1 = tf.add(tf.matmul(fc1, weights['wd1']), biases['bd1'])
fc1 = tf.nn.relu(fc1)
# Dropout
fc1 = tf.nn.dropout(fc1, dropout)
# 第二全連接層
fc2 = tf.reshape(fc1, [-1, weights['wd1'].get_shape().as_list()[0]])
fc2 = tf.add(tf.matmul(fc2, weights['wd1']), biases['bd1'])
fc2 = tf.nn.relu(fc2)
# Dropout
fc2 = tf.nn.dropout(fc2, dropout)
# 網路輸出層
out = tf.add(tf.matmul(fc2, weights['out']), biases['out'])
return out
# 構建模型
pred = alex_net(x, weights, biases, keep_prob)
# 定義損失函數、優化器(學習步長)
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred, labels=y))
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
# 評估函數
correct_pred = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
# 訓練模型和評估模型
# 初始化所有的共用變數
init = tf.global_variables_initializer()
# 開啟一個訓練
with tf.Session() as sess:
sess.run(init)
step = 1
# 開始訓練,直到達到training_iters,即200000
while step * batch_size < training_iters:
# 獲取批數據
batch_x, batch_y = mnist.train.next_batch(batch_size)
sess.run(optimizer, feed_dict={x: batch_x, y: batch_y, keep_prob: dropout})
if step % display_step == 0:
# 計算損失值和準確度,輸出
loss, acc = sess.run([cost, accuracy], feed_dict={x: batch_x, y: batch_y, keep_prob: 1.})
print "Iter " + str(step*batch_size) + ", Minibatch Loss= " + "{:.6f}".format(loss) + ", Training Accuracy= " + "{:.5f}".format(acc)
step += 1
print "Optimization Finished!"
# 計算測試精度
print "Testing Accuracy:", sess.run(accuracy, feed_dict={x: mnist.test.images[:256], y: mnist.test.labels[:256], keep_prob: 1.})
參考資料:
《TensorFlow技術解析與實戰》
歡迎推薦上海機器學習工作機會,我的微信:qingxingfengzi