論》實(shí)戰(zhàn)指南:從詞向量到BERT微調(diào))
簡介《自然語言處理導(dǎo)論》由張奇、桂韜、黃萱菁三位長期從事NLP教學(xué)與科研的學(xué)者編寫面向高校高年級本科生、研究生及對該領(lǐng)域感興趣的入門讀者可作為課程教材或自學(xué)參考。全書共14章以問題與任務(wù)為主線先介紹NLP基本概念與發(fā)展歷史再按詞匯、句法、語義、篇章分析和語言模型展開基礎(chǔ)技術(shù)繼而覆蓋信息抽取、機(jī)器翻譯、情感分析、智能問答、文本摘要與知識圖譜等核心技術(shù)最后討論大模型的穩(wěn)健性與可解釋性并穿插ChatGPT與GPT的相關(guān)介紹。資源為1個(gè)PDF文件壓縮包約35.01MB內(nèi)容完整、目錄清晰便于按章節(jié)系統(tǒng)學(xué)習(xí)或查閱。目前已有1725人學(xué)習(xí)下載適合希望建立NLP知識框架、理解任務(wù)與算法對應(yīng)關(guān)系的讀者參考。1. 自然語言處理導(dǎo)論這本教材為什么值得你花兩周啃完如果你正在找一本能把 NLP 從詞袋模型一路講到預(yù)訓(xùn)練語言模型的中文教材大概率會(huì)刷到這本《自然語言處理導(dǎo)論》。它由張奇、桂韜、黃萱菁三位老師編寫在高校課程和自學(xué)路線里被反復(fù)提及。但真正讓一線工程師愿意翻它的原因不是名氣而是它把「任務(wù)—模型—評測」這條鏈路講得足夠完整從分詞、詞性標(biāo)注、句法分析到詞向量、注意力機(jī)制、Transformer、BERT 和 GPT 系列每一塊都配了形式化定義和可推導(dǎo)的公式而不是只給結(jié)論。我?guī)н^幾個(gè)剛轉(zhuǎn) NLP 的同事他們最??ㄔ凇钢?BERT 好用但說不清它為什么比 LSTM 強(qiáng)」。這本教材的價(jià)值就在于它把這種「為什么」拆成了可驗(yàn)證的數(shù)學(xué)表達(dá)和實(shí)驗(yàn)設(shè)置。適合誰讀適合有 Python 基礎(chǔ)、學(xué)過概率論和線性代數(shù)、想系統(tǒng)補(bǔ)齊 NLP 知識棧的開發(fā)者也適合已經(jīng)會(huì)調(diào) HuggingFace 但想回頭補(bǔ)理論底子的算法工程師。接下來我不復(fù)述書里的章節(jié)而是按「怎么用這本書真正跑通一條 NLP 流水線」的思路把選型、實(shí)現(xiàn)、參數(shù)和踩坑講清楚。2. 從詞袋到預(yù)訓(xùn)練教材里的模型演進(jìn)怎么落到代碼上2.1 為什么先啃詞向量而不是直接上 BERT教材前幾章花了不少篇幅在 n-gram 和詞袋模型上很多人覺得這是「歷史包袱」想直接跳到 Transformer。但我的血淚經(jīng)驗(yàn)是跳過詞向量直接調(diào) BERT遇到 OOV、領(lǐng)域漂移和相似度任務(wù)時(shí)你連問題出在數(shù)據(jù)還是模型都判斷不了。詞向量這一章的核心是分布式假設(shè)——上下文相似的詞語義也相似。教材里給了 Word2Vec 的兩種訓(xùn)練目標(biāo)CBOW 和 Skip-gram并推導(dǎo)了負(fù)采樣如何把 softmax 的計(jì)算量降下來。落到代碼上我一般先用一個(gè)小語料把 Word2Vec 跑通觀察詞向量的最近鄰建立對「語義空間」的直覺。下面這段代碼用 gensim 在自定義語料上訓(xùn)練重點(diǎn)看參數(shù)怎么影響結(jié)果。from gensim.models import Word2Vec # 假設(shè) corpus 是已經(jīng)分好詞的句子列表每個(gè)元素是詞列表 # 例如[[自然, 語言, 處理, 有趣], [詞, 向量, 可以, 計(jì)算, 相似度]] corpus [ [自然, 語言, 處理, 是, 人工智能, 的, 重要, 方向], [詞, 向量, 把, 詞, 映射, 到, 低維, 空間], [深度, 學(xué)習(xí), 推動(dòng), 了, 自然, 語言, 處理, 的, 發(fā)展], [語言, 模型, 可以, 預(yù)測, 下一個(gè), 詞], ] model Word2Vec( sentencescorpus, vector_size100, # 詞向量維度教材里常提 50-300小語料用 100 夠觀察 window5, # 上下文窗口Skip-gram 常用 5-10 min_count1, # 小語料必須設(shè) 1否則低頻詞全被丟 sg1, # 1 表示 Skip-gram0 表示 CBOW negative5, # 負(fù)采樣個(gè)數(shù)教材推導(dǎo)里常見 5-20 epochs30, # 小語料多跑幾輪讓損失收斂 seed42 # 固定隨機(jī)種子方便復(fù)現(xiàn) ) # 查看與「語言」最相近的詞 print(model.wv.most_similar(語言, topn5))邏輯說明Word2Vec 的訓(xùn)練目標(biāo)不是讓模型「理解」語言而是讓共現(xiàn)頻率高的詞在向量空間里靠近。vector_size決定表達(dá)能力太小會(huì)欠擬合太大在小語料上會(huì)過擬合window控制上下文范圍窗口越大主題相關(guān)性越強(qiáng)但句法關(guān)系會(huì)變?nèi)鮯g1在低頻詞上表現(xiàn)通常更好但訓(xùn)練更慢。教材里對負(fù)采樣的推導(dǎo)解釋了為什么negative不需要設(shè)得很大——5 到 20 已經(jīng)能近似 softmax。參數(shù)說明min_count是新手最容易翻車的地方。教材默認(rèn)語料是百萬級設(shè) 5 或 10 合理但你拿幾千條評論做實(shí)驗(yàn)時(shí)設(shè) 5 會(huì)把大量領(lǐng)域詞丟掉導(dǎo)致相似度查詢返回空。epochs也不是越大越好小語料上超過 50 輪基本就在記噪聲了。2.2 從 RNN 到注意力教材里的公式怎么變成可調(diào)試的模塊教材中段會(huì)講序列建模從 RNN、LSTM 到注意力機(jī)制。很多人看公式能懂寫代碼就懵。我的做法是先按教材的公式手寫一個(gè)極簡的注意力層不調(diào)庫把維度對齊這件事徹底搞明白。下面是一個(gè)縮放點(diǎn)積注意力的最小實(shí)現(xiàn)輸入是三個(gè)張量查詢 Q、鍵 K、值 V。import torch import torch.nn.functional as F def scaled_dot_product_attention(Q, K, V, maskNone): Q: (batch, seq_len_q, d_k) K: (batch, seq_len_k, d_k) V: (batch, seq_len_k, d_v) d_k Q.size(-1) # 第一步Q 和 K 轉(zhuǎn)置相乘得到注意力分?jǐn)?shù) scores torch.matmul(Q, K.transpose(-2, -1)) / (d_k ** 0.5) # 第二步如果有 mask把不該看的位置設(shè)成負(fù)無窮 if mask is not None: scores scores.masked_fill(mask 0, float(-inf)) # 第三步softmax 歸一化得到注意力權(quán)重 attn_weights F.softmax(scores, dim-1) # 第四步加權(quán)求和 output torch.matmul(attn_weights, V) return output, attn_weights # 模擬一個(gè) batch2序列長度4維度8 的輸入 Q torch.randn(2, 4, 8) K torch.randn(2, 4, 8) V torch.randn(2, 4, 8) out, weights scaled_dot_product_attention(Q, K, V) print(out.shape) # torch.Size([2, 4, 8]) print(weights.shape) # torch.Size([2, 4, 4])邏輯說明教材里注意力公式寫的是Attention(Q,K,V)softmax(QK^T/√d_k)V代碼就是逐項(xiàng)對應(yīng)。除以√d_k是為了防止點(diǎn)積過大導(dǎo)致 softmax 梯度消失這個(gè)細(xì)節(jié)教材有推導(dǎo)但很多人寫代碼時(shí)會(huì)漏掉結(jié)果訓(xùn)練 loss 直接變 NaN。mask在解碼器和 padding 場景里必須用否則模型會(huì)看到未來 token 或填充位評測指標(biāo)虛高。參數(shù)說明d_k是查詢和鍵的維度必須一致d_v是值的維度可以和d_k不同。實(shí)際項(xiàng)目里我一般讓三者相等減少維度不匹配的排查成本。mask的形狀要能廣播到(batch, seq_len_q, seq_len_k)常見錯(cuò)誤是 mask 維度少了一維導(dǎo)致廣播到 batch 維度上訓(xùn)練時(shí)看不出問題推理時(shí)結(jié)果全錯(cuò)。2.3 預(yù)訓(xùn)練語言模型教材最后一章怎么指導(dǎo)微調(diào)實(shí)踐教材后段會(huì)講 BERT 和 GPT 的預(yù)訓(xùn)練目標(biāo)、模型結(jié)構(gòu)和下游適配。這部分如果只讀不練很容易變成「知道 MLM 是掩碼語言模型但不知道怎么設(shè)掩碼比例」。我的建議是拿一個(gè)中文預(yù)訓(xùn)練模型在自己的小數(shù)據(jù)集上做一次完整的微調(diào)把教材里的「預(yù)訓(xùn)練—微調(diào)」范式跑通。下面以文本分類為例用 HuggingFace 的 transformers 庫寫一個(gè)最小訓(xùn)練循環(huán)。from transformers import AutoTokenizer, AutoModelForSequenceClassification from torch.utils.data import Dataset, DataLoader import torch # 使用一個(gè)中文預(yù)訓(xùn)練模型具體名稱按你本地環(huán)境選擇 model_name bert-base-chinese tokenizer AutoTokenizer.from_pretrained(model_name) model AutoModelForSequenceClassification.from_pretrained(model_name, num_labels2) class TextDataset(Dataset): def __init__(self, texts, labels, tokenizer, max_len128): self.texts texts self.labels labels self.tokenizer tokenizer self.max_len max_len def __len__(self): return len(self.texts) def __getitem__(self, idx): encoding self.tokenizer( self.texts[idx], truncationTrue, paddingmax_length, max_lengthself.max_len, return_tensorspt ) return { input_ids: encoding[input_ids].squeeze(0), attention_mask: encoding[attention_mask].squeeze(0), labels: torch.tensor(self.labels[idx], dtypetorch.long) } # 模擬數(shù)據(jù) texts [這個(gè)產(chǎn)品很好用, 服務(wù)太差了, 物流很快, 質(zhì)量不行] labels [1, 0, 1, 0] dataset TextDataset(texts, labels, tokenizer) loader DataLoader(dataset, batch_size2, shuffleTrue) optimizer torch.optim.AdamW(model.parameters(), lr2e-5) model.train() for epoch in range(3): for batch in loader: optimizer.zero_grad() outputs model( input_idsbatch[input_ids], attention_maskbatch[attention_mask], labelsbatch[labels] ) loss outputs.loss loss.backward() optimizer.step() print(fepoch{epoch}, loss{loss.item():.4f})邏輯說明教材里講 BERT 的輸入是[CLS] tokens [SEP]tokenizer會(huì)自動(dòng)處理這些特殊 token。attention_mask用來告訴模型哪些位置是真實(shí) token哪些是 padding不傳這個(gè)參數(shù)模型會(huì)把 padding 也當(dāng)成有效信息分類邊界會(huì)變模糊。AdamW的權(quán)重衰減和lr2e-5是 BERT 微調(diào)的常見起點(diǎn)教材里可能沒寫具體數(shù)值但這是社區(qū)驗(yàn)證過的穩(wěn)定區(qū)間。參數(shù)說明max_len設(shè) 128 還是 512 取決于你的文本長度分布。我一般先統(tǒng)計(jì)訓(xùn)練集的分位數(shù)取 95% 分位對應(yīng)的長度再往上取整到 128 的倍數(shù)。batch_size受顯存限制小顯存可以用梯度累積模擬大 batch。num_labels必須和你的標(biāo)簽數(shù)一致二分類設(shè) 2多分類設(shè)類別數(shù)設(shè)錯(cuò)會(huì)在 loss 計(jì)算時(shí)直接報(bào)維度錯(cuò)誤。3. 把教材當(dāng)項(xiàng)目手冊用數(shù)據(jù)、訓(xùn)練、評測的三條實(shí)操線3.1 數(shù)據(jù)預(yù)處理教材里的分詞和標(biāo)注怎么對齊真實(shí)語料教材講分詞時(shí)會(huì)給很多規(guī)則和算法比如最大匹配、隱馬爾可夫、條件隨機(jī)場。但真實(shí)語料里你面對的是全角半角混用、URL、表情符號和領(lǐng)域縮寫。我的習(xí)慣是先寫一個(gè)清洗管道把教材里的分詞算法套在清洗后的文本上觀察分詞邊界是否符合預(yù)期。下面是一個(gè)中文清洗和分詞的組合示例。import re import jieba def clean_text(text): # 去除 URL text re.sub(rhttps?://\S, , text) # 去除多余空白 text re.sub(r\s, , text) # 全角轉(zhuǎn)半角簡化版只處理常見字符 text text.replace(, ,).replace(。, .).replace(, !) return text.strip() def tokenize(text): # 使用 jieba 分詞教材里講的最大匹配可以在這里替換成自定義實(shí)現(xiàn) return list(jieba.cut(text)) raw 這個(gè)產(chǎn)品真的很好用 https://example.com 推薦大家試試 cleaned clean_text(raw) tokens tokenize(cleaned) print(cleaned) # 這個(gè)產(chǎn)品真的很好用! 推薦大家試試 print(tokens) # [這個(gè), 產(chǎn)品, 真的, 很, 好用, !, 推薦, 大家, 試試]邏輯說明教材里的分詞算法假設(shè)輸入是規(guī)范文本但真實(shí)數(shù)據(jù)必須先清洗。URL 和特殊符號如果不處理會(huì)被分詞器切成無意義的碎片進(jìn)入模型后變成噪聲。全角轉(zhuǎn)半角是為了統(tǒng)一字符集減少詞表大小。jieba是常用工具但它的詞典和教材里的統(tǒng)計(jì)分詞方法有差異做實(shí)驗(yàn)時(shí)要注意對比。參數(shù)說明re.sub的正則模式要根據(jù)你的數(shù)據(jù)調(diào)整比如有些場景需要保留郵箱或話題標(biāo)簽。jieba.cut默認(rèn)是精確模式還有全模式和搜索引擎模式教材里可能沒展開但實(shí)際做搜索召回時(shí)搜索引擎模式能提高召回率。清洗規(guī)則不要過度把否定詞或程度副詞刪掉會(huì)改變情感極性這是新手常踩的坑。3.2 訓(xùn)練配置學(xué)習(xí)率、批次和序列長度的聯(lián)動(dòng)關(guān)系教材在講模型訓(xùn)練時(shí)通常會(huì)給出損失函數(shù)和優(yōu)化目標(biāo)的定義但不會(huì)告訴你學(xué)習(xí)率設(shè)多少。我的經(jīng)驗(yàn)是學(xué)習(xí)率、批次大小和序列長度三者是聯(lián)動(dòng)的。批次越大梯度估計(jì)越穩(wěn)學(xué)習(xí)率可以適當(dāng)調(diào)大序列越長顯存占用越高批次就得調(diào)小。下面是一個(gè)配置對比表來自我在小規(guī)模文本分類任務(wù)上的實(shí)測記錄。配置項(xiàng)小批次方案大批次方案說明batch_size832受顯存限制32 需要至少 8GB 顯存learning_rate2e-55e-5大批次用更大學(xué)習(xí)率保持梯度更新幅度max_len64128長文本任務(wù)必須用 128 以上warmup_steps100500預(yù)熱步數(shù)約為總步數(shù)的 10%weight_decay0.010.01BERT 微調(diào)常用值防止過擬合這張表不是萬能公式但能幫你建立調(diào)參方向。教材里講優(yōu)化器時(shí)提到 Adam 的自適應(yīng)學(xué)習(xí)率但沒強(qiáng)調(diào) warmup 對 Transformer 穩(wěn)定性的影響。我一般會(huì)加線性預(yù)熱前 10% 的步數(shù)里學(xué)習(xí)率從 0 升到目標(biāo)值避免訓(xùn)練初期梯度爆炸。3.3 評測指標(biāo)教材里的準(zhǔn)確率、召回率和 F1 怎么選教材在講評測時(shí)會(huì)給出準(zhǔn)確率、精確率、召回率和 F1 的定義。但實(shí)際項(xiàng)目里選哪個(gè)指標(biāo)取決于業(yè)務(wù)代價(jià)。比如垃圾文本過濾漏判的代價(jià)遠(yuǎn)大于誤判這時(shí)候召回率比準(zhǔn)確率重要而情感分析里誤判一條好評的代價(jià)可能更高精確率就更關(guān)鍵。我的做法是先算混淆矩陣再根據(jù)業(yè)務(wù)目標(biāo)決定優(yōu)化方向。from sklearn.metrics import confusion_matrix, classification_report # 假設(shè) y_true 是真實(shí)標(biāo)簽y_pred 是模型預(yù)測 y_true [0, 1, 0, 1, 1, 0, 1, 0] y_pred [0, 1, 0, 0, 1, 0, 1, 1] print(confusion_matrix(y_true, y_pred)) print(classification_report(y_true, y_pred, target_names[負(fù)面, 正面]))邏輯說明混淆矩陣的四個(gè)格子分別對應(yīng)真負(fù)、假正、假負(fù)、真正。教材里可能只給公式但實(shí)際排查時(shí)看混淆矩陣比看單一指標(biāo)更快定位問題。比如假負(fù)特別多說明模型對正類不敏感可能需要調(diào)整類別權(quán)重或補(bǔ)充正類樣本。classification_report會(huì)輸出每個(gè)類別的精確率、召回率和 F1多分類任務(wù)里能看出哪個(gè)類別是短板。參數(shù)說明target_names要和標(biāo)簽順序一致否則報(bào)告會(huì)張冠李戴。如果類別不平衡macro avg和weighted avg差異會(huì)很大教材里通常講 macro但實(shí)際業(yè)務(wù)里 weighted 更能反映整體表現(xiàn)。評測集一定要和訓(xùn)練集分布一致否則指標(biāo)再好也是自欺欺人。4. 避坑與排查讀這本教材做實(shí)驗(yàn)時(shí)最容易翻車的五個(gè)地方4.1 詞表大小設(shè)錯(cuò)導(dǎo)致 embedding 維度對不上現(xiàn)象加載預(yù)訓(xùn)練詞向量時(shí)報(bào)IndexError: index out of range或者模型訓(xùn)練時(shí) loss 一直是 NaN。原因教材里講詞表構(gòu)建時(shí)通常假設(shè)你用的是標(biāo)準(zhǔn)數(shù)據(jù)集詞表大小固定。但你自己清洗語料后詞表可能比預(yù)訓(xùn)練詞向量小或者你手動(dòng)加了特殊 token 導(dǎo)致索引偏移。解決先打印詞表和預(yù)訓(xùn)練向量的交集大小確認(rèn)覆蓋率。如果覆蓋率低于 80%要么擴(kuò)充預(yù)訓(xùn)練詞向量要么把低頻詞統(tǒng)一映射到unk。我一般會(huì)寫一個(gè)檢查腳本在訓(xùn)練前跑一遍。4.2 注意力 mask 方向?qū)懛磳?dǎo)致模型偷看未來現(xiàn)象訓(xùn)練 loss 下降很快但驗(yàn)證集指標(biāo)很差生成任務(wù)里模型會(huì)重復(fù)輸出。原因教材講注意力時(shí)mask 的 0 和 1 含義容易記混。有的實(shí)現(xiàn)里 1 表示保留0 表示屏蔽有的反過來。寫反了模型在解碼時(shí)能看到未來 token訓(xùn)練時(shí)表現(xiàn)很好推理時(shí)直接崩。解決寫一個(gè)單元測試構(gòu)造一個(gè)上三角矩陣手動(dòng)算一遍注意力權(quán)重確認(rèn)被 mask 的位置權(quán)重為 0。這個(gè)測試花五分鐘能省幾小時(shí)排查。4.3 學(xué)習(xí)率太大導(dǎo)致預(yù)訓(xùn)練模型災(zāi)難性遺忘現(xiàn)象微調(diào) BERT 時(shí)第一輪 loss 就降到很低但驗(yàn)證集準(zhǔn)確率不如隨機(jī)猜。原因預(yù)訓(xùn)練模型的參數(shù)已經(jīng)在一個(gè)大語料上收斂你用 1e-3 這種學(xué)習(xí)率去更新會(huì)把預(yù)訓(xùn)練學(xué)到的通用表示直接沖掉。教材里可能沒強(qiáng)調(diào)這一點(diǎn)因?yàn)榻滩膫?cè)重原理不涉及工程細(xì)節(jié)。解決微調(diào)學(xué)習(xí)率控制在 1e-5 到 5e-5 之間先用小學(xué)習(xí)率跑一輪看 loss 是否平穩(wěn)下降。如果 loss 震蕩再降一個(gè)數(shù)量級。4.4 評測集泄漏導(dǎo)致指標(biāo)虛高現(xiàn)象模型在測試集上 F1 達(dá)到 0.95上線后效果一塌糊涂。原因教材講數(shù)據(jù)劃分時(shí)通常說按比例隨機(jī)劃分。但真實(shí)數(shù)據(jù)里同一條樣本可能被重復(fù)采集或者訓(xùn)練集和測試集有相同用戶、相同時(shí)間段。隨機(jī)劃分會(huì)讓相似樣本同時(shí)出現(xiàn)在兩邊模型只是記住了模式。解決按時(shí)間劃分或者按用戶 ID 分組劃分。如果數(shù)據(jù)量夠留出一個(gè)完全獨(dú)立的驗(yàn)證集不參與任何調(diào)參。4.5 忽略 padding 對損失計(jì)算的影響現(xiàn)象分類任務(wù)里短文本的預(yù)測總是偏向某一類。原因教材講 batch 訓(xùn)練時(shí)會(huì)提到 padding 對齊序列長度但沒強(qiáng)調(diào)損失計(jì)算時(shí)要忽略 padding 位置。如果不對 padding 做 mask模型會(huì)把填充的 0 當(dāng)成有效 token短文本被大量 0 稀釋預(yù)測自然偏。解決在計(jì)算 loss 時(shí)傳入attention_mask或者手動(dòng)把 padding 位置的損失權(quán)重設(shè)為 0。HuggingFace 的模型默認(rèn)支持這個(gè)參數(shù)但自定義模型要自己實(shí)現(xiàn)。5. 進(jìn)階用法用教材里的評測框架做一次可復(fù)現(xiàn)的對比實(shí)驗(yàn)教材最后一章通常會(huì)講評測方法和基準(zhǔn)數(shù)據(jù)集。我的進(jìn)階建議是不要只跑一個(gè)模型而是用同一套數(shù)據(jù)、同一個(gè)評測腳本對比至少三種方法——詞袋邏輯回歸、LSTM、BERT 微調(diào)。這樣你才能真正理解教材里「預(yù)訓(xùn)練模型帶來巨大提升」這句話的量化含義。下面是一個(gè)對比實(shí)驗(yàn)的骨架代碼重點(diǎn)在固定隨機(jī)種子和統(tǒng)一評測。import numpy as np import torch from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.linear_model import LogisticRegression from sklearn.metrics import f1_score def set_seed(seed42): np.random.seed(seed) torch.manual_seed(seed) if torch.cuda.is_available(): torch.cuda.manual_seed_all(seed) # 假設(shè) train_texts, train_labels, test_texts, test_labels 已經(jīng)準(zhǔn)備好 set_seed(42) # 方法一TF-IDF 邏輯回歸 vectorizer TfidfVectorizer(max_features5000) X_train vectorizer.fit_transform(train_texts) X_test vectorizer.transform(test_texts) clf LogisticRegression(max_iter1000) clf.fit(X_train, train_labels) pred_lr clf.predict(X_test) print(TF-IDF LR F1:, f1_score(test_labels, pred_lr, averagemacro)) # 方法二和三種LSTM 和 BERT 微調(diào)按前面的代碼模板替換模型即可 # 關(guān)鍵是保持?jǐn)?shù)據(jù)劃分、隨機(jī)種子和評測指標(biāo)一致邏輯說明這個(gè)骨架的價(jià)值在于「控制變量」。教材里講不同模型的原理時(shí)你會(huì)覺得 BERT 肯定比 TF-IDF 強(qiáng)但強(qiáng)多少、在什么數(shù)據(jù)量下強(qiáng)只有自己跑一遍才知道。我一般會(huì)記錄每個(gè)方法的訓(xùn)練時(shí)間、顯存占用和 F1做成一張對比表。如果 BERT 只比 TF-IDF 高兩個(gè)點(diǎn)但訓(xùn)練成本高十倍在小數(shù)據(jù)場景下就不值得上 BERT。參數(shù)說明max_features5000是 TF-IDF 的常見起點(diǎn)太大容易過擬合太小會(huì)丟信息。LogisticRegression的max_iter要設(shè)大一點(diǎn)否則小數(shù)據(jù)上可能不收斂。set_seed必須放在所有隨機(jī)操作之前包括數(shù)據(jù)劃分、權(quán)重初始化和 dropout。對比實(shí)驗(yàn)里隨機(jī)種子不固定結(jié)論就沒有說服力。我自己的習(xí)慣是每讀一本教材就挑一個(gè)章節(jié)做一次最小復(fù)現(xiàn)把公式變成代碼把代碼跑出指標(biāo)。這本《自然語言處理導(dǎo)論》我前后翻了三個(gè)月最大的收獲不是記住了多少模型結(jié)構(gòu)而是建立了一套「從公式到實(shí)驗(yàn)」的驗(yàn)證習(xí)慣。遇到新模型時(shí)我會(huì)先問它的訓(xùn)練目標(biāo)是什么評測指標(biāo)怎么算數(shù)據(jù)劃分有沒有泄漏這三個(gè)問題答不上來就不急著調(diào)參。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取