caffe安装,编译(包括CUDA和cuDNN的安装),并训练,测试自己的数据(caffe使用教程)
caffe是一個非常清晰且高效的深度學習框架,目前有著不少的用戶,也漸漸的形成了自己的社區,社區上可以討論相關的問題。
我從開始看深度學習的相關內容到能夠用caffe訓練測試自己的數據,看了不少網站,教程和博客,也走了不少彎路,在此把整個流程梳理和總結一遍,以期望可以可以僅僅通過這一篇文章就可以輕松的用caffe訓練自己的數據,體驗深度學習的樂趣。(本文中包含了很多的鏈接,鏈接中有我看過的詳細的教程和講解,以方便大家理解)
1.安裝和配置caffe(包括安裝CUDA)?
caffe的安裝和編譯,官網上已經寫的非常的詳細了。官網上的安裝鏈接 :?鏈接? ? ? ??只要按照官網的說明一步步的進行,一般都是不會出什么問題的。并且,官網給出來ubuntu,Mac,和Windows環境下安裝和配置的鏈接。條件允許的話,還是盡量在Ubuntu下安裝和配置吧,對于不熟悉Ubuntu的人來說可能比較麻煩,但是我感覺,在linux下安裝,編譯,包括后面的使用都是比較方便的。
這里需要提前說明的一點是,在官方給的安裝文檔里,下面幾個是可以選擇安裝的
- OpenCV?>= 2.4 including 3.0
- IO libraries:?lmdb,?leveldb?(note: leveldb requires?snappy)
- cuDNN for GPU acceleration (v5)
其中,cuDnn是專門針對CUDA的加速套件,可以為在GPU上跑深度學習的程序進行加速,所以這個還是安裝一下吧,為以后跑程序能省些時間。
2. cuDNN的安裝
這里單獨強調一下cuDNN的安裝(網上給的很多教程有問題,會導致后面的編譯失敗),cuDNN的安裝需要在CUDA安裝完成后進行。
cuDnn需要從Nvidia的官網上下載,并且需要先注冊才行,注冊的時候會讓你填寫一些調查問卷,注冊完成后,選擇正確的版本進行下載。我這里下載的是:Download cuDNN v5 (May 27, 2016), for CUDA 8.0? ??cuDNN v5 Library for Linux版本,然后解壓縮,并且放到相應的文件夾下,最后修改一下權限
CXX/LD -o .build_release/tools/upgrade_net_proto_text.bin .build_release/lib/libcaffe.so: undefined reference to caffe::curandGetErrorString(curandStatus)
.build_release/lib/libcaffe.so: undefined reference to caffe::BaseConvolutionLayer::weight_gpu_gemm(double const*, double const*, double*)
.build_release/lib/libcaffe.so: undefined reference to caffe::BaseConvolutionLayer::forward_gpu_bias(double*, double const*)
找了好多資料,最后在stackoverflaw上找到了解決辦法,我這里把鏈接貼出來:鏈接
其實方法就是,在/usr/local/cuda/lib64 目錄下,執行如下操作(網上的大神說,復制過程破壞了軟連接,所以要自己手動建立一下軟連接)
sudo rm libcudnn.so.5 libcudnn.so sudo ln -sf libcudnn.so.5 libcudnn.so sudo ln -sf libcudnn.so.5.1.3 libcudnn.so.5 sudo ldconfig /usr/local/cuda/lib64
此時,再重新編譯,運行 make all ? ? ?然后,make test ?,在然后make runtest ? 就可以了。
3.在MNIST上用caffe訓練LeNet網絡
MNIST是一個手寫數字的數據集,LeNet 是一個比較簡單的深度學習網絡模型。
這個過程,官方是給了教程的,附上鏈接:鏈接
但是當時我按著步驟一步步的執行,最后也能夠完全運行成功,但是程序是怎么運行成功的,怎么跑通的,原理是什么,我還是搞不懂。
為了弄清楚程序具體的執行過程,我嘗試利用自己找的一些數據進行訓練和測試,以便加深對caffe和深度學習的理解。
4.訓練和測試自己的數據
這里要感謝這篇博客的給我的巨大幫助:點擊打開鏈接。雖然博客寫的很好,但是還是有一些不詳細的地方。我在這篇博客的基礎上進行完成和補充,盡量把整個過程描述的更加詳細。
1)準備數據
要想訓練自己的網絡,首先要有圖片數據,前期在學習階段,為了節省時間,先從小的數據集開始訓練和學習比較合適,博客的博主給了一個小數據集的鏈接,共500張圖片,分為大巴,恐龍,大象,鮮花和馬 五個類別,每個類別100張,數據集的下載鏈接為:http://pan.baidu.com/s/1nuqlTnN
編號為3,4,5,6,7開頭的,分別為一類,每一類的100張圖片,用80個作為訓練,20個作為測試,圖片放在caffe目錄下的data目錄下,即訓練圖片的目錄為data/re/train,測試圖片的目錄為data/re/test
2)圖片轉換為lmdb格式
caffe中,不能直接拿jpg,png之類的圖片文件進行訓練,需要將圖片格式轉換為lmdb格式才可以使用。而且caffe提供了轉換格式所需要的工具,我們只需要寫幾行代碼就能轉換完成。
在examples文件夾下新建一個myffle文件夾,這個文件用來存放配置文件,腳本文件和lmdb文件,然后編寫一個腳本文件,create_filelist.sh用來生成train.txt和test.txt兩個文本文件,這連個文本文件包含圖片的列表清單。然后編輯這個腳本文件如下:
#!/usr/bin/env sh DATA=data/re/ MY=examples/myfileecho "Create train.txt..." rm -rf $MY/train.txt for i in 3 4 5 6 7 do find $DATA/train -name $i*.jpg | cut -d '/' -f4-5 | sed "s/$/ $i/">>$MY/train.txt done echo "Create test.txt..." rm -rf $MY/test.txt for i in 3 4 5 6 7 do find $DATA/test -name $i*.jpg | cut -d '/' -f4-5 | sed "s/$/ $i/">>$MY/test.txt done echo "All done"然后運行這個腳本文件 sudo sh examples/myfile/create_filelist.sh 然后就可以得到train.txt和test.txt文件了,打開看看基本上就知道這個文件是干啥的了吧。(就是為每個圖片做類別標記)
(其實,上述步驟的腳本文件如果看不懂或者覺得不方便,用c寫個文件生成train.txt和test.txt也可以。我自己對腳本文件不太熟悉,所以這些操作我有時候會用c寫。)
接著在編寫一個腳本文件,調用convert_imageset命令來轉換數據格式。(就是把圖片格式的文件轉換成了lmdb格式)
sudo vi examples/myfile/create_lmdb.sh在其中插入 #!/usr/bin/env sh MY=examples/myfileecho "Create train lmdb.." rm -rf $MY/img_train_lmdb build/tools/convert_imageset \ --shuffle \ --resize_height=256 \ --resize_width=256 \ /home/xxx/caffe/data/re/ \ $MY/train.txt \ $MY/img_train_lmdbecho "Create test lmdb.." rm -rf $MY/img_test_lmdb build/tools/convert_imageset \ --shuffle \ --resize_width=256 \ --resize_height=256 \ /home/xxx/caffe/data/re/ \ $MY/test.txt \ $MY/img_test_lmdbecho "All Done.."
圖片的大小不一致,所以統一轉換成了256×256 的大小,運行成功后,會在examples/myfile下生成兩個文件,img_train_lmdb和img_val_lmdb,這個兩個文件就是圖片數據集轉換后的文件。
3)計算均值并保存
圖片減去均值再訓練,可以提高訓練速度和精度。因此,一般都會有這個操作。(比如非常有名的描述AlexNet的論文中,也有這一步預操作)
同樣的,減去均值的操作caffe也寫好了,直接調用就行了,即compute_image_mean.cpp文件
sudo build/tools/compute_image_mean examples/myfile/img_train_lmdb examples/myfile/mean.binaryprotocompute_image_mean帶兩個參數,第一個參數是lmdb訓練數據位置,第二個參數設定均值文件的名字及保存路徑。
運行成功后,會在 examples/myfile/ 下面生成一個mean.binaryproto的均值文件。
4)創建神經網絡模型并編寫配置文件
這里,就使用caffe自帶的caffenet模型進行訓練,把該模型和相應的配置文件都拷貝過來,操作如下:
sudo cp models/bvlc_reference_caffenet/solver.prototxt examples/myfile/ sudo cp models/bvlc_reference_caffenet/train_val.prototxt examples/myfile/
solver.prototxt是整個網絡的配置文件,將其修改如下:
net: "examples/myfile/train_val.prototxt" test_iter: 2 test_interval: 50 base_lr: 0.001 lr_policy: "step" gamma: 0.1 stepsize: 100 display: 20 max_iter: 500 momentum: 0.9 weight_decay: 0.005 # snapshot intermediate results snapshot: 500 snapshot_prefix: "examples/myfile/results/my" solver_mode: GPU 關于配置文件參數不理解的地方,可以看鏈接:鏈接
然后,修改 train_val.protxt,修改成如下形式
name: "CaffeNet" layer {name: "data"type: "Data"top: "data"top: "label"include {phase: TRAIN}transform_param {mirror: truecrop_size: 227mean_file: "examples/myfile/mean.binaryproto"} # mean pixel / channel-wise mean instead of mean image # transform_param { # crop_size: 227 # mean_value: 104 # mean_value: 117 # mean_value: 123 # mirror: true # }data_param {source: "examples/myfile/img_train_lmdb"batch_size: 50backend: LMDB} } layer {name: "data"type: "Data"top: "data"top: "label"include {phase: TEST}transform_param {mirror: falsecrop_size: 227mean_file: "examples/myfile/mean.binaryproto"} # mean pixel / channel-wise mean instead of mean image # transform_param { # crop_size: 227 # mean_value: 104 # mean_value: 117 # mean_value: 123 # mirror: false # }data_param {source: "examples/myfile/img_test_lmdb"batch_size: 50backend: LMDB} } layer {name: "conv1"type: "Convolution"bottom: "data"top: "conv1"param {lr_mult: 1decay_mult: 1}param {lr_mult: 2decay_mult: 0}convolution_param {num_output: 96kernel_size: 11stride: 4weight_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: MAXkernel_size: 3stride: 2} } layer {name: "norm1"type: "LRN"bottom: "pool1"top: "norm1"lrn_param {local_size: 5alpha: 0.0001beta: 0.75} } layer {name: "conv2"type: "Convolution"bottom: "norm1"top: "conv2"param {lr_mult: 1decay_mult: 1}param {lr_mult: 2decay_mult: 0}convolution_param {num_output: 256pad: 2kernel_size: 5group: 2weight_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: MAXkernel_size: 3stride: 2} } layer {name: "norm2"type: "LRN"bottom: "pool2"top: "norm2"lrn_param {local_size: 5alpha: 0.0001beta: 0.75} } layer {name: "conv3"type: "Convolution"bottom: "norm2"top: "conv3"param {lr_mult: 1decay_mult: 1}param {lr_mult: 2decay_mult: 0}convolution_param {num_output: 384pad: 1kernel_size: 3weight_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: 1decay_mult: 1}param {lr_mult: 2decay_mult: 0}convolution_param {num_output: 384pad: 1kernel_size: 3group: 2weight_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: 1decay_mult: 1}param {lr_mult: 2decay_mult: 0}convolution_param {num_output: 256pad: 1kernel_size: 3group: 2weight_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: MAXkernel_size: 3stride: 2} } layer {name: "fc6"type: "InnerProduct"bottom: "pool5"top: "fc6"param {lr_mult: 1decay_mult: 1}param {lr_mult: 2decay_mult: 0}inner_product_param {num_output: 4096weight_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: 1decay_mult: 1}param {lr_mult: 2decay_mult: 0}inner_product_param {num_output: 4096weight_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: 1decay_mult: 1}param {lr_mult: 2decay_mult: 0}inner_product_param {num_output: 1000weight_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" }
這個文件其實就是定義了整個網絡的模型,每一個layer就是一層,你在每一層中定義好這是卷積層還是池化層,神經元有多少等等,具體的參數的含義可以看鏈接:點擊打開鏈接
5)訓練和測試
只需要直接輸入下面的命令就可以完成了。(這里需要注意的是,訓練和測試整個的流程是一起執行的,因為上面的train_val.prototxt文件把train和test的參數都設定好了,所以程序訓練完了以后就會直接進入測試數據的階段,其實也可以寫成兩個文件分開執行。在solver.prototxt中,有一行為
snapshot_prefix: "examples/myfile/results/my"
這就表示,你訓練好的權值都在results文件夾下面保存著,以后如果想要使用訓練好的模型,直接調用rusult下的文件進行測試就可以。)
最后的輸出結果中,
Test net output #0:accuracy:0.95
這一行,就表示在測試數據上,用自己訓練的網絡進行分類的正確率達到了95%。
總結
以上是生活随笔為你收集整理的caffe安装,编译(包括CUDA和cuDNN的安装),并训练,测试自己的数据(caffe使用教程)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ubuntu(linux)下安装open
- 下一篇: 【论文笔记】Region-based C