## update: <br>2023.4.17<br>

- 已针对4.12中的问题进行了修正和补充：
  - INT量化位宽较大时，acc骤降，是因为QAdaptiveAvgPool2d的quantize_inference中的写法有问题，修正后结果符合预期。
  - 已检查网络中的细节错误并修正，在QElementwiseAdd的quantize_inference中补充了x = get_nearest_val(self.quant_type,x)
  - 已确认加权计算过程正确
- 发现并尝试解决的新问题：
   - 在完成上述的修改后，INT量化和FP量化的结果与预期相符，但PoT量化出现了量化后推理精度极低的问题(10%~20%)。经过大量实验研究，我发现主要的问题是在PoT量化后的模型中，每层在quantize_inference中对输出进行的激活量化： x = get_nearest_val(self.quant_type,x)导致了较大的误差。<br>
   针对该问题，我进行了具体的研究。影响量化后模型的因素不仅仅是模型的权重参数，每层输出数据在激活量化后也会引入误差。INT量化和FP量化中，输出数据在激活量化后引入的误差比较小(因为INT量化对输出数据就是直接rounding取整，而FP量化因为量化精度比较细致，因此误差也相对较小)，但PoT量化不同，一般情况下在ResNet系列都有比较显著的误差。尤其当模型的层数较深时(比如ResNet50，ResNet152)，量化后的推理精度因为这个原因有很大的损失(从90% => 10%~20%)。<br>
   我最初有上述想法是在反复确认程序框架没有明显问题后，PoT量化的效果总是很差，而模型权重参数的相似度又很高，因此想到了可能是输入输出数据方面的问题。为验证该想法，我进行了实验，在各个量化模块的quantize_inference方法中，我设置在PoT量化时，不进行x = get_nearest_val(self.quant_type,x)，即只对每层的权重参数量化，而不量化每层的输出tensor. 经过实验，PoT量化后的推理精度提升了不少(到达了50%~60%)，总体拟合得到的曲线也比较符合预期了。<br>
   考虑到目前的自变量只是模型量化前后权重参数的分布相似度，我便没有再引入其他指标来刻画每层输出的tensor在量化前后的分布相似度。
  <br>
- 正在尝试的实验：
  对PoT量化进行单独的考虑，先只是量化权值，看一下权值分布相似度跟acc的关系。然后选一个acc比较高的PoT权值保持不变，再用不同的数据表示去量化激活，这时候看激活的位宽和acc的关系。
- 尚未完成的内容：
   - 收敛速度与梯度分布相似度的实验
<br> <br> <br> <br>
- 拟合曲线：
1. PoT量化中只对网络权值量化，INT和FP对网络权值和激活都进行量化：<br>
resnet18:
<img src = "fig/18_flops.png" class="h-90 auto">
<img src = "fig/18_params.png" class="h-90 auto">
resnet50:
<img src = "fig/50_flops.png" class="h-90 auto">
<img src = "fig/50_params.png" class="h-90 auto">
resnet152:
<img src = "fig/152_flops.png" class="h-90 auto">
<img src = "fig/152_params.png" class="h-90 auto">
2. 去掉PoT量化：<br>
resnet18:
<img src = "fig/18_flops_nopot.png" class="h-90 auto">
<img src = "fig/18_params_nopot.png" class="h-90 auto">
resnet50:
<img src = "fig/50_flops_nopot.png" class="h-90 auto">
<img src = "fig/50_params_nopot.png" class="h-90 auto">
resnet152:
<img src = "fig/152_flops_nopot.png" class="h-90 auto">
<img src = "fig/152_params_nopot.png" class="h-90 auto">

## update: <br>2023.4.12<br> 
- 已修改get_param_flops.py, extract_ratio.py, ptq.py中与计算数据分布相似度、计算计算量、参数量加权权重相关的程序，使其能够适应于ResNet系列网络。<br>
(注： 目前需要在得到了param_flops_ResNet18/50/152.txt后，手动删除在layer中重复出现了一次的downsample module的统计数据，考虑到resnet18的只需要删3处，resnet50，152中的需要删4处，故直接手动进行了)
- 已补充ResNet18/50/152的PTQ训练测试结果，在ptq_result_ResNet18/50/152.xlsx中
- 拟合曲线图：
1. ResNet18 - 参数量加权 
<img src = "fig/res18-1.png" class="h-90 auto">
   ResNet18 - 计算量加权
<img src = "fig/res18-2.png" class="h-90 auto">

2. ResNet50 - 参数量加权
<img src = "fig/res50-2.png" class="h-90 auto">
   ResNet50 - 计算量加权
<img src = "fig/res50.png" class="h-90 auto">

3. ResNet152 - 参数量加权
<img src = "fig/res152-1.png" class="h-90 auto">
   ResNet152 - 计算量加权
<img src = "fig/res152-2.png" class="h-90 auto">

- 所有图中在左上方均存在一系列离群点，其中包括了INT量化在量化位宽较高时，acc骤降对应的点，也包括了一些其他的异常点，还需要再对程序、数据进一步分析，调整参数，使部分由于程序设置导致异常的点恢复过来。

- 后续待补充：
1. 分析为什么INT量化位宽较大时，acc骤降，并解决该问题
2. 检查网络量化是否存在细节错误
3. 检查计算数据分布相似度时是否正确加权计算
4. ResNet QAT相关实验
<br><br>
分割线
===============================================<br><br><br>
## update:<br> 2023.4.10 <br>
- 注：new_mzh中的程序改用了与游昆霖同学统一的度量方式、以及一些量化细节约定，将代码重新建立在游昆霖同学版本的程序上。<br>
在量化BN层的过程中遇到了较多问题，感谢游昆霖同学的帮助:D





### 程序改动：

为量化ResNet18，在module.py中新增的量化层包括QConvBNReLu层，QConvBN层，QElementwiseAdd层，QAdaptiveAvgPool2d层。在model.py中建立了ResNet18的量化架构，通过class BasicBlock, class Bottleneck, class MakeLayer等保障了ResNet的扩展性，能够较为方便的扩展成ResNet50和152 

### 待完善：

- ResNet的网络架构相比于AlexNet，VGG等更加的跳跃，各种MakeLayer, Residual的结构使得其不是一个平铺开来的网络，则过去的很多计算相似度等的算法不能直接适用在ResNet上(直接遍历网络参数时，会有包装在conv，bn等层外面的layer, sequential, block等)，关于参数相似度、梯度相似度的分析有待后续研究补充。
QAT方面有待后续补充


- 我在加上正确的QElementwiseAdd层前，PTQ后的acc都不超过15%，足以见到该层的重要性，他是负责残差的相加部分，因为两个层的输出结果是在不同量化范围，所以不能直接相加，而是需要做rescale。

- 目前看到INT量化随位宽增加而先增大后下降，我查看了量化后的参数分布，其整体趋势与全精度模型是较为相似的，因此问题不在Conv，BN等普通的量化层上，我猜想可能是因为量化位宽较大的时候，QElementwiseAdd做rescale的过程中出现了溢出，还有待后续观察确认。