基本原理:利用卷积的线性性,将bn融合到conv2d的kernel和附加一个biasadd
可以融合的pattern: Conv2D+BN,Conv2D+BiasAdd+BN
以TensorFlow的算子为例
conv2d input维度[batch,in_channel,h,w],kernel维度[h,w,in_channel,out_channel]
bn的gamma, betta, mean, var都是一个维度跟conv2d kernel out_channel维数相同的向量,eps是一个很小的常数。
具体做法[1-2]:
融合前:
融合后:
得到conv2d kernel后,其维度为[h,w,in_channel,out_channel],得到bn的4个向量,维度为[out_channel]
使用np.transpose(data,[3,0,1,2])对conv2d kernel转置,是得其第0维维度为out_channel
用一个for循环,对每个维度的kernel值,和bn的4个向量值进行上面公式计算,最后再使用np.transpose(data1,[1,2,3,0])转置回原kernel维度。(公式里面的w和b的公共部分可以先算出来)
同样操作也可以用于depthwise conv2d,但是需要稍微改造下计算方法
depthwise conv2d的kernel维度为kernel维度[h,w,in_channel,m],最终输出的维度为m*in_channel,bn融合在m为1时可以实施。
区别仅仅在于transpose两个transpose perm分别为 [2, 0, 1, 3], [1, 2, 0, 3]
上述融合操作可以通过对读取pb文件直接对graph_def操作重新保存graph_def实现。
矩阵乘+bn一样可以融合:
ref
conv2d+bn融合原理
1. 【28】tensorflow 模型優化手術:給我折下去!模型 folding batch normalization 篇 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天
https://github.com/jason9075/ithome_tensorflow_series
2. Fusing batch normalization and convolution in runtime
conv2d原理
4. Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift https://arxiv.org/abs/1502.03167