習(xí)入門)
說起深度學(xué)習(xí)課程里的“實驗三”十有八九會撞上這樣一句話用 logistic 回歸預(yù)測二分類。我見過不少同學(xué)看到題目后的第一反應(yīng)是“這算哪門子深度學(xué)習(xí)不就是個線性模型套了個激活函數(shù)嗎”真等自己上手跑完才發(fā)現(xiàn)這個實驗從頭到尾踩的坑比后面好多大型網(wǎng)絡(luò)實驗加起來都要多。其實 logistic 回歸是理解整個深度學(xué)習(xí)最理想的一顆釘子。從網(wǎng)絡(luò)結(jié)構(gòu)上看它就是一個沒有隱藏層的單神經(jīng)元模型輸入特征做加權(quán)求和過一個 sigmoid 激活輸出一個 0 到 1 之間的概率。這套流程你吃透了后續(xù)學(xué)多層感知機、CNN、RNN 時就會發(fā)現(xiàn)大家都是在同一個骨架上做文章只是把單神經(jīng)元變成了大網(wǎng)絡(luò)把線性加權(quán)換成了卷積或循環(huán)結(jié)構(gòu)。當(dāng)年我?guī)б晃涣慊A(chǔ)的 A 同學(xué)做這個實驗他花了一個下午把前向傳播、損失函數(shù)、梯度更新通了隔周再去看多層網(wǎng)絡(luò)的反向傳播明顯比別人輕松一大截。這篇文章我會把這個實驗從原理到實操完整拆開把 sigmoid 為什么長這樣、交叉熵為什么比均方誤差好用、數(shù)據(jù)預(yù)處理怎么做不泄露、訓(xùn)練曲線怎么看這些“老師不細(xì)講但考試和工作都要考”的東西一次性說清楚。適合正在做課程實驗的同學(xué)也適合想回頭把這顆地基補扎實的自學(xué)者。1. 實驗整體認(rèn)知與設(shè)計思路1.1 實驗三為什么偏偏選 logistic 回歸很多課程的實驗順序都是精心排過的把 logistic 回歸放在第三個實驗剛好卡在“你已經(jīng)會線性回歸了但還沒接觸神經(jīng)網(wǎng)絡(luò)”的中間地帶。它有兩個身份對經(jīng)典機器學(xué)習(xí)來說它是一個線性分類器對深度學(xué)習(xí)來說它是神經(jīng)網(wǎng)絡(luò)最樸素的雛形。從結(jié)構(gòu)上看logistic 回歸做的事情極其簡單把每個特征乘上一個權(quán)重累加再加一個偏置然后過一個 sigmoid 函數(shù)把結(jié)果壓到 0 到 1 之間。這個結(jié)構(gòu)像什么就是一個最精簡的神經(jīng)元。學(xué)完這個單神經(jīng)元下一步加一層隱藏層就是兩層神經(jīng)網(wǎng)絡(luò)再加幾層就變成了一個標(biāo)準(zhǔn)的多層感知機。所以實驗安排這門課的人真實意圖是讓你先用最少的代碼把前向傳播、損失計算、梯度反傳、參數(shù)更新這條完整流水線走一遍。這個實驗的定位決定了它的學(xué)習(xí)重點不在模型本身的精度而在于理解訓(xùn)練過程。說實話二分類任務(wù)用 logistic 回歸去跑很多時候精度也不會特別高尤其是數(shù)據(jù)不是線性可分的時候它的表現(xiàn)可能就是“夠用”。但正因為模型簡單所有中間過程都可以被清清楚楚地打印出來、畫出來、算出來——權(quán)重怎么變、損失怎么降、決策邊界怎么移動全部都直觀可見。這是深網(wǎng)絡(luò)給不了你的學(xué)習(xí)體驗。1.2 二分類預(yù)測的建模思路二分類在現(xiàn)實中隨處可見一封郵件是不是垃圾郵件一個用戶會不會下單一個病人是不是得了某種疾病本質(zhì)上都是“二選一”的判斷題。這個實驗要做的事情就是給出一組樣本和它們的標(biāo)簽訓(xùn)練一個模型讓模型在面對沒見過的樣本時能給出一個正確的二分類判斷。這里有一個初學(xué)者很容易誤解的地方模型輸出并不是直接的 0 或 1而是一個概率值。比如模型對某條樣本輸出 0.87意思就是“我覺得它有 87% 的概率屬于類別 1”。然后我們再人為約定一個閾值——通常是 0.5——概率大于 0.5 判定為類別 1否則判定為類別 0。后面我還會講到這個閾值不是固定死的不同業(yè)務(wù)場景下調(diào)閾值可能比調(diào)模型參數(shù)還管用。整個實驗的建模流程可以歸納成一條清晰的流水線數(shù)據(jù)準(zhǔn)備拿到特征矩陣 X形狀是 樣本數(shù)×特征數(shù)和標(biāo)簽向量 y形狀是 樣本數(shù)×1。數(shù)據(jù)預(yù)處理標(biāo)準(zhǔn)化、劃分訓(xùn)練集和測試集。模型定義初始化權(quán)重 W 和偏置 b寫出前向傳播函數(shù)。損失計算用交叉熵衡量預(yù)測概率與真實標(biāo)簽的差距。梯度計算與參數(shù)更新讓模型在訓(xùn)練數(shù)據(jù)上一點點往正確的方向調(diào)整。評估在測試集上驗證泛化效果。建議你在動手寫代碼之前先在紙上把這個流程走一遍把每一步的輸入輸出形狀寫清楚。很多人寫著寫著就亂了回頭查 bug 半天最后發(fā)現(xiàn)是某個張量的維度沒對上。2. 核心原理拆解sigmoid 與交叉熵的搭檔邏輯2.1 從線性回歸到概率輸出sigmoid 到底在做什么先回憶一下線性回歸給定特征 x1、x2…… 模型算出一個分?jǐn)?shù) z w1x1 w2x2 ... b。在回歸任務(wù)里這個 z 可以直接作為預(yù)測值。但二分類任務(wù)不行——分類要輸出的是概率概率有天然的取值范圍必須在 0 到 1 之間而線性回歸的 z 范圍是從負(fù)無窮到正無窮直接拿來當(dāng)概率是不合理的。sigmoid 函數(shù)就是來解決這個問題的公式是σ(z) 1 / (1 e^(-z))它的作用是把任意實數(shù) z 壓縮到 (0, 1) 區(qū)間。z 越大輸出越接近 1z 越小輸出越接近 0z 恰好為 0 時輸出為 0.5。這個函數(shù)圖像是一條平滑的 S 型曲線所以它本質(zhì)上做的是一件非常優(yōu)雅的事情把“證據(jù)的強度”轉(zhuǎn)化成“某種結(jié)果發(fā)生的概率”。舉個例子感受一下假設(shè)某個特征的權(quán)重是 0.8x 每增加一個單位z 就增加 0.8sigmoid 輸出就會明顯地向 1 靠攏。相當(dāng)于模型每看到一點新的證據(jù)就它對類別 1 的信心就更足一點而且這種信心的增長不是線性的——靠近中間區(qū)域時變化快到了極值附近就飽和了這和人類的直覺也蠻契合的。在代碼里實現(xiàn)它也非常簡單def sigmoid(z): return 1 / (1 np.exp(-z))不過這里有個小細(xì)節(jié)如果你在損失函數(shù)里面用了 log(p)p 可能被算成 0log(0) 會直接報警。后面我會講怎么用數(shù)值技巧規(guī)避。2.2 決策邊界為什么是線性的把前向傳播的公式展開來看p σ(w1x1 w2x2 ... b)當(dāng)我們把判定閾值設(shè)為 0.5也就是 p 0.5 時預(yù)測為類別 1那實際上等價于看 z w1x1 w2x2 ... b 是否大于 0。z 0 這條線就是模型的決策邊界。因為 z 是特征的線性組合所以 z 0 在二維空間里是一條直線在三維空間里是一個平面在高維空間里是一個超平面。這給 logistic 回歸帶來了兩個鮮明的特點一是可解釋性極強。每個特征的權(quán)重 W 的正負(fù)方向直接告訴我們這個特征對預(yù)測結(jié)果是正向推動還是反向推動絕對值大小代表影響強度。這是很多樹模型和深度網(wǎng)絡(luò)做不到的。二是模型容量有限。當(dāng)數(shù)據(jù)本身線性不可分時比如兩類樣本像陰陽魚一樣糾纏在一起單純一個線性決策邊界是搞不定的。這時你會看到訓(xùn)練精度卡在一個不上不下的位置怎么調(diào)學(xué)習(xí)率都沒用。這不是 bug而是模型表達(dá)能力的限制后續(xù)課程通常會通過引入隱藏層或者核技巧來解決。2.3 交叉熵為什么完勝均方誤差訓(xùn)練模型需要定義一個損失函數(shù)來指導(dǎo)“往哪個方向調(diào)整參數(shù)”。二分類最常用的損失是交叉熵L -[y·log(p) (1-y)·log(1-p)]拆開看當(dāng)真實標(biāo)簽 y 1 時損失變?yōu)?-log(p)p 越接近 1損失越小當(dāng) y 0 時損失變?yōu)?-log(1-p)p 越接近 0損失越小。換句話說模型越自信地猜錯懲罰越大越接近正確答案損失越趨近于 0。這種“對數(shù)懲罰”的特性讓模型不敢在錯誤的方向上過度自信。為什么不直接用均方誤差 MSE (y - p)2 呢這是實驗報告里特別愛問的一道題。關(guān)鍵在于梯度。把 sigmoid 代入 MSE 之后梯度里會冒出一個 σ(z) σ(z)·(1-σ(z)) 項。這個項有個致命弱點當(dāng) z 很大的時候σ 接近 1σ(1-σ) 接近 0當(dāng) z 很小的時候σ 接近 0σ(1-σ) 也接近 0。也就是說模型在預(yù)測得越極端、越自信的時候梯度反而越小訓(xùn)練變得極其緩慢這在深度學(xué)習(xí)中叫“梯度飽和”。而交叉熵配合 sigmoid 之后求導(dǎo)結(jié)果很漂亮梯度變成了 (p - y)·x。這個式子直觀又合理——預(yù)測和真實標(biāo)簽差距越大梯度的幅度越大模型學(xué)得越快預(yù)測接近正確時梯度自然變小。這也是為什么深度學(xué)習(xí)里幾乎不會用 MSE 來做分類任務(wù)的損失函數(shù)。所以你在實驗里如果不小心把損失換成了 MSE會觀察到訓(xùn)練半天損失都降不下去不是代碼 bug而是數(shù)學(xué)選型出了問題。建議你在實驗中分別用交叉熵和 MSE 各跑一次把損失下降曲線對比一下。這個對比實驗做出來你對這個知識點的理解會比只看書深刻得多。3. 實操全流程從數(shù)據(jù)準(zhǔn)備到訓(xùn)練閉環(huán)3.1 數(shù)據(jù)準(zhǔn)備與預(yù)處理的幾個細(xì)節(jié)做這個實驗我建議你先不要直接上復(fù)雜數(shù)據(jù)集而是自己生成一批可分的二維模擬數(shù)據(jù)。好處是直觀后面畫決策邊界時一眼就能看出效果。比如生成兩堆數(shù)據(jù)類別 0 以某個點為中心呈高斯分布類別 1 在另一個點附近分布讓它們之間有一條清晰的分界線。拿到原始數(shù)據(jù)后有幾步預(yù)處理是整個實驗成敗的關(guān)鍵很多人第一步就跑偏了。特征標(biāo)準(zhǔn)化大概是這個實驗里第二重要的預(yù)處理操作。如果 x1 的取值范圍是 0 到 1而 x2 的范圍是 0 到 10000那權(quán)重更新時會被大尺度的特征主導(dǎo)梯度下降會在某些方向上震蕩收斂速度極慢。標(biāo)準(zhǔn)做法是把每個特征減去均值、除以標(biāo)準(zhǔn)差讓數(shù)據(jù)分布在一個相近的尺度上。至于先劃分?jǐn)?shù)據(jù)集還是先標(biāo)準(zhǔn)化這里有一個很容易被忽略的坑。正確順序是先把數(shù)據(jù)拆成訓(xùn)練集和測試集然后用訓(xùn)練集的均值和標(biāo)準(zhǔn)差去標(biāo)準(zhǔn)化訓(xùn)練集和測試集。絕對不要在完整數(shù)據(jù)集上先算均值方差再做標(biāo)準(zhǔn)化因為這樣測試集的信息會偷偷混進訓(xùn)練階段評估結(jié)果會虛高這種現(xiàn)象叫數(shù)據(jù)泄露。實驗數(shù)據(jù)的隨機性本就是這個實驗要模擬的真實情況一旦泄露你后面調(diào)參得到的所有結(jié)論都不可信。我見過不止一個同學(xué)在報告里寫“我的模型在測試集上準(zhǔn)確率 98%”結(jié)果代碼被細(xì)看后發(fā)現(xiàn)他是把數(shù)據(jù)整體標(biāo)準(zhǔn)化之后才劃分的測試集。做實驗不是只看數(shù)字而是要確保數(shù)字背后的邏輯站得住腳。劃分?jǐn)?shù)據(jù)時還有一個小建議二分類數(shù)據(jù)最好用分層采樣保證訓(xùn)練集和測試集里的正負(fù)樣本比例大致一致否則隨機切分完全可能把某個類別的樣本都切到測試集里去。3.2 模型定義與前向傳播logistic 回歸的前向傳播說白了就是三行核心公式# 輸入 X: (n_samples, n_features) # 權(quán)重 W: (n_features, 1) # 偏置 b: 標(biāo)量 # 1. 線性加權(quán) z X W b # 2. 通過 sigmoid 得到概率 p sigmoid(z)這里X W是矩陣乘法的標(biāo)準(zhǔn)寫法如果你用的是帶自動求導(dǎo)的深度學(xué)習(xí)框架這行代碼基本不用改只是封裝成網(wǎng)絡(luò)層的寫法會更簡潔。但我始終建議至少手寫一遍不借助自動求導(dǎo)的實現(xiàn)因為你只有親手寫出梯度才能真正理解反向傳播的細(xì)節(jié)。參數(shù)初始化方面logistic 回歸里把 W 設(shè)成全 0 理論上是可行的因為模型只有一個神經(jīng)元不像多層網(wǎng)絡(luò)那樣存在對稱性問題。但為了和后續(xù)深度學(xué)習(xí)實驗保持習(xí)慣一致我還是建議用小的隨機數(shù)初始化幅度控制在 0.01 左右。這樣寫的好處是你以后改造成多層網(wǎng)絡(luò)時不需要重新適應(yīng)初始化規(guī)則。構(gòu)建完模型后先用一個樣本做前向傳播手動算一遍概率和損失確認(rèn)維度都正確之后再開始訓(xùn)練。這個“先手工算一遍”的習(xí)慣能幫你省下大量調(diào)試時間。3.3 訓(xùn)練循環(huán)的搭建與監(jiān)控訓(xùn)練過程是一個不斷重復(fù)的循環(huán)核心動作可以歸納為三件事做一次前向傳播、算一次損失、更新一次參數(shù)。用偽代碼寫出來非常清晰epochs 500 learning_rate 0.1 for epoch in range(epochs): # 前向 p sigmoid(X_train W b) # 損失加一個小 epsilon 防止 log(0) loss -np.mean(y * np.log(p 1e-8) (1 - y) * np.log(1 - p 1e-8)) # 梯度推導(dǎo)結(jié)果就是 X^T (p-y) 除以樣本數(shù) grad_w X_train.T (p - y) / n_samples grad_b np.mean(p - y) # 參數(shù)更新 W - learning_rate * grad_w b - learning_rate * grad_b # 每 20 輪打印一次狀態(tài) if epoch % 20 0: acc ((p 0.5).reshape(-1) y).mean() print(fepoch {epoch}, loss {loss:.4f}, acc {acc:.4f})關(guān)于這個梯度公式 grad_w X_train.T (p - y) / n_samples我第一次推出來的時候覺得挺驚喜的logistic 回歸的梯度形式竟然和線性回歸的梯度形式長得很像都是“(預(yù)測值 - 真實值) 再乘上特征”。這背后的邏輯是交叉熵和 sigmoid 這一對組合恰好讓非線性激活函數(shù)帶來的影響在梯度里被抵消掉了只剩下一項線性的誤差信號。訓(xùn)練循環(huán)里有一個地方值得單獨強調(diào)你應(yīng)該同時記錄訓(xùn)練集和驗證集的損失與準(zhǔn)確率。很多人只盯著訓(xùn)練集看看到一個漂亮的收斂曲線就以為大功告成其實訓(xùn)練集曲線再漂亮也不能說明泛化能力只有驗證集曲線才能看出模型是否過擬合。還有 batch size 的概念。上面這個循環(huán)是每次把所有數(shù)據(jù)都拿進來更新一次梯度這叫全量梯度下降數(shù)據(jù)量小的時候沒問題。如果數(shù)據(jù)量有幾萬條每次全量計算會很慢可以每次隨機抽一小批數(shù)據(jù)比如 32 或 64 條來更新參數(shù)這就是 mini-batch 梯度下降。實驗階段用全量就夠了但如果你將來做大模型訓(xùn)練會發(fā)現(xiàn) mini-batch 幾乎是標(biāo)配。4. 訓(xùn)練調(diào)參與效果分析4.1 學(xué)習(xí)率怎么調(diào)別在玄學(xué)里浪費半天學(xué)習(xí)率大概是初學(xué)者在實驗中花費時間最多、也最容易讓人抓狂的一個超參數(shù)。我自己常用的策略是先把學(xué)習(xí)率固定在一個基準(zhǔn)值上跑一遍觀察損失曲線的形態(tài)再決定調(diào)大還是調(diào)小。學(xué)習(xí)率典型現(xiàn)象處理建議1.0 及以上損失劇烈震蕩甚至出現(xiàn) NaN立即調(diào)小 10 倍以上0.1正常收斂曲線順滑可以作為默認(rèn)起點0.01穩(wěn)定下降但速度偏慢增加迭代輪數(shù)即可0.001下降非常緩慢效率低可能需要上萬輪不建議看曲線時抓住一個核心信號損失曲線如果一路順滑下降且最終平穩(wěn)說明學(xué)習(xí)率基本合理如果先快速下降然后開始鋸齒狀抖動往往是學(xué)習(xí)率偏大如果從頭到尾都平坦得幾乎不動可能就是學(xué)習(xí)率太小或者特征沒做標(biāo)準(zhǔn)化導(dǎo)致梯度太弱。迭代輪數(shù)也不是越大越好。模型在訓(xùn)練集上損失會一直下降但驗證集的損失通常會先降后升。所以更嚴(yán)謹(jǐn)?shù)淖龇ㄊ怯?xùn)練過程中每輪都記錄驗證集損失當(dāng)驗證集損失開始上升時說明繼續(xù)訓(xùn)練已經(jīng)沒有意義了完全可以早停。這個技巧叫 early stopping在后面的深度學(xué)習(xí)課程中同樣非常實用。4.2 過擬合與欠擬合在曲線上的表現(xiàn)很多人覺得 logistic 回歸是線性模型應(yīng)該不會過擬合這個想法不完全對。當(dāng)特征數(shù)量遠(yuǎn)多于樣本數(shù)量時logistic 回歸照樣會過擬合。欠擬合的特征很典型訓(xùn)練集損失很高訓(xùn)練集準(zhǔn)確率也很低而且無論如何延長訓(xùn)練時間都上不去。這種情況多半是數(shù)據(jù)線性不可分或者特征確實和標(biāo)簽關(guān)系不大。解決方案要么是換更復(fù)雜的模型要么是構(gòu)造更有效的特征單純調(diào)參數(shù)是救不回來的。過擬合的特征正好相反訓(xùn)練集損失一路下降訓(xùn)練準(zhǔn)確率高達(dá) 95% 以上但驗證集準(zhǔn)確率停在 75% 左右上不去驗證集損失不降反升。這時可以在損失函數(shù)中加入正則項比如在交叉熵基礎(chǔ)上加 λ/2·||W||2對應(yīng)的梯度更新代碼只需要多減一項 λ·W。這一步加進去你會觀察到驗證集表現(xiàn)有明顯改善。這也是后續(xù)深度學(xué)習(xí)實驗里 weight decay 概念的起源。4.3 評估指標(biāo)別讓準(zhǔn)確率騙了你實驗報告里如果只寫一個準(zhǔn)確率那你大概率會被追問一個問題如果測試集里 90% 是負(fù)樣本10% 是正樣本一個無腦把所有樣本都預(yù)測為負(fù)樣本的模型準(zhǔn)確率是多少答案是 90%。所以準(zhǔn)確率在類別不平衡的數(shù)據(jù)集上是非常具有欺騙性的。更完整的評估體系是看混淆矩陣以及由它引出的幾個指標(biāo)精確率 Precision TP / (TP FP)就是預(yù)測為正樣本的那些里有多少是真的正樣本。垃圾郵件過濾場景更看重這個誤殺一封正常郵件比漏掉一封垃圾郵件嚴(yán)重得多。召回率 Recall TP / (TP FN)就是真實正樣本里有多少被找出來了。疾病篩查場景更看重這個寧可多查幾次也不能漏診。F1 分?jǐn)?shù)是兩者的調(diào)和平均適合需要同時兼顧精確率和召回率的場景。還有一個在實驗報告中很加分的指標(biāo)是 AUC也就是 ROC 曲線下的面積。它衡量的是模型“隨機抽一對正負(fù)樣本把正樣本排在前面的概率”所以它不受分類閾值的影響能更全面地反映模型的排序能力。AUC 在 0.5 附近說明模型跟瞎猜差不多越接近 1 說明區(qū)分能力越強。我建議你在實驗里把準(zhǔn)確率、精確率、召回率、F1、AUC 都算一遍然后寫進報告順便對比一下它們在當(dāng)前數(shù)據(jù)集下的表現(xiàn)。這樣一份實驗報告交上去老師一眼就能看出你是真把二分類模型玩明白了而不是只會調(diào)一個包然后打印 accuracy。5. 常見問題與避坑實錄5.1 損失不下降、甚至變成 NaN這是每次實驗都有一半人會碰到的問題排查順序很重要不要病急亂投醫(yī)。第一件事看學(xué)習(xí)率。如果 loss 從第一輪開始就是 NaN那大概率是學(xué)習(xí)率設(shè)太大參數(shù)更新一步就飛出去了。先把學(xué)習(xí)率降到 0.001 試試如果恢復(fù)正常再逐步往上加。第二件事看特征尺度。沒有標(biāo)準(zhǔn)化的數(shù)據(jù)特征范圍如果達(dá)到幾千z 的值也會變得很大sigmoid 直接飽和梯度小到幾乎為 0損失變化慢得像蝸牛。這時你看到的就是 loss 在下降趨勢上“一動不動”而不是上下震蕩。第三件事檢查數(shù)據(jù)本身。用代碼檢查一下 X 和 y 里有沒有 NaN這個操作很多人會跳過但真實數(shù)據(jù)里確實容易出現(xiàn)空值。第四件事確認(rèn)形狀。如果 p 和 y 的 shape 不對loss 和梯度都可能算出一個奇怪的值。打印 p.shape 和 y.shape一眼就能發(fā)現(xiàn)。這里也順便給自己留個好習(xí)慣在計算 log(p) 和 log(1-p) 時加一個極小值兜底比如 log(p 1e-8)防止 p 被算出恰好為 0 導(dǎo)致的無窮大問題。5.2 訓(xùn)練集損失在降驗證集準(zhǔn)確率卻紋絲不動這個現(xiàn)象背后的原因通常有三個。數(shù)據(jù)劃分有問題沒有分層抽樣導(dǎo)致驗證集里某一類樣本特別多模型學(xué)到的模式在驗證集上根本不適用。標(biāo)準(zhǔn)化信息泄露直接在全體數(shù)據(jù)上做了標(biāo)準(zhǔn)化再劃分?jǐn)?shù)據(jù)集這種操作會讓模型在驗證集上的表現(xiàn)虛高然后在換一份真實數(shù)據(jù)測試時瞬間打回原形。樣本量太少驗證集只有幾十條樣本時評估結(jié)果方差會很大今天 80%明天 60%根本沒有參考價值。最穩(wěn)妥的方案是先劃分訓(xùn)練集和測試集再只對訓(xùn)練集做標(biāo)準(zhǔn)化。劃分時使用分層采樣保證類別比例一致。如果數(shù)據(jù)量太少可以考慮用交叉驗證來替代單次劃分。5.3 準(zhǔn)確率很高但 F1 很低怎么辦準(zhǔn)確率 85%、F1 卻只有 30%這種情況在類別不平衡的數(shù)據(jù)集里非常典型。你可以想象一下一個數(shù)據(jù)集有 900 個負(fù)樣本和 100 個正樣本模型把所有樣本都預(yù)測為負(fù)類準(zhǔn)確率是 90%但召回率是 0%F1 自然低得可憐。想讓模型真正學(xué)會抓少數(shù)類有兩條路調(diào)整分類閾值。不要把閾值死定為 0.5可以把閾值調(diào)到 0.3 或更低讓模型更容易判定為正類。你可以在驗證集上畫一條 precision-recall 隨閾值變化的曲線看閾值放在哪個位置能讓 F1 最高。給少數(shù)類更大的權(quán)重。在損失函數(shù)中給正樣本乘以一個大于 1 的權(quán)重相當(dāng)于人為放大正樣本的犯錯成本讓模型更愿意去擬合少數(shù)類。這兩條路在 logistic 回歸里都可以輕松實現(xiàn)建議你都試一遍然后在報告里寫清楚你對閾值的理解這會比單純說“我調(diào)了學(xué)習(xí)率”更有說服力。5.4 一個救命調(diào)試技巧先過擬合一個小批量這是我自己用得非常多的調(diào)試套路。在訓(xùn)練之前先只取 8 個樣本作為訓(xùn)練集跑一個小規(guī)模訓(xùn)練。如果代碼邏輯沒問題模型的損失應(yīng)該會在幾十個 epoch 內(nèi)快速降到接近于 0訓(xùn)練準(zhǔn)確率能到 100%。如果小批量數(shù)據(jù)都無法過擬合那說明你的前向傳播、損失函數(shù)或者梯度更新里面一定有 bug先把這個 bug 找出來再說。這么做最大的意義在于它把“模型學(xué)習(xí)的邏輯”和“數(shù)據(jù)規(guī)模帶來的問題”分開排查了。等小批量能過擬合再切回全量數(shù)據(jù)這時你面對的就只剩下學(xué)習(xí)率、正則化這些正經(jīng)調(diào)參問題而不是跟一個寫錯符號的梯度公式搏斗兩個小時。寫到最后的一些實在話這個實驗我前前后后重寫過很多遍每寫一遍都有新的理解。第一遍用深度學(xué)習(xí)框架跑通的時候我只知道調(diào)包很多細(xì)節(jié)是懵的第二遍強迫自己手寫前向和梯度更新才算真正搞懂 sigmoid 和交叉熵為什么是一對好搭檔第三遍加上正則化和評估指標(biāo)才發(fā)現(xiàn)自己以前對實驗報告的理解太淺了。我建議你也找時間做一次“手寫版”的 logistic 回歸哪怕只是抽出半天時間它的價值遠(yuǎn)比你跑來跑去調(diào)學(xué)習(xí)率大得多。最后再分享一個實戰(zhàn)小技巧很多同學(xué)在這個實驗里會把大量時間耗在調(diào)學(xué)習(xí)率上但實際操作中最有效的路徑是先固定一個學(xué)習(xí)率、把整個流程跑通確保代碼無誤再回頭調(diào)參。先保證流程完整再追求性能優(yōu)化——這個順序在后面的所有深度學(xué)習(xí)項目里都不會變。