caffe源码解析:insertSplits对 top输出到多个 Layer的情况进行分割

网友投稿 279 2022-11-23

caffe源码解析:insertSplits对 top输出到多个 Layer的情况进行分割

作用:对 top输出到多个 Layer的情况进行分割,建立完整的网络结构 重要的参数说明举例: layer_idx_to_layer_name[i] 记录各层的名称,如 [0x00000000] "input" blob_name_to_last_top_idx[“conv1”]=(1,0) 这个例子相当于说”conv1” 这层是第1层的第0个top, bottom_idx_to_source_top_idx[bottom_idx=(2,0)] = (1,0);  相当于说:第2层,第0个bottom,对应着第1层,第0个top 即: [(0x00000001, 0x00000000)] (0x00000000, 0x00000000) top_idx_to_bottom_count[(1,0)]=2 表示第1个layer的第0个top有2个top(blob?),要分叉,程序会对此建立新的分叉层   理解:整个函数分为两个部分 1. 遍历整个网络,记录每一个Layer的top的使用情况,记录结构放在 top_idx_to_bottom_count中。 2. 遍历整个网络,对 top_idx_to_bottom_count > 1 的情况进行处理: 分两步走 第一步. 首先是对有多个top层的Layer进行分割,主要的做法是在该层的后面新建一个Layer ,这个新的Layer的会按照 top_idx_to_bottom_count 的个数和约定的分割名称(SplitBlobName)去新建top,参考void ConfigureSplitLayer… 第二步,是对使用同一个top的后续层的bottom的blob进行改名(使用与上一步相同的命名规则)。 下面是源码 void InsertSplits(const NetParameter& param, NetParameter* param_split) { // Initialize by copying from the input NetParameter. param_split->CopyFrom(param); param_split->clear_layer(); map > blob_name_to_last_top_idx; map, pair > bottom_idx_to_source_top_idx; map, int> top_idx_to_bottom_count; map, float> top_idx_to_loss_weight; map, int> top_idx_to_bottom_split_idx; map layer_idx_to_layer_name; // 每层网络的名称 for (int i = 0; i < param.layer_size(); ++i) { const LayerParameter& layer_param = param.layer(i); layer_idx_to_layer_name[i] = layer_param.name(); for (int j = 0; j < layer_param.bottom_size(); ++j) { const string& blob_name = layer_param.bottom(j); if (blob_name_to_last_top_idx.find(blob_name) == blob_name_to_last_top_idx.end()) { LOG(FATAL) << "Unknown bottom blob '" << blob_name << "' (layer '" << layer_param.name() << "', bottom index " << j << ")"; } const pair& bottom_idx = make_pair(i, j); const pair& top_idx = blob_name_to_last_top_idx[blob_name]; bottom_idx_to_source_top_idx[bottom_idx] = top_idx; ++top_idx_to_bottom_count[top_idx]; } for (int j = 0; j < layer_param.top_size(); ++j) { const string& blob_name = layer_param.top(j); blob_name_to_last_top_idx[blob_name] = make_pair(i, j); } // A use of a top blob as a loss should be handled similarly to the use of // a top blob as a bottom blob to another layer. const int last_loss = std::min(layer_param.loss_weight_size(), layer_param.top_size()); for (int j = 0; j < last_loss; ++j) { const string& blob_name = layer_param.top(j); const pair& top_idx = blob_name_to_last_top_idx[blob_name]; top_idx_to_loss_weight[top_idx] = layer_param.loss_weight(j); if (top_idx_to_loss_weight[top_idx]) { ++top_idx_to_bottom_count[top_idx]; } } } for (int i = 0; i < param.layer_size(); ++i) { LayerParameter* layer_param = param_split->add_layer(); layer_param->CopyFrom(param.layer(i)); // Replace any shared bottom blobs with split layer outputs. for (int j = 0; j < layer_param->bottom_size(); ++j) { const pair& top_idx = bottom_idx_to_source_top_idx[make_pair(i, j)]; //表示第i层的第j个bottom, 是第top_idx0层的第top_idx1个top, // 有split_count个bottom const int split_count = top_idx_to_bottom_count[top_idx]; if (split_count > 1) { const string& layer_name = layer_idx_to_layer_name[top_idx.first]; const string& blob_name = layer_param→bottom(j); // 只是改个名称,这个名称由 SplitBlobName创建 layer_param->set_bottom(j, SplitBlobName(layer_name, blob_name, top_idx.second, top_idx_to_bottom_split_idx[top_idx]++)); } } // Create split layer for any top blobs used by other layer as bottom // blobs more than once. for (int j = 0; j < layer_param->top_size(); ++j) { const pair& top_idx = make_pair(i, j); //表示第i层的第j个top有split_count个blob const int split_count = top_idx_to_bottom_count[top_idx]; if (split_count > 1) { // 如果要分叉(对应多个top) const string& layer_name = layer_idx_to_layer_name[i]; //第i层的名称 const string& blob_name = layer_param->top(j); // 第j个top的blob名称 LayerParameter* split_layer_param = param_split->add_layer(); // 新建一层 const float loss_weight = top_idx_to_loss_weight[top_idx]; // 第i层的第j个top有的loss_weight ConfigureSplitLayer(layer_name, blob_name, j, split_count, loss_weight, split_layer_param); if (loss_weight) { layer_param->clear_loss_weight(); top_idx_to_bottom_split_idx[top_idx]++; } } } } }

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:实现带输电功能的USB Type-C直通设备时的关键工程注意事项
下一篇:java连接zookeeper实现zookeeper教程
相关文章

 发表评论

暂时没有评论,来抢沙发吧~