FPGA部署卷积神经网络之量化 Caffe restretto 量化工具解析

Caffe restretto 动态量化

主要记录下DYNAMIC_FIXED_POINT模式下对Lenet5的量化过程。

参考 https://blog.csdn.net/xiaoxiaowenqiang/article/details/81713131
①.输入数据为test_data,在不同batch的数据下,推理iteration遍,得出网络运行在FLOAT32下的基本精度。

  // Run the reference floating point network on validation set to find baseline
  // accuracy.
  Net* net_val = new Net(model_, caffe::TEST);
  net_val->CopyTrainedLayersFrom(weights_);
  float accuracy;
  RunForwardBatches(this->iterations_, net_val, &accuracy);       //this->iterations在运行时输入
  test_score_baseline_ = accuracy;

②.输入数据为train_data, 网络在不同batch的数据下推理10遍,得出网络中层类型为ConvolutionInnerProducttop blobbottom blobweight_param中数据的最大绝对值,其中权重数据不包括bias

void Net::RangeInLayers(vector* layer_name,
      vector* max_in, vector* max_out, vector* max_param) {
  // Initialize vector elements, if needed.
  if(layer_name->size()==0) {
    for (int layer_id = 0; layer_id < layers_.size(); ++layer_id) {
      if (strcmp(layers_[layer_id]->type(), "Convolution") == 0 ||
          strcmp(layers_[layer_id]->type(), "InnerProduct") == 0) {
        layer_name->push_back(this->layer_names()[layer_id]);
        max_in->push_back(0);
        max_out->push_back(0);
        max_param->push_back(0);
      }
    }
  }
  // Find maximal values.
  int index = 0;
  Dtype max_val;
  for (int layer_id = 0; layer_id < layers_.size(); ++layer_id) {
    if (strcmp(layers_[layer_id]->type(), "Convolution") == 0 ||
          strcmp(layers_[layer_id]->type(), "InnerProduct") == 0) {
      max_val = findMax(bottom_vecs_[layer_id][0]);
      max_in->at(index) = std::max(max_in->at(index), max_val);
      max_val = findMax(top_vecs_[layer_id][0]);
      max_out->at(index) = std::max(max_out->at(index), max_val);
      // Consider the weights only, ignore the bias
      max_val = findMax(&(*layers_[layer_id]->blobs()[0]));
      max_param->at(index) = std::max(max_param->at(index), max_val);
      index++;
    }
  }
}

下面列出第一次推理和推理十次后,统计的各个blob中的数据最大绝对值

推理一次

Tables max_in max_out max_params
Conv1 0.99609375 3.49374723 0.612441599
Conv2 3.49374723 11.2924623 0.257983446
ip1 9.2909193 10.6955347 0.0975953862
ip2 10.6955347 26.3756752 0.25352037

推理十次

Tables max_in max_out max_params
Conv1 0.99609375 3.58768392 0.612441599
Conv2 3.5301609 11.5329533 0.257983446
ip1 10.1861591 12.5225191 0.0975953862
ip2 12.5225191 29.3337383 0.25352037

依据上表数据得出每层的输入特征图,卷积权值,输出特征图的整数位宽和小数位宽。
fl表示数据小数位宽,il表示整数位宽,bw(bit_width)表示定点数据位宽。

定点数据范围:

在量化模式下推理的量化过程如下:

template // 模板类型 Dtype
void BaseRistrettoLayer::Trim2FixedPoint_cpu(
      Dtype* data,    // 数据起始指针
      const int cnt,  // 数据数量
      const int bit_width,// 量化总位宽
      const int rounding, // 取整策略
      int fl)             // 小数位量化位宽
{
// 计算定点数据范围
    Dtype max_data = (pow(2, bit_width - 1) - 1) * pow(2, -fl);
    Dtype min_data = -pow(2, bit_width - 1) * pow(2, -fl);

  for (int index = 0; index < cnt; ++index)// 遍历每一个需要量化的数据
  {
    // Saturate data 上下溢出处理
    data[index] = std::max(std::min(data[index], max_data), min_data);

    // Round data
    data[index] /= pow(2, -fl);// 放大小数部分 对应的位宽倍数
    {
    case QuantizationParameter_Rounding_NEAREST:
      data[index] = round(data[index]);// 最近偶数取整
      break;
    case QuantizationParameter_Rounding_STOCHASTIC:
      data[index] = floor(data[index] + RandUniform_cpu());// 随机取整
      break;
    default:
      break;
    }
    data[index] *= pow(2, -fl);// 最后再反量化会小数 缩小对应的位宽倍数
  }
}

上溢处理:等于定点最大值
下溢处理:等于定点最小值
rounding_scheme 量化的舍入方案:
a. 最近偶数(NEAREST)
b. 随机舍入(STOCHASTIC)
默认使用方案A

具体计算举例:
Data=3.5301609 ,符号位1位,整数位2位 ,小数位13位
data_temp = 3.5301609 * 2^13 = 28919.0780928
round(data_temp) = 28919
Data_quant = 28919 / 2^13 = 3.5301513671875

你可能感兴趣的:(FPGA部署卷积神经网络之量化 Caffe restretto 量化工具解析)