一文掌握大模型常用量化方法

📅 2026/7/29 3:55:29
一文掌握大模型常用量化方法
01LLM主流浮点精度随着网络层数深度的增加我们希望前向传播的值和反向传播的值都比较稳定不随着网络层数的加深把这种不稳定不断放大。如果每一模型越做越大显卡越来越贵量化的本质就是因为穷。那大模型有哪些主流的浮点精度千问14b就相当于28G的显存b对应的是G一个小数浮点数默认用float 16 bit一共14b的数一个数用2个字节因此14 × 2 28G显存。float 16这16位数分成三类:第一位是符号位Sign正数还是负数。第二位是指数位Exponent在这里表示2的四次方。指数位是2^1左边是低位右边是高位。第三位是小数位Significand/Mantissa。这里是2^-1 2^-4 2^-7 就是0.5703。它的数字表达就是(-1)^0 * 2^1 * (2^00.5703125)3.140625这个就是一个浮点数的表示。非常像十进制的表达比如103.56它的十进制表示如上所示只不过这里是以10为底FFloat16(FP16)是以2为底。Float16(FP16)它的指数部分决定了数值的范围小数位决定它的精度就是小数点能够后几位这是FP16比较标准的。除了FP16还有很多类型的数据比如FP32、TF32、FP16、BFLOAT16等各种各样的FP32相比FP16是指数位多了范围就更大小数位多了精度就更强但是它一个数占4个字节存储空间就会翻倍。比如FP16和BF16这两个都是16位但对于FP 16它侧重于精度对于BF16它侧重于范围表达方式其实是不一样的一般来说在推理的时候FP16就足够用了但是在训练的时候一定要FP32因为在训练的时候每次改变的东西都非常小每次改变梯度都特别小。如果说精度不够的话那很有可能就被忽略掉了导致学习训练不动因为并不是真的训练不动而是精度不够那些很小的变化体验不到。比如有FP32的数在训练的时候用FP32的数训练这么高的精度。从Huggingface上能下载的模型在推理的时候一般标准都是FP16。 3.14159…把这个数的精度直接给降下来把后这一节全都给抛弃只要前面这一部分因此就变成了FP16精度就降下来了这个在推理上其实够的但这种转化叫精度变低就是比较小的位数表示一些精度比较高的数值这个不叫量化只是叫做牺牲精度。上图为Qwen的量化版本一个float四个字节来表示INT4四位半个字节。一个floatINT8也就是一个字节来表示。Qwen72B用INT4来量化对应36B的模型Qwen还有一个14B的模型正常来说是28B假如这两个基本接近量化的模型会更厉害。02参数量化参数量化跟直接降精度有什么区别比如一个高精度的数值4bit一共能表示2^4也就是16个数拿低精度的16个点跟高精度的这些点一一对应这个过程就叫做量化只不过这个对应的关系叫做量化的映射由不同的量化算法就会产生不同的map。比如100、200、400、800这4个数不需用int8表示只需用二位做个map映射00 - 100、01 - 200、10 - 400、11 - 800即可这就是量化。对于浮点数也是一样的比如原始图像的巧克力量化是把巧克力给变模糊了点量化肯定会带来损失比如用INT 8来量化一共只能表示2^8就是256个数。但是FP 16有可能1000个数那就必然会出现几个数对应的一个数相对于说他们之间的差异可能是0.003和0.00310.0029对应量化后是一个数相对说精度受到了一定的损失。直接降精度FP32直接降到FP16它相当于是把图给缩小了而量化并没有缩小图但是能让图的分辨率变低了。下图这个是FP32到FP16直接粗暴的截断。但是在深度学习中做量化的时候比如用INT 8一位表示符号位7位就是2^7就是128从-127到127一共有256个数把FP32里的每一个数都映射到它对应里来以前需要4个字节现在变到了1个字节存储空间就会减少但是效果会打折。因此不同的量化方法就是根据数值特点尽可能减少损失不同的量化方法主要的目的就是尽量减少量化的损失。量化损失说白了就是原来数多现在用少的数来表示根据鸽笼原理原来有二个一样的东西现在变成一样的了。03最大值量化比如以前是FP16可能是-5、-0.3、-0.2、1、2.1、3等。找出一个绝对值最大的absmax5x/absmax值域在[-1,1]要量化成8位就是[-127,127][(x/absmax)*127]取整。比如说absmax5x2.46、x2.49等量化完之后都是63这个叫做量化的一个损失数值之间没有区分度了。这是一个最简单的量化方法标准的一个公式但是这种量化方法其实有很大的问题。损失是一个问题但是损失这个问题其实在量化里头是不需要拿出来讲的因为你所有方法你都是有损失的除了这个问题外它其实还有很多别的问题。第一个问题比如原来在FP32里头原来可能有1、2、3、4、500它的absmax500左边这四个数除以500都非常小可能映射出来都是0500对应的是127但是中间的1 2 3 4一直到126这些数都被浪费了这个问题的本质是500叫做异常值。第二个问题也比较类似我们知道他的表达是-127到127假如FP32都是正数那一半的空间也被浪费只有右边挤在了正数空间这个就是最大值量化的一个问题。比如有一个向量它的最大值是5.4进行量化之后把每个数给量化成-127到127反量化就是反过来比如量化y [x/absmax]取整反量化就是xabsmax*y每个乘以23.5就是反量化回来了误差就是因为取整符号造成的小数点后面都舍弃掉了所以导致误差取整之后就发现这是个比较好的一个例子原来是多少返回来也是多少但是这种例子其实是比较少见的。因为原来的精度也不是很高如果原来到了小数点后两位这个5.47折腾完以后再回来就是5.443.08量化完后再回来3.06拿量化前的和反量化后的相减它其实是有一些误差的。这个就是量化所带来的量化误差。04零点量化除了最大值量化以外还有零点量化它要解决的问题是刚才说的那两个问题分布稀疏和有一半没有的问题。比如x: -5、0、10absmax10x/absmax主要目的是让它变成一个有限级变成一个-1到1的一个区间压缩到有限级的空间压缩完之后再乘以INT 8的127变成-127到127这个压缩其实不一定要用最大值压缩说白了就里需要知道跨度是多少。还有个方法可以压缩比如最小值min、最大值maxmax-min就是这个跨度任何一点x减最小值除以它(x-min)/(max-min)就是这段长度占整个长度的比例仍然是一个0到1的范围。只要搞成了一个范围有限的就可以进行量化了。比如先计算一个幅度比例因子scale原始数据是FP16(α-β)和现代数据(127-(-128))是INT 8跨度是0.07212。(Xi/(α-β))* 255范围是0到255的数让int_value之后的值有正有负再加一个偏移量zero_point就是让min最小的值被量化之后变成-128。零点值zero_point就是拿最小的值除以这个幅度最后得到结果就可以完成一个量化zero_point是保证让最小值β能够对应到-128这样的话整个的值域就是最大值就是α对应的值是127。这个叫做零点量化。对称的时候原来的值域是-10.8 ~ 10.8因为α0它能保证0点。但是不对称的比如正数要大一些有可能中间的一半相当于它是中间的一半刚好对应零点因为α大了所以它中间的一半其实也是个大于0的数因此0对应的是一个负数量化之后是它是典型的非对称量化刚最大值量化是一个典型的对称量化。这两种方法都叫做线性量化。对称和不对称在实际推理中会有什么影响在大模型里头常用的函数是relu函数就是y x 或 0 x大于0的时候为x小于0的时候为0。如果是对称量化Relu函数一样通过量化之后的结果判别大于0还是小于0一样能够迅速的得到这个值。但是不对称量化有可能量化之后的数它跟0的关系很难从量化之后的一眼能看出来必须通过一个转换一个运算才能看过来没有那么直接因此增大了对函数推理的计算量。所以这个就是不对称量化所带来的一个坏处。比如要是对称量化x10(int 8)肯定能够判断以前的z(量化前的是FP32)肯定可以判断出z大于0x-10肯定可以判断z0。如果是非对称的因为有个零点平移的问题所以x10的时候以前z是大于0还是小于0是未知的。零点量化的好处比如原来的数这里都在大于0的这一块那量化的时候就会把-128到127把这些数值都用满而小于0的部分不给它留空位了就量化到什么位置这样不会造成量化的一个浪费、存储的浪费其实就是带来误差。 因为存储东西不够所以会带来误差本身就不够再浪费一些那误差肯定会更大了。05量化中的异常值和解决方案量化的时候有异常值怎么处理最典型的异常值就是突然来了一个特别大的数就让这些全是0。刚那两个方法不管哪个方法都有这个问题全是0这个是127其他位数全部浪费掉因此对于这种方法非常粗暴。比如设一个Max和min比如设一个-5和5凡是大于5的全当5来算凡是小于-5的全当-5来算直接粗暴但是这里就会造成256这个数跟5这个数对应的都是127也就是说损失一个幸福所有人这叫做手动裁剪。06如何解决最大值量化/零点量化存在的问题这个问题主要就是离群点既然有了离群点以后其实是可以把离群点直接去掉或者直接把它搞成一个-5到5之间的一个数那这个时候离群点这个点其实会有损失的因为离群点它可能未必是错的它有可能反而是一个比较重要的信息。因此有一个做法其实比较巧妙。量化最终是矩阵相乘把这些数值给统计一下这些标黄色的数在X里头都算是比较大的40多30多其他的都是2 0 1 3最终会跟w相乘拎出来的这两列是黄色的第二列和第四列跟w的第二行和第四行相乘相对于说把这两个矩阵拆成两部分一个是对应的是离群点。下面这一块它并不离群它的数值还是比较正常的但是因为要跟离群的点进行运算把它也拉出来下面黄色这两个就不量化了做正常的运算对于上面蓝色这些非离群的这些值做完量化以后就可以进行量化了量化完之后可以进行相乘输入结果再反量化最后相加得到一个最终的结果。量化的东西最后都是矩阵运算矩阵拆解把离群的那一些和不离群的正常的给分开来搞好这个就是常用大模型的一些计算方法。线量化带来的很大的问题就是离群点的问题还有一个问题其实也比较严重叫做数据分布不均匀所以就有一个叫分位数量化。07分位数量化非线性量化数据分布不均匀比如一堆数比较密集量化的时候就量化到128128到128必然会造成比如这段是可以的隔一段不行有两个相对来说比较空洞的造成存储空间浪费分数量化是一个典型的非线性量化它可以很好的来解决这种分布不均匀的一个问题。比如有10个数从小到大排0 1 2 3 4…13等分位数就是画一个十分位均匀的切九份划成十份每一分位对应一个数。比如原来有n个数n1024把这1024个数a1 a2 直到a1024从小到大进行排序用INT8来量化那么INT 8它的值就是-128到127一共有256个数。a1 a2 a3 a4对应-128a5 a6 a7 a8对应-127最后几个就是a1024a1023a1022, a1021对应127。每个在INT 8里头每一个数都能够均匀的对应上四个原来的数而且它根据原来数大小其实是不敏感的对大小不敏感只对排序敏感只关心排序这个就是分位数排序。但是这个地方有个小问题首先它是非线性不像刚才那样乘除一个数加减个偏移量就能进行量化、反量化。需要有一个映射表来进行一个完整的保存这信息就全部给保存起来所以它的运算其实没有那么简单。还有一个很小的问题比如说a4和a5可能一个是0.111一个是0.112可能只差这一点点刚好被分到了两个不同的分位这个也是有可能的这个是它一个小小的一个瑕疵但最大好处是能够保证INT 8空间充分利用这是它最大的一个优势。08量化参数在推理时如何使用量化参数在推理的时候如何使用在推理的时候矩阵的乘法、加法还有激活函数这三种运算。线性量化就是最大值量化和和零点量化比如说矩阵新的元素就是之前的元素对应元素相乘累加。量化前的是FP16把FP16的数用INT 8来表示。这里有两个矩阵m1*m2m3每个矩阵都单独进行量化。m1对应s1z1m2对应s2z2m3对应s3z3直接拿量化后的结果就能算出来m3量化之后的结果相当于说原来计算的是拿FP16来计算FP16计算可以直接转成INT 8之间数的一个计算。拿到模型量化后的参数M1 M2要计算M3正常思路是把m1、m2反量化算成m3但是通过简单数学推导不需要这一步了直接算就会把M3给算出来因此不需要反量化过程直接把M3相乘的结果给算出来这个是利用了线性量化的一个优点这个加法不受量化影响。激活函数relu以前这是FP16量化之前的如果是最大值量化直接判断大于0还是小于0就行了。但是如果是零点量化零点会飘动因此相对来说稍微做个转机原来要判断r10现在只需要判断这个就可以了把这个直接带进去因此也相对零点漂移了所以主要是零点漂移的问题它通过这个方法就可以解决了这是线性函数。线性函数就是量化的比例放大对应的结果也成比例的放大。比较麻烦的是非线性激活函数如sigmoid函数这种非线性函数成比例放大对应的值不是成比例的比如线性函数f(3)3*f(1)C线性它肯定有这种特点非线性不具备这个特点这个比较麻烦的是sigmoid这种非线性函数。把非线性先近似成一个线性的状态。比如随机找8个点它是一个线性的对于这一段里面的函数把它当线性来进行一个插值计算这个点取的越密肯定就是精确的越准但同时带来算力消耗就会越大。首先量化范围是0到256把它分成128份相对说第一个就是0,1第二个是1,2第三个是2,3等。把这个量化之后的数值先把它反算成量化前的int 8把它反成FP 32。这个量化方法可以是任一种分位数量化零点量化等先进行一个量化就知道了量化的方法和反量化的方法首先把INT 8量化成FP 32然后反量化回来要反量化成FP 32比如这里对应的就是x1 x2 x3 x4等。反量化之后代入sigmoid得到y1y2直到y256 把求出来的值再进行量化变成了z1 z2…zn。假如新来的一个数x进行一个量化量化之后它刚好在这个区间比如刚好是0对应就直接查表做一个表。表对应x为int 8y为int8a1 b1对应z1 z2a2 b2对应的z2 z3 a3 b3对应z3 z4等。因为分了区间b1a2b2a3a1最小值对应z1、b1最大值对应z2。把a1 b1反量化成FP16计算完结果以后再量化回来。比如说突然来了个x经过量化以后比如a210 b214量化之后它是在13这个空间x其实属于这个区间这个区间里头最小的值是z2最大的值是z3因为这一块区间其实可以把它进行一个简单线性化那就是z2((z3-z2)/4)*3就是x所对应量化后的结果就直接在这里进行查值。先有一个分位区间把int 8 x量化分成n份a1 b1 a2 b2 a3 b3因为它是连续段所以b1a2b2a3。把这个量化后的先转成FP16再经过sigmoid函数算出y再进行一次量化变成int8的z1 z2、z2 z3、z3 z4。新来一个数先确认它在哪个区间在区间范围内让它有一个近似的关系直接来进行一个线性的运算。无论是什么量化方法还是函数是线性还是非线性都可以这样做。如果说函数是线性的量化方法也是线性的就可以用刚才这种相对来说比较简单的方法来计算。这个方法比较麻烦的是就是需要有一个映射表来保存这些关系。09动态量化动态量化大模型训练完了以后w就可以进行量化了已经都知道它分布了但是有个很大的问题比如ywx wx有个很大的问题。x是输入x输入会直接影响到y但是输入用户在用的时候根本就不知道用户会输入什么xy的这个数值范围是不确定的前面的几种量化方法无论哪种方法都是利用了数的值域这个时候根本不知道它的值域是什么。如果想量化y就很难去直接量化比如拿个模型以后怎么量化这个y因为连x都不知道是什么所以就没有办法去量化。所以就出来一个方法叫动态量化。输入x通过矩阵进行运算算出来一个新的向量yy就动态的来算把这个向量值都拿出来动态的进行量化边计算边量化y会随着x的变化或者α和β会随着x的变化而变化这个叫动态量化。但动态量化最大的问题是计算量太大了每次都进行一个现算计算量太大。10静态量化为了解决这个问题出现了静态量化。不知道x是什么所以没有办法量化y拿一些训练数据的子集来验证数据或者随便找一些数据或合成一些数据或混合或随机搞一些数据把y的值域大概估算出来。静态的把α β z给算好就是动态量化边来数据边量化但是它带来的问题是运算量太大动态算静态量化是拿些数据来模拟真实场景中的输入来进行一个运算带来的问题是模拟的这个跟真实的越近效果越好如果模拟的跟真实的差异很大那么效果肯定不理想这就是静态量化。011量化感知训练量化感知训练。经典的方法是有一个模型训练好了之后得到一个参数进行量化量化成新的参数。但是量化必然带来误差这样的话模型的w是最好的但是因为量化以后损失了一些东西可带来误差有可能量化的模型效果会打一些折扣。量化感知训练就是说训练的时候就考虑了量化误差。训练的时候输入经过第一层然后输出再经过第二层以前是Layer1直接连到Layer2正常神经网络在这里先进行一次量化再进行一次反量化把这个误差直接注入给模型这样的话模型的loss就包含了这个误差所带来的信息在梯度下降的时候就会考虑这些误差这样训练的时候它的效果就会比较好。在训练的时候就把这个误差直接给引入进来。站在一个更加宏观的角度来看这个问题比如说有两个局部极小。一个局部极小为①另外一个是②右边这个明显低一点但是正常思路就认为这个点可能会更好这个点它有个很大的问题w稍微偏一点损失迅速变大它这个地方就比较窄w稍微变一下损失迅速变大左边这个点虽然没有右边那么低但有个好处是w稍微变一下影响并不是很大。所以量化的时候更希望找到左边这样一个点哪怕量化受了点损失偏移过来不会造成效果有多大的折扣这是第一种理解方式。第二种理解方式就是说相当于说在训练的时候引入这个误差以前是训练θ现在直接是 c 塔扰了就是参数加了一个随机干扰项这随机干扰项就是量化带来的这样训练的时候就直接有误差这样能够避免这个问题。012GPTQ量化GPTQ的量化要理解量化的思维方式和思路。GPTQ量化这个量化首先w求逆矩阵w的逆矩阵W^-1这个数值逆矩阵对应的数值跟它误差的强度是有关系的这个地方的h这些数值跟模型的量化误差是有关联的。首先会把0.5量化再反量化变成0.297这是绝对误差再除以一个系数就变成了一个相对误差。相对误差再算第二个元素这样就可以算出来一个误差修正误差修正就是相对误差0.203这个误差修正算第二个元素的时候把第一个元素的误差修正加上去这样就有效的解决w各元素相互耦合、相互影响带来的误差。013Qlora原理和特点Qlora的原理和特点Lora是一个w外挂两个矩阵训练的时候不训练w只训练这两个矩阵Qlora就是lora的量化版本。它量化的是参数w外挂的这两个矩阵仍然是FP 32。w这块其实不参加训练所以随便怎么量化都没问题。如果做一个分位数量化FP32 - int4有可能原来的0被量化之后就不等于0了很容易出现这种情况但是它又认为0这个数很重要。Qlora的做法是正负数分别进行分位数量化FP16 - int4(正数[0,7]负数[-8, 0])所有大于0的正数进行量化因为0在FP16正数里头它肯定是最小的所以0肯定对应int4中的0。在负数里头负数的量化空间是-8到00在负数里头是最大的所以它肯定能量化到0所以可以保证0一定量化到0。就是通过正负两个区间分别做分位数量化一定能保证0一定能量化到0。就是QLORA第一个技术。第二个就是分块absmax量化它会再做一个double双重量化。比如FP16的数x量化到int8absmax不做量化因为这个数FP16保存很大直接把它再进行量化变成INT 8因为它做了两次量化这个就叫双重量化。第三个是一个分页存储这个跟量化关系倒不是很大它就是GPU资源相对比较紧张的时候会把一些梯度转移到CPU内存这个跟量化关系不是很大。最后就是在做模型训练的时候把这个真正要量化的东西源模型再进行一次量化这个是Lora它用的都是BF 16不做任何量化相当于它是在训练推理的时候训练和推理的时候一部分做了量化然后一部分不做量化这就是所谓的QLora。学AI大模型的正确顺序千万不要搞错了2026年AI风口已来各行各业的AI渗透肉眼可见超多公司要么转型做AI相关产品要么高薪挖AI技术人才机遇直接摆在眼前有往AI方向发展或者本身有后端编程基础的朋友直接冲AI大模型应用开发转岗超合适就算暂时不打算转岗了解大模型、RAG、Prompt、Agent这些热门概念能上手做简单项目也绝对是求职加分王给大家整理了超全最新的AI大模型应用开发学习清单和资料手把手帮你快速入门学习路线:✅大模型基础认知—大模型核心原理、发展历程、主流模型GPT、文心一言等特点解析✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑✅开发基础能力—Python进阶、API接口调用、大模型开发框架LangChain等实操✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经以上6大模块看似清晰好上手实则每个部分都有扎实的核心内容需要吃透我把大模型的学习全流程已经整理好了抓住AI时代风口轻松解锁职业新可能希望大家都能把握机遇实现薪资/职业跃迁这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】