Caffe:深入分析(怎么训练)
main()
首先入口函数caffe.cpp
int main(int argc, char** argv) {
......
if (argc == ) {
#ifdef WITH_PYTHON_LAYER
try {
#endif
return GetBrewFunction(caffe::string(argv[]))(); //根据输入参数确定是train还是test,采用string到函数指针的映射实现,非常巧妙
#ifdef WITH_PYTHON_LAYER
} catch (bp::error_already_set) {
PyErr_Print();
return ;
}
#endif
} else {
gflags::ShowUsageWithFlagsRestrict(argv[], "tools/caffe");
}
}
在main函数中GetBrewFunction函数调用了通过工厂模式生成的由string到函数指针的map
typedef int (*BrewFunction)();
typedef std::map<caffe::string, BrewFunction> BrewMap;
BrewMap g_brew_map;
在train、test、device_query、time函数后面都可以看到对这些函数的register,相当于这些函数指针已经在map中存在了
RegisterBrewFunction(train);
RegisterBrewFunction(test);
RegisterBrewFunction(device_query);
RegisterBrewFunction(time);
train()
接着是train过程
// Train / Finetune a model.
int train() {
......
caffe::SolverParameter solver_param;
caffe::ReadSolverParamsFromTextFileOrDie(FLAGS_solver, &solver_param);//从-solver参数读取solver_param
......
shared_ptr<caffe::Solver<float> >
solver(caffe::SolverRegistry<float>::CreateSolver(solver_param));//从参数创建solver,同样采用string到函数指针的映射实现,用到了工厂模式 if (FLAGS_snapshot.size()) {//迭代snapshot次后保存模型一次
LOG(INFO) << "Resuming from " << FLAGS_snapshot;
solver->Restore(FLAGS_snapshot.c_str());
} else if (FLAGS_weights.size()) {//若采用finetuning,则拷贝weight到指定模型
CopyLayers(solver.get(), FLAGS_weights);
} if (gpus.size() > ) {
caffe::P2PSync<float> sync(solver, NULL, solver->param());
sync.Run(gpus);
} else {
LOG(INFO) << "Starting Optimization";
solver->Solve();//开始训练网络
}
LOG(INFO) << "Optimization Done.";
return ;
}
Solver()
看CreateSolver函数是如何构建solver和net的,CreateSolver定义在solver_factory.hpp中,首先需要知道的是solver是一个基类,继承自它的类有SGD等,下面的实现就可以根据param的type构造一个指向特定solver的指针,比如SGD。
static Solver<Dtype>* CreateSolver(const SolverParameter& param) {
const string& type = param.type();
CreatorRegistry& registry = Registry();
CHECK_EQ(registry.count(type), ) << "Unknown solver type: " << type
<< " (known types: " << SolverTypeListString() << ")";
return registry[type](param);
}
关键之处在于上面代码最后一行语句,它的作用是根据配置文件创建对应的Solver对象(默认为SGDSolver子类对象)。此处工厂模式和一个关键的宏REGISTER_SOLVER_CLASS(SGD)发挥了重要作用。
#define REGISTER_SOLVER_CLASS(type)
template <typename Dtype>
Solver<Dtype>* Creator_##type##Solver(
const SolverParameter& param)
{
return new type##Solver<Dtype>(param);
}
REGISTER_SOLVER_CREATOR(type, Creator_##type##Solver)
}
这样一个SGDSolver对象就调用其构造函数被构造出来了。
explicit SGDSolver(const SolverParameter& param)
: Solver<Dtype>(param) { PreSolve(); }
同时,Solver这个基类也被构造出来了,在solver.hpp里
explicit Solver(const SolverParameter& param,
const Solver* root_solver = NULL);
Solver构造函数又会调用Init进行训练网络和测试网络的初始化,Init函数没有被声明为虚函数,不能被覆写,也就是说所有的solver都调用这个函数进行初始化。
template <typename Dtype>
void Solver<Dtype>::Init(const SolverParameter& param) {
......
// Scaffolding code
InitTrainNet();//初始化训练网络
if (Caffe::root_solver()) {
InitTestNets();//初始化测试网络
LOG(INFO) << "Solver scaffolding done.";
}
iter_ = ;//迭代次数设为0
current_step_ = ;
}
InitTrainNet()
接下来看训练网络初始化函数InitTrainNet,具体的内容见Net的网络层的构建(源码分析)
caffe是如何来solve的:在成员函数Solve()内部,
template <typename Dtype>
void Solver<Dtype>::Solve(const char* resume_file) {
......
// For a network that is trained by the solver, no bottom or top vecs
// should be given, and we will just provide dummy vecs.
int start_iter = iter_;
//开始迭代
Step(param_.max_iter() - iter_);
......
}
Step()
下面我们看一下Solver::Step()函数内部实现情况,具体的一次迭代过程。见Caffe参数交换源码分析
这就是整个网络的训练过程。
Caffe:深入分析(怎么训练)的更多相关文章
- 基于英特尔® 至强 E5 系列处理器的单节点 Caffe 评分和训练
原文链接 在互联网搜索引擎和医疗成像等诸多领域,深度神经网络 (DNN) 应用的重要性正在不断提升. Pradeep Dubey 在其博文中概述了英特尔® 架构机器学习愿景. 英特尔正在实现 Prad ...
- 【caffe】执行训练
@tags caffe 训练 是在windows平台上. 主要是使用/caffe.exe,配合动作参数train,以及指定solver文件.e.g.: cd %caffe_root% %caffe_b ...
- win10 caffe python Faster-RCNN训练自己数据集(转)
一.制作数据集 1. 关于训练的图片 不论你是网上找的图片或者你用别人的数据集,记住一点你的图片不能太小,width和height最好不要小于150.需要是jpeg的图片. 2.制作xml文件 1)L ...
- caffe 利用VGG训练自己的数据
写这个是因为有童鞋在跑VGG的时候遇到各种问题,供参考一下. 网络结构 以VGG16为例,自己跑的细胞数据 solver.prototxt: net: "/media/dl/source/E ...
- 【caffe】用训练好的imagenet模型分类图像
因为毕设需要,我首先是用ffmpeg抽取某个宠物视频的关键帧,然后用caffe对这个关键帧中的物体进行分类. 1.抽取关键帧的命令: E:\graduation design\FFMPEG\bin&g ...
- 【神经网络与深度学习】深度学习实战——caffe windows 下训练自己的网络模型
1.相关准备 1.1 手写数字数据集 这篇博客上有.jpg格式的图片下载,附带标签信息,有需要的自行下载,博客附带百度云盘下载地址(手写数字.jpg 格式):http://blog.csdn.net/ ...
- Caffe深入分析(源码)
Caffe的整体流程图: 程序入口:main() int main(int argc, char** argv) { ..... ]))(); .... } g_brew_map实现过程,首先通过 t ...
- caffe + ssd网络训练过程
參考博客:https://blog.csdn.net/xiao_lxl/article/details/79106837 1获取源代码:git clone https://github.com/wei ...
- 【caffe】mnist训练日志
@tags caffe 前面根据train_lenet.sh改写了train_lenet.py后,在根目录下执行它,得到一系列输出,内容如下: I1013 10:05:16.721294 1684 c ...
随机推荐
- python学习笔记(4)
第六章 字符串操作 1.字符串处理 (1)字符串字 spam='Say hi to Bob\' s mother 面量 python中输入字符串:以单引号开始和结束 (2)双引号:字符串可以用双引号开 ...
- 以当前时间作为GUID的方法
在C#中,系统提供了GUID类,用户可以通过该类来获得128位的唯一标识,但是该标识不具有可读性,很难把该GUID显示在界面上,以当前时间精确到毫秒来作为GUID是一个比较不错的做法,但是DateTi ...
- Java Web学习总结(4)HttpServletResponse
Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象.和代表响应的response对象.获取网页提交过来的数据,只需要找request对象就行了.要向网 ...
- Qt项目界面文件(.ui)及其作用(超详细)
http://c.biancheng.net/view/1820.html Qt 项目中,后缀为“.ui”的文件是可视化设计的窗体的定义文件,如 widget.ui.双击项目文件目录树中的文件 wid ...
- Linux--用户与用户组--03
用户管理: 1.useradd 创建用户 -c 指定用户描述 -d 指定家目录 -g 指定主组 -G 指定附加组 附加组可以有多个 -s 指定shell程序 特殊的/sbin/nologin--> ...
- mysql查询每个直播间每个用户最早进入时间和最晚退出时间
myself_sql = 'select room_id,source_id user_id,min(cast(at as datetime)) joinroom,max(cast(at as dat ...
- unittest----skip(跳过用例)
我们在执行测试用例时,有时有些用例时不需要执行的,这时就需要用到unittest给我们提供的跳过用例的方法 @unittest.skip(reason):强制跳过,不需要判断条件.reason是跳过原 ...
- JS基础篇--sort()方法的用法,参数以及排序原理
JS基础篇--sort()方法的用法,参数以及排序原理 sort() 方法用于对数组的元素进行排序,并返回数组.默认排序顺序是根据字符串Unicode码点.语法:arrayObject.sort( ...
- CSS3实现三角形和对话框
这是最终实现的效果,类似于微信对话框的样式. 分析一下这个对话框的结构,由一个小三角形和一个长方形构成.长方形很容易就可以实现,重点是如何用CSS3做出一个小三角形. 一.如何生成一个三角形 总结: ...
- React Native 中 static的navigationOptions中的点击事件不能用this
想在某个页面中设置导航栏,title + 左右按钮(按钮上肯定需要有事件) static navigationOptions = ({ navigation, navigationOptions }) ...