使用最大值计算偏移量的代码
import numpy as np
def saturate(x, int_max, int_min):
# 将数组 x 中的元素限制在 [int_min, int_max] 的范围内
return np.clip(x, int_min, int_max)
def scale_z_cal(x, int_max, int_min):
# 计算量化比例因子 scale 和偏移量 z
scale = (x.max() - x.min()) / (int_max - int_min) # 计算量化的比例因子
z = int_max - np.round(x.max() / scale) # 计算偏移量,使用最大值
return scale, z
def quant_float_data(x, scale, z, int_max, int_min):
# 将浮点数据 x 量化为整数,考虑偏移量 z
xq = saturate(np.round(x / scale + z), int_max, int_min) # 对量化后的数据进行饱和截断
return xq
def dequant_data(xq, scale, z):
# 将量化后的数据 xq 反量化为浮点数
x = ((xq - z) * scale).astype('float32') # 计算反量化结果
return x
if __name__ == '__main__':
# 设置随机数种子以获得可重复的结果
np.random.seed(1)
# 生成 3 个浮点数作为输入数据,并设置它们的值
data_float32 = np.array([-0.75, -0.45, 1.75], dtype='float32')
print("input", data_float32)
# 定义量化的整数范围
int_max = 255
int_min = 0
# 计算量化比例因子和偏移量
scale, z = scale_z_cal(data_float32, int_max, int_min)
print("scale and z ", scale, z)
# 对浮点数据进行量化
data_int8 = quant_float_data(data_float32, scale, z, int_max, int_min)
print("quant result ", data_int8)
# 将量化后的整数数据反量化回浮点数
data_dequnat_float = dequant_data(data_int8, scale, z)
print("dequant result ", data_dequnat_float)
# 打印原始数据和反量化数据之间的差异
print('diff', data_dequnat_float - data_float32)
输出结果和解释:
运行这段代码后,将获得如下输出:
input [-0.75 -0.45 1.75]
scale and z 0.00980392156862745 77.0
quant result [ 0. 31. 255.]
dequant result [-0.7501961 -0.4501961 1.7498039]
diff [-0.0001961 -0.0001961 -0.0001961]
使用最小值计算偏移量的代码
import numpy as np
def saturate(x, int_max, int_min):
# 将数组 x 中的元素限制在 [int_min, int_max] 的范围内
return np.clip(x, int_min, int_max)
def scale_z_cal_using_min(x, int_max, int_min):
# 计算量化比例因子 scale 和偏移量 z,使用最小值计算偏移量
scale = (x.max() - x.min()) / (int_max - int_min) # 计算量化的比例因子
z = int_min - np.round(x.min() / scale) # 计算偏移量,使用最小值
return scale, z
def quant_float_data(x, scale, z, int_max, int_min):
# 将浮点数据 x 量化为整数,考虑偏移量 z
xq = saturate(np.round(x / scale + z), int_max, int_min) # 对量化后的数据进行饱和截断
return xq
def dequant_data(xq, scale, z):
# 将量化后的数据 xq 反量化为浮点数
x = ((xq - z) * scale).astype('float32') # 计算反量化结果
return x
if __name__ == '__main__':
# 使用 [-0.75, -0.45, 1.75] 作为输入数据
data_float32 = np.array([-0.75, -0.45, 1.75], dtype='float32')
print("input", data_float32)
# 定义量化的整数范围
int_max = 255
int_min = 0
# 使用最小值计算量化比例因子和偏移量
scale, z = scale_z_cal_using_min(data_float32, int_max, int_min)
print("scale and z ", scale, z)
# 对浮点数据进行量化
data_int8 = quant_float_data(data_float32, scale, z, int_max, int_min)
print("quant result ", data_int8)
# 将量化后的整数数据反量化回浮点数
data_dequnat_float = dequant_data(data_int8, scale, z)
print("dequant result ", data_dequnat_float)
# 打印原始数据和反量化数据之间的差异
print('diff', data_dequnat_float - data_float32)
代码输出和解释:
运行这段代码后,将获得如下输出:
input [-0.75 -0.45 1.75]
scale and z 0.00980392156862745 77.0
quant result [ 0. 31. 255.]
dequant result [-0.75 -0.45 1.75]
diff [0. 0. 0.]
对比总结
使用最大值计算偏移量适合数据中正值占主要部分的情况,因为它可以最大化正值在整数范围中的分布精度。它在反量化中可能会有小的误差,尤其是在负值较多时。
使用最小值计算偏移量适合负值或正负值混合的数据,可以更精确地反映原始数据。这种方法在反量化过程中可以实现误差的完全消除,如在示例中对比所示。
选择策略
当数据中正值多于负值并且正值的精度非常重要时,优先考虑使用最大值来计算偏移量。
当数据中负值重要或需要兼顾正负值时,使用最小值计算偏移量能够更好地保持数据的完整性和精度。