
做用戶畫像聚類的時(shí)候我拿到過一份上千維的特征表不降維直接跑聚類結(jié)果全是一團(tuán)漿糊后來做了降維再聚類幾個(gè)類別之間的邊界立馬就清楚了。從那以后我就養(yǎng)成了習(xí)慣任何高維數(shù)據(jù)到手先花十分鐘做一輪降維摸底再?zèng)Q定下一步怎么走。這篇文章就把降維里兩條經(jīng)典路線——MDS降維方法和線性降維方法——放在一起講透。MDS這個(gè)名詞在面試題里出現(xiàn)的頻率不低但很多人被它唬住以為是什么高深的流形學(xué)習(xí)。實(shí)際上MDS和PCA的關(guān)系比想象中近得多在歐氏距離下經(jīng)典MDS求出來的坐標(biāo)和PCA投影基本是同一套東西。把這兩塊打通你對(duì)降維的幾何直覺會(huì)上一個(gè)臺(tái)階。這篇文章適合剛接觸降維、想弄懂原理也想要能直接跑的代碼的朋友有經(jīng)驗(yàn)的讀者可以重點(diǎn)看第5節(jié)里面那些坑是我實(shí)際踩過的。1. 降維到底在解決什么問題兩條路線背后的幾何直覺1.1 為什么需要降維不是“壓縮”而是“看清結(jié)構(gòu)”高維數(shù)據(jù)的麻煩遠(yuǎn)不只是“展示不出來”這么簡單。想象你拿一把尺子去量30維空間里的點(diǎn)兩點(diǎn)之間的歐氏距離會(huì)變得非常接近這就是所謂的“維度災(zāi)難”。我見過很多人抱怨明明特征做了標(biāo)準(zhǔn)化K近鄰的效果仍然很飄其實(shí)不是算法的問題是高維空間本身就極度稀疏距離的區(qū)分度被稀釋了。類似的現(xiàn)象還會(huì)導(dǎo)致聚類不穩(wěn)定、回歸過擬合、可視化一片糊。降維要做的事不是簡單丟掉幾個(gè)無關(guān)緊要的特征而是把數(shù)據(jù)從高維空間映射到一個(gè)更低維的空間盡量保留原始數(shù)據(jù)的“結(jié)構(gòu)”——這個(gè)結(jié)構(gòu)可能是方差大的方向可能是樣本之間的相對(duì)遠(yuǎn)近也可能是類別之間的可分性。你可以把它類比成整理照片幾千張高清原圖直接看會(huì)淹沒在細(xì)節(jié)里但你把它們按“相似程度”擺到一張大白紙上關(guān)系和分組一眼就能看出來。降維就是那張大白紙。1.2 兩條路線的分岔線性映射與距離保持圍繞“保留結(jié)構(gòu)”這個(gè)目標(biāo)降維方法分成了兩個(gè)互相對(duì)應(yīng)的流派。線性降維的思路是找一組線性投影方向把高維數(shù)據(jù)直接投影到低維子空間里典型代表就是PCA和LDA。它的輸入是一張樣本特征矩陣輸出是一個(gè)投影矩陣和一份低維坐標(biāo)。線性意味著結(jié)果有很強(qiáng)的可解釋性——你能夠看到每個(gè)原始特征在投影方向上的權(quán)重新樣本過來也能直接套用同一個(gè)投影矩陣映射過去這在真實(shí)業(yè)務(wù)落地里非常方便。MDS的出發(fā)點(diǎn)完全不同。它不關(guān)心特征矩陣只關(guān)心樣本兩兩之間的“距離”或者“不相似度”輸入是一個(gè) N×N 的距離矩陣輸出是一組低維坐標(biāo)讓這組坐標(biāo)在低維空間里重新算出來的距離盡量去逼近輸入的距離矩陣。它甚至可以接受歐氏距離以外的任意度量比如文本里的余弦距離、用戶行為里的Jaccard距離這正是它靈活的地方。這兩條路線看起來八竿子打不著但幾何上有一個(gè)漂亮的交叉點(diǎn)當(dāng)距離矩陣用的是歐氏距離時(shí)經(jīng)典MDS得到的坐標(biāo)和PCA投影出來的是同一份結(jié)果只差一個(gè)旋轉(zhuǎn)或鏡像。理解了這句話你就把線性降維和MDS之間的墻拆掉了。2. 線性降維方法核心拆解PCA、LDA與SVD的關(guān)系2.1 PCA最大方差與最小重構(gòu)誤差PCA大概是所有降維方法里最常用、也最值得先吃透的一個(gè)。它的目標(biāo)一句話概括尋找一組正交方向讓數(shù)據(jù)投影到這些方向上的方差盡可能大。為什么要最大化方差因?yàn)榉讲畲蟮姆较虺休d了樣本之間最多的差異信息反過來說數(shù)據(jù)在某個(gè)方向上幾乎不變那這個(gè)方向上的信息就可以丟掉。這個(gè)邏輯跟“最小化重構(gòu)誤差”是等價(jià)的——最大化投影方差等價(jià)于讓數(shù)據(jù)在低維空間里重構(gòu)回原空間時(shí)誤差最小。計(jì)算步驟非常清晰對(duì)數(shù)據(jù)矩陣做中心化讓每個(gè)特征的均值為0。計(jì)算協(xié)方差矩陣。對(duì)協(xié)方差矩陣做特征值分解。按特征值大小排序取前 k 個(gè)特征值對(duì)應(yīng)的特征向量組成投影矩陣。用中心化后的數(shù)據(jù)乘上投影矩陣得到低維坐標(biāo)。用 NumPy 手寫一個(gè) PCA 大概這樣import numpy as np def pca_fit_transform(X, n_components2): # X: (n_samples, n_features)已經(jīng)中心化的數(shù)據(jù)會(huì)更好 X_centered X - X.mean(axis0) # 協(xié)方差矩陣 cov np.cov(X_centered, rowvarFalse) # 對(duì)稱矩陣用 eigh 數(shù)值更穩(wěn)定 eig_vals, eig_vecs np.linalg.eigh(cov) # 特征值從大到小排列取前 n_components 個(gè) idx np.argsort(eig_vals)[::-1][:n_components] W eig_vecs[:, idx] # 投影后的低維坐標(biāo) Z X_centered W return Z, eig_vals[idx]這段代碼里我特意用了np.linalg.eigh而不是np.linalg.eig因?yàn)閰f(xié)方差矩陣是對(duì)稱矩陣eigh專門針對(duì)對(duì)稱矩陣做了優(yōu)化數(shù)值上更穩(wěn)。實(shí)際工程中更推薦對(duì)中心化后的數(shù)據(jù)矩陣直接做 SVD而不是先算協(xié)方差矩陣因?yàn)閰f(xié)方差矩陣會(huì)放大數(shù)值誤差SVD 一步到位還能很方便地處理大規(guī)模數(shù)據(jù)U, S, Vt np.linalg.svd(X_centered, full_matricesFalse) # Vt 的行就是主方向 W Vt[:n_components].T Z X_centered WSVD 和特征分解在這個(gè)場(chǎng)景下解的是同一個(gè)問題X^T X 的特征向量就是 V^T 的行主成分得分就是 X V。區(qū)別只是數(shù)值路徑不同。PCA 里還有一個(gè)容易被忽視的點(diǎn)解釋方差比例。每個(gè)主成分的特征值除以所有特征值之和就是這個(gè)主成分“解釋了”多少信息。我在實(shí)際項(xiàng)目里通常會(huì)先看一眼前兩個(gè)主成分累計(jì)解釋了多少方差如果連 50% 都不到說明數(shù)據(jù)噪聲很大或者降維本身解決不了當(dāng)前問題得換思路。2.2 LDA給線性降維加上“標(biāo)簽定向”PCA 是無監(jiān)督的它不管樣本屬于哪一類只找方差最大的方向。這在很多場(chǎng)景下夠用但如果你手里有標(biāo)簽而且降維的最終目的是分類PCA 不一定能幫你找到最有利于判別的方向。這時(shí)候該上 LDA。LDA 的目標(biāo)是找一個(gè)投影方向讓類間離散度盡可能大、類內(nèi)離散度盡可能小。翻譯成人話就是不同類別的點(diǎn)投影之后盡量分開同一個(gè)類別的點(diǎn)投影之后盡量聚攏。數(shù)學(xué)上定義兩個(gè)散度矩陣類內(nèi)散度矩陣 S_w衡量每個(gè)類內(nèi)部樣本離自己類中心的遠(yuǎn)近。類間散度矩陣 S_b衡量各類中心離全局中心的遠(yuǎn)近加上類別樣本數(shù)的加權(quán)。LDA 要求解的是廣義特征分解問題S_b w λ S_w w取前 k 個(gè)最大廣義特征值對(duì)應(yīng)的方向作為投影矩陣。這里有個(gè)硬性約束很多人容易踩坑LDA 最多能降到的維度不超過“類別數(shù)減一”。二分類最多降到 1 維三分類最多降到 2 維。如果你想保留更多維度LDA 幫不了你得回到 PCA。舉一個(gè)直觀的例子一批樣本是“正常”和“異?!眱深愒继卣饔?0維。直接跑PCA前兩維可能主要反映的是數(shù)據(jù)整體的分布形狀正常和異常還是重疊在一起但用LDA投影到1維重點(diǎn)變成了“怎么把兩類分得最開”分類器在這個(gè)1維特征上的表現(xiàn)通常會(huì)明顯好于直接用前兩維PCA特征。這也是LDA在特征工程里經(jīng)常作為分類前一步的原因。2.3 線性族的選型PCA、LDA、SVD與因子分析很多新手搞不清楚 PCA、SVD、因子分析這幾個(gè)東西有什么區(qū)別其實(shí)它們的關(guān)系是“兄弟工具”的關(guān)系。SVD 本身不是一種降維方法它是矩陣分解的數(shù)值工具但恰好是 PCA 最穩(wěn)定的實(shí)現(xiàn)方式。你可以把 PCA 理解成目標(biāo)SVD 理解成達(dá)成目標(biāo)的引擎。除了 PCASVD 在推薦系統(tǒng)、文本主題分析里也被廣泛使用只是目標(biāo)函數(shù)完全不同。因子分析則是另一個(gè)思路它假設(shè)觀測(cè)變量是由少數(shù)幾個(gè)不可觀測(cè)的“潛在因子”驅(qū)動(dòng)的比如六門考試成績背后可能有“邏輯能力”和“記憶力”兩個(gè)潛在因子。因子分析和 PCA 看起來很像但 PCA 找的是“方差最大的方向”因子分析找的是“能解釋變量之間相關(guān)結(jié)構(gòu)的潛在因子”。如果你的目的是做可解釋性、找出隱藏結(jié)構(gòu)因子分析更合適如果只是壓縮維度PCA 更快更直接。方法是否使用標(biāo)簽輸出內(nèi)容核心目標(biāo)典型場(chǎng)景PCA否投影方向 低維坐標(biāo)最大化方差無標(biāo)簽數(shù)據(jù)壓縮、可視化去相關(guān)LDA是判別方向 低維坐標(biāo)最大化類間/類內(nèi)距離比分類前的特征提取經(jīng)典MDS否低維坐標(biāo)保持樣本間距離距離矩陣可視化、相似度分析非度量MDS否低維坐標(biāo)保持樣本間距離的排序用戶調(diào)研、偏好感知圖選型的時(shí)候我一般先問自己三個(gè)問題有沒有標(biāo)簽要不要對(duì)新樣本做映射距離的定義是什么。有標(biāo)簽就優(yōu)先試 LDA沒標(biāo)簽、只想快速看結(jié)構(gòu)就用 PCA如果業(yè)務(wù)方給的就是相似度矩陣或者你要用余弦距離這類非歐度量PCA 就不適用了這時(shí)候 MDS 才是正解。3. MDS降維方法核心拆解從距離矩陣到低維坐標(biāo)3.1 經(jīng)典MDS的數(shù)學(xué)骨架二次距離、雙中心化與特征分解MDS 的輸入是一張距離矩陣 DD_ij 表示樣本 i 和樣本 j 之間的距離。它不關(guān)心樣本在原始空間長什么樣只根據(jù)距離推算出“如果把這些距離保持住那么每個(gè)樣本在低維空間里應(yīng)該放在哪個(gè)位置”。經(jīng)典 MDS 的數(shù)學(xué)推導(dǎo)有幾個(gè)關(guān)鍵步驟理解了這幾個(gè)步驟你就能把 MDS 看穿。假設(shè)低維坐標(biāo)是 YN×k我們希望低維空間中樣本間的歐氏距離平方盡量等于 D 的平方。也就是說||y_i - y_j||2 ≈ D_ij2展開左邊||y_i||2 ||y_j||2 - 2 y_i^T y_j。如果直接解這個(gè)方程比較麻煩因?yàn)槎雾?xiàng)和交叉項(xiàng)混在一起。聰明的地方在于構(gòu)造一個(gè)“雙中心化”操作把它線性化。定義中心化矩陣 J I - (1/N) 11^T它的作用是把矩陣的每一列都減去列均值。然后構(gòu)造B -1/2 J D2 J其中 D2 是逐元素平方的距離矩陣??梢宰C明如果距離矩陣 D 來自中心化后的歐氏空間那么 B 正好等于低維坐標(biāo)的 Gram 矩陣 Y Y^T。換句話說B 和 Y Y^T 在數(shù)學(xué)上是同一個(gè)東西。于是求 Y 的問題就變成了對(duì) B 做特征分解取前 k 個(gè)最大的特征值和對(duì)應(yīng)的特征向量然后開方調(diào)整尺度。代碼實(shí)現(xiàn)很直接import numpy as np def classic_mds(D, n_components2): n D.shape[0] # 距離平方 D2 D ** 2 # 雙中心化 J np.eye(n) - np.ones((n, n)) / n B -0.5 * J D2 J # 對(duì)稱矩陣特征分解 eig_vals, eig_vecs np.linalg.eigh(B) # 從大到小排序取前 n_components 個(gè) idx np.argsort(eig_vals)[::-1][:n_components] eig_vals eig_vals[idx] eig_vecs eig_vecs[:, idx] # 特征向量是單位正交的需要乘上特征值的平方根來“伸展”坐標(biāo) Y eig_vecs * np.sqrt(eig_vals) return Y, eig_vals注意最后一步特征值分解得到的特征向量是單位向量它的長度是1但 Gram 矩陣的對(duì)角線包含了坐標(biāo)的平方范數(shù)所以必須讓每個(gè)特征向量乘以對(duì)應(yīng)特征值的平方根坐標(biāo)尺度才是對(duì)的。這一步漏了你得到的圖會(huì)被壓扁或者拉伸變形。為什么這個(gè)方法和 PCA 等價(jià)一句話解釋如果原始數(shù)據(jù) X 已經(jīng)中心化那么樣本間的歐氏距離平方 D2 可以寫成 D2 diag(G)1^T 1diag(G)^T - 2G其中 G X X^T 是 Gram 矩陣。對(duì)它做雙中心化之后B 恰好等于 X X^T。而 PCA 是在對(duì) X^T X 做特征分解。一個(gè)是對(duì)樣本間的 Gram 矩陣分解一個(gè)是對(duì)特征間的協(xié)方差矩陣分解它們共享同一個(gè)奇異值結(jié)構(gòu)。所以最后得到的坐標(biāo)本質(zhì)上是同一個(gè)低維嵌入只是可能有左右方向的翻轉(zhuǎn)。3.2 度量MDS與非度量MDS要“數(shù)值”還是要“次序”經(jīng)典 MDS 要求距離矩陣滿足歐氏空間的度量約束而且它試圖讓低維空間的距離在數(shù)值上逼近原始距離這叫“度量 MDS”。但真實(shí)業(yè)務(wù)里很多“相似度”數(shù)據(jù)根本不滿足歐氏度量比如用戶對(duì)品牌偏好的打分差異、消費(fèi)者對(duì)不同產(chǎn)品的感知相似度。這時(shí)候強(qiáng)行用數(shù)值逼近不一定有意義排序關(guān)系反而更重要。非度量 MDS 的思路就變成了只要低維空間里樣本的相對(duì)遠(yuǎn)近順序和原始距離矩陣的排序一致就行。比如原始距離 A-B 是 1、B-C 是 2、A-C 是 100非度量 MDS 不要求低維空間里 1 和 100 的絕對(duì)比例被還原只要求 A-C 最遠(yuǎn)、A-B 最近。這種放松讓它在處理感覺打分、排序偏好這類數(shù)據(jù)時(shí)特別穩(wěn)定。數(shù)學(xué)上它通過單調(diào)回歸來擬合“距離的排序”迭代優(yōu)化一個(gè)叫“應(yīng)力”stress的目標(biāo)函數(shù)。實(shí)際使用中如果驗(yàn)證集上的經(jīng)典 MDS 出現(xiàn)大量負(fù)特征值或者得到的圖交叉得很奇怪我就會(huì)切到非度量 MDS 試試往往能得到更符合直覺的相對(duì)位置關(guān)系。3.3 MDS的實(shí)操要點(diǎn)距離度量、樣本外映射與大矩陣優(yōu)化MDS 最大的賣點(diǎn)是距離度量可換但這也是最大的坑。同樣一份數(shù)據(jù)你用歐氏距離、余弦距離、曼哈頓距離分別跑 MDS出來的圖完全不一樣。這不是代碼問題而是你在提取數(shù)據(jù)的不同側(cè)面。我在處理文本數(shù)據(jù)時(shí)喜歡用余弦距離處理數(shù)值型用戶畫像時(shí)用歐氏距離處理共現(xiàn)關(guān)系時(shí)用 Jaccard 距離。動(dòng)手之前先問清楚你要刻畫的“相似”到底是什么。第二個(gè)坑是樣本外映射。PCA 訓(xùn)練完留下一個(gè)投影矩陣新樣本直接乘上去就行。但經(jīng)典 MDS 做的是特征分解沒有一個(gè)顯式的 f(x) 可以套用。新樣本來了你得重新對(duì)整個(gè)距離矩陣做一次 MDS這在生產(chǎn)環(huán)境里幾乎不可接受。常見的解決辦法是 Landmark MDS先從全部樣本里挑一小撮“地標(biāo)點(diǎn)”對(duì)地標(biāo)點(diǎn)做經(jīng)典 MDS之后的地標(biāo)坐標(biāo)固定住任何一個(gè)新樣本只要算出它到地標(biāo)點(diǎn)的距離就能通過最小二乘反推出它的低維坐標(biāo)。這個(gè)思路在精度損失不大的情況下把“部署”問題解決了。第三個(gè)坑是計(jì)算復(fù)雜度。距離矩陣是 N×N 的N 到一萬矩陣就是 800MB特征分解的時(shí)間也很可觀N 到十萬基本就別想直接 MDS 了。這時(shí)候要么抽樣要么上 Landmark 方案要么干脆退回到 PCA。我一直覺得降維方法之間不是互相取代的關(guān)系而是根據(jù)數(shù)據(jù)規(guī)模和業(yè)務(wù)約束選最合適的那一個(gè)。4. 實(shí)操過程手寫MDS與PCA并對(duì)比效果4.1 模擬數(shù)據(jù)與手寫PCA為了把原理和代碼對(duì)應(yīng)起來我構(gòu)造一個(gè)模擬數(shù)據(jù)集三類樣本原始特征 20 維其中前兩維決定了類別的分離結(jié)構(gòu)后 18 維全是噪聲。用這樣的數(shù)據(jù)能清楚看到降維到底保留了哪些信息。import numpy as np from sklearn.datasets import make_blobs X, y make_blobs(n_samples300, centers3, n_features20, random_state42) # 把后18維替換成純?cè)肼暷M“有效維度少、噪聲維度多”的真實(shí)場(chǎng)景 rng np.random.default_rng(42) X[:, 2:] rng.normal(sizeX[:, 2:].shape) Z_pca, evals pca_fit_transform(X, n_components2)跑完之后看解釋方差前兩維的方差占比通常會(huì)很低因?yàn)?18 維噪聲把總方差攤薄了。但這個(gè)低比值不代表降維失敗反而說明數(shù)據(jù)里大部分維度是噪聲真正決定類別的結(jié)構(gòu)被保留在前兩維里??梢暬幌氯悩颖驹诙S平面里分得清清楚楚這就達(dá)到了“看清結(jié)構(gòu)”的目的。4.2 手寫經(jīng)典MDS與PCA碰一碰接下來用我上面寫的classic_mds處理同樣的數(shù)據(jù)輸入直接用歐氏距離矩陣from scipy.spatial.distance import pdist, squareform D squareform(pdist(X, metriceuclidean)) Z_mds, mds_evals classic_mds(D, n_components2)把Z_pca和Z_mds放到同一個(gè)坐標(biāo)系里對(duì)比你會(huì)發(fā)現(xiàn)兩幅散點(diǎn)圖長得幾乎一樣——類別結(jié)構(gòu)、相對(duì)密集區(qū)域、離群點(diǎn)全都對(duì)得上。唯一可能不同的是某個(gè)軸的整體方向反了比如 PCA 的第一個(gè)軸指向右上MDS 的第一個(gè)軸指向左下。這非常正常因?yàn)樘卣鞣纸獬鰜淼奶卣飨蛄糠较虮旧砭蛶我庑苑?hào)不改變樣本之間的相對(duì)距離和聚類結(jié)構(gòu)。這就是我開頭說的那件事在歐氏距離下經(jīng)典 MDS 和 PCA 是同一個(gè)解的兩種表達(dá)。很多人在面試?yán)锉粏柕絻烧叩年P(guān)系時(shí)背一句“它們等價(jià)”就完事其實(shí)如果當(dāng)場(chǎng)能指出“經(jīng)典MDS是對(duì)雙中心化距離矩陣做特征分解PCA是對(duì)協(xié)方差矩陣做特征分解兩者共享同樣的奇異向量結(jié)構(gòu)”面試官立刻就會(huì)知道你是真動(dòng)手調(diào)過代碼的。4.3 非歐距離下的MDS換一種度量立刻不同同樣的數(shù)據(jù)集我把距離度量換成余弦距離結(jié)果就不一樣了。from sklearn.metrics.pairwise import cosine_similarity # 余弦距離 1 - 余弦相似度需要保證矩陣對(duì)角線為0 sim cosine_similarity(X) D_cos 1 - sim np.fill_diagonal(D_cos, 0) Z_mds_cos, _ classic_mds(D_cos, n_components2)這一步有一個(gè)很容易踩的細(xì)節(jié)直接用1 - cosine_similarity得到的結(jié)果對(duì)角線是 1 而不是 0必須先手動(dòng)把對(duì)角線置零。否則距離矩陣對(duì)角線上多了 1雙中心化之后會(huì)把原來干凈的 Gram 矩陣結(jié)構(gòu)污染掉得到的低維坐標(biāo)會(huì)整體偏斜。跑出來的坐標(biāo)和 PCA 的投影有明顯差異因?yàn)橛嘞揖嚯x只看方向不看大小它對(duì)樣本向量的“長度”免疫。這在處理文本 TF-IDF 特征時(shí)特別有用——文檔長度差異會(huì)導(dǎo)致歐氏距離被長文檔主導(dǎo)但余弦距離只看內(nèi)容方向的相似度。4.4 sklearn里怎么用MDS參數(shù)與陷阱如果不想手寫直接用sklearn.manifold.MDS也可以但它的實(shí)現(xiàn)和我手寫的經(jīng)典 MDS 有一點(diǎn)重要區(qū)別sklearn 用的是 SMACOF 迭代優(yōu)化不是直接做特征分解。默認(rèn)情況下它會(huì)隨機(jī)初始化多次挑應(yīng)力最小的解。from sklearn.manifold import MDS mds MDS(n_components2, dissimilarityprecomputed, metricTrue, n_init4, max_iter300, random_state42) Z_sk mds.fit_transform(D)幾個(gè)參數(shù)的實(shí)際含義dissimilarityprecomputed表示我傳入的是距離矩陣如果設(shè)為euclidean它會(huì)內(nèi)部先算歐氏距離。metricTrue是度量 MDSmetricFalse是非度量 MDS。n_init4是隨機(jī)初始化次數(shù)越大越容易跳出局部最優(yōu)但時(shí)間成倍增加。max_iter300是最大迭代輪數(shù)數(shù)據(jù)量大時(shí)可以適當(dāng)降低但別低于50。手寫特征分解得到的坐標(biāo)是解析解一次算出sklearn 得到的坐標(biāo)是數(shù)值優(yōu)化解多次迭代逼近。兩者最終結(jié)果基本一致但如果你要追求穩(wěn)定復(fù)現(xiàn)、或者要做大規(guī)模數(shù)據(jù)的精確計(jì)算手寫特征分解其實(shí)更直接。我個(gè)人的習(xí)慣是探索階段用 sklearn 快速出圖正式做分析時(shí)自己寫因?yàn)樽约簩懙臇|西每一行都知道在干什么。5. 常見問題與排查技巧實(shí)錄5.1 負(fù)特征值扎堆距離矩陣可能是“假歐氏”運(yùn)行經(jīng)典 MDS 時(shí)B矩陣的特征值里出現(xiàn)負(fù)數(shù)是很常見的。少量負(fù)特征值多數(shù)來自數(shù)據(jù)噪聲問題不大但如果負(fù)特征值數(shù)量很多、絕對(duì)值還特別大基本上可以斷定你輸入距離矩陣并不滿足歐氏度量所謂“距離”可能只是視覺相似度之類的主觀打分。遇到這種情況我的排查順序是先按特征值從大到小排列看有幾個(gè)正特征值明顯比其余的大。如果正特征值本身就很少而且前 k 個(gè)累計(jì)占比很低那就不要死磕經(jīng)典 MDS 了切到非度量 MDS 試試。另一個(gè)老辦法是給距離加一個(gè)常數(shù)把它“撐”成歐氏距離但這個(gè)方法現(xiàn)在用得少了因?yàn)樗鼤?huì)改變樣本間的相對(duì)比例。5.2 坐標(biāo)鏡像翻轉(zhuǎn)特征向量方向的符號(hào)問題我第一次拿 MDS 結(jié)果和別人對(duì)圖的時(shí)候差點(diǎn)以為是代碼寫錯(cuò)了——明明用同一個(gè)數(shù)據(jù)集兩邊的散點(diǎn)圖形狀一模一樣但 x 軸完全反了。后來我才反應(yīng)過來特征分解給出的特征向量方向本來就是任意的v 和 -v 都是同一個(gè)特征向量。這不只是一個(gè) 學(xué)術(shù)上的小細(xì)節(jié)在實(shí)際協(xié)作里很麻煩。如果你們團(tuán)隊(duì)里有人用 sklearn有人用 R 的 cmdscale兩邊生成的圖很可能左右翻轉(zhuǎn)或上下翻轉(zhuǎn)。解決辦法是統(tǒng)一固定random_state同時(shí)在展示前做一個(gè) Procrustes 對(duì)齊——把兩組坐標(biāo)通過旋轉(zhuǎn)、縮放、平移對(duì)齊到同一個(gè)參考坐標(biāo)系里。這不是算法的錯(cuò)不要在這種問題上浪費(fèi)太多時(shí)間。5.3 大樣本算不動(dòng)內(nèi)存與計(jì)算的取舍距離矩陣的規(guī)模是 O(N2)一萬樣本就是一億個(gè)浮點(diǎn)數(shù)約 800MB十萬樣本直接 80GB內(nèi)存爆掉是分分鐘的事。我在實(shí)際工作中超過兩萬樣本就不太敢直接懟經(jīng)典 MDS 了。幾個(gè)可行的替代方案隨機(jī)抽樣做一次 MDS看整體形狀然后再用其他方法驗(yàn)證細(xì)節(jié)。用 Landmark MDS選幾百個(gè)地標(biāo)點(diǎn)先嵌入再映射其余樣本。如果只是可視化用 t-SNE 或 UMAP 這類更現(xiàn)代的流形方法它們對(duì)大數(shù)據(jù)量更友好。如果業(yè)務(wù)要求可解釋、可部署直接用 PCA別折騰 MDS。5.4 坐標(biāo)軸沒有業(yè)務(wù)含義MDS落地解釋的四種做法MDS 的坐標(biāo)軸不像 PCA 那樣能直接說成“維度1代表某個(gè)特征方向”它只是一個(gè)相對(duì)位置這讓它在跨部門溝通時(shí)特別吃虧。我在給業(yè)務(wù)方解釋 MDS 結(jié)果時(shí)一般會(huì)做四件事給每個(gè)樣本按業(yè)務(wù)標(biāo)簽著色讓大家先看出“哪些樣本聚在一起”。在關(guān)鍵的點(diǎn)附近標(biāo)注原始特征的典型值反推坐標(biāo)位置背后的含義。不用坐標(biāo)軸的意義去解釋只講距離的含義“這兩個(gè)點(diǎn)離得近代表它們的行為更像”。如果非得給坐標(biāo)軸一個(gè)解釋就用特征相關(guān)性去擬合看哪個(gè)原始特征與這個(gè)軸的相關(guān)性最高?,F(xiàn)象可能原因處理方式負(fù)特征值占比高距離矩陣不滿足歐氏度量改用非度量MDS或調(diào)整距離定義兩次運(yùn)行結(jié)果軸方向相反特征向量方向符號(hào)不確定固定隨機(jī)種子或做Procrustes對(duì)齊樣本一多內(nèi)存就不夠距離矩陣O(N2)隨機(jī)抽樣、Landmark MDS、換PCA低維圖上所有點(diǎn)擠成一團(tuán)原始數(shù)據(jù)本身區(qū)分度過低檢查特征質(zhì)量考慮換距離度量新樣本無法映射到舊坐標(biāo)MDS沒有顯式投影函數(shù)預(yù)埋地標(biāo)點(diǎn)用最小二乘反推坐標(biāo)實(shí)際做數(shù)據(jù)分析這一年多我最大的體會(huì)是降維方法不要分開學(xué)要把它們當(dāng)成一整個(gè)工具箱。PCA 能快速摸清全局方差結(jié)構(gòu)LDA 能在有標(biāo)簽時(shí)幫你找到判別方向MDS 能處理各種奇怪的相似度矩陣。先跑一遍 PCA 看解釋方差再根據(jù)業(yè)務(wù)場(chǎng)景決定要不要換 MDS 或 LDA成本很低收益卻很直觀。最后再分享一個(gè)實(shí)用小技巧無論你最后選了哪種降維方法輸出坐標(biāo)之后都記得把坐標(biāo)均值歸零、方差歸一。這樣 Exec 匯報(bào)時(shí)不同方案的結(jié)果可以直接疊圖對(duì)比不會(huì)因?yàn)槌叨炔灰恢露`判聚類效果。這一點(diǎn)看著不起眼但能讓你的圖比大多數(shù)人做得專業(yè)一截。