# Quantization
## Week 1D
----
## 說文解字
+ Quantization 名詞
+ Quantize 動詞
+ 兩者的中文皆為量化的意思
----
## 模型量化
+ 一般模型會存成 16 或 32 位元浮點數
+ FP32, FP16
+ 將模型量化成 8 或 4 位元整數
+ INT8, INT4
+ 可以減少模型的大小
+ 但會損失模型準確率
----
## 量化流程
1. 先計算量化因子 Scaling Factor
2. 將模型權重量化成 INT8 並儲存
3. 讀取 INT8 模型然後轉回 FP16 運算
----
## 計算量化因子
```python=
def quantize_fp16_to_int8(w_fp16):
# 找到權重絕對值的最大值
abs_max_val = np.max(np.abs(w_fp16))
# 計算量化因子 Scaling Factor
sf = 127 / abs_max_val
# 將 FP16 權重轉換為 INT8
w_int8 = np.round(w_fp16 * sf).astype(np.int8)
return w_int8, sf
```
----
## 復原權重
因為 INT8 不能直接做運算
需要還原回 FP16 型態
```python=
def dequantize_int8_to_fp16(w_int8, sf):
# 將 INT8 權重轉換回 FP16
return w_int8.astype(np.float16) / sf
```
----
## 實際運算
```python=
# 假設我們有一組 FP16 權重
w_fp16 = np.array([1.0, -0.5, 0.25, -0.125])
print(f"原始 FP16 權重: {w_fp16}")
# 量化 FP16 權重到 INT8
w_int8, sf = quantize_fp16_to_int8(w_fp16)
print(f"量化 Int8 權重: {w_int8}")
print(f"量化因子: {sf}")
# 從 INT8 權重重建 FP16 權重
rw_fp16 = dequantize_int8_to_fp16(w_int8, sf)
print(f"重建 FP16 權重: {rw_fp16}")
```
----
## 觀察權重變化
```ini=
原始 FP16 權重: [ 1. -0.5 0.25 -0.125]
量化 Int8 權重: [127 -64 32 -16]
量化因子: 127.0
重建 FP16 權重: [ 1. -0.504 0.252 -0.126]
```
----
## 比較差異
```python=
x = np.array([1.0, 0.25, -0.5, -1.0])
y = np.matmul(x, w_fp16)
qy = np.matmul(x, rw_fp16)
loss = y - qy
print(f"原始輸出: {y}")
print(f"量化輸出: {qy}")
print(f"輸出差異: {loss}")
```
----
## 觀察輸出
```yaml=
原始輸出: 0.875
量化輸出: 0.8740234375
輸出差異: 0.0009765625
```
----
## Demo
[Colab Demo](https://colab.research.google.com/drive/1suUbtdS64f_ZvbEcWehIheg9G-88_EQE)
---
# Other
----
## 捕捉信號
`Ctrl + \` 會發送 QUIT 的訊號
```python=
import sys, signal
import subprocess as sp
while True:
def kill(signum, frame):
p.kill()
sys.exit(0)
signal.signal(signal.SIGQUIT, kill)
try:
p = sp.Popen(["make", "-f", "Run.mk", "action"])
p.wait()
except KeyboardInterrupt:
p.kill()
```
{"description":"地獄貓旅行團第 29 週心得分享","slideOptions":"{\"transition\":\"slide\"}","title":"Week 1D - Quantization","contributors":"[{\"id\":\"c7cbb212-2c41-4dfa-8d85-f8e7fa769bf1\",\"add\":2160,\"del\":153}]"}