2w字解析量化技術(shù),全網(wǎng)最全的大模型量化技術(shù)解析

# 2w字解析量化技術(shù),全網(wǎng)最全的大模型量化技術(shù)解析 ??閱讀時長:50分鐘 ??發(fā)布時間:2025-01-31 > 這篇網(wǎng)頁文章主要圍繞機(jī)器學(xué)習(xí)中的量化技術(shù)展開,詳細(xì)介紹了其在大語言模型中的應(yīng)用、基礎(chǔ)概念、技術(shù)方法及不同模型的量化策略。 量化是機(jī)器學(xué)習(xí)領(lǐng)域的一項(xiàng)關(guān)鍵優(yōu)化技術(shù),它能把高精度數(shù)值轉(zhuǎn)化為低精度格式。在大型語言模型(LLM)的世界里,量化可以將32位浮點(diǎn)參數(shù),巧妙地變成8位或4位整數(shù)這種更緊湊的形式,這可太厲害了,能讓模型在資源有限的環(huán)境中輕松實(shí)現(xiàn)高效部署。 ![](https://upload-images.jianshu.io/upload_images/17294212-31cbdea4bc407472.png) ## 一、量化帶來的諸多優(yōu)勢 - **降低內(nèi)存占用**:就像給模型做了一次“瘦身”,讓它占用的內(nèi)存空間大幅減少。 - **加快推理速度**:模型推理時就像裝上了“小馬達(dá)”,速度更快了,能迅速給出結(jié)果。 - **減少能源消耗**:變得更節(jié)能了,在運(yùn)行時消耗的能源大大降低。 - **提升部署靈活性**:不管是在什么樣的設(shè)備上,都能更靈活地進(jìn)行部署。 ## 二、大語言模型的規(guī)模挑戰(zhàn) 如今,現(xiàn)代大語言模型規(guī)模大得超乎想象!像Claude、Gemini、GPT和Llama系列這些模型,個個都包含了幾十億個參數(shù)。如此龐大的規(guī)模,對內(nèi)存提出了超高要求。大部分硬件加速器,比如CPU、GPU和TPU,處理整數(shù)運(yùn)算的速度比浮點(diǎn)運(yùn)算更快,而且還更節(jié)能。要是把模型量化成8位、4位,甚至1位整數(shù),推理速度會加快,耗電量也會降低,在移動設(shè)備和邊緣設(shè)備上,響應(yīng)速度更快,電池續(xù)航時間也更長。在計(jì)算中使用浮點(diǎn)數(shù)時,位寬(所用的位數(shù))在平衡精度和內(nèi)存使用方面起著關(guān)鍵作用。 ### (一)32位浮點(diǎn)(FP32):高精度的代表 ![](https://upload-images.jianshu.io/upload_images/17294212-77a7a96cc33def43.png) 32位浮點(diǎn)格式(也就是FP32),每個數(shù)字都用32位來表示。這種格式把這些位分成三個部分:符號位、指數(shù)位和尾數(shù)(小數(shù)部分)。FP32能提供高精度的數(shù)值表示,因?yàn)樗峙淞烁嗟奈粊砭_捕捉數(shù)字的值。就拿圓周率π來說,F(xiàn)P32會把它存儲為3.1415927410125732,和真實(shí)值非常接近。不過,每個數(shù)字都用32位來存儲,這在處理大量數(shù)據(jù)時,內(nèi)存占用就成了問題。 ![](https://upload-images.jianshu.io/upload_images/17294212-a5f6dcd0019d4b98.png) ### (二)16位浮點(diǎn)(FP16):在精度和內(nèi)存間權(quán)衡 相比之下,16位浮點(diǎn)格式(FP16)就只用16位,這意味著尾數(shù)和指數(shù)位的位數(shù)都變少了。精度自然就降低了,還是以π為例,在FP16里它被存儲為3.140625,雖然很接近,但確實(shí)沒有FP32那么精確。不過,F(xiàn)P16的優(yōu)勢也很明顯,它占用的內(nèi)存只有FP32的一半。對于大規(guī)模數(shù)據(jù)集或模型來說,內(nèi)存使用量能大幅減少,所以很適合那些硬件容量有限的設(shè)備,或者是對精度要求沒那么高、更看重效率的應(yīng)用場景。 雖說減少位大小有這些好處,可量化過程會引入近似誤差,這就可能影響模型的準(zhǔn)確性。最大的挑戰(zhàn)就在于,要在享受減少內(nèi)存占用和加快計(jì)算速度這些好處的同時,把誤差降到最低。 ## 三、量化的基礎(chǔ) ### (一)IEEE-754浮點(diǎn)標(biāo)準(zhǔn) 1. **單精度(FP32)** - **符號位**:1位 - **指數(shù)位**:8位 - **尾數(shù)位**:23位 - **總范圍**:±3.4×1?3? 2. **半精度(FP16)** - **符號位**:1位 - **指數(shù)位**:5位 - **尾數(shù)位**:10位 - **總范圍**:±65,504 3. **Bfloat16(BF16)** - **符號位**:1位 - **指數(shù)位**:8位 - **尾數(shù)位**:7位 - **總范圍**:±3.4×103?,和FP32差不多。 Bfloat16在訓(xùn)練和推理中經(jīng)常用到,尤其是在像TPU這樣的硬件中,它既有和FP32相似的大范圍表示能力,又有FP16低內(nèi)存占用的優(yōu)點(diǎn)。 ### (二)整數(shù)格式 1. **INT8(8位整數(shù))** - **總位數(shù)**:8位 - **符號位(有符號INT8)**:1位 - **數(shù)值位(有符號INT8)**:7位 - **或者數(shù)值位(無符號INT8)**:8位 - **范圍**: - **有符號**:-128到 +127 - **無符號**:0到255 2. **INT4(4位整數(shù))** - **總位數(shù)**:4位 - **符號位(有符號INT4)**:1位 - **數(shù)值位(有符號INT4)**:3位 - **或者數(shù)值位(無符號INT4)**:4位 - **范圍**: - **有符號**:-8到 +7 - **無符號**:0到15 ![](https://upload-images.jianshu.io/upload_images/17294212-d66ad135745f346d.png) ### (三)量化過程 1. **確定數(shù)值的動態(tài)范圍**:要搞清楚數(shù)據(jù)中數(shù)值的變化范圍。 2. **選擇縮放因子(Δ)**:這個因子很關(guān)鍵,會影響量化的效果。 3. **將浮點(diǎn)值映射為整數(shù)**:按照規(guī)則把浮點(diǎn)形式的數(shù)字變成整數(shù)。 4. **存儲縮放因子用于反量化**:方便之后把量化后的整數(shù)再變回浮點(diǎn)值。 ### (四)量化類型 1. **對稱量化**:對稱量化是用一個縮放因子把浮點(diǎn)值轉(zhuǎn)化為整數(shù)的方法,量化后的值以零為中心對稱分布。也就是說,量化值的范圍在正數(shù)和負(fù)數(shù)之間是平衡的,從(-α)到(α)。 ![](https://upload-images.jianshu.io/upload_images/17294212-c4b296a7140e068e.png) 比如說,有這么一組FP32值: ``` 4.72, 2.96, -6.48 0, -3.34, -5.26 8.58, 2.19, -3.67 ``` **計(jì)算縮放因子**:在8位量化中,我們用的范圍是 -127到127。根據(jù)最大絕對值來確定縮放因子。這里最大絕對值α = 8.58,量化位數(shù)(b)是8位,所以對稱整數(shù)范圍就是 -127到127。 ![](https://upload-images.jianshu.io/upload_images/17294212-e6606247fbd093b4.png) **量化數(shù)值**:用縮放因子,把每個FP32值除以縮放因子再四舍五入取整,就得到量化后的INT8值。 ``` 70, 44, -96 0, -49, -78 127, 32, -54 ``` ![](https://upload-images.jianshu.io/upload_images/17294212-327acfce28167639.png) **反量化**:要變回FP32值,就把每個量化后的整數(shù)乘以縮放因子。這個過程中會發(fā)現(xiàn),有些值比如 -3.34和2.96,量化后再反量化回FP32格式時,會損失一些精度,和原來的值不完全一樣。這個差值就是量化誤差,通過計(jì)算原始FP32值和反量化值的差得到。一般來說,量化用的位數(shù)越少,量化誤差就越大,因?yàn)槲粩?shù)少,能表示的值范圍有限,近似的情況就更多,精度也就更低。 ![](https://upload-images.jianshu.io/upload_images/17294212-e851c63321129122.png) 2. **非對稱量化**:非對稱量化不是以零為中心對稱的。它把浮點(diǎn)范圍的最小值(β)和最大值(α),映射到量化范圍的最小值和最大值。還是用剛才那組FP32值來舉例: ![](https://upload-images.jianshu.io/upload_images/17294212-d3a70ef01a547f51.png) ``` 4.72, 2.96, -6.48 0, -3.34, -5.26 8.58, 2.19, -3.67 ``` **計(jì)算縮放因子和零點(diǎn)**:先找出最小值β = -6.48和最大值α = 8.58,然后計(jì)算縮放因子和零點(diǎn)。 **量化每個值**:用縮放因子和零點(diǎn),對每個值進(jìn)行量化,得到下面這些量化后的INT8值: ``` 190, 160, 0 110, 53, 20 255, 147, 47 ``` **反量化**:要變回FP32值,就用相應(yīng)的反量化公式計(jì)算。同樣也可以計(jì)算非對稱量化的誤差,下面的表格能清晰對比兩種量化方式。 ![](https://upload-images.jianshu.io/upload_images/17294212-f19f533713b14ad5.png) ![](https://upload-images.jianshu.io/upload_images/17294212-e6f47a1169bb9eaa.png) ![](https://upload-images.jianshu.io/upload_images/17294212-61b0d6587818e8ea.png) ### (五)特定任務(wù)的量化建議 1. **自然語言處理任務(wù)(NLP)**:訓(xùn)練時用BF16,推理時用INT8。 2. **圖像處理任務(wù)**:訓(xùn)練時用FP16,推理時用INT8或INT4。 3. **Transformer模型**:注意力層可以混合使用INT8和INT4。 ### (六)裁剪 在量化過程中,有一種常用方法是把向量值的范圍映射到低比特表示。這樣能以壓縮格式捕捉向量所有的值,但遇到比其他數(shù)據(jù)大很多或者小很多的異常值時,就出問題了。想象有這么一個向量:[0.5, 1.2, -0.7, 2.0, 0.9, 10.5],這里10.5就是個異常值,比其他值大太多。要是把這個向量的整個范圍映射到低比特格式(比如INT8),其他小的值最后可能都被壓縮成相同或者相似的低比特表示,它們之間的差異信息就沒了。這就是絕對最大(absmax)方法的特點(diǎn),它是根據(jù)數(shù)據(jù)的最大絕對值來設(shè)置范圍的。 #### 1. 用裁剪處理異常值 為了減少異常值的影響,可以采用裁剪的方法,也就是定義一個自定義的動態(tài)范圍,把極端值排除在外。比如說,手動把動態(tài)范圍設(shè)為[-5, 5],那么任何超出這個范圍的值都會被“裁剪”,不管它實(shí)際有多大,都被映射到目標(biāo)范圍的最大值或最小值。在這個例子里,10.5在INT8中會被映射為127,而在[-5, 5]范圍內(nèi)的值能保留更多精度和差異細(xì)節(jié)。裁剪的好處是,對于選定范圍內(nèi)(非異常值)的值,量化誤差能大幅降低,不過異常值的量化誤差會變高。在一些場景中,如果少數(shù)極端值會主導(dǎo)量化尺度,導(dǎo)致大部分?jǐn)?shù)據(jù)精度損失,那這種技術(shù)就特別有用。 ![](https://upload-images.jianshu.io/upload_images/17294212-f16cf5a435900f3c.png) #### 2. 校準(zhǔn) 上面例子里,[-5, 5]這個動態(tài)范圍是隨便選的,只是為了展示裁剪。但實(shí)際上,選擇一個最優(yōu)范圍的過程,也就是校準(zhǔn),對有效的量化至關(guān)重要。校準(zhǔn)的目的是找到一個能包含盡可能多的值,同時又能最小化量化誤差的范圍。在量化機(jī)器學(xué)習(xí)模型時,這一點(diǎn)尤為重要,因?yàn)檫x了錯誤的范圍會嚴(yán)重影響模型的準(zhǔn)確性。 #### 3. 不同類型參數(shù)的校準(zhǔn)技術(shù) 不同類型的參數(shù),校準(zhǔn)要求也不一樣: - **權(quán)重(和偏差)**:在大語言模型(LLMs)里,權(quán)重和偏差可以看作是靜態(tài)值,在模型部署前就確定了。權(quán)重是量化的主要關(guān)注點(diǎn),因?yàn)樗鼈冋剂四P痛笮〉慕^大部分(常常有幾十億個參數(shù)),而偏差數(shù)量相對較少,有時候會用更高的精度(比如INT16)來保存。權(quán)重的校準(zhǔn)技術(shù)通常有: - **基于百分位數(shù)的裁剪**:設(shè)定一個范圍,排除一定比例的極端值,重點(diǎn)關(guān)注數(shù)據(jù)點(diǎn)的中間百分位數(shù)范圍。 - **均方誤差(MSE)最小化**:這種方法能最小化原始權(quán)重和量化后權(quán)重之間的均方誤差,有助于保持模型的準(zhǔn)確性。 - **最小化KL散度(熵)**:目的是最小化原始值和量化值之間的分布差異(KL散度)。 ![](https://upload-images.jianshu.io/upload_images/17294212-263e31485b350b43.png) 比如說,用基于百分位數(shù)的方法,會產(chǎn)生和前面討論的裁剪類似的效果,把異常值排除掉,更好地表示數(shù)據(jù)的中心范圍。 - **激活值**:激活值就不一樣了,它是動態(tài)變化的,會隨著模型的每次輸入而改變。激活值在每個隱藏層都要經(jīng)過激活函數(shù)(比如sigmoid或ReLU),這就使得它們的值取決于當(dāng)時正在處理的具體數(shù)據(jù)。這種可變性讓應(yīng)用單一的量化方案變得很困難,因?yàn)榧せ钪禃鶕?jù)輸入有很大的差異。激活值的校準(zhǔn)一般有兩種主要方法: - **訓(xùn)練后量化(PTQ)**:在模型訓(xùn)練完成后進(jìn)行量化,通常在一個有代表性的數(shù)據(jù)集上進(jìn)行。 - **量化感知訓(xùn)練(QAT)**:在訓(xùn)練過程中就應(yīng)用量化,讓模型在量化值的約束下進(jìn)行調(diào)整和學(xué)習(xí),這樣能提高模型的準(zhǔn)確性。 ## 四、量化技術(shù) ### (一)訓(xùn)練后量化(PTQ) 訓(xùn)練后量化(PTQ)是一種應(yīng)用非常廣泛的技術(shù),在模型訓(xùn)練完成后,用它來量化模型的參數(shù)(權(quán)重和激活值)。在PTQ中,權(quán)重和激活值可以調(diào)整為低精度,而且不需要額外的訓(xùn)練或微調(diào)。 1. **權(quán)重的量化**:權(quán)重可以用對稱量化或者非對稱量化。如果數(shù)據(jù)是以零為中心分布的,一般用對稱量化;要是數(shù)據(jù)有偏差,非對稱量化能更有效地表示不同的數(shù)據(jù)范圍,就更合適。 2. **激活值的量化**:量化激活值比量化權(quán)重要復(fù)雜,因?yàn)榧せ钪禃S著輸入和層的不同而變化。要想準(zhǔn)確量化激活值,就得知道它們可能的范圍,這只能通過讓數(shù)據(jù)在模型中運(yùn)行(推理)來確定。在PTQ中,激活值量化主要有兩種方法:動態(tài)量化和靜態(tài)量化。 3. **動態(tài)量化** ![](https://upload-images.jianshu.io/upload_images/17294212-09c749969569fa15.png) 在動態(tài)量化過程中,當(dāng)數(shù)據(jù)流經(jīng)每個隱藏層時,會收集并分析激活值。具體過程如下: 1. **激活值收集**:數(shù)據(jù)通過隱藏層后,記錄激活值的分布情況。 2. **計(jì)算量化參數(shù)**:根據(jù)這個分布,計(jì)算零點(diǎn)($z$)和縮放因子($s$),用這些參數(shù)把激活值映射到低精度格式。每次數(shù)據(jù)流經(jīng)一個層,這個過程都會重復(fù),也就是說每個層都有自己的$z$和$s$值,不同層的量化方案也不一樣。 ![](https://upload-images.jianshu.io/upload_images/17294212-a833c1b48bc21f21.png) 3. **優(yōu)勢**:動態(tài)量化更準(zhǔn)確,因?yàn)?z$和$s$值是在推理時針對每個層確定的,能適應(yīng)實(shí)際流經(jīng)模型的數(shù)據(jù)。 4. **缺點(diǎn)**:不過,在每個層都重新計(jì)算這些值,會增加推理時的計(jì)算量,可能導(dǎo)致推理過程變慢。 下面這段代碼展示了如何用PyTorch對預(yù)訓(xùn)練的ResNet18模型應(yīng)用動態(tài)量化。動態(tài)量化只應(yīng)用于特定的層(比如線性層),而且不需要校準(zhǔn)數(shù)據(jù)集。 ```python import torch import torchvision model = torchvision.models.resnet18(pretrained=True) model.eval() ``` 這段代碼從`torchvision`加載了一個預(yù)訓(xùn)練的ResNet18模型,并把它設(shè)置為評估模式(`model.eval()`),這樣能確保在推理時批歸一化和隨機(jī)失活層正常工作。 ```python model_quantized = torch.quantization.quantize_dynamic( model, {torch.nn.Linear}, dtype=torch.qint8 ) ``` `torch.quantization.quantize_dynamic`函數(shù)動態(tài)地對特定層進(jìn)行量化,具體說明如下: 1. **模型**:`model`參數(shù)指定了要量化的模型。 2. **要量化的層**:`{torch.nn.Linear}`表示只對線性(全連接)層進(jìn)行量化。動態(tài)量化通常應(yīng)用于像線性層和LSTM層這樣,大部分計(jì)算是矩陣乘法的層,因?yàn)檫@樣可以減少內(nèi)存占用,加快計(jì)算速度。 3. **量化類型**:`dtype=torch.qint8`指定在量化過程中,模型的參數(shù)會被轉(zhuǎn)換為8位整數(shù)(INT8)。在動態(tài)量化中,權(quán)重在加載時就被量化為INT8,而激活值在推理時動態(tài)(實(shí)時)量化。這使得動態(tài)量化比全精度模型更快,占用內(nèi)存更少,還不需要校準(zhǔn)數(shù)據(jù)集。 ```python torch.save(model_quantized.state_dict(), 'dynamic_quantized_model.pth') ``` 最后,把量化后模型的狀態(tài)字典保存到`dynamic_quantized_model.pth`文件里,之后加載這個文件就能進(jìn)行高效推理了。 4. **靜態(tài)量化** 另一方面,靜態(tài)量化在推理前就確定了$z$和$s$值。這涉及到: 1. **校準(zhǔn)數(shù)據(jù)集**:用一個有代表性的數(shù)據(jù)集(校準(zhǔn)數(shù)據(jù)集)在模型中運(yùn)行,收集激活值的分布情況。 2. **計(jì)算量化參數(shù)**:根據(jù)這個分布,計(jì)算并存儲$z$和$s$值。在推理時,這些值會在所有層和激活值中統(tǒng)一使用。 3. **優(yōu)勢**:靜態(tài)量化通常更快,因?yàn)樵谕评頃r不用重新計(jì)算$z$和$s$值,依靠預(yù)先計(jì)算好的值,計(jì)算效率更高。 4. **缺點(diǎn)**:靜態(tài)量化和動態(tài)量化比起來可能沒那么準(zhǔn)確,因?yàn)樗谛?zhǔn)過程中只用了一組$z$和$s$值。如果在實(shí)際推理時激活值的分布變化很大,就可能導(dǎo)致更高的量化誤差。 ```python import torch import torchvision import torch.quantization as quant model = torchvision.models.resnet18(pretrained=True) model.eval() ``` 這段代碼加載了有預(yù)訓(xùn)練權(quán)重的ResNet18模型,并設(shè)置為評估模式(`model.eval()`),這是推理和量化的必要步驟。 ```python model.qconfig = torch.quantization.get_default_qconfig("fbgemm") ``` 用`torch.quantization.get_default_qconfig("fbgemm")`設(shè)置量化配置。FBGEMM后端針對x86 CPU進(jìn)行了優(yōu)化,通常使用8位整數(shù)(INT8)量化,能實(shí)現(xiàn)更快、更節(jié)省內(nèi)存的推理。 ```python model_prepared = torch.quantization.prepare(model, inplace=False) ``` `prepare`函數(shù)會在模型的層中插入量化觀察器,收集靜態(tài)量化所需的激活統(tǒng)計(jì)信息。設(shè)置`inplace=False`會創(chuàng)建模型的修改副本。 ```python for _ in range(20): input_tensor = torch.randn(1, 3, 224, 224) model_prepared(input_tensor) ``` 在校準(zhǔn)過程中,樣本數(shù)據(jù)(形狀為`(1, 3, 224, 224)`的隨機(jī)張量,代表批量大小為1、分辨率為224x224的RGB圖像)會通過模型。這些運(yùn)行過程會收集激活統(tǒng)計(jì)信息,用于確定量化的縮放因子和零點(diǎn)。 **輸入形狀說明**:`(1, 3, 224, 224)`是ResNet18期望的輸入形狀。在這個例子中,你可以自由調(diào)整批量大小。例如,將輸入形狀設(shè)置為`(32, 3, 224, 224)`,將一次性處理32張圖像,如果硬件允許,這可以提高推理時的吞吐量。不過,通道數(shù)(RGB圖像為3)和分辨率(224x224)應(yīng)保持不變,以與ResNet18兼容,因?yàn)樗谕膱D像具有這些維度。 ```python model_quantized = torch.quantization.convert(model_prepared, inplace=False) ``` `convert`函數(shù)應(yīng)用收集到的量化參數(shù)(縮放因子和零點(diǎn)),創(chuàng)建量化版本的模型。這會用量化版本替換某些層,針對INT8操作進(jìn)行優(yōu)化。 ```python torch.save(model_quantized.state_dict(), "quantized_model.pth") ``` 最后,量化模型的狀態(tài)字典(參數(shù))被保存到文件中。之后加載這個文件,就能以量化形式進(jìn)行高效推理。 ### 4位量化 將模型精度降低到4位(甚至更低)一直頗具挑戰(zhàn),因?yàn)殡S著比特精度的每一次降低,量化誤差都會增加。低比特量化雖然效率很高,但如果處理不當(dāng),可能會降低模型精度。不過,隨著量化技術(shù)的進(jìn)步,現(xiàn)在模型能夠在保持性能的同時達(dá)到4位精度。 #### 4位量化的方法 對于大型語言模型,4位量化通常采用兩種主要方法: 1. **GPTQ**:主要針對GPU進(jìn)行優(yōu)化,并使用加權(quán)量化誤差校正。 2. **GGML和GGUF**:這些技術(shù)旨在支持混合精度和CPU卸載,其中GGUF在GGML的基礎(chǔ)上進(jìn)行了改進(jìn),克服了其一些局限性。 3. **AWQ**:專為高效4位量化而設(shè)計(jì),采用激活感知方法,無需重新訓(xùn)練數(shù)據(jù)即可最小化精度損失,適用于在資源受限環(huán)境中的CPU和GPU上進(jìn)行部署。 ![](https://upload-images.jianshu.io/upload_images/17294212-b00a82a89be091e6.png) 在實(shí)際場景中,這些方法適用于4位精度,但如果再降低精度(例如到3位或2位精度),可能會引入過多量化誤差,在不顯著降低模型精度的情況下很難維持其準(zhǔn)確性。 #### GPTQ GPTQ是在高性能模型中實(shí)現(xiàn)4位量化的常用選擇。GPTQ采用非對稱量化方法,一次對一層進(jìn)行量化。通過獨(dú)立處理每一層,GPTQ確保在進(jìn)入下一層之前,每一層都能得到專門的處理。 ![](https://upload-images.jianshu.io/upload_images/17294212-f617bf9a9d0098db.png) 以下是GPTQ處理量化的詳細(xì)步驟: 1. **獨(dú)立層量化**:GPTQ按順序?qū)γ恳粚舆M(jìn)行量化,為每一層應(yīng)用獨(dú)特的設(shè)置。首先使用逆海森矩陣對權(quán)重進(jìn)行變換,這一過程可以表明每個權(quán)重對模型輸出變化的敏感程度。 - **量化中的海森矩陣**:在量化的背景下,尤其是對于神經(jīng)網(wǎng)絡(luò),逆海森矩陣(模型損失函數(shù)的二階導(dǎo)數(shù))有助于我們了解模型輸出對每個權(quán)重變化的敏感程度。逆海森值較低的權(quán)重更敏感,意味著這些權(quán)重的微小變化可能會對模型輸出產(chǎn)生顯著影響。在量化過程中,逆海森矩陣有助于對這些敏感權(quán)重進(jìn)行優(yōu)先級排序,以便更精細(xì)地分配精度,減少量化誤差并保持模型精度。 2. **基于逆海森敏感性的量化**:計(jì)算完逆海森矩陣后,GPTQ對層內(nèi)的每個權(quán)重進(jìn)行量化,然后再反量化。這使得該方法能夠計(jì)算量化誤差($q$),捕捉將權(quán)重轉(zhuǎn)換為低比特格式時損失的精度。 ![](https://upload-images.jianshu.io/upload_images/17294212-013eb29e51d1fa03.png) 3. **加權(quán)量化誤差調(diào)整**:GPTQ通過將量化誤差與逆海森敏感性值($h$)進(jìn)行權(quán)衡,進(jìn)一步優(yōu)化量化誤差。這一調(diào)整過程會優(yōu)先考慮對精度至關(guān)重要的權(quán)重,有效地生成加權(quán)量化誤差,從而保留更重要的細(xì)節(jié)。其中,$q$是量化誤差。 ![](https://files.mdnice.com/user/13819/22e93173-1649-43a6-9d49-43ce519b2025.png) ![](https://files.mdnice.com/user/13819/377d7996-7737-4095-8479-5c449b91a791.png) 4. **權(quán)重間的誤差重新分配**:GPTQ不會讓量化誤差孤立地存在于單個權(quán)重上,而是將誤差在層內(nèi)相關(guān)權(quán)重之間重新分配。這種方法確保即使在精度降低的情況下,模型的功能仍能保持一致。例如,權(quán)重$x_2$的誤差為$0.3$,可以通過應(yīng)用按$h_2$($x_2$的敏感性)縮放的$q$來平衡。 ![](https://upload-images.jianshu.io/upload_images/17294212-503e52fa33dae338.png) ![](https://upload-images.jianshu.io/upload_images/17294212-18d3c6ebde5d43ba.png) 5. **迭代優(yōu)化**:GPTQ對層內(nèi)的每個權(quán)重迭代應(yīng)用這一過程,使相關(guān)權(quán)重能夠“分擔(dān)”量化誤差,直到所有值都以平衡精度和功能的方式完成量化。最終得到的層,其權(quán)重經(jīng)過更新,能更好地適應(yīng)4位量化的限制。 #### GPTQ敏感性感知方法的優(yōu)勢 GPTQ對權(quán)重敏感性的關(guān)注使其即使在較低精度下也能保持準(zhǔn)確性。通過在相互關(guān)聯(lián)的權(quán)重之間重新分配量化誤差,它確保了模型性能的穩(wěn)健性。這種方法特別有效,因?yàn)閷觾?nèi)的權(quán)重通常具有復(fù)雜的關(guān)系,保留這些連接有助于保持模型的整體完整性。 #### GPTQ中的其他優(yōu)化技巧 為了進(jìn)一步提高4位量化的效率,GPTQ融入了一些專門的優(yōu)化技術(shù): 1. **阻尼因子**:降低逆海森矩陣中高敏感性的影響,防止某些權(quán)重變得過于不穩(wěn)定。 2. **延遲批處理**:以計(jì)算高效的方式對更新進(jìn)行分組,最小化處理開銷。 3. **喬列斯基分解**:預(yù)先計(jì)算逆海森矩陣,以便更快地進(jìn)行量化,利用數(shù)學(xué)分解技術(shù)實(shí)現(xiàn)更流暢的執(zhí)行。 #### 神經(jīng)網(wǎng)絡(luò)中的涌現(xiàn)特征 1. **定義**:涌現(xiàn)特征是在大型神經(jīng)網(wǎng)絡(luò)中觀察到的一種現(xiàn)象,不同層在識別和標(biāo)記數(shù)據(jù)中的特定特征時趨于一致。這種一致性表明數(shù)據(jù)的某些方面被有效地捕捉到了,它可以被視為網(wǎng)絡(luò)所學(xué)“知識”的一種體現(xiàn)。 2. **特征**: - **大權(quán)重**:涌現(xiàn)特征通常表現(xiàn)為權(quán)重明顯大于網(wǎng)絡(luò)中平均權(quán)重。例如,如果網(wǎng)絡(luò)中的平均權(quán)重約為$0.5$,涌現(xiàn)特征可能由$10.0$或$-8.5$這樣的權(quán)重表示。這表明這些權(quán)重在模型的決策過程中起著至關(guān)重要的作用。 - **信息集中**:這些大權(quán)重有助于網(wǎng)絡(luò)處理和解釋輸入數(shù)據(jù),有效地充當(dāng)模型已學(xué)會識別的特征的指示符。 3. **示例**:考慮神經(jīng)網(wǎng)絡(luò)中的以下權(quán)重矩陣: - 在這個矩陣中,權(quán)重$-10.0$、$8.5$和$-15.0$可以被視為涌現(xiàn)特征。它們的量級比矩陣中的其他權(quán)重明顯更大。 - 這些權(quán)重對模型的輸出至關(guān)重要,表明它們代表了模型進(jìn)行預(yù)測所依賴的重要特征。 4. **在量化中的重要性**:在量化方面,涌現(xiàn)特征至關(guān)重要。代表涌現(xiàn)特征的權(quán)重通常保持較高精度,不進(jìn)行量化。做出這一決策是為了保持模型的性能和準(zhǔn)確性。通過以原始精度保留這些權(quán)重,網(wǎng)絡(luò)可以保留其所學(xué)知識,并有效地響應(yīng)輸入數(shù)據(jù),確保在量化過程中保留關(guān)鍵特征。 ### GGUF GGUF是一種先進(jìn)的量化方法,當(dāng)GPU內(nèi)存(VRAM)不足時,它能夠?qū)⒋笮驼Z言模型(LLM)的層卸載到CPU上。這種靈活性使模型能夠高效利用CPU和GPU資源,便于在各種硬件配置上進(jìn)行部署。 ![](https://upload-images.jianshu.io/upload_images/17294212-176192790aa0592c.png) #### GGUF詳細(xì)步驟解析 1. **塊結(jié)構(gòu)**:在GGUF中,每一層的權(quán)重被組織成層次化的塊結(jié)構(gòu)。 - **超級塊**:這些是較大的段,包含多個子塊,為量化提供整體上下文和尺度。 - **子塊**:這些是超級塊內(nèi)的較小單元,其中的權(quán)重會被單獨(dú)進(jìn)行量化處理。 - **示例**:假設(shè)有一個LLM層的權(quán)重如下。在這個例子中,我們可以定義一個包含三個子塊的超級塊。每個子塊可能包含一行權(quán)重,權(quán)重劃分如下: - **超級塊1**: - **子塊1**:[0.5, 0.3, -0.1] - **子塊2**:[-0.7, 0.2, -0.6] - **子塊3**:[0.8, 0.4, -0.1] 2. **縮放因子提取**:從這些塊中提取兩個關(guān)鍵組件: - **縮放因子($s$)**:用于對子塊中的權(quán)重進(jìn)行量化的乘數(shù)。 - **Alpha($\alpha$)**:表示每個子塊內(nèi)的最大絕對權(quán)重值。 - **示例**:對于子塊1,$\alpha = \max(|0.5|, |0.3|, |-0.1|) = 0.5$,子塊的縮放因子$s$可以根據(jù)其值計(jì)算得出。 3. **量化過程**:為了量化一個“子”塊,應(yīng)用絕對最大(absmax)量化:量化后的權(quán)重 = $s$×權(quán)重。假設(shè)子塊1的$s = 0.5$,每個權(quán)重的量化過程如下: - 對于$0.5$:量化后的權(quán)重 = $0.5×0.5 = 0.25$ - 對于$0.3$:量化后的權(quán)重 = $0.5×0.3 = 0.15$ - 對于$-0.1$:量化后的權(quán)重 = $0.5× -0.1 = -0.05$ 4. **逐塊量化**:在量化過程中,超級塊的縮放因子($s_{\text{super}}$)用于指導(dǎo)每個子塊縮放因子($s_{\text{sub}}$)的量化。這種方法考慮到超級塊提供的更廣泛上下文,使得量化過程更加準(zhǔn)確。例如,如果超級塊的縮放因子$s_{\text{super}} = 1.0$,它可以用于調(diào)整子塊的量化級別。 ![](https://upload-images.jianshu.io/upload_images/17294212-13f7cbe2b8af8182.png) 5. **零點(diǎn)調(diào)整**:在應(yīng)用量化時,可能需要一個額外的最小值($m$)來調(diào)整量化的零點(diǎn)。這有助于保持模型輸出的完整性,處理方式與縮放因子類似。 #### 量化級別 GGUF具有通用性,能夠適應(yīng)各種量化級別(主要是4位)。每個級別可能涉及不同的量化策略,以平衡精度和資源效率。 GGUF是一種強(qiáng)大的量化方法,它使大型語言模型能夠高效利用CPU和GPU資源。通過采用層次化塊結(jié)構(gòu)并利用縮放因子,GGUF即使在較低精度的約束下也能保持模型性能。這種在管理硬件資源方面的靈活性,使GGUF成為在不同環(huán)境中部署LLM的有吸引力的選擇。 ### AWQ(激活感知權(quán)重量化) AWQ是一種針對大型語言模型(LLMs)的訓(xùn)練后量化(PTQ)方法,專注于4位僅權(quán)重量化,旨在最小化推理成本的同時保持模型精度。與量化感知訓(xùn)練(QAT)方法不同,AWQ無需反向傳播或重新訓(xùn)練,因此適用于大型模型的擴(kuò)展。這種技術(shù)特別適合像邊緣設(shè)備這樣資源受限的硬件,通過有策略地保護(hù)對精度至關(guān)重要的權(quán)重來實(shí)現(xiàn)高效推理。 #### AWQ的關(guān)鍵組件 1. **激活感知權(quán)重量化**:AWQ識別并保護(hù)每一層中最重要的權(quán)重,這些權(quán)重對于維持模型性能至關(guān)重要。通過關(guān)注與高激活特征對應(yīng)的權(quán)重,AWQ最小化了可能導(dǎo)致顯著精度下降的量化誤差。權(quán)重$w$的量化函數(shù)$Q(w)$定義為: $$Q(w)=\text{clip}(\lfloor\frac{w}{\Delta}\rceil,\ -2^{N - 1},\ 2^{N - 1}-1)\times\Delta$$ 其中,$\Delta$是由權(quán)重的最大絕對值確定的量化尺度,$N$是比特精度(例如,4位量化時$N = 4$)。 2. **顯著權(quán)重保護(hù)**:AWQ根據(jù)激活幅度對1%最重要的權(quán)重進(jìn)行選擇性縮放,而不是對所有權(quán)重進(jìn)行統(tǒng)一量化。這種策略通過防止高影響力權(quán)重的退化,保留了大型語言模型中的關(guān)鍵知識。與可能對校準(zhǔn)集過擬合的GPTQ不同,AWQ的激活感知方法避免了過擬合,使其在不同任務(wù)和數(shù)據(jù)集上具有通用性。對于顯著權(quán)重,AWQ使用縮放量化方法: $$Q_{\text{salient}}(w)=s\times\text{clip}(\lfloor\frac{w}{\Delta}\rceil,\ -2^{N - 1},\ 2^{N - 1}-1)\times\Delta$$ 其中$s>1$是用于保護(hù)關(guān)鍵權(quán)重的縮放因子,$x$代表與權(quán)重相關(guān)的激活。這通過對激活進(jìn)行反向縮放來減少最重要權(quán)重的量化誤差。 3. **通過縮放最小化誤差**:AWQ按通道調(diào)整重要權(quán)重的縮放因子,在不使用額外訓(xùn)練數(shù)據(jù)的情況下降低量化誤差。通過逐通道縮放,AWQ對量化過程進(jìn)行微調(diào),平衡顯著權(quán)重和非顯著權(quán)重之間的誤差,以最小化總體損失。這種方法顯著降低了量化誤差并提高了性能,特別是在低比特設(shè)置下,如4位甚至3位組量化設(shè)置。縮放后顯著權(quán)重的誤差可以表示為: $$\text{Error}_{\text{scaled}}=\sum_{i = 1}^{n}(w_i - Q_{\text{salient}}(w_i))^2$$ 其中,顯著權(quán)重的相對誤差被最小化,使AWQ在保持關(guān)鍵模型精度方面更加穩(wěn)健。 4. **無數(shù)據(jù)優(yōu)化**:與一些可能對特定校準(zhǔn)分布過擬合的PTQ方法不同,AWQ不需要大型校準(zhǔn)集。通過僅分析每個通道的平均激活幅度,AWQ保持了穩(wěn)定性,并能更好地泛化到不同的數(shù)據(jù)分布,確保LLMs在不同任務(wù)和領(lǐng)域中保持廣泛的泛化能力。每一層的最優(yōu)縮放因子可以通過優(yōu)化得到: $$L(s)$$ 其中$L(s)$是表示量化誤差的目標(biāo)函數(shù),逐通道縮放用于根據(jù)輸入激活幅度調(diào)整權(quán)重。 5. **層間靈活性**:AWQ可以根據(jù)模型推理路徑中不同層的相對重要性,對不同層應(yīng)用不同的量化尺度。這種層間靈活性使AWQ能夠避免在關(guān)鍵層進(jìn)行過于激進(jìn)的量化,確保即使在激進(jìn)量化的情況下,整體精度也能得到保留。 6. **部署優(yōu)勢**:AWQ能夠在CPU和GPU硬件上高效部署高性能的4位量化模型,降低內(nèi)存和計(jì)算需求。對于資源受限的邊緣和移動環(huán)境中的LLMs來說,AWQ是理想選擇,因?yàn)樗谛阅芘c低內(nèi)存和計(jì)算開銷之間取得了平衡。AWQ的選擇性權(quán)重縮放方法實(shí)現(xiàn)的效果可與混合精度技術(shù)(例如,將1%的權(quán)重保持為FP16)相媲美,但對于低功耗部署來說,它對硬件更加友好。 ### B. 量化感知訓(xùn)練(QAT) 量化感知訓(xùn)練(QAT)是一種在量化過程中用于提高神經(jīng)網(wǎng)絡(luò)準(zhǔn)確性的技術(shù)。與訓(xùn)練后量化(PTQ)不同,PTQ是在模型訓(xùn)練完成后進(jìn)行量化,而QAT則將量化直接融入訓(xùn)練過程中。這種整合使模型能夠適應(yīng)量化帶來的變化,從而獲得更好的性能。 ![](https://upload-images.jianshu.io/upload_images/17294212-e661327cfee20ad9.png) #### QAT的工作原理 1. **偽量化**:在訓(xùn)練階段,引入“偽”量化。這涉及將權(quán)重量化為較低精度(例如INT4),然后立即將它們反量化回浮點(diǎn)表示(例如FP32)。這使模型能夠在仍以高精度進(jìn)行訓(xùn)練的同時,模擬量化對權(quán)重的影響。 ![](https://upload-images.jianshu.io/upload_images/17294212-9898c26909d462d2.png) 2. **損失計(jì)算**:模型在損失計(jì)算過程中使用這些量化后的權(quán)重,從而了解量化如何影響輸出。通過這樣做,模型調(diào)整其權(quán)重更新,不僅最小化標(biāo)準(zhǔn)損失,還最小化潛在的量化誤差。 3. **探索損失曲面**:QAT旨在在損失曲面中找到“寬”的最小值。寬最小值表示更穩(wěn)定的解決方案,因?yàn)闄?quán)重的小變化不會顯著影響輸出。相比之下,窄最小值可能會導(dǎo)致更大的量化誤差,因?yàn)闄?quán)重的小變化可能會導(dǎo)致模型性能的大幅波動。 4. **與PTQ的比較**:雖然PTQ在高精度(如FP32)下可能會產(chǎn)生較低的損失,但QAT在較低精度格式(如INT4)下實(shí)現(xiàn)較低的損失。這對于將以較低比特精度部署的模型是有益的,確保它們在量化后仍能保持性能。 #### 示例場景 假設(shè)有一個需要對圖像進(jìn)行分類的神經(jīng)網(wǎng)絡(luò)。在QAT過程中,如果模型學(xué)習(xí)到一個在FP32中能有效最小化損失,但在降低到INT4時會引入顯著量化誤差的權(quán)重,QAT會在整個訓(xùn)練過程中幫助調(diào)整該權(quán)重,以避免這個問題。這會產(chǎn)生一個即使在量化后也能有效運(yùn)行的更新權(quán)重。 #### 損失曲面:“寬”與“窄”最小值 損失曲面代表了模型權(quán)重與損失函數(shù)之間的關(guān)系,在量化中起著關(guān)鍵作用。 1. **寬最小值**:損失曲面中的這些區(qū)域具有較淺的斜率,這意味著權(quán)重值的小變化(如量化引入的變化)只會導(dǎo)致?lián)p失的最小增加。寬最小值對量化更具彈性,從而產(chǎn)生較低的量化誤差。 2. **窄最小值**:這些區(qū)域具有陡峭的斜率,即使是微小的權(quán)重變化也會導(dǎo)致?lián)p失的顯著增加。窄最小值對量化更敏感,會導(dǎo)致更高的量化誤差。 ![](https://upload-images.jianshu.io/upload_images/17294212-be4fcf4f5c7612ae.png) 量化感知訓(xùn)練(QAT)通過在反向傳播過程中考慮量化效應(yīng),幫助模型找到這些寬最小值。相比之下,訓(xùn)練后量化(PTQ)在訓(xùn)練過程中不考慮量化,因此如果模型收斂在窄最小值處,可能會導(dǎo)致更高的量化誤差。 ### BitNet:大語言模型1比特量化的時代 #### BitNet簡介 超越常見的4比特量化,BitNet引入了極端量化,僅使用1比特值(即 -1和1)來表示權(quán)重。BitNet通過將量化直接集成到Transformer架構(gòu)(大型語言模型(LLMs)的核心組件)中來實(shí)現(xiàn)這一點(diǎn)。這種方法顯著降低了內(nèi)存需求和計(jì)算開銷,使得在資源受限的設(shè)備上大規(guī)模部署LLMs成為可能。 #### 標(biāo)準(zhǔn)Transformer架構(gòu) 大多數(shù)LLMs都構(gòu)建在Transformer架構(gòu)之上,該架構(gòu)在計(jì)算中嚴(yán)重依賴線性層。這些線性層通常以更高的精度(例如FP16)表示,模型的大部分權(quán)重都存在于此。BitNet對此進(jìn)行了修改,引入了BitLinear層,用1比特值取代了FP16權(quán)重。 #### BitLinear層 BitLinear層的操作與傳統(tǒng)線性層類似,但權(quán)重僅用1比特(-1或1)表示,激活值用INT8表示 。BitLinear在訓(xùn)練期間使用一種“偽”量化來評估權(quán)重和激活量化的效果,類似于量化感知訓(xùn)練(QAT)。 #### BitLinear組件分步解析 1. **權(quán)重量化**:在訓(xùn)練過程中,權(quán)重存儲為INT8值,然后使用符號函數(shù)將其量化為1比特: 這個函數(shù)將權(quán)重分布移動到以零為中心,將零左側(cè)的值賦值為 -1,右側(cè)的值賦值為1。另外還會跟蹤一個值β(權(quán)重的平均絕對值),稍后用于反量化。 ![](https://upload-images.jianshu.io/upload_images/17294212-30beef2ca1bfa5cf.png) 2. **激活量化**:BitLinear采用絕對最大(absmax)量化將FP16激活值轉(zhuǎn)換為INT8,這確保了激活值在矩陣乘法中具有更高的精度。BitLinear還記錄激活值的最高絕對值α,用于反量化步驟。 3. **反量化**:使用α和β,BitNet通過以下縮放因子將激活值反量化回FP16: 這一步將值重新調(diào)整回其原始比例,在保持計(jì)算效率的同時,實(shí)現(xiàn)更準(zhǔn)確的激活值。 #### BitNet向1.58比特量化的轉(zhuǎn)變 雖然最初的BitNet量化僅對權(quán)重使用 -1和1,但BitNet 1.58b版本引入了三進(jìn)制表示:-1、0和1。這個小小的增加(允許權(quán)重也取0值)在計(jì)算效率方面帶來了顯著的改進(jìn)。 #### 1.58比特量化中添加零的好處 1. **簡化矩陣乘法**:在典型的矩陣乘法中,每個權(quán)重都與一個輸入相乘,然后將結(jié)果相加。在1.58比特量化中,矩陣乘法中的權(quán)重可以表示特定的操作: - 1:加上相應(yīng)的值 - 忽略該值 - -1:減去相應(yīng)的值 通過消除不必要的乘法,三進(jìn)制權(quán)重顯著加快了計(jì)算速度,并實(shí)現(xiàn)了更高效的特征過濾。 2. **量化策略:絕對均值量化**:BitNet 1.58b使用絕對均值量化(absmax的一種變體),將權(quán)重分布壓縮在絕對均值(α)附近,然后將權(quán)重量化為 -1、0或1: 與absmax不同,絕對均值量化確保在量化之前壓縮權(quán)重分布,通過減少量化誤差來提高性能。 #### 關(guān)鍵要點(diǎn) 1. **1比特量化**:BitNet的原始方法將權(quán)重簡化為 -1和1,在內(nèi)存使用和計(jì)算能力方面實(shí)現(xiàn)了高效的LLMs。 2. **帶三進(jìn)制權(quán)重的1.58比特量化**:BitNet 1.58b中零的加入使計(jì)算速度更快,因?yàn)槟P涂梢酝耆^某些操作。 3. **縮放優(yōu)勢**:BitNet的效率隨著模型規(guī)模的增長而提高,較大的模型(例如,超過300億個參數(shù))在1比特和FP16量化之間的性能差距更小。 這種新穎的方法使BitNet能夠提供輕量級、延遲優(yōu)化的LLMs。據(jù)作者稱,一個130億參數(shù)的1.58比特精度的BitNet模型在延遲、內(nèi)存和能耗方面,比一個小得多的30億參數(shù)的FP16模型更高效。 ## 本系列文章 >[1. LLM大模型架構(gòu)專欄|| 從NLP基礎(chǔ)談起](https://mp.weixin.qq.com/s/MYx5V29WczQzxPybKBbT7Q?token=516670980&lang=zh_CN) [2.LLM大模型架構(gòu)專欄|| 自然語言處理(NLP)之建模](https://mp.weixin.qq.com/s/Vdk4cmWSnyRhO9MHSotWFQ?token=516670980&lang=zh_CN) [3. LLM大模型架構(gòu)之詞嵌入(Part1)](https://mp.weixin.qq.com/s/V79xObji_6NHt7_CFOtT5A?token=516670980&lang=zh_CN) [4. LLM大模型架構(gòu)之詞嵌入(Part2)](https://mp.weixin.qq.com/s/FqHQN-SqKk2RPhh5CmPKBA?token=516670980&lang=zh_CN) [5. LLM大模型架構(gòu)之詞嵌入(Part3)](https://mp.weixin.qq.com/s/VAkj3UNEcxN3kMXN7xwnYQ?token=1160071256&lang=zh_CN) [6. LLM架構(gòu)從基礎(chǔ)到精通之循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)](https://mp.weixin.qq.com/s/AkQ9ZMmG5-ypY0fd-jEdPg?token=1869920405&lang=zh_CN) [7. LLM架構(gòu)從基礎(chǔ)到精通之LSTM](https://mp.weixin.qq.com/s/TkE9dF_4J7e6l1HMYjC0TQ?token=1869920405&lang=zh_CN) [8. LLM架構(gòu)從基礎(chǔ)到精通之門控循環(huán)單元(GRUs)](https://mp.weixin.qq.com/s/lfo9rLgvIBV-hjcv7lL0JQ?token=458235218&lang=zh_CN) [9. 20000字的注意力機(jī)制講解,全網(wǎng)最全](https://mp.weixin.qq.com/s/zmHyJPVSZA2UcKBTbkpY9g?token=458235218&lang=zh_CN) [10. 深入探究編碼器 - 解碼器架構(gòu):從RNN到Transformer的自然語言處理模型](https://mp.weixin.qq.com/s/ou647Jo8RD6xb7EAoB-aIw?token=458235218&lang=zh_CN) [11. 2w8000字深度解析從RNN到Transformer:構(gòu)建NLP應(yīng)用的架構(gòu)演進(jìn)之路](https://mp.weixin.qq.com/s/9fSaTfrex01GmSfdy9v5_A?token=458235218&lang=zh_CN) 歡迎關(guān)注公眾號 **柏企科技圈** 與**柏企閱文** 如果您有任何問題或建議,歡迎在評論區(qū)留言交流! 本文由[mdnice](https://mdnice.com/?platform=6)多平臺發(fā)布
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容