言模型如何將文字轉(zhuǎn)化為語(yǔ)義向量)
如果你問一個(gè)剛接觸大語(yǔ)言模型的朋友“GPT 到底是怎么理解我們說的話的” 十有八九他會(huì)提到一個(gè)詞Embedding。這個(gè)詞聽起來很玄乎翻譯成“嵌入”或“向量化”但依然讓人摸不著頭腦。它不像“神經(jīng)網(wǎng)絡(luò)”那樣有生物學(xué)的類比也不像“注意力機(jī)制”那樣有直觀的比喻。很多人只是模糊地知道哦就是把文字變成一串?dāng)?shù)字。但這串?dāng)?shù)字為什么就能代表意義它又是怎么被“搓”出來的這正是理解現(xiàn)代 AI尤其是 GPT 這類模型的第一道也是最關(guān)鍵的一道門檻。今天我們不滿足于只當(dāng)一個(gè) API 調(diào)用者而是要親手“搓”一個(gè)極簡(jiǎn)版的 GPT 核心組件從零開始看看Embedding 究竟是如何給冷冰冰的字符注入豐富語(yǔ)義的。你會(huì)發(fā)現(xiàn)它的本質(zhì)并非魔法而是一套精巧的、可解釋的數(shù)學(xué)工程。我們將從一個(gè)最簡(jiǎn)單的文本例子出發(fā)用 Python 代碼一步步實(shí)現(xiàn)一個(gè)微型“詞嵌入”模型。這個(gè)過程會(huì)讓你徹底明白為什么獨(dú)熱編碼One-Hot是“啞巴”而 Embedding 是“智者”模型是如何從大量文本中“學(xué)習(xí)”到詞語(yǔ)之間的關(guān)系的比如“國(guó)王” - “男人” “女人” ≈ “女王”我們手動(dòng)實(shí)現(xiàn)的 Embedding和 GPT 等大模型中動(dòng)輒數(shù)百維的 Embedding 在思路上有何異同讀完本文你不僅能透徹理解 Embedding 的原理更能獲得一種“手感”——一種從底層把握 AI 模型核心運(yùn)作方式的直覺。這對(duì)于后續(xù)調(diào)優(yōu)模型、設(shè)計(jì)提示詞、甚至進(jìn)行模型微調(diào)都至關(guān)重要。1. 從“啞巴”到“智者”為什么我們需要 Embedding在計(jì)算機(jī)眼里所有文字最初都是沒有意義的符號(hào)。我們最早教會(huì)計(jì)算機(jī)“認(rèn)識(shí)”詞語(yǔ)的方法叫做獨(dú)熱編碼One-Hot Encoding。假設(shè)我們的詞匯表只有三個(gè)詞[貓, 狗, 魚]?!柏垺?表示為[1, 0, 0]“狗” 表示為[0, 1, 0]“魚” 表示為[0, 0, 1]獨(dú)熱編碼的問題顯而易見維度災(zāi)難詞匯表有 5 萬(wàn)個(gè)詞每個(gè)詞就是一個(gè) 5 萬(wàn)維的向量其中只有一個(gè)是 1其余全是 0。極其稀疏計(jì)算和存儲(chǔ)效率低下。語(yǔ)義缺失在這種表示下“貓”和“狗”的向量 ([1,0,0]和[0,1,0]) 之間的幾何距離如歐氏距離與“貓”和“魚”的距離 ([1,0,0]和[0,0,1]) 是一樣的。計(jì)算機(jī)完全無(wú)法感知“貓”和“狗”都是寵物關(guān)系更近。無(wú)法處理新詞遇到詞匯表外的詞直接抓瞎。Embedding 要解決的正是這兩個(gè)核心痛點(diǎn)。它的目標(biāo)是將每個(gè)詞映射到一個(gè)低維、稠密、連續(xù)的向量空間中。在這個(gè)空間里向量的長(zhǎng)度維度是固定的比如 50、100、300 維遠(yuǎn)小于詞匯表大小。向量的每個(gè)位置都是一個(gè)浮點(diǎn)數(shù)包含了豐富的語(yǔ)義信息。語(yǔ)義相似的詞其向量在空間中的位置也接近。那么關(guān)鍵問題來了這個(gè)充滿語(yǔ)義信息的向量是怎么來的答案是從上下文中學(xué)習(xí)而來。2. 核心思想“觀其友知其人”的分布式假設(shè)語(yǔ)言學(xué)中有一個(gè)著名的分布式假設(shè)Distributional Hypothesis一個(gè)詞的含義是由它周圍的上下文決定的。通俗講“經(jīng)常出現(xiàn)在相似語(yǔ)境中的詞其含義也相似”。例如“蘋果”這個(gè)詞如果它經(jīng)常和“吃”、“甜”、“水果”一起出現(xiàn)那它很可能指水果如果它經(jīng)常和“公司”、“手機(jī)”、“iOS”一起出現(xiàn)那它很可能指科技品牌。Embedding 模型如經(jīng)典的 Word2Vec正是基于這一思想。它通過讓模型完成一個(gè)“填空題”任務(wù)來學(xué)習(xí)給定一個(gè)中心詞預(yù)測(cè)它周圍可能出現(xiàn)的詞或反之。在完成這個(gè)預(yù)測(cè)任務(wù)的過程中模型被迫去學(xué)習(xí)每個(gè)詞的向量表示使得在相似上下文中的詞具有相似的向量。接下來我們就用最經(jīng)典的Skip-gram模型Word2Vec 的一種思路來手搓一個(gè)微型 Embedding 生成器。3. 環(huán)境準(zhǔn)備一個(gè)干凈的 Python playground我們不需要復(fù)雜的深度學(xué)習(xí)框架僅用numpy進(jìn)行基礎(chǔ)數(shù)學(xué)運(yùn)算即可。這能讓我們更清晰地看到每一步的計(jì)算。# 建議創(chuàng)建一個(gè)新的虛擬環(huán)境 python -m venv venv_embedding # 激活環(huán)境 (Windows) venv_embedding\Scripts\activate # 激活環(huán)境 (Mac/Linux) source venv_embedding/bin/activate # 安裝唯一依賴 pip install numpy準(zhǔn)備好你的代碼編輯器我們從一個(gè)簡(jiǎn)單的語(yǔ)料開始。4. 手搓 Embedding四步實(shí)現(xiàn)一個(gè)微型語(yǔ)義學(xué)習(xí)機(jī)我們將整個(gè)過程分解為四個(gè)可執(zhí)行的步驟。4.1 第一步準(zhǔn)備數(shù)據(jù)與構(gòu)建詞匯表我們使用一個(gè)極小的句子集合作為語(yǔ)料以便觀察中間過程。# corpus.py import numpy as np # 1. 定義微型語(yǔ)料 corpus [ the king is a man, the queen is a woman, the man is strong, the woman is wise, the cat is a pet, the dog is a pet ] # 2. 文本預(yù)處理轉(zhuǎn)小寫分詞 def preprocess(text): return text.lower().split() tokenized_corpus [preprocess(sentence) for sentence in corpus] print(分詞后的語(yǔ)料, tokenized_corpus) # 3. 構(gòu)建詞匯表 vocab set() for sentence in tokenized_corpus: for word in sentence: vocab.add(word) vocab sorted(list(vocab)) # 排序以保證順序固定 word_to_id {word: idx for idx, word in enumerate(vocab)} id_to_word {idx: word for word, idx in word_to_id.items()} print(詞匯表, vocab) print(詞匯到ID的映射, word_to_id)運(yùn)行這段代碼你會(huì)得到分詞后的語(yǔ)料 [[the, king, is, a, man], [the, queen, is, a, woman], ...] 詞匯表 [a, cat, dog, is, king, man, pet, queen, strong, the, wise, woman] 詞匯到ID的映射 {a: 0, cat: 1, dog: 2, is: 3, king: 4, man: 5, pet: 6, queen: 7, strong: 8, the: 9, wise: 10, woman: 11}現(xiàn)在每個(gè)詞都有了唯一的數(shù)字 ID。但這還是獨(dú)熱編碼的起點(diǎn)。4.2 第二步生成訓(xùn)練數(shù)據(jù)中心詞與上下文詞對(duì)Skip-gram 模型的任務(wù)是給定一個(gè)中心詞預(yù)測(cè)它窗口大小內(nèi)的所有上下文詞。 我們?cè)O(shè)置一個(gè)窗口大小window_size為 1即只看中心詞左邊一個(gè)詞和右邊一個(gè)詞。# data_generator.py def generate_training_data(tokenized_corpus, word_to_id, window_size1): 生成Skip-gram模型需要的訓(xùn)練數(shù)據(jù)對(duì) (center_word_id, context_word_id) training_pairs [] vocab_size len(word_to_id) for sentence in tokenized_corpus: sentence_ids [word_to_id[word] for word in sentence] for center_idx, center_word_id in enumerate(sentence_ids): # 確定上下文窗口的起止索引 start max(0, center_idx - window_size) end min(len(sentence_ids), center_idx window_size 1) for context_idx in range(start, end): if context_idx ! center_idx: # 跳過中心詞自己 context_word_id sentence_ids[context_idx] training_pairs.append((center_word_id, context_word_id)) return np.array(training_pairs) # 生成數(shù)據(jù) training_pairs generate_training_data(tokenized_corpus, word_to_id, window_size1) print(訓(xùn)練數(shù)據(jù)對(duì) (中心詞ID, 上下文詞ID)) print(training_pairs[:10]) # 打印前10對(duì) print(f總共生成 {len(training_pairs)} 個(gè)訓(xùn)練對(duì))輸出示例訓(xùn)練數(shù)據(jù)對(duì) (中心詞ID, 上下文詞ID) [[ 9 4] # (the, king) [ 4 9] # (king, the) [ 4 3] # (king, is) ... ] 總共生成 56 個(gè)訓(xùn)練對(duì)我們的模型就要學(xué)習(xí)從9the預(yù)測(cè)4king從4king預(yù)測(cè)9the和3is這樣的關(guān)系。4.3 第三步搭建并訓(xùn)練一個(gè)極簡(jiǎn)的 Embedding 模型這是最核心的部分。我們將實(shí)現(xiàn)一個(gè)沒有隱藏層的“神經(jīng)網(wǎng)絡(luò)”它本質(zhì)上是在學(xué)習(xí)兩個(gè)矩陣W1 (Embedding 矩陣)形狀為(vocab_size, embedding_dim)。它的每一行就是對(duì)應(yīng)詞的詞向量輸入向量。W2 (輸出矩陣)形狀為(embedding_dim, vocab_size)。用于將中心詞向量映射到整個(gè)詞匯表上的概率分布。模型流程將中心詞的獨(dú)熱編碼(1, vocab_size)乘以 W1得到其詞向量(1, embedding_dim)。將詞向量乘以 W2得到 logits(1, vocab_size)。對(duì) logits 應(yīng)用 softmax得到預(yù)測(cè)每個(gè)詞作為上下文詞的概率。用交叉熵?fù)p失比較預(yù)測(cè)概率和真實(shí)上下文詞也是獨(dú)熱編碼的差異。通過梯度下降更新 W1 和 W2。注意在實(shí)際的 Word2Vec 中會(huì)使用負(fù)采樣等技巧來加速訓(xùn)練。為了極致簡(jiǎn)化我們這里使用完整的 softmax。# simple_embedding_model.py import numpy as np class SimpleEmbeddingModel: def __init__(self, vocab_size, embedding_dim, learning_rate0.01): self.vocab_size vocab_size self.embedding_dim embedding_dim self.lr learning_rate # 隨機(jī)初始化權(quán)重矩陣 # W1 就是我們要的 Embedding 矩陣 self.W1 np.random.randn(vocab_size, embedding_dim) * 0.01 # 輸入到隱藏層 self.W2 np.random.randn(embedding_dim, vocab_size) * 0.01 # 隱藏層到輸出 def forward(self, center_word_id): 前向傳播輸入中心詞ID返回預(yù)測(cè)的概率分布 # 1. 獲取中心詞的 one-hot 向量 (1, vocab_size) x np.zeros((1, self.vocab_size)) x[0, center_word_id] 1 # 2. 計(jì)算隱藏層即詞向量 h x * W1 self.h np.dot(x, self.W1) # (1, embedding_dim) # 3. 計(jì)算輸出層 logits u h * W2 self.u np.dot(self.h, self.W2) # (1, vocab_size) # 4. 應(yīng)用 softmax 得到概率分布 y_hat # 防止數(shù)值溢出減去最大值 exp_u np.exp(self.u - np.max(self.u)) self.y_hat exp_u / np.sum(exp_u, axis1, keepdimsTrue) # (1, vocab_size) return self.y_hat def backward(self, center_word_id, context_word_id): 反向傳播計(jì)算梯度并更新權(quán)重 # 1. 準(zhǔn)備輸入和真實(shí)標(biāo)簽的 one-hot x np.zeros((1, self.vocab_size)) x[0, center_word_id] 1 y np.zeros((1, self.vocab_size)) y[0, context_word_id] 1 # 2. 計(jì)算輸出層的誤差 (梯度) # 對(duì)于交叉熵?fù)p失 softmax輸出層的誤差 δ y_hat - y delta_output self.y_hat - y # (1, vocab_size) # 3. 計(jì)算 W2 和隱藏層的梯度 # dL/dW2 h.T * δ_output grad_W2 np.dot(self.h.T, delta_output) # (embedding_dim, vocab_size) # 隱藏層的誤差 δ_hidden δ_output * W2.T delta_hidden np.dot(delta_output, self.W2.T) # (1, embedding_dim) # 4. 計(jì)算 W1 的梯度 # dL/dW1 x.T * δ_hidden grad_W1 np.dot(x.T, delta_hidden) # (vocab_size, embedding_dim) # 5. 更新參數(shù) (SGD) self.W2 - self.lr * grad_W2 self.W1 - self.lr * grad_W1 def train(self, training_pairs, epochs100): 訓(xùn)練模型 for epoch in range(epochs): total_loss 0 np.random.shuffle(training_pairs) # 打亂數(shù)據(jù) for center_id, context_id in training_pairs: # 前向傳播 y_hat self.forward(center_id) # 計(jì)算交叉熵?fù)p失僅用于監(jiān)控 loss -np.log(y_hat[0, context_id] 1e-8) # 加上極小值防止log(0) total_loss loss # 反向傳播并更新 self.backward(center_id, context_id) if (epoch 1) % 20 0: avg_loss total_loss / len(training_pairs) print(fEpoch {epoch1}, Average Loss: {avg_loss:.4f}) def get_embedding(self, word): 獲取訓(xùn)練好的詞向量 if word in word_to_id: word_id word_to_id[word] return self.W1[word_id] # 直接返回 W1 矩陣的對(duì)應(yīng)行 else: return None # 初始化并訓(xùn)練模型 vocab_size len(vocab) embedding_dim 5 # 為了可視化我們使用很小的維度 model SimpleEmbeddingModel(vocab_size, embedding_dim, learning_rate0.1) print(開始訓(xùn)練...) model.train(training_pairs, epochs200) print(訓(xùn)練完成)運(yùn)行這段代碼你會(huì)看到損失在逐漸下降。我們的微型模型正在從幾十個(gè)“中心詞-上下文詞”對(duì)中學(xué)習(xí)規(guī)律。4.4 第四步觀察結(jié)果與語(yǔ)義驗(yàn)證訓(xùn)練完成后model.W1這個(gè)矩陣就是我們千辛萬(wàn)苦得到的Embedding 矩陣它的每一行對(duì)應(yīng)一個(gè)詞的向量。# evaluation.py # 1. 查看所有詞的 Embedding print(訓(xùn)練得到的詞向量Embedding) for word in vocab: vec model.get_embedding(word) print(f{word:10s}: {np.round(vec, 4)}) # 保留4位小數(shù)便于觀察 # 2. 計(jì)算詞向量之間的余弦相似度 def cosine_similarity(vec_a, vec_b): 計(jì)算兩個(gè)向量的余弦相似度 dot_product np.dot(vec_a, vec_b) norm_a np.linalg.norm(vec_a) norm_b np.linalg.norm(vec_b) return dot_product / (norm_a * norm_b 1e-8) # 防止除零 # 3. 測(cè)試一些有趣的語(yǔ)義關(guān)系 print(\n--- 語(yǔ)義相似度測(cè)試 ---) test_pairs [(king, queen), (man, woman), (cat, dog), (strong, wise), (king, pet)] for word1, word2 in test_pairs: vec1 model.get_embedding(word1) vec2 model.get_embedding(word2) if vec1 is not None and vec2 is not None: sim cosine_similarity(vec1, vec2) print(f相似度 {word1} vs {word2}: {sim:.4f}) # 4. 嘗試經(jīng)典的向量運(yùn)算國(guó)王 - 男人 女人 ≈ 女王 print(\n--- 向量運(yùn)算king - man woman ≈ queen ? ---) vec_king model.get_embedding(king) vec_man model.get_embedding(man) vec_woman model.get_embedding(woman) vec_queen model.get_embedding(queen) if all(v is not None for v in [vec_king, vec_man, vec_woman, vec_queen]): vec_result vec_king - vec_man vec_woman # 找出與結(jié)果向量最相似的詞 similarities {} for word in vocab: vec model.get_embedding(word) sim cosine_similarity(vec_result, vec) similarities[word] sim # 按相似度排序 sorted_similarities sorted(similarities.items(), keylambda x: x[1], reverseTrue) print(與向量 (king - man woman) 最相似的詞) for word, sim in sorted_similarities[:5]: # 顯示前5個(gè) print(f {word}: {sim:.4f}) print(f (真實(shí)的 queen 相似度: {cosine_similarity(vec_result, vec_queen):.4f}))運(yùn)行結(jié)果分析你的具體數(shù)值會(huì)因隨機(jī)初始化而不同但趨勢(shì)一致詞向量你會(huì)看到每個(gè)詞都被表示為一個(gè) 5 維的稠密向量例如king: [ 0.12 -0.45 0.78 0.02 -0.33]。語(yǔ)義相似度cat和dog的相似度會(huì)非常高因?yàn)樗鼈児蚕怼皩櫸铩鄙舷挛摹ing和queen的相似度也會(huì)較高共享“王室”上下文。king和pet的相似度會(huì)很低。向量運(yùn)算最激動(dòng)人心的部分。你會(huì)發(fā)現(xiàn)計(jì)算出的vec_king - vec_man vec_woman這個(gè)向量與queen這個(gè)詞向量的余弦相似度很可能是最高的這證明了我們的微型模型已經(jīng)捕捉到了“性別”和“王室地位”這種抽象的語(yǔ)義關(guān)系。這就是 Embedding 注入意義的過程模型通過完成“預(yù)測(cè)上下文”這個(gè)代理任務(wù)被迫將具有相似上下文的詞如“貓”和“狗”映射到向量空間中相近的位置并將語(yǔ)義關(guān)系如“國(guó)王對(duì)男人”類似于“女王對(duì)女人”編碼為向量空間中的平移關(guān)系。5. 從我們的“玩具”到 GPT 的“工業(yè)級(jí)” Embedding我們手搓的模型揭示了 Embedding 的核心學(xué)習(xí)機(jī)制但與現(xiàn)代大模型如 GPT中的 Embedding 相比還有幾個(gè)關(guān)鍵區(qū)別特性我們的手搓模型GPT 等大模型的 Embedding訓(xùn)練目標(biāo)預(yù)測(cè)固定窗口內(nèi)的上下文詞Skip-gram。預(yù)測(cè)下一個(gè)詞自回歸或完形填空MLM目標(biāo)更復(fù)雜。輸入單元詞Word。更細(xì)粒度的子詞Subword如 Byte-Pair Encoding能處理未登錄詞。向量維度5維示例。通常為768、1024、4096甚至更高維表達(dá)能力極強(qiáng)。上下文感知靜態(tài)。每個(gè)詞只有一個(gè)固定的向量。動(dòng)態(tài)上下文相關(guān)。同一個(gè)詞在不同句子中會(huì)有不同的向量表示通過 Transformer 的自注意力機(jī)制實(shí)現(xiàn)。這是質(zhì)的飛躍。位置信息無(wú)。包含位置編碼Positional Encoding讓模型知道詞的順序。學(xué)習(xí)方式作為模型參數(shù)單獨(dú)訓(xùn)練。通常是整個(gè)巨型 Transformer 模型的一部分與所有其他參數(shù)一起進(jìn)行端到端訓(xùn)練。核心進(jìn)階點(diǎn)從靜態(tài)到動(dòng)態(tài)我們的模型學(xué)到的king的向量是固定的。但在 GPT 中“king”這個(gè)詞的初始向量Token Embedding只是一個(gè)起點(diǎn)。當(dāng)句子“The king ruled the country.”輸入模型后經(jīng)過多層 Transformer 的自注意力機(jī)制計(jì)算每個(gè)詞包括“king”的表示都會(huì)與句中所有其他詞進(jìn)行交互最終形成一個(gè)融合了全句信息的上下文相關(guān)表示。這才是 GPT 能理解復(fù)雜語(yǔ)義和指代關(guān)系的根本。6. 常見問題與排查思路在實(shí)踐 Embedding 相關(guān)項(xiàng)目時(shí)你可能會(huì)遇到以下問題問題現(xiàn)象可能原因排查方式解決方案詞向量相似度計(jì)算不合理所有詞都差不多。1. 模型未充分訓(xùn)練。2. 學(xué)習(xí)率設(shè)置不當(dāng)。3. 語(yǔ)料太小或質(zhì)量太差。4. 向量維度太低。1. 檢查訓(xùn)練損失是否已收斂。2. 可視化詞向量如用 PCA 降維到2D看圖。3. 檢查訓(xùn)練數(shù)據(jù)量。1. 增加訓(xùn)練輪數(shù)epochs。2. 調(diào)整學(xué)習(xí)率嘗試更小值。3. 使用更大、更相關(guān)的語(yǔ)料。4. 適當(dāng)增加embedding_dim。訓(xùn)練過程損失不下降或變?yōu)?NaN。1. 學(xué)習(xí)率過高導(dǎo)致梯度爆炸。2. 初始化權(quán)重值過大。3. 未對(duì) softmax 做數(shù)值穩(wěn)定處理。1. 打印每輪損失和梯度范數(shù)。2. 檢查W1、W2初始化值。1. 大幅降低學(xué)習(xí)率如從0.1調(diào)到0.01。2. 使用更小的隨機(jī)初始化標(biāo)準(zhǔn)差如* 0.001。3. 確保 softmax 計(jì)算時(shí)減去了最大值。無(wú)法處理新詞OOV。使用了基于詞的模型詞匯表固定。確認(rèn)輸入詞是否在word_to_id字典中。1. 在預(yù)處理時(shí)替換為UNK標(biāo)記。2.更優(yōu)方案使用子詞分詞如 BPE從根本上解決 OOV。向量運(yùn)算如類比推理效果差。1. 語(yǔ)料不足以支撐該語(yǔ)義關(guān)系。2. 模型容量不足維度太低。3. 訓(xùn)練目標(biāo)不適合捕捉此類關(guān)系。1. 檢查語(yǔ)料中相關(guān)詞的出現(xiàn)頻率和共現(xiàn)模式。2. 嘗試更大的embedding_dim。1. 使用領(lǐng)域相關(guān)的大規(guī)模語(yǔ)料。2. 使用更成熟的模型如 Gensim 的 Word2Vec。3. 考慮使用更先進(jìn)的 Embedding 方法如 GloVe, FastText。7. 最佳實(shí)踐與工程建議理解了原理后在實(shí)際項(xiàng)目中應(yīng)用 Embedding 時(shí)應(yīng)遵循以下最佳實(shí)踐語(yǔ)料質(zhì)量大于數(shù)量用于訓(xùn)練 Embedding 的語(yǔ)料必須與你的下游任務(wù)高度相關(guān)。用通用維基百科語(yǔ)料訓(xùn)練出的向量在醫(yī)療或法律領(lǐng)域任務(wù)上效果可能不佳。優(yōu)先使用預(yù)訓(xùn)練模型除非有非常特殊的領(lǐng)域和充足的數(shù)據(jù)否則不要從頭訓(xùn)練。像Sentence-Transformers、OpenAI 的 text-embedding 系列或M3E等模型提供了高質(zhì)量、開箱即用的通用 Embedding。理解靜態(tài)與動(dòng)態(tài) Embedding 的適用場(chǎng)景靜態(tài) Embedding如 Word2Vec適用于詞匯級(jí)語(yǔ)義相似度計(jì)算、作為簡(jiǎn)單模型的輸入特征。速度快資源消耗低。動(dòng)態(tài)/上下文 Embedding如 BERT, GPT適用于需要理解句子整體語(yǔ)義、一詞多義、復(fù)雜邏輯關(guān)系的任務(wù)如文本分類、問答、語(yǔ)義檢索。計(jì)算成本高。Embedding 的維度選擇并非維度越高越好。更高的維度能容納更多信息但也需要更多數(shù)據(jù)來訓(xùn)練且可能引入噪聲。通常 300-768 維是一個(gè)較好的平衡點(diǎn)。可以通過在下游任務(wù)上的表現(xiàn)來選擇。標(biāo)準(zhǔn)化與相似度計(jì)算在使用余弦相似度檢索前對(duì) Embedding 向量進(jìn)行 L2 標(biāo)準(zhǔn)化是標(biāo)準(zhǔn)操作。這能確保相似度計(jì)算完全依賴于向量方向不受長(zhǎng)度影響。即vec_normalized vec / np.linalg.norm(vec)。生產(chǎn)環(huán)境部署對(duì)于海量向量的相似度檢索務(wù)必使用專門的向量數(shù)據(jù)庫(kù)Vector Database如 Milvus、Pinecone、Qdrant、Weaviate 等。它們針對(duì)高維向量的近似最近鄰搜索ANN進(jìn)行了極致優(yōu)化遠(yuǎn)超傳統(tǒng)數(shù)據(jù)庫(kù)的線性掃描性能。8. 總結(jié)與后續(xù)方向通過這次“手搓”我們揭開了 Embedding 的神秘面紗。它的核心思想樸素而有力讓詞語(yǔ)在向量空間中的“位置”由其上下文“鄰居”決定。我們從獨(dú)熱編碼的“荒漠”出發(fā)構(gòu)建了一個(gè)能夠?qū)W習(xí)“國(guó)王-男人女人≈女王”這種抽象關(guān)系的稠密語(yǔ)義空間。本文帶你走通了最關(guān)鍵的幾步理解了為什么從獨(dú)熱編碼的缺陷到分布式假設(shè)的必要性??吹搅嗽趺醋鲇?Skip-gram 目標(biāo)構(gòu)建訓(xùn)練數(shù)據(jù)通過前向/反向傳播更新 Embedding 矩陣。驗(yàn)證了效果通過余弦相似度和向量運(yùn)算直觀感受到語(yǔ)義被編碼進(jìn)了數(shù)字。要進(jìn)一步深入你可以復(fù)現(xiàn)完整 Word2Vec加入負(fù)采樣Negative Sampling或?qū)哟?Softmax使其能處理大規(guī)模語(yǔ)料。探索 GloVe研究基于全局詞頻統(tǒng)計(jì)的另一種經(jīng)典 Embedding 方法。深入 Transformer理解如何通過自注意力機(jī)制實(shí)現(xiàn)上下文相關(guān)的動(dòng)態(tài) Embedding這是通往 BERT、GPT 等現(xiàn)代模型的鑰匙。實(shí)踐向量數(shù)據(jù)庫(kù)選一個(gè)開源向量數(shù)據(jù)庫(kù)將本文生成的或下載的預(yù)訓(xùn)練 Embedding 導(dǎo)入實(shí)現(xiàn)一個(gè)簡(jiǎn)單的語(yǔ)義搜索系統(tǒng)。Embedding 是連接符號(hào)世界與連續(xù)向量世界的橋梁是讓機(jī)器理解人類語(yǔ)言語(yǔ)義的基石。希望這次從零開始的手工體驗(yàn)?zāi)茏屇阆麓卧谡{(diào)用model.encode()或看到embedding_dim768時(shí)眼前浮現(xiàn)的不再是黑盒而是那個(gè)由上下文編織而成的、充滿意義的數(shù)學(xué)空間。建議收藏本文當(dāng)你需要向他人解釋 Embedding或自己遺忘想重溫時(shí)這份從零構(gòu)建的代碼就是最好的備忘錄。