如何提高定点数据类型的利用率?

问题描述 投票:0回答:1

我正在尝试对卷积神经网络使用量化,以减少从 FP32 位数据类型到 Int16 数据类型的内存占用。问题是我得到的结果很差,因为这是我第一次使用这种表示形式,所以我对正确的实现有一些疑问。

首先,我使用以下函数(均匀量化)对输入数据和权重进行量化:

#define FXP 16

int16_t quantize(float a, int fxp){
    int32_t maxVal = ((1 << (FXP-1)) - 1);
    int32_t value = a * (1 << fxp); //mapping
    
    //rounding
    if (a>=0){
        value += 0.5f;
    }else{
        value -= 0.5f;
    }
    
    //clipping
    if(value > maxVal){
        return (int16_t)maxVal;
    }else if(value < -maxVal){
    
        return -(int16_t)maxVal;
    }else{
        return (int16_t)value;
    }
}


int16_t value = quantize(test_data[i],10);

在这种情况下,我使用的是 Q5.10 格式(从我掌握的数据来看,它似乎是最适合使用的格式)。一旦所有数字都被转换,网络中的算术(乘法和加法/减法——例如在卷积中使用)以这种方式实现:

  for(int k=0; k<output_fea; k++){
      int32_t accumulator = 0;
      
      for(int l=minimum; l<maximum; l++){
        for(int j=0; j<input_fea; j++){
          accumulator += (data[l][j]*weights[k][l][j] + (1<<((FXP_VALUE-1))))>>FXP_VALUE; //both data and weights array are int16_t
        }
      }
      
      //before going from int32_t to int16_t
      if(accumulator>INT16_MAX){
        accumulator=INT16_MAX;
      }else if(accumulator<INT16_MIN){
        accumulator=INT16_MIN;
      }

      result[i][k] = (int16_t)ReLU(accumulator); //result is int16_t
    }  
  }

我做的对吗?我可以采取任何措施来改善结果并减少近似值吗?

我正在考虑为每一层使用不同的比例因子,但我不明白如何在乘法和加法/减法中考虑到这一点。例如,如果我在第一层中使用 Q2.14 作为权重,使用 Q5.10 作为数据,我必须将乘法的结果重新缩放到一个通用的比例,但是我该如何选择合适的比例以及我应该如何重新缩放该结果

c fixed-point
1个回答
0
投票

您应该通过舍入和裁剪来检查您的值中引入了多少误差。继续使用浮点值,但只引入四舍五入;然后只介绍剪裁;然后介绍两者。您的结果中引入了多少错误?

此外,关于定点格式:即使它 seems 使用的最佳格式,也许它不是最好的。尝试不同的格式;检查每种格式的结果错误。尝试在不同的计算阶段(即不同的层)使用不同的格式。每个应用程序都有自己的问题,因此您必须凭直觉了解舍入和裁剪(分别)对结果的影响程度。

如果您的结果对舍入误差非常敏感,您可能希望对某些阶段使用

int16
,对其他阶段使用
float32

© www.soinside.com 2019 - 2024. All rights reserved.