From 50dcb6c6937d8d1b21980029c100535e6253e65e Mon Sep 17 00:00:00 2001 From: HuanjunKong Date: Sat, 18 May 2019 18:06:41 +0800 Subject: [PATCH] add doc --- doc/bconv_CN.md | 29 +++++++++++++++++++++++++++++ doc/design_CN.md | 19 +++++++++++++++++++ doc/onnx2bnn_CN.md | 28 ++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 doc/bconv_CN.md create mode 100644 doc/design_CN.md create mode 100644 doc/onnx2bnn_CN.md diff --git a/doc/bconv_CN.md b/doc/bconv_CN.md new file mode 100644 index 0000000..dfa0504 --- /dev/null +++ b/doc/bconv_CN.md @@ -0,0 +1,29 @@ +#### 二值卷积实现 +##### 定点化输入 +在执行二值卷积之前,网络需要手动插入一层`Binarize`。顾名思义就是把 float 输入调整为二进制格式。详见 +``` + dabnn/bitpack.h#pack_mat_64 +``` + +注意此处转换时,使用的公式是: +``` + bin_val = 0 if float_val > 0.0f else 1 +``` +数值反过来,是为了后续方便实现。原本是`xnor`操作,调整输入后即为`xor`操作,某些步骤不需要再取反。 + + +卷积实现有很多种办法,dabnn在项目早期提供了两种优化实现。 +##### 展开 +以汇编方式直接跑卷积。俗话说“有多少人工,就有多少智能”,这些代码就是最好的注解: +``` + dabnn/bconv.h +``` + +##### im2col +这个方法最早来自`Caffe`,原本是想先用`im2col`重排输入,用连续的输入提高 Cache 命中率,然后用研究了很多年的`gemm`方法一波带走。 +``` + dabnn/bgemm.h +``` + +##### 注意事项 +第一版`Binarize`和当前版本实现方式不同。 diff --git a/doc/design_CN.md b/doc/design_CN.md new file mode 100644 index 0000000..b20e66a --- /dev/null +++ b/doc/design_CN.md @@ -0,0 +1,19 @@ +#### 背景和发展方向 +二值网络比较年轻,较有名的文献来自 2016 年的 [XNOR-Net](https://arxiv.org/abs/1603.05279v4)。初版精度不高,因此 [Bi-Real Net](https://arxiv.org/abs/1808.00278v5) 提出了一些精度提升方法。今年(2019)[BENN](https://arxiv.org/abs/1806.07550v2) 用机器学习方法进一步提升了 BNN 在分类任务上的表现,结果甚至超过单精度浮点模型。论文同时表明 BNN 由于天生泛化性差导致了在鲁棒性和稳定性上的缺陷。 + +但是从移动端工程应用的角度来看,定点网络可以节省数十倍的内存、提升数倍推理速度,同时降低十倍以上能耗。这意味着原本设备充电一次只能用一个小时,现在理论上可以用十小时以上。能耗相关可参见[相关测试](https://camo.githubusercontent.com/e725038be60ce4bb698b22480603b636a92beeaf/687474703a2f2f66696c652e656c656366616e732e636f6d2f776562312f4d30302f35352f37392f7049594241467373565f5341504f63534141435742546f6d6531633033392e706e67)。 + +综合算法和工程来看,部分二值网络实用意义和竞争优势可能在以下两点: + +1. 与已量产设备融合。嵌入式设备在设计过程中,为了节约成本往往会做成“刚好够用”的状态。二值卷积在计算过程中既不需要大量的 SIMD 乘法操作,内存需求也远低于 8bit 模型,对原有系统干扰极小; +2. 在分类任务中以混合精度的方式替换已有方法。 + +卷积曾出现过很多变种,但是其中大部分已被历史淘汰。BNN 要想避免此命运,最简单的方法莫过于尽快落在某个产品或项目上,证明自己的价值。 + + +#### 软件架构 +在使用流程和软件结构方面,dabnn 和已开源的推理库(如 [ncnn](https://github.com/Tencent/ncnn)、[Tengine](https://github.com/OAID/Tengine)、[FeatherCNN](https://github.com/Tencent/FeatherCNN) 等)差距不大: + +1. 模型训练可使用 [bmxnet](),也可用[修改过的 PyTorch]() ,最终导出为[修改后的的 onnx 格式]()。onnx 主要增加了一些图优化方法,具体可查询相关项目; +2. 由于 protobuf-lite 静态库远大于 flatbuffers,为节省内存并减小 SDK 和模型体积,推理时需要把 onnx 格式转换成 dabnn 内部格式,流程和**注意事项**可参照 [onnx2bnn_CN.md](onnx2bnn_CN.md); +3. 二值卷积实现请查阅 [bconv_CN.md](bconv_CN.md) diff --git a/doc/onnx2bnn_CN.md b/doc/onnx2bnn_CN.md new file mode 100644 index 0000000..d69f621 --- /dev/null +++ b/doc/onnx2bnn_CN.md @@ -0,0 +1,28 @@ +#### 模型转换流程 + +1. 请先阅读开源版本的 [onnx 格式说明](https://github.com/onnx/onnx/blob/master/docs/IR.md); +2. 读取所有参数和 Layer。对于二值卷积,把参数转为二进制格式。 +``` + bin_val = 1 if float_val > 0.0f else 0 +``` +此处实现和 `bmxnet` 相比,在`0.0f`的处理上有差异。`bmxnet`的转换函数为: +``` + bin_val = 1 if float_val >= 0.0f else 0 +``` +此处和一些同学讨论过,有的认为权重刚好是 0.0f 的情况几乎不存在;也有的说如果权重是 0.0f,训练几乎失败。目前的结论是不影响。 + +3. 其他 Layer 正常处理。 + +#### 注意事项(必看) + +由于`BNN`商业化程度不高,且`onnx`当前版本对`BNN`支持不够完善,模型转换过程中有些硬编码规则需要额外说明。 + +1. bias 参数在转换模型的过程中会被重命名为 `{name}_conv_b`,而`kernel`权重会被重命名为`{name}_conv_w`; + +2. 由于`onnx`当前版本还没有对应的名称,训练平台(如`PyTorch`)导出为`onnx`格式时,需要把`domain`字段设为`dabnn`以标记此层为二值卷积层; + +3. `onnx`格式为 NCHW,而`dabnn`内置格式为 NHWC,与 `TensorFlow`/`SNPE` 一致。这么设计是为了方便后续卷积计算; + +4. 二值卷积参数之和暂时需要是 64 的倍数; + +5. `group` 必须要为 1,因此目前不支持分组卷积和`MobileNet`。