戰(zhàn):從條件向量場(chǎng)到少步采樣)
做生成模型這兩年Flow MatchingFM這個(gè)名字出現(xiàn)的頻率越來(lái)越高。我第一次真正理解它是在復(fù)現(xiàn)擴(kuò)散模型的過(guò)程中發(fā)現(xiàn)不少人把 DDPM 的噪聲預(yù)測(cè)直接改成速度預(yù)測(cè)訓(xùn)練流程更簡(jiǎn)單采樣還能用更少的步數(shù)生成質(zhì)量卻幾乎不掉。后來(lái)才意識(shí)到這就是 Flow Matching 的核心思想之一。Flow Matching 本質(zhì)上是生成模型的一套訓(xùn)練框架目標(biāo)是把一個(gè)簡(jiǎn)單分布——通常是標(biāo)準(zhǔn)高斯噪聲——通過(guò)一個(gè)隨時(shí)間變化的向量場(chǎng)平滑地“推”到數(shù)據(jù)分布上。它解決了傳統(tǒng)連續(xù)歸一化流訓(xùn)練困難、采樣昂貴的痛點(diǎn)又能直接兼容擴(kuò)散模型那套網(wǎng)絡(luò)結(jié)構(gòu)和采樣器。任何用過(guò)擴(kuò)散模型的人或者想系統(tǒng)入門(mén)生成模型的人把這一套吃透都很有價(jià)值。這篇文章會(huì)從核心原理講到實(shí)操細(xì)節(jié)把我踩過(guò)的坑一并寫(xiě)出來(lái)盡量講人話。1. Flow Matching 到底在解決什么問(wèn)題1.1 它在生成模型地圖上的位置先梳理一下生成模型的大致路線。一類(lèi)是 GAN 那種對(duì)抗式思路訓(xùn)練一個(gè)生成器騙過(guò)判別器一類(lèi)是變分自編碼器把數(shù)據(jù)壓到隱空間再采樣重建還有一類(lèi)是基于似然的模型比如自回歸模型一步一步預(yù)測(cè)下一個(gè) token 或像素。擴(kuò)散模型和 Flow Matching 都屬于“先加噪再學(xué)去噪”這個(gè)大家族從純?cè)肼暢霭l(fā)通過(guò)一個(gè)確定性的或帶隨機(jī)性的過(guò)程一步步演變成數(shù)據(jù)樣本。這個(gè)家族里有個(gè)共同點(diǎn)我們并不直接學(xué)數(shù)據(jù)的概率密度而是學(xué)一個(gè)“演變規(guī)則”。擴(kuò)散模型學(xué)的是噪聲預(yù)測(cè)或分?jǐn)?shù)Flow Matching 學(xué)的則是速度場(chǎng)velocity field。形式不同底層邏輯相通。如果只看采樣過(guò)程兩者都像在解一個(gè)常微分方程O(píng)DE給定初始噪聲按學(xué)到的場(chǎng)一步一步推進(jìn)到數(shù)據(jù)。Flow Matching 的特殊之處在于它把“連續(xù)歸一化流”Continuous Normalizing Flow下稱(chēng) CNF這種理論上很優(yōu)雅、實(shí)操上很難訓(xùn)的模型拉回到了可以落地的水平。CNF 的名字里帶“流”因?yàn)樗逊植甲兓醋髁W釉谙蛄繄?chǎng)中隨時(shí)間流動(dòng)。雖然表達(dá)式很漂亮但訓(xùn)練困難一直勸退很多人。Flow Matching 就是來(lái)解決這個(gè)問(wèn)題的。1.2 連續(xù)歸一化流到底難在哪要理解 Flow Matching 的價(jià)值得先明白 CNF 為什么讓人頭疼。CNF 定義一個(gè)隨時(shí)間變化的向量場(chǎng) v(x, t)粒子從這個(gè)場(chǎng)里流動(dòng)密度隨時(shí)間演化。給定初始分布 p_0這個(gè)向量場(chǎng)就唯一決定了一個(gè)后續(xù)分布 p_t并且它們之間由“連續(xù)性方程”約束?p_t/?t -?·(p_t v_t)如果我要讓 p_1 正好等于數(shù)據(jù)分布理論上只需要找到一個(gè)合適的向量場(chǎng)讓這個(gè)方程的解在 t1 時(shí)落到數(shù)據(jù)分布上。問(wèn)題在于我怎么知道某個(gè)向量場(chǎng)對(duì)應(yīng)哪個(gè)分布直接算的話需要對(duì)整個(gè)空間做積分還要考慮無(wú)窮多個(gè)粒子軌跡的相互作用。高維數(shù)據(jù)比如 128×128×3 的圖像下這個(gè)全局向量場(chǎng)根本無(wú)法顯式寫(xiě)出更別說(shuō)監(jiān)督訓(xùn)練。傳統(tǒng)做法是用最大似然估計(jì)但每一步都需要通過(guò)積分來(lái)模擬整條軌跡成本極高而且積分誤差會(huì)隨著訓(xùn)練不斷累積。這就是為什么早年 CNF 只在小規(guī)模、低維數(shù)據(jù)上玩得轉(zhuǎn)拿到圖像和音頻上基本動(dòng)彈不得。1.3 用一條條件化思路破局Flow Matching 的破局思路非常樸素我不去求那個(gè)不可見(jiàn)的全局向量場(chǎng)而是自己“構(gòu)造”一堆條件向量場(chǎng)再把它們的期望當(dāng)作訓(xùn)練目標(biāo)。什么意思呢假設(shè)你知道每個(gè)真實(shí)樣本 x_1那么你可以人為指定一條從噪聲到 x_1 的路徑——比如“噪聲和真實(shí)樣本做線性插值”。對(duì)每一條這樣的單樣本路徑向量場(chǎng)是能顯式寫(xiě)出來(lái)的。然后讓神經(jīng)網(wǎng)絡(luò)去擬合這個(gè)條件向量場(chǎng)對(duì)所有的樣本、所有的時(shí)間 t 求平均。關(guān)鍵點(diǎn)在于這些條件向量場(chǎng)的邊緣聚合效應(yīng)恰好等價(jià)于某個(gè)全局概率路徑的向量場(chǎng)。也就是說(shuō)一個(gè)原本要解全局問(wèn)題的任務(wù)被拆成了無(wú)數(shù)個(gè)局部的、簡(jiǎn)單的條件回歸任務(wù)。每個(gè)條件回歸只看“從當(dāng)前狀態(tài)走向哪個(gè)目標(biāo)樣本”不需要知道整個(gè)分布的演化。這個(gè)拆法在數(shù)學(xué)上是可證明的在期望意義下匹配條件向量場(chǎng)和匹配邊緣向量場(chǎng)梯度方向是一致的。這個(gè)思想并不復(fù)雜但效果很直接——訓(xùn)練變成純粹的回歸問(wèn)題像監(jiān)督學(xué)習(xí)一樣穩(wěn)定不需要最大似然不需要對(duì)抗訓(xùn)練也不需要數(shù)值積分。只要網(wǎng)絡(luò)容量夠多訓(xùn)一段時(shí)間就能得到一個(gè)能用的向量場(chǎng)。這套框架就是 Flow MatchingFM也常被稱(chēng)為條件流匹配Conditional Flow MatchingCFM。2. 概率路徑和向量場(chǎng)到底怎么構(gòu)造2.1 先厘清幾個(gè)基本概念Flow Matching 里有三個(gè)關(guān)鍵角色概率路徑probability path、向量場(chǎng)vector field、流flow。概率路徑描述的是“t 時(shí)刻的分布長(zhǎng)什么樣”記作 p_t(x)。當(dāng) t0 時(shí)是噪聲分布通常取標(biāo)準(zhǔn)高斯當(dāng) t1 時(shí)是數(shù)據(jù)分布。中間態(tài)則是從噪聲到數(shù)據(jù)的過(guò)渡分布。向量場(chǎng) v_t(x) 告訴每個(gè)位置的粒子該往哪個(gè)方向運(yùn)動(dòng)是學(xué)習(xí)的目標(biāo)。流則是這個(gè)向量場(chǎng)的積分結(jié)果沿著向量場(chǎng)走粒子從初始位置會(huì)運(yùn)動(dòng)到終點(diǎn)。把三者串起來(lái)理解給定一個(gè)初始分布和一個(gè)向量場(chǎng)粒子演化出的分布軌跡就是概率路徑。反過(guò)來(lái)如果你想好了概率路徑也能反推向量場(chǎng)。Flow Matching 的思路是先手工設(shè)計(jì)一條好的條件概率路徑每個(gè)真實(shí)樣本 x_1 有自己的“私人路線”再據(jù)此算出條件向量場(chǎng)最后用神經(jīng)網(wǎng)絡(luò)回歸這個(gè)條件向量場(chǎng)。網(wǎng)絡(luò)學(xué)到的東西會(huì)被用作采樣時(shí)的 ODE 速度。2.2 最常用的線性插值路徑怎么算最常見(jiàn)的路徑構(gòu)造方式是線性插值。對(duì)任意一個(gè)真實(shí)樣本 x_1再?gòu)臉?biāo)準(zhǔn)高斯里取樣一個(gè)噪聲 x_0定義x_t (1-t) x_0 t x_1t0 時(shí) x_t 就是純?cè)肼晅1 時(shí)正好是數(shù)據(jù)點(diǎn)。t 在中間時(shí)x_t 是噪聲和數(shù)據(jù)的加權(quán)平均。這個(gè)線性插值路徑對(duì)應(yīng)的分布也很好算如果把 x_0 的分布固定為標(biāo)準(zhǔn)高斯那么給定 x_1 時(shí) x_t 服從一個(gè)均值為 t x_1、方差為 (1-t)2 的高斯分布。下一步是求條件向量場(chǎng)。對(duì)上面的式子兩邊對(duì) t 求導(dǎo)dx_t/dt x_1 - x_0但問(wèn)題是采樣時(shí) x_0 我們不知道網(wǎng)絡(luò)也看不到 x_0。所以要把式子改寫(xiě)掉。因?yàn)?x (1-t)x_0 t x_1反解出 x_0 (x - t x_1)/(1-t)代入導(dǎo)數(shù)式dx_t/dt x_1 - (x - t x_1)/(1-t) (x_1 - x)/(1-t)這就是那個(gè)經(jīng)典的條件向量場(chǎng)形式u_t(x|x_1) (x_1 - x) / (1-t)注意看好這個(gè)向量場(chǎng)只依賴(lài)當(dāng)前的 x、目標(biāo) x_1 和時(shí)間 t不再依賴(lài)噪聲 x_0。訓(xùn)練時(shí)網(wǎng)絡(luò)輸入 (x_t, t)輸出一個(gè)和 x 同維度的向量目標(biāo)就是讓輸出逼近 (x_1 - x)/(1-t)。順帶說(shuō)一句如果你的路徑定義換成更一般的 a(t)x_0 b(t)x_1向量場(chǎng)形式會(huì)變成 (b(t)x_1 a(t)x_0)再消去 x_0 就得到一般式。線性插值只是最簡(jiǎn)單、最好用的那一種。2.3 路徑形狀直接決定采樣效率路徑設(shè)計(jì)不只是“隨便定一條線”它直接影響采樣需要多少步。擴(kuò)散模型的概率路徑是彎的。從純?cè)肼暤綌?shù)據(jù)中間過(guò)程看起來(lái)像一條弧線粒子走的是曲線軌跡。對(duì)曲線軌跡做數(shù)值積分步數(shù)少了誤差就大這就是為什么擴(kuò)散模型動(dòng)輒需要幾十上百步采樣。Flow Matching 如果用線性插值路徑粒子軌跡更接近直線。直線軌跡的數(shù)值積分誤差要小得多同樣是 Euler 方法20 步可能就夠用加速到 10 步也不覺(jué)得質(zhì)量有明顯下降。更極致的是把軌跡“拉直”。如果你用最優(yōu)傳輸?shù)呐鋵?duì)方式——把和噪聲樣本“最匹配”的數(shù)據(jù)樣本配到一起——那么每一條條件路徑會(huì)非常接近直線甚至接近“每個(gè)粒子沿直線從噪聲走到數(shù)據(jù)”。路徑越直少步采樣的上限越高這也是后面整流、再訓(xùn)練reflow這類(lèi)玩法的底層動(dòng)機(jī)。斷論很簡(jiǎn)單路徑的彎曲程度基本決定了最終能用多少步采樣換回同級(jí)別的質(zhì)量。3. 訓(xùn)練目標(biāo)和完整流程3.1 訓(xùn)練損失是怎么來(lái)的Flow Matching 的訓(xùn)練目標(biāo)長(zhǎng)得很像普通的 L2 回歸。用 θ 參數(shù)化的網(wǎng)絡(luò) v_θ(t, x) 去逼近條件向量場(chǎng) u_t(x|x_1)損失是L E_{t, x_1, x_0} [ || v_θ(t, x_t) - (x_1 - x)/(1-t) ||2 ]x_0 從標(biāo)準(zhǔn)高斯采樣x_1 從數(shù)據(jù)集采樣t 從 [0, 1] 采樣x_t (1-t)x_0 t x_1。有人可能會(huì)困惑為什么回歸“帶條件的私人向量場(chǎng)”最后學(xué)到的卻是一個(gè)“全局向量場(chǎng)”這正是上一章說(shuō)的關(guān)鍵定理。所有條件路徑的邊緣分布如果等于真實(shí)數(shù)據(jù)的邊緣分布那么條件向量場(chǎng)關(guān)于 x_1 的期望就重構(gòu)出了全局向量場(chǎng)。而平方損失在取期望時(shí)條件向量場(chǎng)里對(duì) x_1 的隱式依賴(lài)恰好被積分掉導(dǎo)致梯度和直接回歸全局向量場(chǎng)一致。所以即使網(wǎng)絡(luò)從沒(méi)見(jiàn)過(guò) x_1 的“身份”從數(shù)據(jù)分布平均意義上看它就是那個(gè)全局速度場(chǎng)。這個(gè)性質(zhì)的直接意義是你可以用最簡(jiǎn)單的最小二乘邏輯去理解整個(gè)訓(xùn)練不用管什么連續(xù)性方程、什么最大似然穩(wěn)定的很。3.2 訓(xùn)練與采樣偽代碼走一遍直接給一套能跑的偽代碼方便你對(duì)照著復(fù)現(xiàn)。# 訓(xùn)練單步更新 import torch def train_step(model, x1, optimizer): # x1: batch 的真實(shí)數(shù)據(jù), shape [B, C, H, W] B x1.size(0) # 采樣時(shí)間 t ~ U[0, 1)工程上常用 [0, 0.999] 避免除零 t torch.rand(B, devicex1.device) * 0.999 t t[:, None, None, None] # 廣播到空間維度 # 采樣噪聲 x0 ~ N(0, I) x0 torch.randn_like(x1) # 線性插值得到中間狀態(tài) xt (1 - t) * x0 t * x1 # 條件向量場(chǎng)目標(biāo) u x1 - x0 # 等價(jià)于 (x1 - xt) / (1 - t) # 網(wǎng)絡(luò)預(yù)測(cè)速度 v_pred model(xt, t.squeeze()) # MSE 損失 loss torch.mean((v_pred - u) ** 2) optimizer.zero_grad() loss.backward() optimizer.step() return loss.item()注意這里目標(biāo)寫(xiě)成了x1 - x0和(x1 - xt)/(1-t)完全等價(jià)因?yàn)?xt (1-t)x0 t x1。用哪一種都行數(shù)值上推薦后者更穩(wěn)一些尤其是 t 接近 1 時(shí)前者的梯度路徑不會(huì)有分母爆炸問(wèn)題但前者實(shí)現(xiàn)更簡(jiǎn)單。我在自己的實(shí)現(xiàn)里兩種都試過(guò)差異不大關(guān)鍵是別在 t1 處讓分母變成零。采樣是反向過(guò)程順著 ODE 積分。記住路徑方向是從噪聲到數(shù)據(jù)也就是 t 從 0 往 1 走# 采樣Euler 法求解 ODE def sample(model, steps20, latentNone): if latent is None: x torch.randn(1, C, H, W, devicedevice) else: x latent.clone() dt 1.0 / steps for i in range(steps): t torch.full((1,), i / steps, devicedevice) v model(x, t) x x dt * v return x有一個(gè)比較容易搞反的細(xì)節(jié)很多擴(kuò)散代碼里采樣是 t 從大的往小的走從純?cè)肼暤綌?shù)據(jù)是 tT→0而 Flow Matching 線性插值路徑里 t 從 0 到 1 才是去噪方向。寫(xiě)循環(huán)之前先想清楚你的 t 語(yǔ)義不然會(huì)訓(xùn)出來(lái)亂飛的場(chǎng)。3.3 和擴(kuò)散模型的等價(jià)性與差異用慣擴(kuò)散模型的人一定會(huì)發(fā)現(xiàn)Flow Matching 的這套訓(xùn)練和擴(kuò)散模型本質(zhì)上可以互相轉(zhuǎn)化。擴(kuò)散模型前向過(guò)程是 x_t √(α?_t) x_1 √(1-α?_t) ε網(wǎng)絡(luò)預(yù)測(cè)噪聲 εFlow Matching 是線性插值網(wǎng)絡(luò)預(yù)測(cè)速度 v。兩邊的網(wǎng)絡(luò)輸入結(jié)構(gòu)幾乎一樣就是“帶噪樣本 時(shí)間”只是輸出頭的含義不同。如果把擴(kuò)散模型的 ODE 形式改寫(xiě)模型輸出的噪聲項(xiàng)可以變成一個(gè)組合的速度量。反過(guò)來(lái)Flow Matching 學(xué)到的速度也能還原成某種分?jǐn)?shù)或噪聲預(yù)測(cè)。換句話說(shuō)選擇一個(gè)特定的概率路徑和一個(gè)特定的噪聲調(diào)度擴(kuò)散模型就是 Flow Matching 在某種參數(shù)化下的特例。這也是為什么很多庫(kù)比如社區(qū)的 diffusers 生態(tài)可以直接用幾乎相同的 U-Net 或 DiT 主干同時(shí)支持兩種范式。差異主要在訓(xùn)練目標(biāo)的簡(jiǎn)潔性上。擴(kuò)散模型的訓(xùn)練往往需要仔細(xì)設(shè)計(jì)噪聲調(diào)度、損失加權(quán)Flow Matching 的默認(rèn)配置就是均勻時(shí)間采樣、L2 速度回歸超參數(shù)少了好幾個(gè)。我的體感是在沒(méi)有專(zhuān)門(mén)調(diào)參的情況下Flow Matching 的穩(wěn)定性通常更好尤其是對(duì)梯度的尺度波動(dòng)沒(méi)擴(kuò)散那么敏感。4. 實(shí)操中真正要關(guān)心的細(xì)節(jié)4.1 時(shí)間采樣策略別只會(huì)均勻采樣論文和最簡(jiǎn)單的實(shí)現(xiàn)都用 t ~ U[0,1]這個(gè)確實(shí)能訓(xùn)。但實(shí)際訓(xùn)練中均勻采樣不是最優(yōu)的。原因在于損失在不同 t 區(qū)間的量級(jí)和重要性不均勻。t 接近 0 時(shí)x_t 基本就是噪聲目標(biāo)向量場(chǎng)很大概率指向真實(shí)數(shù)據(jù)分布這個(gè)區(qū)域的損失很“重”但網(wǎng)絡(luò)學(xué)到的主要是如何從噪聲起步t 接近 1 時(shí)x_t 已經(jīng)很接近數(shù)據(jù)結(jié)構(gòu)細(xì)節(jié)最多但目標(biāo)值的絕對(duì)值小損失量級(jí)也被壓縮網(wǎng)絡(luò)容易忽略這一段的細(xì)節(jié)優(yōu)化。真正決定生成內(nèi)容“長(zhǎng)什么樣”的中間時(shí)間段在均勻采樣下被分配的樣本不見(jiàn)得夠。我實(shí)踐下來(lái)有兩種有效做法。第一種是把 t 的采樣分布往中間聚攏比如用 logit-normal 分布或者 beta 分布讓中段時(shí)間被更多次采樣。第二種是簡(jiǎn)單粗暴地把 t 的范圍截?cái)啾热绮蓸訁^(qū)間 [0.001, 0.999]避免端點(diǎn)極端情況。注意截?cái)嗖灰^(guò)度否則網(wǎng)絡(luò)在極端 t 區(qū)域沒(méi)有見(jiàn)過(guò)樣本推理時(shí)會(huì)空轉(zhuǎn)。還可以做自適應(yīng)重要性采樣先跑一小段訓(xùn)練記錄損失曲線然后按損失大小調(diào)整 t 的概率密度把更多訓(xùn)練配額分給“還沒(méi)學(xué)好的時(shí)間點(diǎn)”。這類(lèi)做法收益有時(shí)候不小但工程復(fù)雜度略高小項(xiàng)目可以先不上。4.2 網(wǎng)絡(luò)工程與超參數(shù)Flow Matching 對(duì)主干網(wǎng)絡(luò)的選法幾乎照搬擴(kuò)散模型U-Net、DiT、帶時(shí)間嵌入的 Transformer 都可以。輸入是帶噪樣本和時(shí)間輸出和輸入同維度。關(guān)鍵差別只有一個(gè)輸出通道預(yù)測(cè)的是速度而非噪聲但這不影響網(wǎng)絡(luò)結(jié)構(gòu)設(shè)計(jì)只影響初始化。實(shí)話說(shuō)直接在現(xiàn)有擴(kuò)散代碼里把輸出頭改成預(yù)測(cè)速度然后換掉訓(xùn)練目標(biāo)一般就能跑通。訓(xùn)練超參方面我建議先沿用擴(kuò)散模型的默認(rèn)配置圖像類(lèi)的 U-Net 用約 1e-4 的學(xué)習(xí)率Transformer 類(lèi)主干通常配合 AdamW微調(diào)時(shí)甚至可以拉到 1e-5。batch size 的影響比學(xué)習(xí)率更隱蔽——Flow Matching 的條件向量場(chǎng)期望是在所有樣本上取的batch 太小期望的估計(jì)方差大損失曲線會(huì)抖但最終影響有限。EMA指數(shù)移動(dòng)平均強(qiáng)烈建議開(kāi)和老經(jīng)驗(yàn)一樣能顯著改善采樣質(zhì)量方差。數(shù)據(jù)的預(yù)處理也值得上心。輸入必須做歸一化到比如 [-1, 1]不然和標(biāo)準(zhǔn)高斯噪聲的量綱對(duì)不上。如果你的數(shù)據(jù)本身方差特別大或特別小線性插值的中間態(tài)方差會(huì)被噪聲主導(dǎo)網(wǎng)絡(luò)學(xué)到的是“不動(dòng)”而不是“演化”。時(shí)間嵌入建議用標(biāo)準(zhǔn)的 sinusoidal embedding 或者 RoPE 風(fēng)格的位置編碼。有的實(shí)現(xiàn)會(huì)把時(shí)間 t 先做縮放再進(jìn)網(wǎng)絡(luò)比如乘 1000 再編碼模仿擴(kuò)散模型的 timestep 習(xí)慣這個(gè)細(xì)節(jié)是否必要有爭(zhēng)議但兼容性更好我傾向于保留。4.3 采樣器與步數(shù)的權(quán)衡Flow Matching 訓(xùn)練完得到的是一個(gè)確定性 ODE采樣就是對(duì)它做數(shù)值積分。最簡(jiǎn)單也是我用得最多的是 Euler 方法。路徑比較直的時(shí)候20 步 Euler 足夠10 步也能出圖只是細(xì)節(jié)略軟。想要在少步數(shù)下提升質(zhì)量換成 Heun 法二階 Runge-Kutta是最便宜的升級(jí)一個(gè)額外評(píng)估步可以把 10 步 Euler 的質(zhì)量拉到接近 20 步。還有一類(lèi)技巧是把擴(kuò)散界成熟的 ODE 求解器搬過(guò)來(lái)用比如 DPM-Solver 這類(lèi)高階求解器在 Flow Matching 的 ODE 上同樣有效。實(shí)際操作時(shí)我一般不自己寫(xiě)求解器直接用訓(xùn)練框架里現(xiàn)成的采樣器接口改改 step 數(shù)和 order。步數(shù)不是越少越好。太少的步數(shù)即使路徑很直也會(huì)出現(xiàn)“中間崩塌”現(xiàn)象大量噪聲粒子走到半路就開(kāi)始互相碰撞生成結(jié)果出現(xiàn)平均化、顏色發(fā)灰。如果模型路徑不太直這個(gè)問(wèn)題更明顯。想壓步數(shù)正確路線是先做整流把路徑拉直再降步數(shù)而不是硬用 2 步去 Ealer 一個(gè)彎路徑。5. 踩坑記錄常見(jiàn)問(wèn)題與排查思路5.1 訓(xùn)練崩潰、NaN 或損失爆炸Flow Matching 雖然比擴(kuò)散穩(wěn)定但照樣有主人遇過(guò) NaN。最常見(jiàn)原因有三個(gè)。第一個(gè)是 t1 處的除零。如果你在損失里用(x1 - xt)/(1-t)這種顯式分母采樣點(diǎn)一旦正好落在 1分母為 0梯度直接爆炸。解決方法是把 t 的采樣上限定在 0.999。別想著“概率為零不會(huì)碰到”浮點(diǎn)邊界下什么都可能發(fā)生。第二個(gè)是學(xué)習(xí)率過(guò)大加上混合精度。fp16 訓(xùn)練時(shí)速度場(chǎng)的梯度尺度偶爾很大容易被裁剪成 NaN。我自己的排查順序是先關(guān)掉混合精度跑幾百步如果消失那問(wèn)題在動(dòng)態(tài)損失縮放如果還在再把學(xué)習(xí)率減半?;旌暇缺旧砗?Flow Matching 沒(méi)有矛盾但首次復(fù)現(xiàn)時(shí)建議先跑 fp32減少變量。第三個(gè)是網(wǎng)絡(luò)初始化不當(dāng)。某些代碼里直接把擴(kuò)散模型權(quán)重遷移過(guò)來(lái)當(dāng)初始化預(yù)測(cè)頭的統(tǒng)計(jì)特性不匹配早期損失巨大且不穩(wěn)定。如果從零訓(xùn)練最好讓最后一層輸出用零初始化或者小方差初始化讓初始預(yù)測(cè)速度接近零這樣開(kāi)始的優(yōu)化比較平緩。排查時(shí)先看 loss 曲線NaN 之前一般伴隨 loss 突然飆升到極大值。把 t 的分布畫(huà)出來(lái)如果爆炸集中在 t 接近 0 或接近 1 的區(qū)間基本就是對(duì)端點(diǎn)的處理有問(wèn)題。5.2 生成模糊、偏灰或者全是“平均值”另一個(gè)高頻問(wèn)題采樣結(jié)果看起來(lái)模模糊糊像數(shù)據(jù)集的平均臉顏色發(fā)灰細(xì)節(jié)全丟。這個(gè)本質(zhì)上是生成分布沒(méi)有完全推到數(shù)據(jù)分布上粒子在半路停了或者方向不對(duì)。先做最小化排查按這個(gè)順序先加采樣步數(shù)。如果從 10 步加到 50 步有明顯改善說(shuō)明路徑不夠直或積分器太粗糙此時(shí)對(duì)癥下藥是整流或換 Heun而不是一味加步數(shù)。對(duì)比訓(xùn)練集上的重構(gòu)能力。拿真實(shí)樣本作為初始 x_t 的端點(diǎn)做一次完整 ODE 積分看能不能回到原圖附近。如果不能說(shuō)明網(wǎng)絡(luò)沒(méi)有把尾部細(xì)節(jié)學(xué)好重點(diǎn)檢查 t 接近 1 的采樣密度。檢查數(shù)據(jù)歸一化和反歸一化。生成結(jié)果偏灰常常是模型在 [-1,1] 空間輸出卻被當(dāng)成了 [0,1] 空間顯示或者噪聲初始化方差和數(shù)據(jù)不在同一量綱。檢查 EMA。有些實(shí)現(xiàn)把 EMA 權(quán)重忘在舊狀態(tài)模型實(shí)際能力已經(jīng)上去了但采樣用的是陳舊版本。還有一點(diǎn)容易忽略Flow Matching 里的噪聲是 x_0 ~ N(0, I)但如果你在隱空間訓(xùn)練比如先編碼到 VAE 的 latent那個(gè) latent 的先驗(yàn)分布未必是標(biāo)準(zhǔn)高斯。這時(shí)候把采樣起點(diǎn)改成數(shù)據(jù)分布估算的均值和方差效果立刻不一樣。5.3 和擴(kuò)散基線對(duì)比時(shí)常見(jiàn)的對(duì)比誤區(qū)Flow Matching 最常被問(wèn)的問(wèn)題就是“和擴(kuò)散比到底誰(shuí)強(qiáng)”。我見(jiàn)過(guò)太多不公允的對(duì)比結(jié)論也不可信。最容易犯的錯(cuò)誤是不同 NFE函數(shù)評(píng)估次數(shù)下對(duì)比。擴(kuò)散模型用 1000 步、Flow Matching 用 10 步這不叫公平對(duì)比。正確做法是固定 NFE例如兩邊都用 20 步或 50 步然后用同一個(gè)評(píng)價(jià)指標(biāo)算。另一個(gè)錯(cuò)誤是用不同的網(wǎng)絡(luò)骨架一邊是 U-Net 一邊是更大的 DiT網(wǎng)絡(luò)容量本身就不是一個(gè)量級(jí)。對(duì)比前先把骨干統(tǒng)一、數(shù)據(jù)預(yù)處理統(tǒng)一、訓(xùn)練步數(shù)統(tǒng)一。還有一個(gè)坑Flow Matching 和擴(kuò)散使用不同的噪聲調(diào)度時(shí)最優(yōu)采樣器也不同。拿擴(kuò)散專(zhuān)用采樣器去跑 Flow Matching 的模型或者反過(guò)來(lái)都會(huì)給出一個(gè)系統(tǒng)性偏差的結(jié)果。如果你只是為了比較生成能力先各自用各自最優(yōu)的采樣配置再比較如果你為了驗(yàn)證“少步采樣”那就要明確說(shuō)明是哪種路徑、哪種采樣器下的結(jié)論。6. 一些擴(kuò)展思考和我的實(shí)操建議6.1 少步采樣整流、再訓(xùn)練與一步生成既然路徑越直越能少步采樣那“把路徑拉直”就成了一門(mén)生意。做法是先訓(xùn)練好一個(gè) Flow Matching 模型然后拿它去采一批 (噪聲, 生成結(jié)果) 的配對(duì)再用這些配對(duì)重新訓(xùn)練一個(gè)新的 Flow Matching 模型但這次樣本配對(duì)更“對(duì)齊”路徑更直。這個(gè)過(guò)程可以重復(fù)每一步都會(huì)讓軌跡更接近直線。到第二輪之后2 步、甚至 1 步采樣就有了實(shí)用意義。這個(gè)思路也延伸到了蒸餾方向直接把多步模型的輸出提煉到一個(gè)“一步生成”的模型里。Flow Matching 因?yàn)槌跏悸窂骄拖鄬?duì)直蒸餾難度低于擴(kuò)散模型。我自己試過(guò)在中等規(guī)模數(shù)據(jù)上兩輪整流后 8 步 Euler 質(zhì)量基本持平 50 步原始模型這個(gè)收益是實(shí)打?qū)嵉?。需要提醒的是整流?xùn)練會(huì)損失一定的分布覆蓋度——路徑被壓直的同時(shí)模型可能把某些邊緣樣本“平均化”了。所以如果你的目標(biāo)不只是 FID而是多樣性整流輪數(shù)要克制。6.2 應(yīng)用場(chǎng)景不止圖像Flow Matching 的應(yīng)用早已不限于圖像生成。視頻、音頻、3D 點(diǎn)云、分子構(gòu)象生成都有相關(guān)實(shí)踐。原因很簡(jiǎn)單這個(gè)框架完全不依賴(lài)數(shù)據(jù)的具體形態(tài)只要你定義一個(gè)從噪聲到樣本的插值路徑就能訓(xùn)練。文本和離散數(shù)據(jù)也有對(duì)應(yīng)的離散 Flow Matching 做法把連續(xù)向量場(chǎng)改成離散轉(zhuǎn)移概率概念連續(xù)化后再訓(xùn)練。觸類(lèi)旁通的感覺(jué)很強(qiáng)你理解了連續(xù)版本離散版本的核心思想是同一個(gè)。還有一個(gè)非常實(shí)用的方向是 latent 空間加速先訓(xùn)練自編碼器把高維數(shù)據(jù)壓到低維再在低維上運(yùn)行 Flow Matching訓(xùn)練成本和采樣成本都能降一個(gè)數(shù)量級(jí)。做應(yīng)用落地時(shí)這往往比研究采樣器更提效。6.3 最后幾條掏心窩的建議如果讓我給剛開(kāi)始接觸 Flow Matching 的人提建議第一條是先跑最小實(shí)現(xiàn)再上大模型。你完全可以在一個(gè)小數(shù)據(jù)集上花半小時(shí)把線性插值路徑、L2 損失、Euler 采樣這“三件套”跑通看到損失下降和樣本生成再去做花樣。我見(jiàn)過(guò)不少同學(xué)一上來(lái)就上大模型大集群結(jié)果出了 NaN 都不知道去哪查。第二條把“路徑設(shè)計(jì)”和“采樣器設(shè)計(jì)”分開(kāi)思考。路徑?jīng)Q定上限采樣器決定你離上限多遠(yuǎn)。少步采樣時(shí)要先檢討路徑彎不彎而不是一味堆高階求解器。第三條養(yǎng)成記錄 t 分布和損失分段的習(xí)慣。Flow Matching 的調(diào)試大多藏在“哪個(gè)時(shí)間段沒(méi)學(xué)好”里把 t 維度攤開(kāi)看損失曲線排查效率能高一倍。最后說(shuō)句實(shí)在話Flow Matching 不是什么玄學(xué)它就是把擴(kuò)散模型里那套“沿軌跡回歸”的思想做了一次極致的簡(jiǎn)化。你理解了概率路徑和條件向量場(chǎng)這兩根柱子后面無(wú)論看到什么新變體都不會(huì)慌。踩過(guò)幾次坑之后現(xiàn)在我做生成模型項(xiàng)目的第一選擇已經(jīng)不是擴(kuò)散了默認(rèn)先試 Flow Matching實(shí)測(cè)下來(lái)的穩(wěn)定性和迭代速度都更省心。