Caffe_Net

1.基本数据

    vector<shared_ptr<Layer<Dtype> > > layers_; // 记录每一层的layer参数
vector<vector<Blob<Dtype>*> > bottom_vecs_;
vector<vector<int> > bottom_id_vecs_;
vector<vector<bool> > bottom_need_backward_;
/// top_vecs stores the vectors containing the output for each layer
vector<vector<Blob<Dtype>*> > top_vecs_;
vector<vector<int> > top_id_vecs_;
vector<vector<int> > param_id_vecs_;
vector<string> layer_names_;
//learnable_params_[learnable_param_ids_[i]] == params_[i].get()
vector<Blob<Dtype>*> learnable_params_;//层间权重与bias

2. 常用的函数

介绍了Caffe内的Net的常用函数:
   const string& name(){return name_;}//网络的名称
const vector<string>& layer_names{return layer_names_;}// net每层的layer名称
// net内每层的layer的Blob名称
const vector<string>& blob_names(){return blob_names_;}
//net内层次间的权值与bias
const vector<shared_ptr<Blob<Dtype>>>& blobs(){return blob_;};
//net内的layers
const vector<shared_ptr<Layer<Dtype>>>& layers(){return layers_;};
//net->bottom_vecs() 返回该layer的输入,输出向量,
//以及具体的 top_id_vecs[layer_id][top_id];
const vector<vector<Blob<Dtype>*> >& bottom_vecs(){ return bottom_vecs_;}
const vector<vector<Blob<Dtype>*> >& top_vecs() { return top_vecs_;}
const vector<vector<int> >& bottom_id_vecs(){ return bottom_id_vecs_;}
const vector<vector<int> >& top_id_vecs() { return top_id_vecs_;}
void CopyTrainedLayersFrom(const string trained_filename);//加载权重
//网络的输入输出
//感觉等效于bottom_vecs_[0]
const vector<Blob<Dtype>*>& input_blobs(){return net_input_blobs_;}
const vector<Blob<Dtype>*>& output_blobs()
{return net_output_blobs;}//top_vecs[top_vecs.size()-1]; const int num_input(){return net_input_blobs_.size()};//输入blob的size
//has_blob()然后find return
const shared_ptr<Blob<Dtype>>blob_by_name(const string& blob_name); // 前向计算loss和网络的输出
const vector<Blob<Dtype>*>& forward(Dtype* loss = NULL);
// --- *loss = ForwardFromTo(0.layers_.size()-1);
// --- 此处调用 Dtype* Net<Dtype>::ForwardFrom(int start,int end)
for (size_t i = start; i < end; i++){
//多态,调用具体的Layer的Forward函数,并返回该层次的loss
Dtype layer_loss = layers_[i]->Forward(bottom_vecs_[i],top_vecs_[i]);
loss += layer_loss;
}
return loss; // backward反向,更新权值
void Net<Dtype>::Backward(){ //
BackwardFromTo(layers_size()-1,0); // 具体函数实现如第三部分
if (debug_info_) {
/*层次的参数*/
}
}

3.具体函数实现

template <typename Dtype>
const int Net<Dtype>::AppendBottom(const NetParamter& param, int layer_id,
int bottom_id,set<string>* availabel_blobs,map<string,int>* blob_name_to_idx){
const LayerParammeter& layer_param = param.layer(layer_id);
const string& blob_name = layer_param.bottom(bottom_id);
const int blob_id = (*blob_name_to_idx)[blob_name];
//layer输入的shape等
bottom_vecs_[layer_id].push_back(blobs_[blob_id].get());
bottom_id_vecs_[layer_id].push_back(blob_id);
//LOG CONV<--data 等,只要是丢入输入
} // learnable_params_
//conv的shape一般为num_output*input_channels*kernel_width*kernel_height
//bias的shape一般为Num_output
template <typename Dtype>
void Net<Dtype>::AppendParam(const NetParameter& param, const int layer_id,
const int param_id) {
const int learnable_param_id = learnable_params_.size();
learnable_params_.push_back(params_[net_param_id].get());
learnable_param_ids_.push_back(learnable_param_id);
has_params_lr_.push_back(param_spec->has_lr_mult());
has_params_decay_.push_back(param_spec->has_decay_mult());
params_lr_.push_back(param_spec->lr_mult());
params_weight_decay_.push_back(param_spec->decay_mult());
} template <typename Dtype>
void Net<Dtype>::BackwardFromTo(int start,int end){
for(int i = start;i >= end;--i){
//backward 调用各层次的backward更新权值和bias
layers_[i].Backward(top_vecs_[i],bottom_need_backward_[i],
bottom_vecs_[i]);
}
}

4.基本流程

基本流程:Net构造函数开始

  // 递归更新变量
vectot<string>*stage ;
int level; //起始调用
net_.reset(new Net<float>(model_file, TEST)); //送入prototxt文件和Test OR Train
explicit Net(const string& param_file,Phase phase,const int level = 0,
vector<string>* stage = NULL,const Net* root_net = NULL); // 解析保存在NetParamter param内,这里用到了
//protobuf::TextFormat::Parse(FileInputStream*,param)
ReadNetParamsFromTextFileOrDie(param_file,&param); // 读取了NetParamter 后需要进行整个网络的初始化工作
Init(param); //初始化网络的接口,下续为具体实现
FilterNet(param, &filtered_param);// 打印网络结构 /*内部会完成split added 如果有必要(残差结构),记录层与层之间的联系关系与层次的名称
等,是否有loss_weight,layer的size等*/
InsertSplits(filtered_param,&param); for (size_t i = 0; i < param.layer_size(); i++) { //遍历setupLayer
const LayerParammeter& layer_param = param.layer(i);//层次的参数
layers_.push_back(LayerRegistry<Dtype>::CreateLayer(layer_param));
// CreateLayer会走layer_factory的CreateLayer的注册 ,比如input,conv,bn...
layer_names_.push_back(layer_param.name()); //开始继续遍历每层输入的具体的细节,第i个layer的第botom_id个输入
for (size_t bottom_id = 0; bottom_id < layer_param.bottom_size();
bottom_id++) {
const int blob_id =
AppendBottom(param,i,bottom_id,&availabel_blobs,&blob_name_to_idx);
} //开始继续遍历每层输出的具体细节,第i个layer的第 top_id的输出
for (size_t top_id = 0; top_id < layer_param.top_size();
top_id++) {
AppendTop(param,i,top_id,&availabel_blobs,&blob_name_to_idx);
if (layer_param.type()== "Input") {//输入
const int blob_id = blobs_.size() - 1;
net_input_blob_indices_.push_back(blob_id);
net_input_blobs_.push_back(blobs_[blob_id].get());
}
} //多态,具体调用具体的layer的Setup函数
layers_[layer_id]->SetUp(bottom_vecs_[layer_id], top_vecs_[layer_id]); //每个输出遍历
for (size_t top_id = 0; top_id < top_vecs_[layer_id].size();
top_id++) {
/*完成层次的blob_loss_weights,并统计memory_used_*/;
memory_used_ += top_vecs_[layer_id][top_id]->count();
}
//总的memory_used_: memory_used_*sizeof(Dtype); //如果层次间有学习权值和偏置,则需要再次设置,比如conv
//num_param_blobs weights And bias
for (int param_id = 0; param_id < num_param_blobs; ++param_id) {
AppendParam(param, layer_id, param_id);
} } /*接下来需要研究网络的backwards问题,决定哪些层次对loss有贡献,并且检查哪些层次
不需要back_propagate_down操作,遍历是反向的操作*/
for (size_t layer_id = layers_.size()-1; layer_id >= 0; --layer_id){
bool layer_contributes_loss = false;//默认是无贡献的
bool layer_skip_propagate_down = true;// 默认不参与backwards的loss贡献 //Layer内的输出遍历
for (size_t top_id = 0; top_id < top_vecs_[layer_id].size();
top_id++) {
//blob_name_[index]名字
string& blob_name = blob_names_[top_id_vecs_[layer_id][top_id]];
if (layer_[layer_id]->loss(top_id)||
blobs_under_loss.find(blob_name) != blobs_under_loss.end()) {
//该层次的layerloss不为0或者loss_weight = 1;
layer_contributes_loss = true;
}
if (blobs_skip_backp.find(blob_name) == blobs_skip_backp.end()) {
layer_skip_propagate_down = false;
}
} //同理 Layer内的输入遍历
for (size_t bottom_id = 0; bottom_id < bottom_vecs_[layer_id].size();
bottom_id++) {
if (layer_contributes_loss) {
string* blob_name = blob_names_[bottom_id_vecs_[layer_id][bottom_id]];
blobs_under_loss.insert(blob_name);
}
else{
bottom_need_backward_[layer_id][bottom_id] = false;
}
if (!bottom_need_backward_[layer_id][bottom_id]) {
string&blob_name = blob_names_[bottom_id_vecs_[layer_id][bottom_id]];
blok_skip_backp.insert(blob_name);
}
} /*code*/ }//init函数尾

Caffe学习--Net分析的更多相关文章

  1. Caffe学习--Layer分析

    Caffe_Layer 1.基本数据结构 //Layer层主要的的参数 LayerParamter layer_param_; // protobuf内的layer参数 vector<share ...

  2. Caffe学习--Blob分析

    Caffe_blob 1.基本数据结构 Blob为模板类,可以理解为四维数组,n * c * h * w的结构,Layer内为blob输入data和diff,Layer间的blob为学习的参数.内部封 ...

  3. Caffe学习笔记(三):Caffe数据是如何输入和输出的?

    Caffe学习笔记(三):Caffe数据是如何输入和输出的? Caffe中的数据流以Blobs进行传输,在<Caffe学习笔记(一):Caffe架构及其模型解析>中已经对Blobs进行了简 ...

  4. Caffe学习笔记(一):Caffe架构及其模型解析

    Caffe学习笔记(一):Caffe架构及其模型解析 写在前面:关于caffe平台如何快速搭建以及如何在caffe上进行训练与预测,请参见前面的文章<caffe平台快速搭建:caffe+wind ...

  5. Caffe学习笔记2--Ubuntu 14.04 64bit 安装Caffe(GPU版本)

    0.检查配置 1. VMWare上运行的Ubuntu,并不能支持真实的GPU(除了特定版本的VMWare和特定的GPU,要求条件严格,所以我在VMWare上搭建好了Caffe环境后,又重新在Windo ...

  6. Caffe学习系列(3):视觉层(Vision Layers)及参数

    所有的层都具有的参数,如name, type, bottom, top和transform_param请参看我的前一篇文章:Caffe学习系列(2):数据层及参数 本文只讲解视觉层(Vision La ...

  7. Caffe学习系列(23):如何将别人训练好的model用到自己的数据上

    caffe团队用imagenet图片进行训练,迭代30多万次,训练出来一个model.这个model将图片分为1000类,应该是目前为止最好的图片分类model了. 假设我现在有一些自己的图片想进行分 ...

  8. Caffe学习系列(22):caffe图形化操作工具digits运行实例

    上接:Caffe学习系列(21):caffe图形化操作工具digits的安装与运行 经过前面的操作,我们就把数据准备好了. 一.训练一个model 右击右边Models模块的” Images" ...

  9. Caffe学习系列(21):caffe图形化操作工具digits的安装与运行

    经过前面一系列的学习,我们基本上学会了如何在linux下运行caffe程序,也学会了如何用python接口进行数据及参数的可视化. 如果还没有学会的,请自行细细阅读: caffe学习系列:http:/ ...

随机推荐

  1. C# 正则表达式

    C# 正则表达式 正则表达式 是一种匹配输入文本的模式..Net 框架提供了允许这种匹配的正则表达式引擎.模式由一个或多个字符.运算符和结构组成. 定义正则表达式 下面列出了用于定义正则表达式的各种类 ...

  2. 想写一个 Sketch 插件 结果 一查不可收拾 ~~ 涉及到 Symbol 符号/ Layer 图层 / Overrides 可替换变量 等等

    var sketch = context.api() var document = sketch.selectedDocument; var selection = document.selected ...

  3. React router内是如何做到监听history改变的

    问题背景 今天面试的时候,被问到这么个问题.在html5的history情况下,pushstate和replacestate是无法触发pushstate的事件的,那么他是怎么做到正确的监听呢?我当时给 ...

  4. SpringMVC视频

    视频内容: 1.下载spring mvc以及spring mvc示例演示http://pan.baidu.com/s/1kTHRfDH 2.配置完善&初步探究控制器拦截http://pan.b ...

  5. HDU 3763 CD【二分查找】

    解题思路:给出两个数列an,bn,求an和bn中相同元素的个数因为注意到n的取值是0到1000000,所以可以用二分查找来做,因为题目中给出的an,bn,已经是单调递增的,所以不用排序了,对于输入的每 ...

  6. iOS保持流畅有哪些秘诀? 除了黑科技GPU还有这些重要原因 期待安卓8.0流畅度逆袭

    经常有人提起iPhone使用起来要比Android手机流畅,现在谈谈为什么iOS使用中会让人觉得更加流畅一些.一方面iPhone的顶级硬件为iOS的流畅打好了基础,另一方面,专一定制的系统是保证体验的 ...

  7. CorelDRAW 2018新增功能介绍

    2018年4月11日,CorelDRAW 2018正式对外发布,最新版设计软件包已经过全面更新,是近几年来发行的最强大版本,可协助绘图专业人士将创意转换为令人惊艳的专业视觉设计.CorelDRAW 2 ...

  8. EntityFramework 一

    EntityFramework EF核心库 EntityFramework.SqlServer EF针对sqlsever的库 引用 system.Data.Entity   EF相比SQL语句方便,但 ...

  9. data is not None

    在读django的form源码: def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, initial=Non ...

  10. [NOIP补坑计划]NOIP2016 题解&做题心得

    感觉16年好难啊QAQ,两天的T2T3是不是都放反了啊…… 场上预计得分:100+80+100+100+65+100=545(省一分数线280) ps:loj没有部分分,部分分见洛咕 题解: D1T1 ...