代码参考:Ristretto工程github开源代码
博客参考:神经网络量化之 Ristretto、增量量化INQ、IAO代码实战分析
./build/tools/caffe train
--solver=examples/mnist/lenet_solver.prototxt
--gpu 1
参数说明:
solver
:训练配置文件,里面有指向lenet_train_test.prototxt
的链接。假设生成的模型为lenet_iter_10000.caffemodel
./build/tools/ristretto quantize
--model=examples/mnist/lenet_train_test.prototxt
--weights=examples/mnist/lenet_iter_10000.caffemodel
--model_quantized=examples/mnist/quantized.prototxt
--iterations=100
--gpu=1
--trimming_mode=dynamic_fixed_point
--error_margin=1
参数说明:
model
:原始32位浮点网络定义文件。
weights
:原始32位浮点网络参数。
model_quantized
:量化后生成的网络定义文件quantized.prototxt
。
iterations
:用于评分网络的批次迭代次数。
gpu
:GPU ID。
trimming_mode
:量化策略可以是dynamic_fixed_point
、minifloat
或integer_power_of_2_weights
。
error_margin
:与32位浮点数网络相比绝对精度下降百分比。
./build/tools/caffe train
--solver=examples/mnist/solver_finetune.prototxt
--weights=examples/mnist/lenet_iter_10000.caffemodel
--gpu=1
参数说明:
solver
:网络微调超参数配置文件,里面有指向quantized.prototxt
的链接。假设微调后模型为quantized_lenet_iter_10000.caffemodel
//未量化评价
./build/tools/caffe test
--model=examples/mnist/lenet_train_test.prototxt
--weights=examples/mnist/lenet_iter_10000.caffemodel
--gpu=1
--iterations=100
//量化但未微调评价
./build/tools/caffe test
--model=examples/mnist/quantized.prototxt
--weights=examples/mnist/lenet_iter_10000.caffemodel
--gpu=1
--iterations=100
//量化且微调后评价
./build/tools/caffe test
--model=examples/mnist/quantized.prototxt
--weights=examples/mnist/quantized_lenet_iter_10000.caffemodel
--gpu=1
--iterations=100
参数说明:
model
:网络定义文件。
weights
:32位浮点网络参数。
CNN的不同部分具有显着的动态范围,
在大的层中,输出是数以千计的积累的结果,因此网络参数比层输出小得多。
定点只具有有限的能力来覆盖宽动态范围。
使用B位来表示,其中一位符号位s, fl是分数长度(小数长度),其余为整数位,
除去符号位s,后面的都是尾数,每个尾数位数字为xi
n = (-1)^s * 2^(-fl)*sum(2^i * xi) , 0 =< i <= B-2
第一项确定符号,
第二项确定分数比例,
第三项确定总值大小(所有尾数对应的十进制的值)。
由于网络中的中间值具有不同的范围,所以希望将定点数值分组为具有常数f1(不同小数长度)的组中。
所以分配给小数部分的比特数在 同一组内是恒定的,但与其他组相比是不同的。
这里每个网络层分为三组:
一个用于层输入,
一个用于权重,
一个用于层输出。
这可以更好地覆盖层激活和权重的动态范围,因为权重通常特别小,层的输入输出通常比较大(上一层各个神经元累计)。
上图为4个数 属于两个不同组的动态定点数的例子。
注意第二组的分数长度是负数。
所以第二组的分数长度是-1,整数长度是9,位宽是8。
第一组的分数长度为2,整数长度为6,位宽为8。
量化参数
//动态bits
quantization_param {
bw_layer_in: 4
bw_layer_out: 4
bw_params: 2
fl_layer_in: 4
fl_layer_out: 2
fl_params: 1
}
量化参数
//8bits
quantization_param {
precision: MINIFLOAT
mant_bits: 3
exp_bits: 4
}
量化参数
//weight为4bits
quantization_param {
precision: INTEGER_POWER_OF_2_WEIGHTS
bw_layer_in: 8
bw_layer_out: 8
fl_layer_in: 8
fl_layer_out: 6
exp_min: -8
exp_max: -1
}
反向更新策略
前向传播时,使用量化后的参数进行计算,同时保留量化后的参数和全精度的参数。
反向传播时,对全进度的参数进行更新。
之后再次对更新的参数进行量化,再次前向传播,反向传播更新全精度权重,如此往复。
保存网络权重时,保存量化后的参数,但是是以全精度位宽进行保存的,所以宏观上权重文件大小不变。
// Message for layers with reduced word with arithmetic
message QuantizationParameter{
enum Precision {
DYNAMIC_FIXED_POINT = 0;
MINIFLOAT = 1;
INTEGER_POWER_OF_2_WEIGHTS = 2;
}
optional Precision precision = 1 [default = DYNAMIC_FIXED_POINT];
enum Rounding {
NEAREST = 0;
STOCHASTIC = 1;
}
optional Rounding rounding_scheme = 2 [default = NEAREST];
// Dynamic fixed point word width
optional uint32 bw_layer_in = 3 [default = 32];
optional uint32 bw_layer_out = 4 [default = 32];
optional uint32 bw_params = 5 [default = 32];
optional int32 fl_layer_in = 6 [default = 16];
optional int32 fl_layer_out = 7 [default = 16];
optional int32 fl_params = 8 [default = 16];
// Minifloat word width
optional uint32 mant_bits = 9 [default = 23];
optional uint32 exp_bits = 10 [default = 8];
// Integer-power-of-two weights
optional int32 exp_min = 11 [default = -8];
optional int32 exp_max = 12 [default = -1];
}