1 最近一直在學習caffe深度學習模型,便于日后的復習,就開始隨筆記些東西。有錯誤的話,歡迎朋友們的批評指正,一起學習。
? 日后準備深入學習下算法知識,補一些自己的短板。如果大家配置中遇到問題,歡迎私信交流。
2 win條件下具體的配置見下文?!究劭郏?396750111】
3.1 構建數據集?
數據集的下載如下圖:
3.2 windows下進行環境搭建??
3.2.1 Caffe下載及安裝?
1. 微軟提供window工具包https://github.com/Microsoft/caffe,右下角Download
ZIP,解壓后文件夾是caffe-master。
?????? 2.復制caffe-master/windows下CommonSettings.props.example,改為CommonSettings.props,把它拖到Nootepad+++打開,更改這三項(因為沒有GPU),保存。CommonSettings.props簡單配置如下圖:
3. 雙擊caffe-master/windows下的Caffe.sln,用VS2013(下面3.2.3會介紹具體方法)打開,生成解決方案;官網自帶的有16個項目。
Caffe的16個項目生成解決方案如下圖:
4. Nuget所需要的第三方庫安裝,在線下載的。第三方庫Nuget下載下來如下,放到與caffe-master并列的文件夾即可。
5. 編譯成功后會在caffe-master\Build\x64\Release中出現各種編譯后的文件。
編譯成功后如下圖:
3.2.2 Python的Anaconda配置及安裝 ??
?????? 1.Windows下Anaconda2和Anaconda3共存,我先安裝Anaconda3,安裝在I:\Anaconda3。
??? 2. 然后我再安裝Anaconda2,需要安裝在F:\Anaconda3\envs\py2。
3. Anaconda2環境測試成功。
環境方面就介紹到這里呢,具體得操作才行,期待和你的交流~
第4章 算法設計與實現?
4.1卷積神經網絡
卷積神經網絡中,一般卷積層后都會跟著池化層。在通過卷積獲得了特征之后,就可以利用這些特征去做分類。雖然在理論上,可以用所有提取得到的特征去訓練分類器,例如用Softmax來進行分類,但是這樣會面臨著計算量的巨大挑戰。假設對于一個256 x
256像素的圖像,在一個8x8的輸入上,已經通過實驗預先學習獲得了100個特征,然后將特征和圖像進行卷積,每做一次運算,都會得到一個249 x 249維的卷積特征,由于有100個特征,那對于一個樣本,將會得到一個62001x100維的卷積特征向量。超過六百萬的特征輸入,任何分類器都難以處理,并且可能出現過擬合的情況。
為了解決這個問題,則需要降低特征的維數,而圖像具有一種“靜態性”的屬性,這也是采用卷積后的特征表示圖像的原因,正因為這個屬性,從一個圖像區域提取到的特征,很有可能也可以用來表示圖像的另一個區域。于是為了描述一些很大的圖像,對于圖像的不同位置的特征,可以進行合并統計,比較常用的是用圖像區域上的某個特定特征的最大值(或平均值)來對圖像進行描述。與使用全部的特征相比,這些概要統計特征不僅具有較低的維度,同時還會改善結果,可以有效降低過擬合。這種操作方法就被稱作池化,根據池化方法可以分為平均池化、最大值池化和隨機池化。從以上可以看出,局部感受野、權值共享和空間亞采樣是卷積神經網絡的三個特性,通過這三者的結合可以得到某種程度上的尺度、位移和形變不變性。
4.2 Googlenet算法模型
4.21 Googlenet算法簡介
GoogleNet和VGG是2014年imagenet競賽的雙雄,這兩類模型結構有一個共同特點是go deeper。跟VGG不同的是,GoogleNet做了更大膽的網絡上的嘗試而不是像VGG繼承了Lenet以及AlexNet的一些框架,該模型雖然有22層,但大小卻比AlexNet和VGG都小很多,性能優越。
深度學習以及神經網絡快速發展,人們容易通過更高性能的硬件,更龐大的帶標簽數據和更深更寬的網絡模型等手段來獲得更好的預測識別效果,但是這一策略帶來了兩個重要的缺陷。
(1)更深更寬的網絡模型會產生巨量參數,從而容易出現過擬合現象。
(2)網絡規模加大會極大增加計算量,消耗更多的計算資源。
解決這兩個缺陷的根本方法就是將全連接甚至一般的卷積都轉化為稀疏連接。一方面現實生物神經系統的連接也是稀疏的,另一方面有文獻表明:對于大規模稀疏的神經網絡,可以通過分析激活值的統計特性和對高度相關的輸出進行聚類來逐層構建出一個最優網絡。這點表明臃腫的稀疏網絡可能被不失性能地簡化。雖然數學證明有著嚴格的條件限制,但Hebbian定理有力地支持了這一結論。
由于計算機軟硬件對非均勻稀疏數據的計算效率很差,所以在AlexNet模型重新啟用了全連接層,其目的是為了更好地優化并行運算。具體方法是采用將多個稀疏矩陣合并成相關的稠密子矩陣的方法來提高計算性能,Google團隊沿著這個思路提出了名為Inception 結構來實現此目的。
4.22 Googlenet算法模型
1.Inception模型
Inception結構的主要思想是找出如何讓已有的稠密組件接近與覆蓋卷積視覺網絡中的最佳局部稀疏結構。有文獻提出一個層與層的結構,在結構的最后一層進行相關性統計,將高相關性的聚集到一起。這些聚類構成下一層的單元,且與上一層單元連接。假設前面層的每個單元對應于輸入圖像的某些區域,這些單元被分為濾波器組。Google團隊首先提出來的是Inception模型,如下圖所示:
Googlenet模型如下:
2.選擇GoogLeNet的原因
(1)GoogLeNet采用了模塊化的結構,方便增添和修改;
(2)網絡最后采用了average pooling來代替全連接層,但是,實際在最后還是加了一個全連接層,主要是為了方便以后大家finetune;雖然移除了全連接,但是網絡中依然使用了Dropout ;為了避免梯度消失,網絡額外增加了2個輔助的softmax用于向前傳導梯度。
(3)本文的主要想法其實是想通過構建密集的塊結構來近似最優的稀疏結構,從而達到提高性能而又不大量增加計算量的目的,上面的這些模型特點很好的實現了這個想法。GoogleNet的caffemodel大小約50M,性能很優異。
第5章 系統測試 ?
5.1 模型程序書寫
5.11 訓練數據轉換程序
制作標簽:
生成train.txt? test.txt標簽文檔
生成lmdb訓練數據程序:
G:\caffe-master\Build\x64\Release\convert_imageset.exe ^
--resize_height=256 --resize_width=256 ^
--shuffle ^
--backend="lmdb" ^
G:\caffe-master\models\my_models_recognition\data\train\^
G:\caffe-master\models\my_models_recognition\labels\train.txt^
G:\caffe-master\models\my_models_recognition\lmdb\train\
pause
%執行數據轉換的可執行文件%
%重新設定圖片的大小%
%打亂圖片%
%轉換格式%
%圖片路徑%
%圖片標簽%
%lmdb轉換后的數據存放在此目錄%
運行lmdb訓練數據程序
?生成lmdb訓練數據
5.12 測試數據轉換程序
生成lmdb訓測試數據程序:
G:\caffe-master\Build\x64\Release\convert_imageset.exe ^
--resize_height=256 --resize_width=256 ^
--shuffle ^
--backend="lmdb" ^
G:\caffe-master\models\my_models_recognition\data\test\ ^
G:\caffe-master\models\my_models_recognition\labels\test.txt^
G:\caffe-master\models\my_models_recognition\lmdb\test\
pause
%執行數據轉換的可執行文件%
%重新設定圖片的大小%
%打亂圖片%
%轉換格式%
%圖片路徑%
%圖片標簽%
%lmdb轉換后的數據存放在此目錄%
5.13 訓練模型程序
訓練模型程序:
name: "CaffeNet"
layer {
?name: "data"
?type: "Data"
?top: "data"
?top: "label"
?include {
???phase: TRAIN
?}
#?transform_param {
#??mirror: true
#??crop_size: 227
#??mean_file: "data/ilsvrc12/imagenet_mean.binaryproto"
# }
# mean pixel / channel-wise meaninstead of mean image
?transform_param {
???crop_size: 227
???mean_value: 104
???mean_value: 117
???mean_value: 123
???mirror: true
?}
?data_param {
???source:"G:/caffe-master/models/my_models_recognition/lmdb/train"
???batch_size: 100
???backend: LMDB
?}
}
layer {
?name: "data"
?type: "Data"
?top: "data"
?top: "label"
?include {
???phase: TEST
?}
#?transform_param {
#??mirror: false
#???crop_size: 227
#??mean_file: "data/ilsvrc12/imagenet_mean.binaryproto"
#?}
# mean pixel / channel-wise meaninstead of mean image
?transform_param {
???crop_size: 227
???mean_value: 104
???mean_value: 117
???mean_value: 123
???mirror: false
?}
?data_param {
???source:"G:/caffe-master/models/my_models_recognition/lmdb/test"
???batch_size: 50
???backend: LMDB
?}
}
layer {
?name: "conv1"
?type: "Convolution"
?bottom: "data"
?top: "conv1"
?param {
???lr_mult: 1
???decay_mult: 1
?}
?param {
???lr_mult: 2
???decay_mult: 0
?}
?convolution_param {
???num_output: 96
???kernel_size: 11
???stride: 4
???weight_filler {
?????type: "gaussian"
?????std: 0.01
???}
???bias_filler {
?????type: "constant"
?????value: 0
???}
?}
}
layer {
?name: "relu1"
?type: "ReLU"
?bottom: "conv1"
?top: "conv1"
}
layer {
?name: "pool1"
?type: "Pooling"
?bottom: "conv1"
?top: "pool1"
?pooling_param {
???pool: MAX
???kernel_size: 3
???stride: 2
?}
}
layer {
?name: "norm1"
?type: "LRN"
?bottom: "pool1"
?top: "norm1"
?lrn_param {
???local_size: 5
???alpha: 0.0001
???beta: 0.75
?}
}
layer {
?name: "conv2"
?type: "Convolution"
?bottom: "norm1"
?top: "conv2"
?param {
???lr_mult: 1
???decay_mult: 1
?}
?param {
???lr_mult: 2
???decay_mult: 0
?}
?convolution_param {
???num_output: 256
???pad: 2
???kernel_size: 5
???group: 2
???weight_filler {
?????type: "gaussian"
?????std: 0.01
???}
???bias_filler {
?????type: "constant"
?????value: 1
???}
?}
}
layer {
?name: "relu2"
?type: "ReLU"
?bottom: "conv2"
?top: "conv2"
}
layer {
?name: "pool2"
?type: "Pooling"
?bottom: "conv2"
?top: "pool2"
?pooling_param {
???pool: MAX
???kernel_size: 3
???stride: 2
?}
}
layer {
?name: "norm2"
?type: "LRN"
?bottom: "pool2"
?top: "norm2"
?lrn_param {
???local_size: 5
???alpha: 0.0001
???beta: 0.75
?}
}
layer {
?name: "conv3"
?type: "Convolution"
?bottom: "norm2"
?top: "conv3"
?param {
???lr_mult: 1
???decay_mult: 1
?}
?param {
???lr_mult: 2
???decay_mult: 0
?}
?convolution_param {
???num_output: 384
???pad: 1
???kernel_size: 3
???weight_filler {
?????type: "gaussian"
?????std: 0.01
???}
???bias_filler {
?????type: "constant"
?????value: 0
???}
?}
}
layer {
?name: "relu3"
?type: "ReLU"
?bottom: "conv3"
?top: "conv3"
}
layer {
?name: "conv4"
?type: "Convolution"
?bottom: "conv3"
?top: "conv4"
?param {
???lr_mult: 1
???decay_mult: 1
?}
?param {
???lr_mult: 2
???decay_mult: 0
?}
?convolution_param {
???num_output: 384
???pad: 1
???kernel_size: 3
???group: 2
???weight_filler {
?????type: "gaussian"
?????std: 0.01
???}
???bias_filler {
?????type: "constant"
?????value: 1
???}
?}
}
layer {
?name: "relu4"
?type: "ReLU"
?bottom: "conv4"
?top: "conv4"
}
layer {
?name: "conv5"
?type: "Convolution"
?bottom: "conv4"
?top: "conv5"
?param {
???lr_mult: 1
???decay_mult: 1
?}
?param {
???lr_mult: 2
???decay_mult: 0
?}
?convolution_param {
???num_output: 256
???pad: 1
???kernel_size: 3
???group: 2
???weight_filler {
?????type: "gaussian"
?????std: 0.01
???}
???bias_filler {
?????type: "constant"
?????value: 1
???}
?}
}
layer {
?name: "relu5"
?type: "ReLU"
?bottom: "conv5"
?top: "conv5"
}
layer {
?name: "pool5"
?type: "Pooling"
?bottom: "conv5"
?top: "pool5"
?pooling_param {
???pool: MAX
???kernel_size: 3
???stride: 2
?}
}
layer {
?name: "fc6"
?type: "InnerProduct"
?bottom: "pool5"
?top: "fc6"
?param {
???lr_mult: 1
???decay_mult: 1
?}
?param {
???lr_mult: 2
???decay_mult: 0
?}
?inner_product_param {
???num_output: 512
???weight_filler {
?????type: "gaussian"
?????std: 0.005
???}
???bias_filler {
?????type: "constant"
?????value: 1
???}
?}
}
layer {
?name: "relu6"
?type: "ReLU"
?bottom: "fc6"
?top: "fc6"
}
layer {
?name: "drop6"
?type: "Dropout"
?bottom: "fc6"
?top: "fc6"
?dropout_param {
???dropout_ratio: 0.5
?}
}
layer {
?name: "fc7"
?type: "InnerProduct"
?bottom: "fc6"
?top: "fc7"
?param {
???lr_mult: 1
???decay_mult: 1
?}
?param {
???lr_mult: 2
???decay_mult: 0
?}
?inner_product_param {
???num_output: 512
???weight_filler {
?????type: "gaussian"
?????std: 0.005
???}
???bias_filler {
?????type: "constant"
?????value: 1
???}
?}
}
layer {
?name: "relu7"
?type: "ReLU"
?bottom: "fc7"
?top: "fc7"
}
layer {
?name: "drop7"
?type: "Dropout"
?bottom: "fc7"
?top: "fc7"
?dropout_param {
???dropout_ratio: 0.5
?}
}
layer {
?name: "fc8"
?type: "InnerProduct"
?bottom: "fc7"
?top: "fc8"
?param {
???lr_mult: 1
???decay_mult: 1
?}
?param {
???lr_mult: 2
???decay_mult: 0
?}
?inner_product_param {
???num_output: 5
???weight_filler {
?????type: "gaussian"
?????std: 0.01
???}
???bias_filler {
?????type: "constant"
?????value: 0
???}
?}
}
layer {
?name: "accuracy"
?type: "Accuracy"
?bottom: "fc8"
?bottom: "label"
?top: "accuracy"
?include {
???phase: TEST
?}
}
layer {
?name: "loss"
?type: "SoftmaxWithLoss"
?bottom: "fc8"
?bottom: "label"
?top: "loss"
}
5.2 模型迭代訓練???
運行訓練程序(此處心里苦啊,沒有gpu,懟了十幾個小時?。?/b>
運行訓練模型程序完成(13小時)
?1000次模型迭代,生成Image訓練模型(多少次,大家可以定噠)
5.3 模型測試
1.測試程序
import caffe
import numpy as np
import matplotlib.pyplot as plt
import os
import PIL
from PIL import Image
import sys
#定義Caffe根目錄
caffe_root = 'G:/caffe-master/'
#網絡結構描述文件
deploy_file = caffe_root+'models/my_models_recognition/deploy.prototxt'
#訓練好的模型
model_file =caffe_root+'models/my_models_recognition/model/caffenet_train_iter_5000.caffemodel'
#gpu模式
#caffe.set_device(0)
caffe.set_mode_gpu()
#定義網絡模型
net = caffe.Classifier(deploy_file, #調用deploy文件
??????????????????????model_file,? #調用模型文件
??????????????????????channel_swap=(2,1,0),? #caffe中圖片是BGR格式,而原始格式是RGB,所以要轉化
??????????????????????raw_scale=255,???????? #python中將圖片存儲為[0, 1],而caffe中將圖片存儲為[0,
255],所以需要一個轉換
??????????????????????image_dims=(227, 227)) #輸入模型的圖片要是227*227的圖片
#分類標簽文件
imagenet_labels_filename = caffe_root+'models/my_models_recognition/labels/label.txt'
#載入分類標簽文件
labels = np.loadtxt(imagenet_labels_filename, str)
#對目標路徑中的圖像,遍歷并分類
for root,dirs,files inos.walk(caffe_root+'models/my_models_recognition/image/'):
??? for file infiles:
??????? #加載要分類的圖片
??????? image_file= os.path.join(root,file)
???????input_image = caffe.io.load_image(image_file)
??????? #打印圖片路徑及名稱
??????? image_path= os.path.join(root,file)
???????print(image_path)
??????? #顯示圖片
???????img=Image.open(image_path)
???????plt.imshow(img)
???????plt.axis('off')
??????? plt.show()
??????? #預測圖片類別
??????? prediction= net.predict([input_image])
??????? print 'predictedclass:',prediction[0].argmax()
??????? #輸出概率最大的前5個預測結果
??????? top_k =prediction[0].argsort()[::-1]
??????? fornode_id in top_k:????
??????????? #獲取分類名稱
???????????human_string = labels[node_id]
??????????? #獲取該分類的置信度
??????????? score= prediction[0][node_id]
???????????print('%s (score = %.5f)' % (human_string, score))
??? 2.測試結果
測試代碼運行
?測試代碼運行結果圖(準確率還是可以的,開森,撒花~)
起飛啦~ 下次再補充啦