----------------------------------------------ubuntu16.04.2----------------------------------------------------------html
#獲取數據mysql
cd data/mnist算法
sh get_mnist.shsql
#轉換格式數據庫
sh examples/mnist/create_mnist.sh
# 訓練模型
ubuntu
sh examples/mnist/train_lenet.sh網絡
# 測試模型ide
./build/tools/caffe test -model=examples/mnist/lenet_train_test.prototxt -weights=examples/mnist/lenet_iter_10000.caffemodel -gpu=0
# 識別手寫數字文本圖片:
函數
classification examples/mnist/lenet.prototxt examples/mnist/lenet_iter_10000.caffemodel examples/mnist/mean.binaryproto data/mnist/synset_words.txt examples/images/1.png佈局
------------------------------------------------win7vs2013----------------------------------------------------------
轉換:
convert_mnist_data data/mnist/train-images.idx3-ubyte data/mnist/train-labels.idx1-ubyte examples/mnist/mnist_train_lmdb --backend=lmdb
convert_mnist_data data/mnist/t10k-images.idx3-ubyte data/mnist/t10k-labels.idx1-ubyte examples/mnist/mnist_test_lmdb --backend=lmdb
訓練:
caffe train --solver=examples/mnist/lenet_solver.prototxt
測試:
caffe test -model=examples/mnist/lenet_train_test.prototxt -weights=examples/mnist/lenet_iter_10000.caffemodel -gpu=0
計算模型的耗時狀況:
caffe time -model=examples/mnist/lenet_train_test.prototxt -weights=examples/mnist/lenet_iter_10000.caffemodel -gpu=0
------------------------>
... ... ... ... ... ...
I0705 16:50:08.214988 7784 caffe.cpp:413] loss backward: 0.10135 ms.
I0705 16:50:08.214988 7784 caffe.cpp:418] Average Forward pass: 4.75881 ms.
I0705 16:50:08.214988 7784 caffe.cpp:420] Average Backward pass: 5.6007 ms.
I0705 16:50:08.214988 7784 caffe.cpp:422] Average Forward-Backward: 14.5615 ms.
I0705 16:50:08.214988 7784 caffe.cpp:424] Total Time: 728.073 ms.
I0705 16:50:08.214988 7784 caffe.cpp:425] *** Benchmark ends ***
---------------------------------------------------------------------------------------------------------------------------------
計算平均值:
compute_image_mean.exe -backend=lmdb examples/mnist/mnist_train_lmdb examples/mnist/mean.binaryproto
識別一張圖像:
(cifar10 )classification.exe examples/cifar10/cifar10_quick.prototxt examples/cifar10/cifar10_quick_iter_5000.caffemodel.h5 examples/cifar10/mean.binaryproto data/cifar10/synset_words.txt examples/images/cat.jpg (參考)
classification.exe examples/mnist/lenet.prototxt examples/mnist/lenet_iter_10000.caffemodel examples/mnist/mean.binaryproto data/mnist/synset_words.txt examples/images/le01.jpg
classification examples/mnist/lenet.prototxt examples/mnist/lenet_iter_10000.caffemodel examples/mnist/mean.binaryproto data/mnist/synset_words.txt examples/images/1.png
-----------------------------------------------------------------------------------------------------------------------------
synset_words:
0
1
2
3
4
5
6
7
8
9
------------------------------------------------------原理解釋------------------------------------------------------------
一個典型的例子說明
一種典型的用來識別數字的卷積網絡是LeNet-5(效果和paper等見這)。當年美國大多數銀行就是用它來識別支票上面的手寫數字的。可以達到這種商用的地步,它的準確性可想而知。畢竟目前學術界和工業界的結合是最受爭議的。
LeNet-5共有7層,不包含輸入,每層都包含可訓練參數(鏈接權重)。輸入圖像爲32*32大小。這要比Mnist數據庫(一個公認的手寫數據庫)中最大的字母還大。這樣作的緣由是但願潛在的明顯特徵如筆畫斷電或角點可以出如今最高層特徵監測子感覺野的中心。
咱們先要明確一點:每一個層有多個Feature Map,每一個Feature Map經過一種卷積濾波器提取輸入的一種特徵,而後每一個Feature Map有多個神經元。
C1層是一個卷積層(爲何是卷積?卷積運算一個重要的特色就是,經過卷積運算,可使原信號特徵加強,而且下降噪音),由6個特徵圖Feature Map構成。特徵圖中每一個神經元與輸入中5*5的鄰域相連。特徵圖的大小爲28*28,這樣能防止輸入的鏈接掉到邊界以外(是爲了BP反饋時的計算,不致梯度損失,我的看法)。C1有156個可訓練參數(每一個濾波器5*5=25個unit參數和一個bias參數,一共6個濾波器,共(5*5+1)*6=156個參數),共156*(28*28)=122,304個鏈接。
S2層是一個下采樣層(爲何是下采樣?利用圖像局部相關性的原理,對圖像進行子抽樣,能夠減小數據處理量同時保留有用信息),有6個14*14的特徵圖。特徵圖中的每一個單元與C1中相對應特徵圖的2*2鄰域相鏈接。S2層每一個單元的4個輸入相加,乘以一個可訓練參數,再加上一個可訓練偏置。結果經過sigmoid函數計算。可訓練係數和偏置控制着sigmoid函數的非線性程度。若是係數比較小,那麼運算近似於線性運算,亞採樣至關於模糊圖像。若是係數比較大,根據偏置的大小亞採樣能夠被當作是有噪聲的「或」運算或者有噪聲的「與」運算。每一個單元的2*2感覺野並不重疊,所以S2中每一個特徵圖的大小是C1中特徵圖大小的1/4(行和列各1/2)。S2層有12個可訓練參數和5880個鏈接。
圖2:卷積和子採樣過程:卷積過程包括:用一個可訓練的濾波器fx去卷積一個輸入的圖像(第一階段是輸入的圖像,後面的階段就是卷積特徵map了),而後加一個偏置bx,獲得卷積層Cx。子採樣過程包括:每鄰域四個像素求和變爲一個像素,而後經過標量Wx+1加權,再增長偏置bx+1,而後經過一個sigmoid激活函數,產生一個大概縮小四倍的特徵映射圖Sx+1。
因此從一個平面到下一個平面的映射能夠看做是做卷積運算,S-層可看做是模糊濾波器,起到二次特徵提取的做用。隱層與隱層之間空間分辨率遞減,而每層所含的平面數遞增,這樣可用於檢測更多的特徵信息。
C3層也是一個卷積層,它一樣經過5x5的卷積核去卷積層S2,而後獲得的特徵map就只有10x10個神經元,可是它有16種不一樣的卷積核,因此就存在16個特徵map了。這裏須要注意的一點是:C3中的每一個特徵map是鏈接到S2中的全部6個或者幾個特徵map的,表示本層的特徵map是上一層提取到的特徵map的不一樣組合(這個作法也並非惟一的)。(看到沒有,這裏是組合,就像以前聊到的人的視覺系統同樣,底層的結構構成上層更抽象的結構,例如邊緣構成形狀或者目標的部分)。
剛纔說C3中每一個特徵圖由S2中全部6個或者幾個特徵map組合而成。爲何不把S2中的每一個特徵圖鏈接到每一個C3的特徵圖呢?緣由有2點。第一,不徹底的鏈接機制將鏈接的數量保持在合理的範圍內。第二,也是最重要的,其破壞了網絡的對稱性。因爲不一樣的特徵圖有不一樣的輸入,因此迫使他們抽取不一樣的特徵(但願是互補的)。
例如,存在的一個方式是:C3的前6個特徵圖以S2中3個相鄰的特徵圖子集爲輸入。接下來6個特徵圖以S2中4個相鄰特徵圖子集爲輸入。而後的3個以不相鄰的4個特徵圖子集爲輸入。最後一個將S2中全部特徵圖爲輸入。這樣C3層有1516個可訓練參數和151600個鏈接。
S4層是一個下采樣層,由16個5*5大小的特徵圖構成。特徵圖中的每一個單元與C3中相應特徵圖的2*2鄰域相鏈接,跟C1和S2之間的鏈接同樣。S4層有32個可訓練參數(每一個特徵圖1個因子和一個偏置)和2000個鏈接。
C5層是一個卷積層,有120個特徵圖。每一個單元與S4層的所有16個單元的5*5鄰域相連。因爲S4層特徵圖的大小也爲5*5(同濾波器同樣),故C5特徵圖的大小爲1*1:這構成了S4和C5之間的全鏈接。之因此仍將C5標示爲卷積層而非全相聯層,是由於若是LeNet-5的輸入變大,而其餘的保持不變,那麼此時特徵圖的維數就會比1*1大。C5層有48120個可訓練鏈接。
F6層有84個單元(之因此選這個數字的緣由來自於輸出層的設計),與C5層全相連。有10164個可訓練參數。如同經典神經網絡,F6層計算輸入向量和權重向量之間的點積,再加上一個偏置。而後將其傳遞給sigmoid函數產生單元i的一個狀態。
最後,輸出層由歐式徑向基函數(Euclidean Radial Basis Function)單元組成,每類一個單元,每一個有84個輸入。換句話說,每一個輸出RBF單元計算輸入向量和參數向量之間的歐式距離。輸入離參數向量越遠,RBF輸出的越大。一個RBF輸出能夠被理解爲衡量輸入模式和與RBF相關聯類的一個模型的匹配程度的懲罰項。用機率術語來講,RBF輸出能夠被理解爲F6層配置空間的高斯分佈的負log-likelihood。給定一個輸入模式,損失函數應能使得F6的配置與RBF參數向量(即模式的指望分類)足夠接近。這些單元的參數是人工選取並保持固定的(至少初始時候如此)。這些參數向量的成分被設爲-1或1。雖然這些參數能夠以-1和1等機率的方式任選,或者構成一個糾錯碼,可是被設計成一個相應字符類的7*12大小(即84)的格式化圖片。這種表示對識別單獨的數字不是頗有用,可是對識別可打印ASCII集中的字符串頗有用。
使用這種分佈編碼而非更經常使用的「1 of N」編碼用於產生輸出的另外一個緣由是,當類別比較大的時候,非分佈編碼的效果比較差。緣由是大多數時間非分佈編碼的輸出必須爲0。這使得用sigmoid單元很難實現。另外一個緣由是分類器不只用於識別字母,也用於拒絕非字母。使用分佈編碼的RBF更適合該目標。由於與sigmoid不一樣,他們在輸入空間的較好限制的區域內興奮,而非典型模式更容易落到外邊。
RBF參數向量起着F6層目標向量的角色。須要指出這些向量的成分是+1或-1,這正好在F6 sigmoid的範圍內,所以能夠防止sigmoid函數飽和。實際上,+1和-1是sigmoid函數的最大彎曲的點處。這使得F6單元運行在最大非線性範圍內。必須避免sigmoid函數的飽和,由於這將會致使損失函數較慢的收斂和病態問題。
5)訓練過程
神經網絡用於模式識別的主流是有指導學習網絡,無指導學習網絡更多的是用於聚類分析。對於有指導的模式識別,因爲任同樣本的類別是已知的,樣本在空間的分佈再也不是依據其天然分佈傾向來劃分,而是要根據同類樣本在空間的分佈及不一樣類樣本之間的分離程度找一種適當的空間劃分方法,或者找到一個分類邊界,使得不一樣類樣本分別位於不一樣的區域內。這就須要一個長時間且複雜的學習過程,不斷調整用以劃分樣本空間的分類邊界的位置,使盡量少的樣本被劃分到非同類區域中。
卷積網絡在本質上是一種輸入到輸出的映射,它可以學習大量的輸入與輸出之間的映射關係,而不須要任何輸入和輸出之間的精確的數學表達式,只要用已知的模式對卷積網絡加以訓練,網絡就具備輸入輸出對之間的映射能力。卷積網絡執行的是有導師訓練,因此其樣本集是由形如:(輸入向量,理想輸出向量)的向量對構成的。全部這些向量對,都應該是來源於網絡即將模擬的系統的實際「運行」結果。它們能夠是從實際運行系統中採集來的。在開始訓練前,全部的權都應該用一些不一樣的小隨機數進行初始化。「小隨機數」用來保證網絡不會因權值過大而進入飽和狀態,從而致使訓練失敗;「不一樣」用來保證網絡能夠正常地學習。實際上,若是用相同的數去初始化權矩陣,則網絡無能力學習。
訓練算法與傳統的BP算法差很少。主要包括4步,這4步被分爲兩個階段:
第一階段,向前傳播階段:
a)從樣本集中取一個樣本(X,Yp),將X輸入網絡;
b)計算相應的實際輸出Op。
在此階段,信息從輸入層通過逐級的變換,傳送到輸出層。這個過程也是網絡在完成訓練後正常運行時執行的過程。在此過程當中,網絡執行的是計算(實際上就是輸入與每層的權值矩陣相點乘,獲得最後的輸出結果):
Op=Fn(…(F2(F1(XpW(1))W(2))…)W(n))
第二階段,向後傳播階段
a)算實際輸出Op與相應的理想輸出Yp的差;
b)按極小化偏差的方法反向傳播調整權矩陣。
6)卷積神經網絡的優勢
卷積神經網絡CNN主要用來識別位移、縮放及其餘形式扭曲不變性的二維圖形。因爲CNN的特徵檢測層經過訓練數據進行學習,因此在使用CNN時,避免了顯式的特徵抽取,而隱式地從訓練數據中進行學習;再者因爲同一特徵映射面上的神經元權值相同,因此網絡能夠並行學習,這也是卷積網絡相對於神經元彼此相連網絡的一大優點。卷積神經網絡以其局部權值共享的特殊結構在語音識別和圖像處理方面有着獨特的優越性,其佈局更接近於實際的生物神經網絡,權值共享下降了網絡的複雜性,特別是多維輸入向量的圖像能夠直接輸入網絡這一特色避免了特徵提取和分類過程當中數據重建的複雜度。
流的分類方式幾乎都是基於統計特徵的,這就意味着在進行分辨前必須提取某些特徵。然而,顯式的特徵提取並不容易,在一些應用問題中也並不是老是可靠的。卷積神經網絡,它避免了顯式的特徵取樣,隱式地從訓練數據中進行學習。這使得卷積神經網絡明顯有別於其餘基於神經網絡的分類器,經過結構重組和減小權值將特徵提取功能融合進多層感知器。它能夠直接處理灰度圖片,可以直接用於處理基於圖像的分類。
卷積網絡較通常神經網絡在圖像處理方面有以下優勢:
a)輸入圖像和網絡的拓撲結構能很好的吻合;
b)特徵提取和模式分類同時進行,並同時在訓練中產生;
c)權重共享能夠減小網絡的訓練參數,使神經網絡結構變得更簡單,適應性更強。
---------------------------------> 上面都是俺copy來的 <-----------------------------------
做者不屑於講裏面參數的計算過程,俺看了很久很久纔算出來,下面是我對做者上文中參數計算的理解:
1.C1層是一個卷積層(爲何是卷積?卷積運算一個重要的特色就是,經過卷積運算,可使原信號特徵加強,而且下降噪音),由6個特徵圖Feature Map構成。特徵圖中每一個神經元與輸入中5*5的鄰域相連。特徵圖的大小爲28*28,這樣能防止輸入的鏈接掉到邊界以外(是爲了BP反饋時的計算,不致梯度損失,我的看法)。C1有156個可訓練參數(每一個濾波器5*5=25個unit參數和一個bias參數,一共6個濾波器,共(5*5+1)*6=156個參數),共156*(28*28)=122,304個鏈接。
---->
2.S2層是一個下采樣層(爲何是下采樣?利用圖像局部相關性的原理,對圖像進行子抽樣,能夠減小數據處理量同時保留有用信息),有6個14*14的特徵圖。特徵圖中的每一個單元與C1中相對應特徵圖的2*2鄰域相鏈接。S2層每一個單元的4個輸入相加,乘以一個可訓練參數,再加上一個可訓練偏置。結果經過sigmoid函數計算。可訓練係數和偏置控制着sigmoid函數的非線性程度。若是係數比較小,那麼運算近似於線性運算,亞採樣至關於模糊圖像。若是係數比較大,根據偏置的大小亞採樣能夠被當作是有噪聲的「或」運算或者有噪聲的「與」運算。每一個單元的2*2感覺野並不重疊,所以S2中每一個特徵圖的大小是C1中特徵圖大小的1/4(行和列各1/2)。S2層有12個可訓練參數和5880個鏈接。
---->6個2*2的小方框,每一個有一個參數,加上一個偏置,也就是(1+1)*6=12個可訓練參數
---->對於S2層的每個圖的每個點,鏈接數是(2*2+1)=5,總共是14*14*6*(2*2+1)=5880個鏈接
3.C3層也是一個卷積層,它一樣經過5x5的卷積核去卷積層S2,而後獲得的特徵map就只有10x10個神經元,可是它有16種不一樣的卷積核,因此就存在16個特徵map了。這裏須要注意的一點是:C3中的每一個特徵map是鏈接到S2中的全部6個或者幾個特徵map的,表示本層的特徵map是上一層提取到的特徵map的不一樣組合(這個作法也並非惟一的)。
例如,存在的一個方式是:C3的前6個特徵圖以S2中3個相鄰的特徵圖子集爲輸入。接下來6個特徵圖以S2中4個相鄰特徵圖子集爲輸入。而後的3個以不相鄰的4個特徵圖子集爲輸入。最後一個將S2中全部特徵圖爲輸入。這樣C3層有1516個可訓練參數和151600個鏈接。
---->這裏的參數和鏈接數最很差理解啦
---->從C3的角度看,它有16個圖.把每一個圖對應的參數加起來就好了:
6*(3*25+1) + 6*(4*25+1) + 3*(4*25+1)+ 1*(6*25+1)=1516個可訓練參數
---->上面的1516*10*10=151600個鏈接
4.S4層是一個下采樣層,由16個5*5大小的特徵圖構成。特徵圖中的每一個單元與C3中相應特徵圖的2*2鄰域相鏈接,跟C1和S2之間的鏈接同樣。S4層有32個可訓練參數(每一個特徵圖1個因子和一個偏置)和2000個鏈接。
---->16個2*2的小方框,每一個有一個參數,加上一個偏置,也就是(1+1)*16=32個可訓練參數
---->對於S4層的每個圖的每個點,鏈接數是(2*2+1)=5,總共是5*5*16*(2*2+1)=2000個鏈接
5. C5層是一個卷積層,有120個特徵圖。每一個單元與S4層的所有16個單元的5*5鄰域相連。因爲S4層特徵圖的大小也爲5*5(同濾波器同樣),故C5特徵圖的大小爲1*1:這構成了S4和C5之間的全鏈接。之因此仍將C5標示爲卷積層而非全相聯層,是由於若是LeNet-5的輸入變大,而其餘的保持不變,那麼此時特徵圖的維數就會比1*1大。C5層有48120個可訓練鏈接。
---->120*(5*5*16+1)=48120個可訓練鏈接
6. F6層有84個單元(之因此選這個數字的緣由來自於輸出層的設計),與C5層全相連。有10164個可訓練參數。如同經典神經網絡,F6層計算輸入向量和權重向量之間的點積,再加上一個偏置。而後將其傳遞給sigmoid函數產生單元i的一個狀態。
---->84*(120+1)=10164個可訓練鏈接
-------------------------------------------網絡解析------------------------------------------------
根據caffe所給樣例,lenet網絡結構以下:
概要:
層數:10
分別爲:mnist,mnist,conv1,pool1,conv2,
pool2,ip1, relu1, ip2, accuracy, loss
=================================================================
name: "LeNet"
layer {
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param {
scale: 0.00390625
}
data_param {
source: "examples/mnist/mnist_train_lmdb"
batch_size: 64
backend: LMDB
}
}
layer {
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TEST
}
transform_param {
scale: 0.00390625
}
data_param {
source: "examples/mnist/mnist_test_lmdb"
batch_size: 100
backend: LMDB
}
}
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 20
kernel_size: 5
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv2"
type: "Convolution"
bottom: "pool1"
top: "conv2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 50
kernel_size: 5
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "pool2"
type: "Pooling"
bottom: "conv2"
top: "pool2"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "ip1"
type: "InnerProduct"
bottom: "pool2"
top: "ip1"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 500
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "relu1"
type: "ReLU"
bottom: "ip1"
top: "ip1"
}
layer {
name: "ip2"
type: "InnerProduct"
bottom: "ip1"
top: "ip2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 10
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "accuracy"
type: "Accuracy"
bottom: "ip2"
bottom: "label"
top: "accuracy"
include {
phase: TEST
}
}
layer {
name: "loss"
type: "SoftmaxWithLoss"
bottom: "ip2"
bottom: "label"
top: "loss"
}
----------------------------關鍵步驟解釋-------------------------------- -------------------------finish and to do ----------------------------