论 大模型量化

大模型量化的原因

模型部署有一个永恒的目标,让模型的memory usage更少,运行更快。量化(Quantize)既可以减少模型的memory usage(比如,weight的type由FP32转成Int8,可以让memory usage减少到原来的四分之一),又可以使模型运行的更快(比如,整型运算要比浮点型运算快的多),如此优秀。

但是,对量化的约束就是,要保证量化后的性能不变(或者性能损失可以忽略)。量化自然有量化误差(quantization error),量化误差会传播(spread),至于对性能的影响,一般是恶化的。

量化的知识

公式

f ∈ [ f min , f max ] f \in [f_{\text{min}}, f_{\text{max}}] f[fmin,fmax] q ∈ [ q min , q max ] q \in [q_{\text{min}}, q_{\text{max}}] q[qmin,qmax],于是

q = clip ( round ( f s ) + z , q m i n , q m a x ) q = \text{clip} \left( \text{round}\left(\frac{f}{s} \right) + z , q_{min}, q_{max} \right) q=clip(round(sf)+z,qmin,qmax)

其中,
s = f max − f min q max − q min s = \frac{f_{\text{max}} - f_{\text{min}}}{q_{\text{max}} - q_{\text{min}}} s=qmaxqminfmaxfmin

z = q min − round ( f min s ) z = q_{\text{min}} - \text{round}\left(\frac{f_{\text{min}}}{s} \right) z=qminround(sfmin)

与之对应的Dequantize函数:
f = ( q − z ) ⋅ s f = (q - z) \cdot s f=(qz)s

大模型量化策略

基本思路

对于 q min q_{\text{min}} qmin q max q_{\text{max}} qmax 的选择,一般先上 int8/uint8,性能可以下探至 int4,性能不行提升到 int16/uint16。如下列表显示 int16/uint16/int8/uint8/int4 q q q 的取值范围:

q q q q min q_{\text{min}} qmin q max q_{\text{max}} qmax
int16-3276832767
uint16065535
int8-128127
uint80255
int4-87

统计待量化的变量的数值分布特征,包括histogramminmaxaveragemedium等,结合 q q q 的范围选出合适的 f min f_{\text{min}} fmin f max f_{\text{max}} fmax,需要用到一些度量量化误差的方法。记待量化的变量的数值集合为 { f i } \{ f_i \} {fi} u = min ⁡ ( f i ) u = \min(f_i) u=min(fi) v = max ⁡ ( f i ) v = \max(f_i) v=max(fi)

min-max策略

min-max策略的效果不是很好,主要是因为会出现extreme large magnitude value,导致量化精度比较低。

non-symmetric

f min = u , f max = v f_{\text{min}} = u, f_{\text{max}} = v fmin=u,fmax=v

symmetric

f min = − max ⁡ ( ∣ u ∣ , ∣ v ∣ ) , f max = max ⁡ ( ∣ u ∣ , ∣ v ∣ ) f_{\text{min}} = -\max(|u|, |v|), f_{\text{max}} = \max(|u|, |v|) fmin=max(u,v),fmax=max(u,v)

MMSE策略

带量化的变量的 histogram 作为近似的概率分布,根据后面介绍的算法搜索出若干对 ( f min , f max ) (f_{\text{min}}, f_{\text{max}}) (fmin,fmax)的candidate,计算量化前的原始数据与量化后的数据的 Mean Squared Error 作为 Quantization Error,最终保留量化误差最小的candidate。

搜索算法

  1. 可以想象出 histogram 的大致样子:两侧frequency低,中间frequency高,类似于正态分布。
    举例说明一个变量的histogram
  2. 主要思路就是,沿着两侧向中间,去除占比少的bin,认为这些bin里的数据是outlier。
  3. 具体的见如下 pseudocode:
# inputs
import numpy as np
histogram = np.array([...]) # 记录的就是直方图里从左到右的bin的frequency
u, v = ... # 待统计变量的最小值u,和最大值v

# solution
tot_freq = np.sum(histogram) # 待统计变量的数值sample的总个数
n_bins = len(histogram) # bin的总个数
bin_width =  (v - u) / n_bins # 每个bin覆盖的数值范围

ratio_thr_lower = 0.0 # 直方图左侧剔除的bin的frequency的占比上限
ratio_thr_upper = 0.0 # 直方图右侧剔除的bin的frequency的占比上限
ratio_step = 1e-5     # 尝试的过程就是不断增加上限值,上限值的增量step
index_bin_lower = 0   # 对于某一次尝试而言,左侧的起始搜索bin的index
index_bin_upper = n_bins - 1 # 对于某一次尝试而言,右侧的起始搜索bin的index

min_quant_error = float("inf") # 最小的量化误差
min_index_bin_lower = 0 # 记录最小的量化误差对应的左侧bin的index
min_index_bin_upper = n_bins - 1 # 记录最小的量化误差对应的右侧bin的index

while index_bin_lower < index_bin_upper:
	next_ratio_thr_lower = ratio_thr_lower + ratio_step
	next_ratio_thr_upper = ratio_thr_upper + ratio_step
	
	l = index_bin_lower
	while l < (n_bins - 1) and np.sum(histogram[:l+1]) < next_ratio_thr_lower * tot_freq:
		l = l + 1
	
	r = index_bin_upper
	while r > 0 and np.sum(histogram[r:]) < next_ratio_thr_upper * tot_freq:
		r = r - 1
	
	if (l - index_bin_lower) > (index_bin_upper - r):
		ratio_thr_lower = next_ratio_thr_lower
		index_bin_lower = l
	else:
		ratio_thr_upper = next_ratio_thr_upper
		index_bin_upper = r
	
	quant_error = calculate_quant_error(..., index_bin_lower, index_bin_upper, ...) # 使用选择出的新的f_min和f_max去计算
	if quant_error < min_quant_error:
		min_quant_error = quant_error
		min_index_bin_lower = index_bin_lower
		min_index_bin_upper = index_bin_upper
	else:
		break

  • 16
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值