之前因为有caffe的项目要放到服务器上面,但是其实不需要在服务器上面重新安装caffe,所以写了个makefile. 这里改写了个简单的,比较容易读的,只运行caffe.cpp,如果由其他的,可以按照makefile的规则添加就好。
首先,还是要说一下关于caffe的依赖,参考之前的两篇博客:http://blog.csdn.net/thystar/article/details/51179064 和http://blog.csdn.net/thystar/article/details/50837750
这里,我们运行下caffe.cpp的train过程:
因为我的caffe是gpu编译的,这里我们需要用cpu,所以,编译会报错:fatal error: cublas_v2.h: 没有那个文件或目录。需要改下代码:在device_alternate.cpp中添加#define CPU_ONLY 1即可
因为这里不需要用gpu,所以稍微改下train的代码,把跟gpu下相关的代码删掉:
改完后的代码如下:
int train() {
CHECK_GT(FLAGS_solver.size(), 0) << "Need a solver definition to train."; /// FLAGS_solver是一个字符串,这里这个字符串是“examples/mnist/lenet_solver.prototxt”
CHECK(!FLAGS_snapshot.size() || !FLAGS_weights.size())
<< "Give a snapshot to resume training or weights to finetune "
"but not both.";
caffe::SolverParameter solver_param;
caffe::ReadSolverParamsFromTextFileOrDie(FLAGS_solver, &solver_param);///读取文件,并将相应的值赋给solver_param
caffe::SignalHandler signal_handler(
GetRequestedAction(FLAGS_sigint_effect),
GetRequestedAction(FLAGS_sighup_effect));
Caffe::set_mode(Caffe::CPU);
shared_ptr >
solver(caffe::SolverRegistry::CreateSolver(solver_param));///完成网络的初始化
solver->SetActionFunction(signal_handler.GetActionFunction());
if (FLAGS_snapshot.size()) {
LOG(INFO) << "Resuming from " << FLAGS_snapshot;
solver->Restore(FLAGS_snapshot.c_str());
} else if (FLAGS_weights.size()) {
CopyLayers(solver.get(), FLAGS_weights);
}
LOG(INFO) << "Starting Optimization";
solver->Solve();///开始训练,优化过程中所有的输出都来自这一步
LOG(INFO) << "Optimization Done.";
return 0;
}
RegisterBrewFunction(train);
然后,来写个Makefile,
首先,需要指定caffe路径,
# this is a makefile for caffe
TARGET := mnist
# caffe directory
CAFFE_DIR := /home/sindyz/caffe-master
# caffe include
CAFFE_INCLUDE := $(CAFFE_DIR)/include
# caffe build
CAFFE_BUILD := $(CAFFE_DIR)/build
# caffe build lib
CAFFE_BUILD_LIB := $(CAFFE_BUILD)/lib
# caffe build src
CAFFE_BUILD_SRC := $(CAFFE_BUILD)/src
# dependency libraries and caffe linking libs
LFLAGS := -pthread -lnsl -lX11
LFLAGS += -lcaffe -lglog -lgflags \
-lprotobuf -lboost_system -lboost_filesystem \
-lboost_thread -lboost_coroutine -lboost_context -lboost_regex\
-lm -lhdf5_hl -lhdf5 -lleveldb -lsnappy -llmdb \
-lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_objdetect\
-lstdc++ -lcblas -latlas
LFLAGS += -Wl,-rpath=$(CAFFE_BUILD_LIB)
这里需要说明的是,如果指示在本机上运行-rpath=$(CAFFE_BUILD_LIB)是没有问题的。如果要放到别的系统上,需要把所有的链接库文件全部放到lib目录下,一并上传。具体步骤后面会介绍
后面的就是要定义运行规则:
# rules
CFLAGS := -g -I . -I $(CAFFE_INCLUDE) -I $(CAFFE_DIR)/src \
-I $(CAFFE_BUILD_SRC) -I ./ \
-Wall -DCPU_ONLY -DUSE_OPENCV
CC := g++
SRC += caffe.cpp
$(TARGET):$(SRC)
$(CC) -o $(TARGET) -O0 -std=c++11 $(SRC) $(CFLAGS) $(LFLAGS) -L$(CAFFE_BUILD_LIB) -Wno-sign-compare
clean :
@rm -f $(TARGET)
OK, 在当前目录下打开命令窗口,输入make编译。
编译成功后,运行:./mnist train --solver=examples/mnist/lenet_solver.prototxt
这里运行的是mnist这个数据集
现在,说一下如果要把这个项目放到别的linux系统要怎么弄。
首先,需要找出本项目所有依赖库:我的生成的执行文件名是mnist.
在当前目录下执行:
cp $(ldd mnist | cut -d \( -f1 | cut -d \> -f2) lib/
lib目录要提前建好,这样,所有的依赖库都被放到lib目录下;
命令行中间的部分其实是个正则表达式,可以直接ldd mnist下看看库文件的输出形式
然后,需要改下makefile, 把原来的-rpath=$(CAFFE_BUILD_LIB) 该为当前lib目录-rpath=./lib
即可。
最后需要说明的两个地方是,1. 拷贝到别的系统的文件只需mnist这个执行文件,lib文件和数据的存放文件examples/mnist目录。
2. 如果用centos,g++的默认版本太低。需要跟新下,跟新执行如下命令:
$ cat /etc/centos-release
CentOS release 6.7 (Final)
$ sudo yum install centos-release-scl
$ sudo yum install devtoolset-3-toolchain
$ scl enable devtoolset-3 bash
$ gcc --version
gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)
...
$ g++ --version
g++ (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)
...
$ gfortran --version
GNU Fortran (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)