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 ...
随机推荐
- Tomcat编译jsp生成Servlet文件的存放位置
转自:http://www.cnblogs.com/Leon5/archive/2010/12/07/1899300.html Tomcat将jsp编译成servlet后的文件存放在\work\Cat ...
- python3中编码与解码的问题
python3中编码与解码的问题 ASCII .Unicode.UTF-8 ASCII 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和1两种状态,因此 ...
- /etc/nscd.conf - 域名服务缓存守护进程配置文件
描述 DESCRIPTION 该文件 /etc/nscd.conf 在启动 nscd(8) 时读入.每一行或者指定一个属性和值,或者指定一个属性.服务和一个值.域之间通过空格或者TAB分开.‘#’表示 ...
- 继续死磕python
一.数据运算 算术运算 比较运算 赋值运算 逻辑运算 成员运算 身份运算 位运算 其中左右移运算是逻辑左右移即缺失位补0,而算数右移缺失补符号位(注意逻辑运算都是补码运算即都取补码再运算,然后结果也是 ...
- VB中preserve的用法
注:本文转载自:http://zhidao.baidu.com/question/161401549.html ReDim 语句用来定义或重定义原来已经用带空圆括号(没有维数下标)的 Private. ...
- 10年前文章_ vi编辑器查找与替换方法
vi编辑器查找与替换方法1.查找:/ 当前行往下找:? 当前行往上找找到后继续查找同方向 n反方向 N2.替换格式: range s/source/target/g解释:range表示要搜索的范围 & ...
- socket客户端的备份机制
SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0); //设定服务器的地址信息 SOCKADDR_IN addrSrv; addrSrv.sin_a ...
- DevExpress v18.2版本亮点——Analytics Dashboard篇(二)
行业领先的.NET界面控件——DevExpress v18.2版本亮点详解,本文将介绍了DevExpress Analytics Dashboard v18.2 的版本亮点,新版30天免费试用!点击下 ...
- ESP8266-12F 中断
外部中断: 基于ESP8266的NodeMcu的数字IO的中断功能是通过attachInterrupt,detachInterrupt函数所支持的.除了D0/GPIO16,中断可以绑定到任意GPIO的 ...
- python+selenium实现发送一封带附件的邮件
163邮件登录首页 登录成功断言是否有退出按钮 点击退出退出登录 from selenium import webdriver import unittest import time class Vi ...