携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第 10 天,点击查看活动详情
欢迎关注我的公众号 [极智视界],获取我的更多笔记分享
大家好,我是极智视界,本文介绍一下 ubuntu 离线编译 Caffe GPU 及手写数字集(MNIST)识别。
需已经安装好 CUDA 和 cudnn,故以下操作都是在此基础上进行离线编译 caffe 及深度学习入门 mnist 实践。
一、依赖安装
确保安装好 Anaconda、OpenCv,验证 OpenCv 有没有安装好的方法,输入:
pkg-config opencv --modversion
若正确输出版本号,则说明安装成功。也可查看 OpenCv 的安装路径,使用如下命令:
pkg-config opencv --libs
二、编译Caffe
1、下载caffe包
网址:github.com/bvlc/caffe.… , 下载解压,将 caffe-master 重命名为 caffe。
2、修改配置文件Makefile.config及Makefile文件
cd caffe
cp Makefile.config.example Makefile.config
vim Makefile.config
输入hi,回车 进入编辑模式。
修改如下:
- 将
USE_CUDNN=1的注释取消; - 修改
OPENCV_VERSION := 3; - 若使用
CUDA 9.0以上,将CUDA_ARCH :=中的-gencode arch=compute_20,code=sm_20 \ -gencode arch=compute_20,code=sm_21 \ 给注释或者删除; - 在原来
INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include /usr/include/hdf5/serial LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib现在改成(64位系统):
INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include /usr/include/hdf5/serial /path/to/your/opencv/include LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib /usr/lib/x86_64-linux-gnu/hdf5/serial /path/to/your/opencv/lib;
Esc + : wq 回车
vim Makefile
- 将
NVCCFLAGS += -ccbin = $(CXX)-Xcompiler-fPIC $(COMMON_FLAGS)替换为:NVCCFLAGS += -D_FORCE_INLINES -ccbin = $(CXX) -Xcompiler -fPIC $(COMMON_FLAGS);
3、编译
依次执行下列命令:
make all -j8
make test -j8
make runtest -j8
编译的时候要祈祷,我就是一开始因为 OpenCv 没有安装完整,导致 caffe 编译各种报错。
若一切顺利,就大吉大利了。
一般make 和 test 编译过了就能用了, runtest 可能会报错,不过还是能用,目前影响未知。
三、手写数字集(MNIST)识别
1、数据集下载
因为是离线状态,故无法直接使用 caffe 自带的 caffe\data\mnist\get_mnist.sh 来获取样本数据。
可以直接在网址下载数据集,百度搜索一下一大把。
解压至 caffe\data\mnist\ 文件下,不出意外应该有四个数据文件,分别是测试集图片、测试集标签、训练集图片和训练集标签,如下:
2、转换格式
下载的数据集为二进制格式,必须转换成 caffe 能识别的 lmdb 格式:
./examples/mnist/create_mnist.sh
会在 /examples/mnist 目录下生成 mnist_train_lmdb 和 mnist_test_lmdb 文件夹。
3、训练
./examples/mnist/train_lenet.sh
训练后,会在 examples/mnist 下生成四个文件,分别是迭代 5000 次和 10000 次的模型。
lenet_iter_5000.caffemodel
lenet_iter_5000.solverstate
lenet_iter_10000.caffemodel
lenet_iter_10000.solverstate
4、C++调用模型
工程目录结构:
- mnist
- data
- 1.bmp
- 3.bmp
- ...
- include
- lib
- demo
- pro
- models
- lenet_iter_10000.caffemodel
- lenet_train_test.prototxt
- 3rdparty
- opencv
- src
打开 lenet_train_test.prototxt
将前面两个 data 层:
layer{
name:"mnist"
type:"Data"
...
}
layer{
name:"mnist"
type:"Data"
...
}
替换成:
input:"data"
input_shape{
dim:1 # batchsize
dim:1 # number of channels
dim: 28 # width
dim: 28 # height
}
将最后两个层 accuracy、loss 层:
layer{
name:"accuracy"
type:"Accuracy"
...
}
layer{
name:"loss"
type:"SoftmaxWithLoss"
...
}
替换成:
layer{
name:"prob"
type:"Softmax"
bottom:"ip2"
top:"prob"
}
模型调用主代码:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
// find best class
static void getMaxClass(const cv::Mat &probBlob, int *classId, double *classProb)
{
cv::Mat probMat = probBlob.reshape(1, 1);
cv::Point classNumber;
cv::minMaxLoc(probMat, NULL, classProb, NULL, &classNumber);
*classId = classNumber.x;
}
int main()
{
std::string modelTxt = "../models/lenet_train_test.prototxt";
std::string modelBin = "../models/lenet_iter_10000.caffemodel";
cv::Mat img = cv::imread("../data/3.bmp");
cv::Mat inputBlob = cv::dnn::blobFromImage(img, 0.00390625f, cv::Size(28, 28),cv::Scalar(), false);
cv::dnn::Net net;
try
{
net = cv::dnn::readNetFromCaffe(modelTxt, modelBin);
}
catch(cv::Exception &ee)
{
std::cerr << "Exception: " << ee.what() << std::endl;
if(net.empty())
{
std::cout << "Can't load the network bt using the flowing files:" << std::endl;
std::cout << "modelTxt: " << modelTxt << std::endl;
std::cout << "modelBin: " << modelBin << std::endl;
exit(-1);
}
}
cv::Mat pred;
net.setInput(inputBlob, "data");
pred = net.forward("prob");
std::cout << pred << std::endl;
int classId;
double classProb;
getMaxClass(pred, &classId, &classProb);
std::cout << "Best Class: " << classId << std::endl; // 预测的数字
std::cout << "Probability: " << classProb * 100 << std::endl; // 概率
return 0;
}
好了,以上分享了 ubuntu 离线编译 Caffe GPU 及手写数字集(MNIST)识别。希望我的分享能对你的学习有一点帮助。