备案网站打不开,影视网站建设多少钱,芜湖网站建设开发,wordpress中文商城模板之前在简书的文章#xff0c;搬迁过来 ^-^ 本文是作者原创#xff0c;如有理解错误#xff0c;恳请大家指出#xff0c;如需引用#xff0c;请注明出处。 #Caffe FeatureMap数据流的建立 ##用语解释 FeatureMap: 输入的图片信息或者经过多层处理后的图片信息。weights: 只…之前在简书的文章搬迁过来 ^-^ 本文是作者原创如有理解错误恳请大家指出如需引用请注明出处。 #Caffe FeatureMap数据流的建立 ##用语解释 FeatureMap: 输入的图片信息或者经过多层处理后的图片信息。weights: 只针对卷积层存在的权重系数。caffe :文中提到的caffe均指caffed1.0,如果使用caffe2.0会特别指出。在讲解FeatureMap的数据流之前首先需要明确一下caffe的大体结构caffe的整体逻辑结构分为3层分别是Net,Layer和Blob分别的作用如下 Net: 该层处于CAFFE的最顶层主要负责对模型文件的读写根据模型文件的内容建立相应的Layer填充对应层的数据并进行相关的调用。Layer: 该层是实际的执行单元常见的如卷积层Pooling层都是处于这一逻辑层。Blob:该层是一个内存管理的模块为Layer和Net提供相应的存储空间屏蔽上层对于内存分配CPU,GPU切换的感知。由上面的讲解分层关系不难看出FeatureMap在整个Caffe框架中不属于任何一个Layer所以它被最顶层的Net层所持有。Net层就需要能够通过caffe的模型文件推倒出每一层所依赖的输入这样才能构建出一个完整的数据链。在这种需求下Caffe引入了两个定义 bottom: Layer的输入数据。top: Layer的输出数据。 具体的形式如下图单输入和多输入的情形 所以Net在调用Layer之前就一定知道了Layer的所需要的输入数据也就是需要Net层所持有的Blob变量需要被那些层所引用。这些在模型文件中也有直观的反应(为了方便截图删除了下图proto中关于Convlution的参数配置) 上述的工作都在Net的Init(void Net::Init(const NetParameter in_param))函数里面进行了处理主要实现的就是根据上图左侧的模型文件得到需要建立的Layer的类型并将各个Layer间的数据链接起来。函数中的关键参数如下 名称功能in_param存放由protobuf转换出的模型文件bottom_vecs_存放每一层中的输入数据类型为vectorvectorBlob* top_vecs_存放每一层中的输出数据类型为vectorvectorBlob* available_blobs存放每一层中的输出数据类型为vectorvectorBlob* ##常规的数据链建立流程是单输入单输出的场景 链接本层的bottom数据 int Net::AppendBottom(const NetParameter param, const int layer_id, const int bottom_id, setstring* available_blobs, mapstring, int* blob_name_to_idx) ,该函数会使用从当前layer持有的bottom信息中得到对应bottom的层名然后利用该名称找到对应的blob并加入到bottom_vecs_。 链接本层的top数据void Net::AppendTop(const NetParameter param, const int layer_id,const int top_id, setstring* available_blobs, mapstring, int* blob_name_to_idx),该操作就是将本层的输出数据加入到top_vecs_中并与 layer_id相关联这里同时负责Blob对象的申请。 需要指出的是新的Blob对象是在top中进行创建的在Bottom中只是将上一层top的指针添加进来同时在这个过程中CAFFE还利用available_blobs进行了异常校验在每次新加入top的时候记录对应的Blob名称在bottom中链接上一层top之后在available_blobs中将对应的Blob名称剔除。相关伪代码如下 for (int layer_id 0; layer_id param.layer_size(); layer_id) {AppendBottom;AppendTop;}
复制代码 ##多输入的数据链的建立 细心的同学应该已经发现当数据为多bottom输入的时候因为available_blobs的数据被上一次的链接过程删掉则再次链接相同bottom的时候会出先异常告警在这种情况下我们就要引入CAFFE的另外一处理函数 void InsertSplits(const NetParameter param, NetParameter* param_split)该函数的主要功能就是对 top输出到多个 Layer的情况进行分割。 整个函数分为两个部分 遍历整个网络记录每一个Layer的top的使用情况记录结构放在 top_idx_to_bottom_count中。 遍历整个网络对 top_idx_to_bottom_count 1 的情况进行处理: a. 首先是对top被多个层使用的Layer进行分割主要的做法是在该层的后面新建一个Layer 这个新的Layer的会按照 top_idx_to_bottom_count 的个数和约定的分割名称SplitBlobName去新建top添加层的代码如下此处只展示核心的创建过程具体调用流程请自行跟踪 //该函数执行新层的添加void ConfigureSplitLayer(const string layer_name, const string blob_name,const int blob_idx, const int split_count, const float loss_weight,LayerParameter* split_layer_param) {split_layer_param-Clear();split_layer_param-add_bottom(blob_name);split_layer_param-set_name(SplitLayerName(layer_name, blob_name, blob_idx));split_layer_param-set_type(Split);for (int k 0; k split_count; k) {//split_count就是该top被引用的个数//添加了分割后的top//命名由SplitBlobName生成 split_layer_param-add_top(SplitBlobName(layer_name, blob_name, blob_idx, k));if (loss_weight) {if (k 0) {split_layer_param-add_loss_weight(loss_weight);} else {split_layer_param-add_loss_weight(0);}}}}
复制代码 b. 之后是对使用同一个top的后续层的bottom的blob进行改名使用与上一步相同的命名规则进行改名。 下面以SqueezeNet1.1为例展示了添加新的分割层的实例 ![Upload new_split_layer.jpg failed. Please try again.] 通过这样一个分割的转化达到了对多输入数据流的建立。 ##遗留问题 上面讲的是在初始化阶段对FeatureMap数据的链接关系的建立但是对于weights的填充和初始图片的输入并没有进行分析。