沒有標準答案的學習
到目前為止,你在這一級學過的每一種經典方法——迴歸、決策樹、最近鄰、支援向量機——都屬於 監督學習:每個樣本都帶著一個 標籤,模型學習的是把輸入映射到這些已知的答案。但現實世界裡的大多數資料並沒有標籤。你手裡有一百萬個客戶、一堆感測器讀數、一個裝滿文件的資料夾——卻沒有人告訴你「正確」的分組是什麼。這就是 無監督學習 的世界:在沒有標準答案時去發現結構。
本章的兩件大事是 聚類——把相似的點歸到一起——以及 降維——把很多 特徵 壓縮成少數幾個,同時保留要緊的東西。兩者都基於同一個想法:資料並不是隨機雜訊,而是棲身於某種更簡單的隱藏形狀之上,我們的工作就是把它揭示出來。但有個我們稍後會回頭討論的陷阱:「相似」和「結構」是由你來定義的,而不是資料自己宣告出來的。
k 均值:偏愛圓團的主力工具
k 均值 幾乎是每個人學的第一個聚類演算法,這是有道理的:它快、簡單,而且往往已經夠用。你告訴它想要多少個組 k;它撒下 k 個中心,把每個點分配給離它最近的中心,再把每個中心移動到它所轄點的平均位置,如此往復。每一輪都只會讓總的平方距離下降,所以它總會穩定下來——通常只需幾趟。
- 選定 k,撒下 k 個中心,通常取自資料中的隨機點。
- 分配步:把每個點貼上離它最近的那個中心的標號。
- 更新步:把每個中心移動到分配給它的那些點的平均位置。
- 重複分配與更新,直到再也沒有變動——聚類已經收斂。
這份優雅是有附加條件的。k 均值畫的是直線邊界,並且暗中假設各個簇都是大小相近的圓團——給它兩彎月牙、或者一胖一瘦兩個組,它就會切錯。它還對中心的初始位置敏感,所以好的實作會跑很多次、保留最好的那次。又因為一切都由距離驅動,你必須先做 特徵縮放,否則取值範圍最大的那個特徵會悄悄地一手遮天。
層次聚類:你資料的家譜
層次聚類 回答的是另一個問題。它不強迫你一開始就選定 k,而是建構一整棵巢狀的分組之樹。常見的自底向上版本,先把每個點當作它自己的一個簇,然後反覆合併最接近的兩個簇,直到所有東西歸為一個大簇。這些合併的記錄構成一棵叫做譜系圖(dendrogram)的樹——你可以在任意高度「切一刀」,從而讀出你想要的或多或少的簇數。
這棵樹本身就是回報:它不僅顯示哪些點成組,還顯示組如何巢狀進更大的組——物種歸入屬、屬歸入科,或者話題歸入主題。代價是速度。樸素的實作會在每一步比較每一對簇,其規模大致隨點數的立方增長,所以單純的層次聚類對超大資料集並不實用。你還必須選一個「連接(linkage)」規則——兩個簇之間的距離指的是它們最近的兩點、最遠的兩點,還是它們的平均——而這個選擇會悄悄地改變答案的形狀。
於是有個粗略的經驗法則:當你點很多、並且對想要幾個組心裡有數時,用 k 均值;當資料較小、並且組與組之間的巢狀「關係」本身就是有趣的故事時,用層次聚類。
PCA:找出真正重要的方向
發現結構的另一半是降維。真實的資料集常常有幾百個特徵,但其中很多是一起變動的——身高與臂展,或者十幾道彼此相關的問卷題。主成分分析(PCA)會找出一組新的座標軸,叫做主成分,並按這樣的順序排列:第一個指向資料散佈最開的那個方向,第二個指向次開的方向(且與第一個成直角),依此類推。只保留前面少數幾個,你就在幾乎不丟東西的前提下壓縮了資料。
在底層,PCA 就是你在線性代數那一級見過的 特徵向量與特徵值,把它們作用在資料的共變異數矩陣上:特徵向量就是各主成分的方向,每個特徵值則告訴你有多少變異數沿著它那個方向。這就是全部的訣竅——沒有標籤,沒有訓練迴圈,只有資料如何散佈的幾何。
# from many features down to 2, for plotting X = standardize(X) # center & scale first! components = top_eigenvectors(cov(X), keep=2) X2d = X @ components # each row is now just (x, y) plot(X2d) # eyeball the structure
PCA 的兩大用途是視覺化——把高維資料壓成二維,讓你在跑任何聚類演算法之前就能親眼看見簇——以及對抗 維數災難,也就是當特徵太多時距離會變得沒有意義。兩點老實話:PCA 只能捕捉 線性 結構,所以它會錯過彎曲或扭轉的形狀,而非線性方法本能抓住它;而且它的成分是你原有特徵的混合物,這會讓它們難以命名或解釋。和 k 均值一樣,它也需要 標準化的輸入,否則尺度最大的特徵會劫持第一主成分。
用好它——以及那些老實的限度
實務中這些工具會串起來用。一個常見的套路是先用 PCA 削掉雜訊與維度,再在壓縮後的資料上跑 k 均值或層次聚類,最後用一張二維 PCA 圖憑肉眼檢驗結果。聚類還驅動著你大概用過的日常任務:客戶分群、按主題給文件歸類、壓縮影像的顏色,以及 異常檢測——那些遠離每一個簇的點,就是可疑分子。
現在說說這個領域往往會誇大的硬道理。聚類 永遠 會返回一些簇——哪怕在純隨機雜訊上也一樣。演算法對它找到的組是不是真實的毫無概念;它只是去最小化你選定的某個數字。k 的不同取值、距離度量、縮放方式或連接規則的不同選擇,會從同一份資料裡產出天差地別的「發現」。所以你看到的結構,一部分是資料的屬性,一部分是你那些假設的屬性,而一個誠實的分析者會把這兩者分開來看。
解法不是換一個更好的演算法,而是更好的紀律:去驗證。同樣的分組在一片新的資料上還成立嗎?這些簇對領域專家來說有意義嗎?換一個隨機種子,k 的選擇還撐得住嗎?把無監督的結果當成有待檢驗的假設,而不是可以直接上報的事實——這樣你就能拿到這些方法真正能給的價值(那可不少),同時不會被那些其實根本不存在的結構騙到。