這個mnist手寫體數字識别的例子可以說是caffe中的 Hello World。mnist最初用于支票上的手寫數字識别,針對mnist識别的專門模型是Lenet,這是由Yan LeCun大神搞出來的,可以說是最早的CNN執行個體。通過這個例子我們來看一下使用caffe大概是個什麼流程
第一步自然是要有資料了,沒有資料怎麼學習呢?
我們之前談到資料一般是儲存在caffe目錄下data這個目錄的

再進入mnist目錄看一下:
這裡隻有1個file,即是get_mnist.sh腳本,我們就是運作它來下載下傳mnist資料的,
來看一下此腳本裡面寫的什麼
打開此腳本:vim get_mnist.sh
這裡面的内容了解一下即可,主要是讓大家看看稀奇,可見它用了一個for循環,下載下傳了4個檔案,并解壓了它們。
這裡可能和其他一些地方分别把四個檔案的名字和網址都列出來不一樣,可能是caffe版本的問題,但是所執行的任務是一樣的,for循環大家總看得懂吧
廢話有點多了,回到caffe根目錄,輸入下面的代碼,
./data/mnist/get_mnist.sh
然後就顯示以下内容
下載下傳完畢,原來的檔案夾裡多了四個檔案
下載下傳的資料為二進制檔案,需要轉換為LEVELDB或LMDB,
Mnist這個例程儲存在我之前Caffe随記(一)中談及的caffe目錄下example這個目錄,轉到此目錄可見如下,可以看到有個叫做mnist的檔案夾,我們就要用到裡面的東西
打開mnist目錄
我們會用到create_mnist.sh這個腳本(然後我們還偶遇了上篇博文中提到的lenet_solver.prototxt這個腳本)
打開腳本看看裡面的内容: vim create_mnist.sh
這裡還是講一下這個腳本中寫的内容把,
首先,定義了幾個路徑變量:EXAMPLE、DATA、BUILD,因為這裡路徑變量定義的原因,是以我們等會兒調用這個腳本時要回到caffe這個根目錄哦!
下面的這幾個變量等會兒執行時就用這幾個路徑替換
然後,定義了 BACKEND這個變量為”lmdb”,是以下面程式中的BACKEND就用lmdb替換
接着,rm –rf $EXAMPLE/mnist_train_${BACKEND}這兩句是在删除原來這個路徑下的檔案,
也就是如果你之前轉換過一次,他會先删除原來轉換得到的檔案,然後再重新轉換一次;
最後,$BUILD/convert_mnist_data.bin這句話就是在調用BUILD這個路徑下的一個可執行檔案:
convert_mnist_data.bin, 看名字就知道是在轉換格式啦
緊跟 $DATA/train-images-idx3-ubyte\
$DATA/train-labels-idx1-ubyte\
這兩個參數就是我們剛剛第1步下載下傳後的檔案,你看DATA對應的路徑是不是第1步中的?這是訓練集資料train,一個資料一個标簽
緊跟 $EXAMPLE/mnist_train_${BACKEND} --backend=${BACKEND}EXAMPLE/mnist_train_
這個參數是把轉換後的檔案儲存到哪裡
對于test資料也是同樣的操作
這就是這個腳本的較長的描述
那麼我們回到caffe根目錄輸入以下代碼:
./examples/mnist/create_mnist.sh
再去剛剛那個EXAMPLE目錄也就是examples/mnist目錄去看看:
這裡的兩個檔案夾中存放的就是我剛剛轉換了的資料
我們用的網絡是LeNer-5模型,這個模型當初Yan LeCun用的是sigmoid激活函數,但是至AlexNet之後的網絡基本都用ReLU激活函數了,是以這個模型在caffe中用的也是ReLU
有興趣的可以vim打開這個看一下這個檔案,這裡我就不貼圖占篇幅了,caffe随記(二)中Net那一部分(點選打開)我就是舉得這個例子。
檔案的目錄:
,caffe/example/mnist/lenet_train_test.prototxt 上一張圖檔其實就能看到這個檔案的位置
Data準備好了,Net也定義了,下面就該輪到訓練了
在caffe根目錄下運作 ./example/mnist/train_lenet.sh
其實先不急運作,咱們來看看這個腳本的内容再說:
如圖,這個腳本的内容很少,重要的就最後一行:
./build/tools/caffe train 這一句其實是在運作一個可執行檔案,最後我們會詳解一下,這裡不急,因為這裡面用的也是相對路徑,那個點代表的是根目錄caffe,是以我們也要在caffe根目錄下執行這個檔案。
後面的--solver=examples/mnist/lenet_solver.prototxt 是 參數
這個檔案我也不打開看了,因為我的caffe随記(三)中講sovler(點選可打開)時舉的例子就是這個,這個就是我用來訓練時需要的核心檔案。腳本的内容就是這樣,下面執行把。
執行結果會列印出來很多東西:
①GPU資訊
我用的0号GPU: Tesla K40c (實驗室的伺服器,自己當然是買不起的- -)
②solver檔案的參數資訊:
③lenet_train_test.prototxt網絡的資訊和各層的建立過程
你可能會發現列印了兩次網絡,但其實一個是TRAIN一個是TEST,如下所示
和
細節我就不貼圖了,太長了
然後就等着Iteration一直顯示到10000,因為sovler.prototxt中規定了最大疊代次數10000,可以點此轉到我那篇博文;
根據GPU或者CPU性能不同等待的時間不一樣,千萬不要以為你電腦卡住了,隻要它的Iteration一直在增長就說明是在運作
然後會在5000和10000次的時候各輸出2個資料一共是2x2=4個檔案,
lenet_iter_5000.caffemodel、lenet_iter_5000.solverstate
lenet_iter_10000.caffemodel、lenet_iter_10000.solverstate
這四個檔案
同樣是因為solver中定義了每5000次疊代存儲一次資料,可以點此轉到我那篇博文。
獲得訓練出的模型之後,我們就可以用它來測試一把了。
運作 ./examples/mnist/test_lenet.sh
也許出于某些原因你的./examples/mnist目錄下沒有test_lenet.sh這個腳本檔案,無妨,你其實可以自己寫一個,調用linux指令touch 建立一個test_lenet.sh檔案,然後再vim編輯它即可,來看看它的内容是什麼:
#!/usr/bin/env sh
./build/tools/caffe.bin test--model=examples/mnist/lenet_train_test.prototxt –gpu 0--weights=examples/mnist/lenet_iter_10000.caffemodel -iterations 100
第一行 #!/usr/bin/env sh是說用sh方式執行這個腳本,
第二行 ./build/tools/caffetest 還是在調用可執行檔案./build/tools/caffe.bin,然後test是它的參數,表明我現在是在測驗了,
之前我們在train的時候已經碰到了./build/tools/caffe 這個指令,隻不過那個時候參數是train,你可以往上翻到第4步去看看。
後面的--model=examples/mnist/lenet_train_test.prototxt仍然是參數,就是指定Net模型
後面的–gpu 0是我自己添上的一個參數,表明我是指定使用0号GPU來執行,
為什麼我要自己加個這個呢?因為如果不加GPU的話,caffe.bin這個檔案預設調用CPU來運作,這裡不急,我後面會單獨詳解這個caffe.bin這個可執行檔案
後面的--weights=examples/mnist/lenet_iter_10000.caffemodel仍然是參數,這個必須要帶上,因為這就是你第4步訓練出來的模型(也就是得到的權值檔案),
後面的-iterations100仍然是參數,表明疊代次數
然後去根目錄下運作此腳本即可,如果你是自己建立的這個腳本,如果不修改權限的話,也許需要在前面加上sh 這個指令才能運作。
當然其實經過上面的腳本檔案講解後,你完全可以直接在根目錄下輸入腳本裡面的那個指令内容,如下:
./build/tools/caffe.bin test \
> -model examples/mnist/lenet_train_test.prototxt \
> -weightsexamples/mnist/lenet_iter_10000.caffemodel \
> -iterations 100
你看,這裡我通過 直接在caffe根目錄下輸入指令來執行test操作,這裡我就沒有輸入gpu 0,它列印的資訊顯示Use CPU
如果我選擇調用我自己剛剛那個腳本檔案來運作,因為那個檔案裡面我謝了GPU參數,是以就用GPU來運作咯,如下:
你看用的就是我的gpu 0, Tesla K40c
最終結果如下
平均準确率達到0.9904
至此,本篇講解mnist的例子就到此結束了,完成這個實驗,你就已經在caffe中玩了一次 Hello World!了
關于 .build/tools/caffe.bin這個可執行檔案,我在下一篇部落格來詳細介紹一下,點選這裡