到詞向量:Embedding層的前向查表與反向訓(xùn)練)
上一篇我們把一段文本切成了 token并且給每個(gè) token 按詞表順序編了個(gè)號(hào)。那會(huì)兒我就在評(píng)論區(qū)看到一批人卡在同一步編號(hào)嘛整數(shù)喂給模型不就完事了但實(shí)際寫(xiě)代碼的時(shí)候你會(huì)發(fā)現(xiàn)模型接受的根本不是整數(shù)本身而是先過(guò)一個(gè)叫 Embedding 的層出來(lái)后每個(gè)編號(hào)都成了一串浮點(diǎn)數(shù)——比如tensor([0.0245, -0.0193, 0.0832, ...])。這就很反直覺(jué)一個(gè) 3怎么突然就有意思了我第一次在調(diào)試大模型中間張量的時(shí)候也對(duì)著屏幕愣了半天。干過(guò)傳統(tǒng)編程的人都知道id 就是 id數(shù)據(jù)庫(kù)里主鍵是 3 不代表比 2 大、比 4 小??傻搅松疃葘W(xué)習(xí)里編號(hào)查完表之后拿出來(lái)的向量竟然能用來(lái)算蘋(píng)果和香蕉的距離甚至能算詞和詞的類(lèi)比關(guān)系。這篇文章就把這件事徹底講透Embedding 到底做了一步什么操作編號(hào)為什么能變成詞向量以及這個(gè)詞向量在大模型里又是怎么被繼續(xù)改造的。1. 先打破一個(gè)直覺(jué)編號(hào)進(jìn) Embedding 層本質(zhì)是查表1.1 前向傳播一個(gè)矩陣行抽取操作先看代碼。PyTorch 里最典型的 Embedding 層長(zhǎng)得這樣import torch import torch.nn as nn # 詞表大小 10000向量維度 64 emb nn.Embedding(num_embeddings10000, embedding_dim64) # 假設(shè)三個(gè) token id ids torch.tensor([3, 17, 892]) vectors emb(ids) print(vectors.shape) # torch.Size([3, 64]) print(vectors)看到?jīng)]輸入是[3, 17, 892]這三個(gè)整數(shù)輸出的形狀是(3, 64)也就是每個(gè)編號(hào)各自拿到了一條 64 維的浮點(diǎn)向量。關(guān)鍵點(diǎn)來(lái)了這個(gè)操作的前向計(jì)算沒(méi)有任何語(yǔ)義理解它就是一次查表。你可以把它完全等價(jià)成下面這行vectors emb.weight[ids]emb.weight的形狀是(10000, 64)也就是一張有 10000 行的表每行是一個(gè) 64 維向量。ids里面的編號(hào) 3、17、892 就當(dāng)成行號(hào)從表里把對(duì)應(yīng)的行抽出來(lái)。所以嚴(yán)格講編號(hào)本身并不是變成了詞向量而是編號(hào)作為一個(gè)索引幫你從 Embedding 矩陣?yán)锇褜?duì)應(yīng)的那一行向量取了出來(lái)。這個(gè)類(lèi)比就像你去學(xué)校檔案室學(xué)生編號(hào)本身是 3 號(hào)、17 號(hào)這些數(shù)字沒(méi)有任何性格、成績(jī)、興趣信息。但管理員拿著編號(hào)去柜子里抽檔案拿到的那份檔案才真正記錄了這個(gè)人是什么樣。Embedding 矩陣就是那個(gè)檔案柜每個(gè) token 編號(hào)背后掛著一份向量檔案。1.2 真正改變向量語(yǔ)義的不是查表是反向傳播如果只是查表那你可能馬上要問(wèn)表里存的那些浮點(diǎn)數(shù)從哪來(lái)一開(kāi)始是什么答案是一開(kāi)始是隨機(jī)數(shù)。nn.Embedding(10000, 64)在你創(chuàng)建它的瞬間權(quán)重矩陣?yán)锏乃兄刀际菑囊粋€(gè)隨機(jī)分布里采出來(lái)的噪聲。你用隨機(jī)初始化的權(quán)重去查表查出來(lái)的向量之間沒(méi)有任何語(yǔ)義關(guān)系——你把蘋(píng)果和火星的編號(hào)拿去查查到的那兩行向量跟扔骰子沒(méi)有區(qū)別。那后面為什么有語(yǔ)義了因?yàn)橛?xùn)練過(guò)程會(huì)反復(fù)修改這張表里每一行的數(shù)值。前向傳播只是取反向傳播才是改。每訓(xùn)練一步模型根據(jù)損失函數(shù)算出梯度然后沿著梯度方向微調(diào)整個(gè) Embedding 矩陣?yán)锏膮?shù)。經(jīng)過(guò)海量文本的反復(fù)更新蘋(píng)果那一行的數(shù)值會(huì)慢慢變得跟香蕉水果等詞的向量相近跟火星的向量相去甚遠(yuǎn)。這里有個(gè)初學(xué)者常犯的誤區(qū)以為 Embedding 層本身帶有什么 NLP 魔法。其實(shí)它就是一個(gè)普通的可學(xué)習(xí)參數(shù)矩陣跟全連接層的權(quán)重矩陣沒(méi)有本質(zhì)區(qū)別。它的語(yǔ)義完全是被訓(xùn)練任務(wù)逼出來(lái)的。2. 為什么不能直接拿編號(hào)當(dāng)數(shù)字獨(dú)熱編碼差在哪2.1 直接喂編號(hào)的致命問(wèn)題既然編號(hào)是整數(shù)為什么不直接把3、17、892當(dāng)成數(shù)值特征喂給模型這樣連 Embedding 層都省了。問(wèn)題出在數(shù)值的序和大小關(guān)系上。編號(hào) 3 和編號(hào) 4 在詞表里相鄰但它倆的語(yǔ)義可能毫無(wú)關(guān)系。比如一個(gè)按字母排序的詞表里3 號(hào)是 about4 號(hào)是 above這倆語(yǔ)義接近還說(shuō)得過(guò)去可如果 892 號(hào)是 apple、893 號(hào)是 abandon 呢中間沒(méi)有任何幾何意義。你要是直接把編號(hào)作為數(shù)值特征模型會(huì)忍不住學(xué)到數(shù)值越大代表某種信號(hào)越強(qiáng)這種關(guān)系。這是神經(jīng)網(wǎng)絡(luò)的天性它看到數(shù)字 100 和 200就會(huì)天然假設(shè) 200 的強(qiáng)度是 100 的兩倍。但 token id 之間根本不存在這種線性關(guān)系。喂原始編號(hào)等于給模型喂了一堆有誤導(dǎo)性的數(shù)值信號(hào)訓(xùn)練會(huì)很難收斂。2.2 分布式表示從工牌號(hào)到性格量表那不用編號(hào)用**獨(dú)熱編碼one-hot encoding**呢這也是很多人第一個(gè)想到的辦法。獨(dú)熱編碼的做法是詞表 10000 個(gè)詞就用 10000 維的向量。每個(gè)詞對(duì)應(yīng)一個(gè)維度這個(gè)詞出現(xiàn)時(shí)那個(gè)維度置 1其余全是 0。比如貓是 3 號(hào)向量就是[0, 0, 1, 0, ..., 0]。這個(gè)方案有兩個(gè)硬傷。第一個(gè)硬傷是維度爆炸。詞表越大向量就越長(zhǎng)。現(xiàn)實(shí)中的大模型詞表動(dòng)輒幾萬(wàn)甚至十幾萬(wàn) token每次都要操作這么稀疏的高維向量存儲(chǔ)和計(jì)算都扛不住。第二個(gè)硬傷更致命任意兩個(gè)不同的獨(dú)熱向量在空間里都是完全正交的余弦相似度永遠(yuǎn)是 0。貓和狗的向量沒(méi)有一絲相似之處貓和火星的向量也沒(méi)有模型完全沒(méi)有辦法從向量本身推斷出任何語(yǔ)義親疏關(guān)系。稠密 Embedding 用的則是另一套思路不搞一個(gè)詞一個(gè)位置的開(kāi)關(guān)式表示而是用一個(gè)固定長(zhǎng)度的稠密實(shí)數(shù)向量來(lái)表示每個(gè)詞每個(gè)維度上都有數(shù)值。你可以把每個(gè)維度理解為模型自己從數(shù)據(jù)里發(fā)現(xiàn)的某種抽象特征——雖然這個(gè)特征具體代表什么人很難說(shuō)清但多個(gè)維度組合起來(lái)就能構(gòu)成一個(gè)詞的多維畫(huà)像。打個(gè)比方獨(dú)熱編碼像工牌號(hào)每個(gè)員工一個(gè)編號(hào)編號(hào)只回答你是誰(shuí)分布式表示像一份性格量表每個(gè)員工在幾個(gè)維度上打分比如外向程度、細(xì)心程度。有了量表就算你沒(méi)見(jiàn)過(guò)這兩個(gè)人也能算出來(lái)他們?cè)谛愿窨臻g里靠得近不近。2.3 獨(dú)熱編碼和稠密向量的定量對(duì)比我把兩種表示擺一起對(duì)比你感受會(huì)更直接對(duì)比項(xiàng)獨(dú)熱編碼稠密 Embedding維度等于詞表大小比如 50000自定常見(jiàn) 128~1024稀疏度極度稀疏99.99% 是 0稠密處處非零詞間相似度任意兩詞相似度恒為 0余弦相似度可比較可學(xué)習(xí)性不可學(xué)習(xí)固定編碼端到端訓(xùn)練更新存儲(chǔ)成本詞表 5 萬(wàn)就要 5 萬(wàn)維5 萬(wàn) x 512 參數(shù)遠(yuǎn)小于前者說(shuō)到底Embedding 就是用可學(xué)習(xí)的稠密低維實(shí)數(shù)向量替代不可學(xué)習(xí)的稀疏高維獨(dú)熱向量。它保留了每個(gè)詞的獨(dú)立身份又給了模型表達(dá)詞與詞之間關(guān)系的手段。這個(gè)思路在深度學(xué)習(xí)里叫分布式表示distributed representation——語(yǔ)義不再由單個(gè)維度獨(dú)立承擔(dān)而是分布在一組維度的組合模式上。3. 語(yǔ)義是訓(xùn)練打磨出來(lái)的梯度如何重塑向量空間3.1 語(yǔ)言學(xué)假設(shè)相似語(yǔ)境等于相似語(yǔ)義現(xiàn)在到了最核心的問(wèn)題Embedding 矩陣?yán)锬且粋€(gè)個(gè)浮點(diǎn)數(shù)是怎么從隨機(jī)噪聲變成能承載語(yǔ)義的結(jié)構(gòu)的這背后有一個(gè)語(yǔ)言學(xué)層面的假設(shè)圈內(nèi)叫分布式假設(shè)distributional hypothesis一個(gè)詞的意思由它經(jīng)常出現(xiàn)的上下文決定。說(shuō)得再直白點(diǎn)如果兩個(gè)詞經(jīng)常出現(xiàn)在相同的語(yǔ)境里那它們的語(yǔ)義大概率是相近的。蘋(píng)果和香蕉都會(huì)出現(xiàn)在我吃了一個(gè)__這個(gè)__很甜水果店里的__這樣的上下文里所以它們應(yīng)該是近義詞或同類(lèi)詞。蘋(píng)果和火星幾乎不會(huì)共享上下文所以它們的距離應(yīng)該很遠(yuǎn)。那怎么把這種直覺(jué)變成一個(gè)可計(jì)算的訓(xùn)練目標(biāo)最經(jīng)典的思路就是 word2vec 里的兩個(gè)任務(wù)Skip-gram 和 CBOW。Skip-gram給你一個(gè)中心詞讓你預(yù)測(cè)它周?chē)鷷?huì)出現(xiàn)哪些詞。CBOW給你周?chē)纳舷挛脑~讓你預(yù)測(cè)中間那個(gè)詞是誰(shuí)。不管哪種本質(zhì)上都是讓模型學(xué)會(huì)一件事利用詞之間的共現(xiàn)關(guān)系預(yù)測(cè)上下文。3.2 訓(xùn)練任務(wù)如何把相鄰詞的向量拉近以 Skip-gram 為例。假設(shè)語(yǔ)料里有一句話(huà)蘋(píng)果 是 一種 非常 好吃 的 水果。我們?nèi)≈行脑~好吃窗口大小設(shè)為 2那么模型的任務(wù)就是看到好吃的向量去預(yù)測(cè)它周?chē)赡艹霈F(xiàn)蘋(píng)果一種非常的這些詞的概率。這個(gè)預(yù)測(cè)過(guò)程不是直接拿好吃的向量去比而是把中心詞向量跟上下文詞的向量分別做點(diǎn)積點(diǎn)積結(jié)果經(jīng)過(guò) softmax 變成概率。模型希望真實(shí)上下文詞的概率盡可能高于是損失函數(shù)會(huì)引導(dǎo)梯度更新——本質(zhì)上是在做一件事把中心詞的向量往真實(shí)上下文詞向量的方向上推同時(shí)把那些沒(méi)有出現(xiàn)的隨機(jī)詞向量往反方向推一點(diǎn)。所以如果一個(gè)詞經(jīng)常和另一堆詞共同出現(xiàn)它們的向量就會(huì)被反復(fù)互相推近。訓(xùn)練幾十萬(wàn)步之后蘋(píng)果和香蕉因?yàn)樯舷挛母叨戎丿B向量空間里自然靠在一起蘋(píng)果和火星因?yàn)樯舷挛暮翢o(wú)交集被推得越來(lái)越遠(yuǎn)。這里我不想堆公式給你講個(gè)直覺(jué)想象你在空曠操場(chǎng)上擺了 5 萬(wàn)張卡片每張卡片是一個(gè)詞。有一個(gè)訓(xùn)練信號(hào)反復(fù)告訴你每次出現(xiàn)蘋(píng)果時(shí)周?chē)鷳?yīng)該站著甜、水果、樹(shù)、汁、紅這些卡片每次看到這堆卡片時(shí)中心位置大概率是蘋(píng)果。你不斷根據(jù)這類(lèi)信號(hào)挪動(dòng)卡片位置最終所有卡片會(huì)自動(dòng)聚類(lèi)成水果類(lèi)聚一堆、動(dòng)物類(lèi)聚一堆、動(dòng)詞類(lèi)聚一堆的布局。你甚至不需要?jiǎng)e人告訴你蘋(píng)果是水果僅憑共現(xiàn)統(tǒng)計(jì)規(guī)律這個(gè)幾何結(jié)構(gòu)自己就冒出來(lái)了。這非常神奇但背后的機(jī)制并不神秘Embedding 向量是訓(xùn)練信號(hào)在參數(shù)空間里留下的痕跡。3.3 大模型依然沿用了這套底層邏輯說(shuō)到大模型很多人會(huì)問(wèn)GPT 這類(lèi)模型又不專(zhuān)門(mén)訓(xùn)練 embedding那它的詞向量靠譜嗎靠譜。因?yàn)榇竽P偷挠?xùn)練任務(wù)是預(yù)測(cè)下一個(gè) token這個(gè)任務(wù)的底層邏輯跟 Skip-gram 是互通的。每次模型看到前文、要預(yù)測(cè)下一個(gè) token 時(shí)它都在隱式地學(xué)習(xí) token 之間的共現(xiàn)規(guī)律。所有 token 的 embedding 參數(shù)都參與了反向傳播一樣會(huì)被海量語(yǔ)料反復(fù)打磨。區(qū)別在于大模型的輸入 Embedding 只是第一層后面還有幾十層 Transformer 會(huì)繼續(xù)改寫(xiě)這些向量。但作為起點(diǎn)的 Embedding 層本身早就在訓(xùn)練中形成了非常豐富的靜態(tài)語(yǔ)義結(jié)構(gòu)。你可以把它理解為大模型的 Embedding 層是一本靜態(tài)詞典Transformer 層則在這本詞典的基礎(chǔ)上根據(jù)當(dāng)前上下文再做動(dòng)態(tài)調(diào)節(jié)。4. 大模型里的 Embedding 遠(yuǎn)比查表復(fù)雜從靜態(tài)向量到上下文表征4.1 編號(hào)對(duì)應(yīng)的是 token 而不是詞先把概念捋一下在大模型里你分配編號(hào)的對(duì)象嚴(yán)格來(lái)說(shuō)不是詞而是 token。token 可能是完整的詞比如 apple可能是詞根比如 un可能是標(biāo)點(diǎn)甚至可能是單個(gè)字符。所以更準(zhǔn)確的說(shuō)法是大模型學(xué)到的叫token embedding不是傳統(tǒng)意義上的 word embedding。這帶來(lái)一個(gè)很實(shí)際的影響一個(gè)單詞可能被拆成好幾個(gè) token每個(gè) token 單獨(dú)編號(hào)、單獨(dú)有向量。比如 unbelievable 可能被切成 un、believ、able。那它的語(yǔ)義就不存在單一向量里而是由這幾個(gè) token 組合表達(dá)。這就解釋了為什么大模型的詞表里經(jīng)常能看到奇怪的 ##able 這種條目——那是子詞 token不是完整詞。4.2 位置編碼和 Transformer 改造編號(hào)過(guò)了 Embedding 層拿到初始向量之后接著還要做一件事加位置信息。如果沒(méi)有位置編碼蘋(píng)果 吃 了 和 吃了 蘋(píng)果 這兩句的輸入向量序列是完全一樣的模型無(wú)法區(qū)分蘋(píng)果在第一個(gè)位置還是第三個(gè)位置。所以 Transformer 架構(gòu)會(huì)給每個(gè)位置的向量注入位置信息常見(jiàn)的有絕對(duì)位置編碼、相對(duì)位置編碼或者是旋轉(zhuǎn)位置編碼RoPE這類(lèi)更現(xiàn)代的做法。做完這些之后向量序列才進(jìn)入 Transformer 層。每一層里每個(gè) token 的向量都會(huì)經(jīng)過(guò)注意力機(jī)制去看序列里其他 token 的向量然后更新自己的值。注意這里有本質(zhì)變化Embedding 層查出來(lái)的初始向量是固定的、與上下文無(wú)關(guān)的但經(jīng)過(guò) Transformer 之后每個(gè) token 的最終向量是隨著上下文動(dòng)態(tài)變化的。NLP 界有個(gè)經(jīng)典例子word2vec 學(xué)到的 bank 只有一個(gè)向量不管是河岸還是銀行都用它但在 BERT 里bank 出現(xiàn)在 river bank 和 central bank 兩條句子里時(shí)最終向量是完全不同的。這就是靜態(tài) embedding 和上下文 embeddingcontextualized embedding的區(qū)別。4.3 想檢查理解程度該看哪一層如果你要排查大模型經(jīng)常會(huì)遇到一個(gè)困惑到底該把哪一層的輸出叫embedding我的經(jīng)驗(yàn)是分場(chǎng)景要看基礎(chǔ)的詞義結(jié)構(gòu)看輸入 Embedding 層的輸出就夠了。它反映的是靜態(tài)語(yǔ)義。要看模型在具體語(yǔ)境下的理解得看最后一層或倒數(shù)幾層的輸出。那里面包含了對(duì)整個(gè)句子的上下文建模結(jié)果。很多向量檢索系統(tǒng)、RAG 應(yīng)用里說(shuō)的把文本編碼成向量通常指的不是第一層 Embedding而是模型輸出的語(yǔ)義向量比如 CLS 位置或最后一層的平均池化。兩者差距很大別搞混。還有一個(gè)高維向量經(jīng)常被誤解的點(diǎn)768 維甚至 4096 維的向量并不是這個(gè)詞有 768 種意思每維對(duì)應(yīng)一種。真實(shí)情況是模型學(xué)出來(lái)的每個(gè)維度本身很難用人能理解的方式解釋語(yǔ)義是散在整體方向上的。這就像你沒(méi)辦法單獨(dú)指著紅酒果香維度的某一個(gè)物理量說(shuō)它代表什么但兩個(gè)酒的多維輪廓一比較相似度就出來(lái)了。5. 自己動(dòng)手三種方式驗(yàn)證 Embedding 里藏了什么理論講再多不如自己上手看一眼。你不需要完整訓(xùn)練一個(gè)大模型隨便拿一個(gè)預(yù)訓(xùn)練好的 embedding 文件或者訓(xùn)練一個(gè)小模型就能做這三件事。5.1 降維可視化看詞聚類(lèi)第一步把高維向量降維到二維平面肉眼觀察詞的分布。常用工具是 t-SNE 或 UMAP。import numpy as np from sklearn.manifold import TSNE import matplotlib.pyplot as plt # 假設(shè) vectors 是詞向量矩陣shape(N, dim) # 先抽一批高頻詞別全量跑 indices np.arange(0, 1000) embedding_subset vectors[indices] tsne TSNE(n_components2, random_state42, perplexity30) coords tsne.fit_transform(embedding_subset) for i, (x, y) in enumerate(coords): plt.scatter(x, y, s5) plt.annotate(vocab[indices[i]], (x, y), fontsize8) plt.show()跑完你會(huì)發(fā)現(xiàn)非常直觀數(shù)字類(lèi)聚在一邊顏色類(lèi)聚在一邊食物類(lèi)聚在一邊。如果訓(xùn)練語(yǔ)料足夠大、質(zhì)量足夠好甚至可以觀察到男女性別詞沿著同一方向分開(kāi)排列。這個(gè)幾何結(jié)構(gòu)就是語(yǔ)義相似度的可視化證明。實(shí)操細(xì)節(jié)t-SNE 全量跑幾萬(wàn)詞會(huì)非常慢先隨機(jī)抽 1000~2000 個(gè)詞子集perplexity 一般取 15~50太小會(huì)顯得聚成一團(tuán)太大結(jié)構(gòu)又會(huì)被打散。5.2 余弦相似度查最近鄰可視化適合宏觀觀察最近鄰檢索則適合具體驗(yàn)證某個(gè)詞的朋友圈。import numpy as np # vecs: (N, dim) 已歸一化 # target_idx: 要查的詞 query vecs[target_idx] sims vecs query # 如果向量都是 L2 歸一化的點(diǎn)積等價(jià)余弦相似度 top_indices np.argsort(sims)[::-1][1:11] # 排除自己 for idx in top_indices: print(vocab[idx], sims[idx])我拿一個(gè)小語(yǔ)料訓(xùn)練過(guò)的 embedding 做過(guò)實(shí)驗(yàn)查 dog前幾位往往是 cat, pet, puppy, leash查 beautiful出現(xiàn)的是 gorgeous, lovely, pretty, wonderful。這種結(jié)果真的會(huì)讓人有種模型是不是懂點(diǎn)事的錯(cuò)覺(jué)。補(bǔ)充一個(gè)經(jīng)驗(yàn)小語(yǔ)料幾 MB 文本訓(xùn)練出來(lái)的 embedding 一般不太干凈最近鄰里會(huì)混入很多噪聲。如果你看到 beautiful 的最近鄰是 page 這種完全不搭邊的詞別懷疑代碼就是訓(xùn)練數(shù)據(jù)太少、共現(xiàn)統(tǒng)計(jì)不夠。5.3 詞類(lèi)比運(yùn)算測(cè)試這是 word2vec 時(shí)期最有名的玩法vector(king) - vector(man) vector(woman) ≈ vector(queen)。原理不復(fù)雜因?yàn)橛?xùn)練好的向量空間里國(guó)王和王后的差異方向跟男人和女人的差異方向基本一致所以做一次向量加減法得到的結(jié)果應(yīng)該落在queen附近。result_vec vectors[king_idx] - vectors[man_idx] vectors[woman_idx] # 然后拿 result_vec 和全詞表做余弦相似度檢索 # 如果一切正常排名第一的應(yīng)該是 queen在大模型那種超大詞表里這個(gè)測(cè)試有時(shí)候會(huì)失效因?yàn)?token 切分和上下文建模會(huì)改變很多細(xì)節(jié)。但在中小規(guī)模 embedding 上進(jìn)行這個(gè)檢驗(yàn)仍然是判斷語(yǔ)義質(zhì)量的好方法。如果連這類(lèi)簡(jiǎn)單的類(lèi)比結(jié)構(gòu)都沒(méi)學(xué)出來(lái)你基本可以斷定語(yǔ)料量不夠或者訓(xùn)練不充分。6. 實(shí)操中容易踩的六個(gè) Embedding 坑最后說(shuō)說(shuō)我在實(shí)際項(xiàng)目里積累的一些教訓(xùn)。這些坑教科書(shū)上很少寫(xiě)但幾乎每個(gè)人都會(huì)踩一遍??右籩mbedding_dim 寧小勿大。向量維度不是越大越好。維度越高Embedding 層的參數(shù)量就越大詞表大小 × 維度在小數(shù)據(jù)集上特別容易過(guò)擬合。通用經(jīng)驗(yàn)中小語(yǔ)料用 128~256大規(guī)模預(yù)訓(xùn)練模型用 768 起步。你要是拿 20 萬(wàn)條數(shù)據(jù)去訓(xùn)一個(gè)維度 4096 的 embedding大概率訓(xùn)出一堆噪聲??佣还潭S機(jī)種子復(fù)現(xiàn)不出來(lái)。由于 Embedding 矩陣是隨機(jī)初始化的哪怕你數(shù)據(jù)、代碼完全一樣不設(shè)隨機(jī)種子跑兩次最終向量也有差異。調(diào)參階段務(wù)必設(shè)置random.seed、np.random.seed、torch.manual_seed有 GPU 還要額外設(shè)置torch.cuda.manual_seed_all。我見(jiàn)過(guò)有人兩天前跑出一個(gè)很好的結(jié)果隔天換了臺(tái)機(jī)器復(fù)現(xiàn)不出來(lái)最后發(fā)現(xiàn)是 embedding 初始化不同造成的??尤⒄{(diào)時(shí)凍結(jié)還是更新 Embedding要想清楚。如果你用預(yù)訓(xùn)練 embedding 做下游任務(wù)、數(shù)據(jù)量又少建議凍結(jié) Embedding 層省顯存、防過(guò)擬合。如果任務(wù)領(lǐng)域跟預(yù)訓(xùn)練語(yǔ)料差異極大比如預(yù)訓(xùn)練語(yǔ)料是通用文本下游是一堆專(zhuān)業(yè)術(shù)語(yǔ)可以考慮解凍并微調(diào)讓模型吸收領(lǐng)域信息。折中方案用較低的學(xué)習(xí)率微調(diào) Embedding??铀挠?jì)算相似度前先歸一化。高維向量用歐氏距離容易受向量模長(zhǎng)影響而模型學(xué)習(xí)到的模長(zhǎng)往往跟詞頻有關(guān)系——高頻詞模長(zhǎng)偏大低頻詞偏小。比較語(yǔ)義相似度優(yōu)先用余弦相似度計(jì)算前先對(duì)向量做 L2 歸一化。做向量檢索系統(tǒng)時(shí)同樣建議統(tǒng)一歸一化否則召回質(zhì)量波動(dòng)很大??游錙OV詞表外詞的處理。模型訓(xùn)練時(shí)詞表是封閉的推理時(shí)碰到完全沒(méi)見(jiàn)過(guò)的新詞分詞器會(huì)切成更小的 token 或子詞盡量繞開(kāi)完全無(wú)向量可用的局面。如果你在維護(hù)自己的詞表遇到真正的新 token常見(jiàn)做法是隨機(jī)初始化一個(gè)向量或者取已有近義詞向量的平均值做初始化。直接全零初始化要謹(jǐn)慎零向量在空間里會(huì)變成所有詞的公共鄰居檢索時(shí)容易出奇怪結(jié)果??恿斎?embedding 和輸出層權(quán)重共享的問(wèn)題。不少 Transformer 架構(gòu)里輸入 Embedding 矩陣和最后的輸出 softmax 投影是同一個(gè)權(quán)重矩陣這叫 weight tying。好處是省參數(shù)量、訓(xùn)練更穩(wěn)。但如果你手動(dòng)微調(diào)模型改了輸入 Embedding 的權(quán)重輸出投影會(huì)同步變化反過(guò)來(lái)也一樣。調(diào)試時(shí)別以為它倆是兩個(gè)獨(dú)立副本否則會(huì)白排查很久。寫(xiě)到這里Embedding 從編號(hào)到詞向量的最后一層窗戶(hù)紙也應(yīng)該捅破了。它的本質(zhì)就三句話(huà)前向是一次查表反向是不斷改寫(xiě)表格內(nèi)容表格里的每一行最終被訓(xùn)練成了語(yǔ)義空間里的一個(gè)坐標(biāo)點(diǎn)。從我個(gè)人的實(shí)操體驗(yàn)來(lái)說(shuō)做模型調(diào)試時(shí)間長(zhǎng)了你會(huì)發(fā)現(xiàn)幾乎所有跟語(yǔ)義沾邊的問(wèn)題——任務(wù)遷移、檢索排序、模型泛化——追根溯源都會(huì)落到向量空間的結(jié)構(gòu)上。所以這一步基礎(chǔ)打牢后面玩大模型會(huì)順很多。