論文名稱:Densely Connected Convolutional Networks(CVPR 2017, Best Paper Award)
論文鏈接:https://arxiv.org/pdf/1608.06993.pdf
源碼鏈接:https://github.com/liuzhuang13/DenseNet
caffe版源碼: https://github.com/liuzhuang13/DenseNetCaffe
1. 下載Caffe版DenseNet源碼
源碼中包含以下6個文件:
make_densenet.py:用於生成train_densenet.prototxt文件、test_densenet.prototxt文件以及solver.prototxt文件
train_densenet.protoxt: 訓練時用到的模型網絡文件
test_denset.prototxt:訓練過程中驗證部分用到的網絡文件
solover.prototxt:caffe用到的solover文件
train.sh:ubuntu環境下的訓練文件
train_densenet.prototxt與test_densenet.prototxt文件指定了需要用到cifar10數據集及其均值,如圖。
因此我們需要先準備cifar10數據集。
2. 創建cifar10數據集
2. 1 下載cifar10數據集
官網下載bin格式的cifar10 : http://www.cs.toronto.edu/~kriz/cifar.html
即CIFAR-10 binary version (suitable for C programs)格式版本,解壓存放在 :caffe-master\examples\cifar10\input_folder當中(input_folder文件夾需要自己創建),
如圖:
2. 2 轉換爲lmdb格式
首先在VS中編譯出Caffe的convert_cifar_data.exe工具,在caffe-master\Build\x64\Release\目錄下。
在caffe-master\examples\cifar10 下創建一個bat文件(convert_cifar10_lmdb.bat),輸入以下:
..\..\Build\x64\Release\convert_cifar_data.exe input_folder output_folders lmdb
pause
然後雙擊運行,可以看到在 caffe-master\examples\cifar10下會生成output_folders文件夾,裏面存放的就是轉換好lmdb格式數據,如圖:
如果需要leveldb格式,則將bat文件中的lmdb改爲lveldb,再運行即可。
2.3 生成mean.binaryproto均值文件
首先在VS中編譯出Caffe的compute_image_mean.exe工具,在caffe-master\Build\x64\Release\目錄下。
在caffe-master\examples\cifar10 下創建一個bat文件(get_mean_binaryproto_lmdb.bat),輸入以下:
..\..\Build\x64\Release\compute_image_mean.exe -backend=lmdb ../../examples\cifar10\output_folders\cifar10_train_lmdb mean.binaryproto
Pause
雙擊運行後,即在affe-master\examples\cifar10下生成lmdb格式的mean.binaryproto文件,如圖:
同理如果需要leveldb格式,修改bat文件中的lmdb爲leveldb即可。
3. 訓練Cifar10
3.1 更改模型文件數據集路徑
在DenseNetCaffe根目錄下創建data文件夾,將cifar10_train_lmdb與cifar10_test_lmdb兩個文件夾以及mean.binaryproto文件到拷到data下,如圖:
更改train_densenet.prototxt與test_densenet.prototxt文件中的數據集路徑即均值文件路徑
也可以更改make_densenet.py文件中的路徑來生成3個prototxt文件,如圖:
3.2 訓練模型
在DenseNetCaffe根目錄下創建一個train.bat文件,編輯以下代碼:
SET GLOG_logtostderr=1
C:\zhh\caffe-master\Build\x64\Release\caffe.exe train --solver C:\zhh\DenseNetCaffe\solver.prototxt
pause
另外,需要注意的是,原模型訓練需要較大的顯存,我本機顯存爲8GB,運行train.bat文件加載模型開始訓練後會報out of memory錯誤,即顯存不足。可通過降低train_densenet.prototxt文件中的batch_size來降低所需要的顯存,這裏我將batch_size修改爲32,運行train.bat,即開始訓練,如圖:
迭代次數達到設定的最高值23萬時,模型訓練停止,模型訓練的準確率已接近1,損失值接近0
在DensetNet根目錄下生成了權重文件,如下:
4. 測試模型
4.1 對測試集圖像數據進行測試
在DensetNet根目錄下創建test.bat,如下:
SET GLOG_logtostderr=1
C:\zhh\caffe-master\Build\x64\Release\caffe.exe test -model=C:\zhh\DenseNetCaffe\test_densenet.prototxt -weights=C:\zhh\DenseNetCaffe\_iter_230000.caffemodel -iterations=100
pause
雙擊運行,得到對100個批次測試集數據的測試,如下:
I0708 13:51:39.630722 14688 caffe.cpp:286] Running for 100 iterations.
I0708 13:51:43.784732 14688 caffe.cpp:309] Batch 0, Accuracy1 = 0.96
I0708 13:51:44.222826 14688 caffe.cpp:309] Batch 0, SoftmaxWithLoss1 = 0.0977751
I0708 13:51:47.511251 14688 caffe.cpp:309] Batch 1, Accuracy1 = 0.92
I0708 13:51:47.512169 14688 caffe.cpp:309] Batch 1, SoftmaxWithLoss1 = 0.485769
I0708 13:51:50.807596 14688 caffe.cpp:309] Batch 2, Accuracy1 = 0.9
I0708 13:51:50.807596 14688 caffe.cpp:309] Batch 2, SoftmaxWithLoss1 = 0.317953
I0708 13:51:54.090023 14688 caffe.cpp:309] Batch 3, Accuracy1 = 0.94
I0708 13:51:54.090023 14688 caffe.cpp:309] Batch 3, SoftmaxWithLoss1 = 0.216393
I0708 13:51:57.379446 14688 caffe.cpp:309] Batch 4, Accuracy1 = 0.94
I0708 13:51:57.379446 14688 caffe.cpp:309] Batch 4, SoftmaxWithLoss1 = 0.395111
I0708 13:52:00.693857 14688 caffe.cpp:309] Batch 5, Accuracy1 = 0.92
I0708 13:52:00.693857 14688 caffe.cpp:309] Batch 5, SoftmaxWithLoss1 = 0.424328
……………
I0708 14:00:43.962534 14688 caffe.cpp:309] Batch 95, Accuracy1 = 0.84
I0708 14:00:43.962534 14688 caffe.cpp:309] Batch 95, SoftmaxWithLoss1 = 0.692951
I0708 14:00:47.326921 14688 caffe.cpp:309] Batch 96, Accuracy1 = 1
I0708 14:00:47.327920 14688 caffe.cpp:309] Batch 96, SoftmaxWithLoss1 = 0.00866098
I0708 14:00:50.655325 14688 caffe.cpp:309] Batch 97, Accuracy1 = 1
I0708 14:00:50.656323 14688 caffe.cpp:309] Batch 97, SoftmaxWithLoss1 = 0.021941
I0708 14:00:54.095676 14688 caffe.cpp:309] Batch 98, Accuracy1 = 0.88
I0708 14:00:54.095676 14688 caffe.cpp:309] Batch 98, SoftmaxWithLoss1 = 0.576406
I0708 14:00:57.427078 14688 caffe.cpp:309] Batch 99, Accuracy1 = 0.9
I0708 14:00:57.427078 14688 caffe.cpp:309] Batch 99, SoftmaxWithLoss1 = 0.586738
I0708 14:00:57.428077 14688 caffe.cpp:314] Loss: 0.312385
I0708 14:00:57.429077 14688 caffe.cpp:326] Accuracy1 = 0.9232
I0708 14:00:57.429077 14688 caffe.cpp:326] SoftmaxWithLoss1 = 0.312385 (* 1 = 0.312385 loss)
4.2 測試其他圖片
這裏我們編寫Python文件調用Caffe對我們自己的圖片文件進行測試。
(1)準備測試圖片
在densenet根目錄下創建images文件夾,存放要測試的圖片,如下,圖像爲RGB格式,32x32大小
(2)生成densenet.prototxt文件
4.1中使用的prototxt文件爲test_densenet.prototxt,爲訓練時用到的網絡文件,實際在測試及部署需要deploy prototxt文件,可在test_densenet.prototxt上改寫,如下步驟:
- 拷貝test_densenet.prototxt文件,並重命名爲densent.prototxt
- 在densent.prototxt中,刪除第1層,即name爲Data1的層,並添加如下層:
layer {
name: "data"
type: "Input"
top: "data"
input_param { shape: { dim: 1 dim: 3 dim: 32 dim: 32 } }
}
- 將第2層(即nama爲Convolution1的層)中的bottom: "Data1"改爲bottom: "data"
- 刪除最後一層,即name爲Accuracy1的層
- 對最後name爲SoftmaxWithLoss1的層改寫,如下:
改寫前:
layer {
name: "SoftmaxWithLoss1"
type: "SoftmaxWithLoss"
bottom: "InnerProduct1"
bottom: "Data2"
top: "SoftmaxWithLoss1"
}
改寫後:
layer {
name: "prob"
type: "Softmax"
bottom: "InnerProduct1"
top: "softmax"
}
(3)生成mean.npy文件
Caffe中需要的是mean.binaryproto二進制文件,但Caffe的Python接口需要npy格式的文件,因此需要將mena.binaryproto轉爲mean.npy格式。在mean.binaryproto的目錄下(DenseNetCaffe\data)創建make_meannpy.py文件,代碼如下:
import numpy as np
import caffe
MEAN_PROTO_PATH = 'mean.binaryproto'
MEAN_NPY_PATH = 'mean.npy'
blob = caffe.proto.caffe_pb2.BlobProto()
data = open(MEAN_PROTO_PATH, 'rb').read()
blob.ParseFromString(data)
array = np.array(caffe.io.blobproto_to_array(blob))
mean_npy = array[0]
np.save(MEAN_NPY_PATH, mean_npy)
運行,即在data目錄下生成mean.npy文件
(4) 編寫test_densenet.py文件
在densenet根目錄下創建test_densenet.py文件,編寫代碼如下:
import os.path as osp
import numpy as np
import caffe
this_dir = osp.dirname(__file__)
net_file = osp.join(this_dir, 'densenet.prototxt')
pretrained_file = osp.join(this_dir, '_iter_230000.caffemodel')
image_file = osp.join(this_dir, 'images/05_32x32.png')
mean_file = osp.join(this_dir, 'data/mean.npy')
classes = ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']
input_image = caffe.io.load_image(image_file, color=True) #load_image讀進來的圖像數據爲RGB格式,範圍爲0~1
mean_npy = np.load(mean_file)
mean = mean_npy.mean(1).mean(1)
caffe.set_mode_gpu()
net = caffe.Classifier(net_file,
pretrained_file,
mean=mean,
raw_scale=255, #數據範圍調整爲0~255
channel_swap=(2,1,0)) #轉換爲BGR格式
prediction = net.predict([input_image], oversample=True)
idx = prediction[0].argmax()
print image_file + ' predicted_class:', classes[idx]
運行以上程序,即可預測出圖片的類別,如下: