## update 2023.5.14

### 采用了CRNN的结构实现LSTM-OCR，相比于之前的版本有了更好、更通用的处理OCR问题的能力。我使用了360CC数据集(中文OCR训练数据集，共360w张图片，我只用了其中3w训练数据和3k张测试数据)来训练和测试模型。

1. config文件夹里是配置文件:

  - alphabets.py是字典
  - 360CC_config.yaml是使用360CC数据集时的配置文件
  - OWN_config.yaml是使用其他数据集时的配置文件
  

2. dataset文件夹:

- txt文件夹中的char_std_5990.txt是360cc数据集的字典
- test.txt中是配置测试集数据
- train.txt中是配置训练集数据
- _360cc.py用于构建360cc dataset来训练/测试
- _own.py用于构建自己的dataset来训练/测试

3. lstm_utils.py中是LSTM-OCR中需要用到的一些特定的函数、类等

4. module.py中增加了对LSTM量化相关的组件，补充了对于BiLSTM的部分权值参数的伪量化，修改了QLinear的quantize_inference方法，使其仍然是真量化。

5. train.py中的train和validate函数考虑了OCR问题的特点，有了较大修改。同理ptq.py中的direct_inference, full_inference, quantize_inference也有一定修改。

6. 由于QLSTM采用伪量化，而其他层采用真量化，因此在model.py中与QLSTM直接连接的层需要通过dequantize_tensor(x)或quantize_tensor(x)来处理下数据。

7. ptq_result_lstm-ocr.txt和ptq_result_lstm-ocr.xlsx是实验结果，仍采用acc作为评价指标，当一个句子被完全识别正确时，算是识别正确一次。

8. 拟合图像如下 <br>
flops:
<img src = "fig/flops_lstmocr.png" class="h-90 auto">
params:
<img src = "fig/params_lstmocr.png" class="h-90 auto">



## update 2023.5.4

### 对fp32的模型进行了改进，并进行了初步的PTQ实验(只做到了对部分参数伪量化 naive fakequantization，结果在ptq_result.txt中)

1. 对fp32的改进
   
- 支持多层LSTM，并用nn.ModuleList组织

2. 对PTQ的尝试

- 对LSTM的结构，数据流向，输入输出有了更细致的理解。PTQ遇到的主要问题有：

    - BiLSTM涉及到了双向的output，需要用SUM或者CONCAT处理，PTQ时可能需要引入更多module处理。
    - LSTM内部进行的运算较为复杂，如下图所示：<img src = "fig/math.png" class="h-90 auto">
    首先涉及到了多个门i，f，g，他们内部有Wx+b+Wh+b的结构，他们的scale是否整体考虑(即，是共用一个scale，还是多个scale并在＋的时候做rescale)是一个问题。<br>他们外部的sigmoid或tanh也是一个问题(会导致不方便在各个层间通过scale变换保证PTQ结果的正确性)。<br>对c',h'的更新涉及到的*，+也是一个问题。
    - LSTM内部各个门的权值被组织在`weight_ih_l[k]`、`weight_hh_l[k]`、`bias_ih_l[k]`和`bias_hh_l[k]`中，分属在不同行中，是否应该把这个权值矩阵拆开，分别量化后再合并。
- 暂时还没想好怎么处理上述问题，于是进行了简单的尝试性实验：
  
  - 先只处理单向的LSTM，不考虑双向所需的SUM和CONCAT
  - 将`weight_ih_l[k]`、`weight_hh_l[k]`、`bias_ih_l[k]`和`bias_hh_l[k]`各自整体量化，没有再对每个张量切成四块再分别对`weight_ir_l[k]`,`weight_hr_l[k]`,`bias_r_l[k]`,`weight_if_l[k]`,`weight_hf_l[k]`,`bias_f_l[k]`,`weight_ii_l[k]`,`weight_hi_l[k]`进行量化
  - 对weight和bias和每层的输出tensor采取伪量化的方法，避免层间的scale变换。<br><br>后果：<br> (1) freeze后的权值不再是量化后的值，而是其量化值经过scale变换后的值
  <br>(2) 没有考虑tanh，sigmoid的量化，他们不再是矩阵乘的形式，还没想好怎么消掉scale。只模拟了将权值和输出张量量化产生的rounding，溢出等误差。
  <br>(3) 与实际可直接部署到硬件的lstm量化可能有差异。(不过目前我不太确定LSTM实际的量化应该怎么做，在网上没有找到很多lstm量化相关的资料)
  <br>(4) 与之前的其他网络的PTQ量化略有差异，与scale相关的的计算顺序有些不同，但运算原理是类似的。

- 有待改进：

  - 对LSTM的PTQ量化的更真实模拟，考虑sigmoid，tanh，各种乘加组合
  - 补充对BiLSTM的PTQ量化 (如果还按现在的简化版处理方式，BiLSTM很容易实现，因为不需要考虑各种scale方面的问题，直接SUM或者CONCAT即可)
  - 可以考虑把`weight_ih_l[k]`、`weight_hh_l[k]`、`bias_ih_l[k]`和`bias_hh_l[k]`拆开，按各自门的权值分别伪量化后再组合
  - 使用更复杂的数据集
  - 度量相似度
  - 找到比较好的指标来度量精度
  - fuse BN-Fc的量化
## update 2023.5.2

basic version： FP32版本，只有单个lstm cell，训练数据集采用序列化的MNIST，仅作记录方便后续修改。