基于caffe框架下的fixedpoint量化工具Ristretto的使用说明

代码参考:Ristretto工程github开源代码
博客参考:神经网络量化之 Ristretto、增量量化INQ、IAO代码实战分析

1. Ristretto工具使用

1.0. 训练初始模型

./build/tools/caffe train 
--solver=examples/mnist/lenet_solver.prototxt
--gpu 1

参数说明:
solver:训练配置文件,里面有指向lenet_train_test.prototxt的链接。假设生成的模型为lenet_iter_10000.caffemodel

1.1. 量化

./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_pointminifloatinteger_power_of_2_weights
error_margin:与32位浮点数网络相比绝对精度下降百分比。

1.2. 网络微调

./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

1.3. 评价精度

//未量化评价
./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位浮点网络参数。

2. 量化策略

2.1. 动态定点法(Dynamic Fixed Point Approximation)

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
}

2.2. 迷你浮点法(Minifloat Approximation)

量化参数

//8bits
quantization_param {
  precision: MINIFLOAT
  mant_bits: 3
  exp_bits: 4
}

2.3. 乘法变移位法(Turning Multiplications Into Bit Shifts)

量化参数

//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
  }

3. 更新策略

反向更新策略

前向传播时,使用量化后的参数进行计算,同时保留量化后的参数和全精度的参数。
反向传播时,对全进度的参数进行更新。
之后再次对更新的参数进行量化,再次前向传播,反向传播更新全精度权重,如此往复。
保存网络权重时,保存量化后的参数,但是是以全精度位宽进行保存的,所以宏观上权重文件大小不变。

4. proto文件量化参数定义

// 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]; 
}

你可能感兴趣的:(图像处理)