尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Caffe BatchReindex 层详解:沿 batch 轴的重排、选取与复制

Caffe BatchReindex 层详解:沿 batch 轴的重排、选取与复制 Caffe BatchReindex 层详解沿 batch 轴的重排、选取与复制【免费下载链接】caffeCaffe: a fast open framework for deep learning.项目地址: https://gitcode.com/gh_mirrors/ca/caffeBatchReindex批量重索引是 Caffe 提供的一种无参数数据整理层它允许你使用一个整数索引 Blob 沿第一个轴batch 轴对输入进行选取、重排甚至复制样本。本文以 docs/tutorial/layers/batchreindex.md 为骨架结合 Caffe 仓库中该层的头文件、CPU/GPU 实现与单元测试完整讲解其接口约定、前向/反向原理、边界校验与实战用法帮助你在数据预处理、样本重采样等场景中正确使用这一层。层概览在 Caffe 的层文档体系中BatchReindex 是一个极简但语义清晰的层其官方速览信息如下层类型Layer typeBatchReindex头文件include/caffe/layers/batch_reindex_layer.hppCPU 实现src/caffe/layers/batch_reindex_layer.cppCUDA GPU 实现src/caffe/layers/batch_reindex_layer.cu从类声明include/caffe/layers/batch_reindex_layer.hpp可以看出该层直接继承自LayerDtypetype()返回字符串BatchReindex这也是网络描述文件prototxt中type字段需要填写的名字ExactNumBottomBlobs() 2严格接收 2 个输入 BlobExactNumTopBlobs() 1严格输出 1 个 Blob。该层在源码中通过REGISTER_LAYER_CLASS(BatchReindex)见 src/caffe/layers/batch_reindex_layer.cpp注册到 Caffe 的层注册表中。Caffe 的层工厂会依据LayerParameter中的type字段查表创建对应的层实例注册机制的定义可参考 include/caffe/layer_factory.hpp。核心语义y x1[x2]BatchReindex 的作用非常直观沿着输入 Blob 的第一个轴batch 轴进行索引gather。用官方头文件注释的话说它可以用来选取select、重排reorder、甚至复制replicatebatch 中的样本。第二个 Blob 会被强制转换为整数作为第一个 Blob 第一轴的索引。输入输出约定如下见 include/caffe/layers/batch_reindex_layer.hppbottom[0]形状为N × D1 × D2 × ...的数据 Blobbottom[1]形状为M的一维索引 Blob元素会被强转成int使用top[0]形状为M × D1 × D2 × ...的输出 Blob满足$$ y_{n, d_1, d_2, \dots} x_{1}[, x_{2}[n],, d_1,, d_2,, \dots ,] $$也就是说输出的第n个样本是输入中第x2[n]个样本的完整拷贝。由于索引允许重复同一个输入样本可以被输出多次复制由于索引可以是任意排列输入样本的顺序可以被重排由于M可以和N不相等batch 的规模可以被改变。Reshape 的形状推导在Reshapesrc/caffe/layers/batch_reindex_layer.cpp中层会对输入形状做严格约束并推导输出形状首先CHECK_EQ(1, bottom[1]-num_axes())强制要求索引 Blob 必须是一维的输出形状为[M] shape(bottom[0])[1:]即把 bottom[0] 从第 1 维往后的所有维度原样保留仅把第一维替换为索引长度M。一个典型例子取自单元测试 src/caffe/test/test_batch_reindex_layer.cpp输入5×4×3×2索引长度 6则输出形状为6×4×3×2。测试中会显式断言输出的num 索引 Blob 的 num而channels/height/width与输入完全一致。参数无参数该层在文档中标明No parameters无参数。这与它的设计目标一致——BatchReindex 是一个纯粹的数据搬运层不学习任何权重也没有任何可调的超参数因此在 prototxt 中配置它时无需也不允许编写param块。从类实现看构造函数只是把LayerParameter透传给基类既不解析额外字段也不初始化任何可训练参数。前向传播实现CPU 实现前向在 src/caffe/layers/batch_reindex_layer.cpp 中实现思路是经典的 gather 循环int inner_dim bottom[0]-count() / bottom[0]-shape(0); for (int index 0; index top[0]-count(); index) { int n index / inner_dim; // 当前输出样本编号 int in_n static_castint(permut[n]); // 从索引 Blob 取出源样本编号 out[index] in[in_n * inner_dim index % inner_dim]; }这里inner_dim N 个样本的总元素数 / N即单个样本的扁平化长度。每个输出元素只需一次索引访存即可填好。GPU 实现GPU 前向在 src/caffe/layers/batch_reindex_layer.cu 中由内核BRForward完成计算逻辑与 CPU 完全一致只是按CUDA_KERNEL_LOOP(index, count)让每个线程处理一个输出元素并用CAFFE_GET_BLOCKS/CAFFE_CUDA_NUM_THREADS划分线程块最后通过CUDA_POST_KERNEL_CHECK检查内核执行错误。在CPU_ONLY编译模式下GPU 版本会被替换为STUB_GPU桩实现见 src/caffe/layers/batch_reindex_layer.cpp保证纯 CPU 构建也能通过编译。索引合法性校验无论 CPU 还是 GPU 路径前向的第一步都是调用check_batch_reindexsrc/caffe/layers/batch_reindex_layer.cpp对每个索引执行两条检查CHECK_GE(ridx_data[i], 0)索引不能为负否则报错 Index specified for reindex layer was negative.CHECK_LT(ridx_data[i], initial_num)索引必须小于输入 batch 大小否则报错 Index specified for reindex layer was greater than batch size.。另外如果输出元素总数为 0空 batch前向会直接提前返回避免启动空内核。这些防御性检查保证了越界索引会在运行期被立即捕获而不是静默产生错误数据。反向传播实现CPU 反向反向需要把输出梯度按同样的索引散开并累加回输入见 src/caffe/layers/batch_reindex_layer.cppCHECK(!propagate_down[1]) Cannot backprop to index.; caffe_set(bottom[0]-count(), Dtype(0), bot_diff); // 先把输入梯度清零 for (int index 0; index top[0]-count(); index) { int n index / inner_dim; int in_n static_castint(permut[n]); bot_diff[in_n * inner_dim index % inner_dim] top_diff[index]; }两个关键点索引不可求导propagate_down[1]必须为false否则直接报错 Cannot backprop to index.。因为索引 Blob 是离散整数不存在连续梯度重复索引会累加如果多个输出位置指向同一个输入样本该输入位置收到的梯度是这些输出梯度之和因此使用而不是。前向的复制在反向中自然对应梯度求和。GPU 反向GPU 反向src/caffe/layers/batch_reindex_layer.cu稍复杂为了让每个 CUDA 线程只负责一个输出元素它先把(索引, 位置)对按索引排序pair_sort_first比较器再预处理出三个辅助数组——top_indexes每个输入样本对应的输出位置列表、begins每个输入样本的列表起始下标、counts每个输入样本的列表长度随后由内核BRBackward对每个输入位置并行完成多段梯度求和。注释中src/caffe/layers/batch_reindex_layer.cu对这一列表的列表list of lists技巧有详细说明。使用示例在 prototxt 中配置 BatchReindex 非常简单因为它没有参数只需声明两个输入一个输出layer { name: reindex type: BatchReindex bottom: data # 形状 N x C x H x W bottom: permute # 形状 M一维整数索引元素取值 ∈ [0, N) top: reindexed # 形状 M x C x H x W }实际使用中第二个 Blob 通常由数据层或上游计算层例如Python层动态生成用于实现有放回抽样、按权重重采样、数据增强中的随机选择等逻辑。注意索引 Blob 会被static_castint强转为整数使用因此浮点值会被截断请确保其内容本身就是整数语义。测试验证仓库在 src/caffe/test/test_batch_reindex_layer.cpp 中为该层提供了完整测试可作为理解其行为的权威参考TestForward输入为按0..119填充的5×4×3×2Blob索引为{4, 0, 4, 0, 1, 2}逐元素断言top[i] bottom[perm[n] * inner_dim inner_idx]并验证输出形状为6×4×3×2。注意索引{4, 0, 4, ...}中样本 4 出现两次、样本 3 从未出现正好演示了复制与丢弃两种行为TestGradient使用GradientChecker1e-4的差分步长、1e-2的容差对第一个输入做穷举梯度校验验证反向传播的数值正确性包括重复索引位置的梯度累加是否符合数值微分结果。这两个测试分别覆盖了前向的索引语义和反向的梯度正确性且通过TYPED_TEST_CASE(BatchReindexLayerTest, TestDtypesAndDevices)在 CPU 与 GPU 两种设备、float 与 double 两种精度下都会运行。小结BatchReindex 是 Caffe 中一个轻量但实用的数据操作层无参数、无学习目标纯粹依据第二个一维索引 Blob 对第一个输入沿 batch 轴做 gather。它的前向完成选取/重排/复制反向将梯度按索引散开并对重复位置求和同时强制禁止对索引求导。配合 include/caffe/layers/batch_reindex_layer.hpp、src/caffe/layers/batch_reindex_layer.cpp、src/caffe/layers/batch_reindex_layer.cu 与 src/caffe/test/test_batch_reindex_layer.cpp 一起阅读可以完整掌握其实现细节并在自己的网络中放心使用。【免费下载链接】caffeCaffe: a fast open framework for deep learning.项目地址: https://gitcode.com/gh_mirrors/ca/caffe创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表