跳至主要內容

    KNN:用鄰居判斷,為什麼也會失準?

    從三個鄰居的投票開始,理解k、距離加權、尺度與高維資料的限制

    sunny 桑尼· · 15 MIN READ · 271 次瀏覽

    KNN:用鄰居判斷,為什麼也會失準?
    本文目錄

    如果想知道一筆新訂單會不會延遲,有一種做法很直接:找幾筆條件相近的舊訂單,看看它們發生了什麼事。

    KNN,也就是k-nearest neighbors,用的正是這個想法。它先定義資料之間的距離,再找最近的k個訓練樣本;分類時投票,迴歸時平均。困難在於:數字很接近,未必代表業務情境真的相似。

    這篇從三筆自訂資料算一次分類與迴歸,再對照原始教材圖,理解k、加權、縮放與高維限制。算例只為拆解機制,不代表距離一個欄位就足以預測真實配送延遲。

    KNN先記住樣本,預測時才找鄰居

    線性迴歸把訓練資料濃縮成係數;KNN通常保留訓練樣本,可能另外建立搜尋索引。收到新輸入後,再計算鄰近關係。

    因此,有些教材把它稱為lazy learning或instance-based learning。這不表示它完全沒有訓練成本,也不表示它不能泛化到新資料;意思是它沒有先學出同樣形式的一組線性係數,預測依靠儲存的樣本。

    最基本的流程是:

    1. 決定哪些欄位代表一筆資料,並完成可在新資料上使用的前處理。
    2. 定義距離,例如縮放後數值特徵的歐氏距離。
    3. 找出新輸入距離最近的k個訓練樣本。
    4. 分類依鄰居標籤投票,迴歸依鄰居目標取平均;必要時按距離加權。

    同一組資料,換距離、縮放或k,鄰居都可能改變。

    三個鄰居,先投票一次

    以下是自訂的一維教學資料,只有配送距離一個特徵。新訂單距離為2公里,先找三個最接近的訓練點。

    訓練樣本距離欄位x(公里)與新訂單的差距延遲標籤y
    A1.90.11:延遲
    B2.20.20:未延遲
    C2.30.30:未延遲

    在一維空間,歐氏距離就是絕對差。k=1時,只看A,預測延遲;k=3且等權投票時,未延遲有兩票、延遲有一票,預測未延遲。

    這不是誰一定比較正確,而是兩種設定使用不同範圍的局部證據。小k較容易受單點標籤或雜訊影響;較大k通常讓邊界平滑,但也可能把不同情境一起平均,錯過小群體的規律。

    選奇數k可以減少二元等權投票的平手,卻不能消除所有平手:多類別、距離相同或加權投票仍可能碰到。特別是第k與第k+1個樣本同距離但標籤不同,實作的選取及排序規則也可能影響結果。

    同樣三個鄰居,改成近的人票比較重

    常見距離加權讓每票與距離的倒數成正比:

    權重aᵢ = 1 / dᵢ
    某類別的加權份額 = 該類鄰居的權重總和 / 全部所選鄰居的權重總和
    

    上例A、B、C的權重約為10、5、3.333。延遲類別只有A,卻拿到10;未延遲類別合計約8.333,因此加權結果改成延遲,延遲份額約0.5455。

    等權份額1/3與加權份額0.5455,都是這三個鄰居的局部統計,不能直接保證部署後有相同比例的訂單延遲。要把輸出用於風險決策,還需要檢查機率校準與決策閾值。

    若距離恰好為0,不能直接計算1/0。實際工具需要特別處理重合點,例如只讓重合鄰居參與;重合點的標籤本身衝突時,也不能假裝有唯一真相。本篇程式會明確處理這個情況。

    圖1|來源使用Iris的花萼長、寬,k=11;左圖等權,右圖依距離倒數加權。兩個模型都在Pipeline內用訓練資料擬合StandardScaler;圖上仍以原始公分標示座標,不代表搜尋使用未縮放距離。散點包含全資料,背景是模型預測區域,不能靠看這張圖就算出獨立測試準確率。來源:scikit-learn developers,Nearest Neighbors Classification,BSD 3-Clause,原圖未改。

    距離加權可以讓非常近的點更有影響力,也可能讓錯誤標籤更有影響力。它是要驗證的設定,不是自動升級版。

    迴歸不投票,改算鄰居目標的平均

    若目標是連續分鐘數,KNN也可以作迴歸。為了只改一個地方,沿用前面三個特徵值,把目標換成自訂的10、20、30分鐘。

    等權預測 = (10 + 20 + 30) / 3 = 20分鐘
    
    距離加權預測
    = (10×10 + 5×20 + (10/3)×30) / (10 + 5 + 10/3)
    ≈ 16.3636分鐘
    

    最近的A是10分鐘,因此加權平均比20更接近它。這裡的兩組標籤分別用來教分類與迴歸,不是同一批實際觀測的兩個業務欄位。

    圖2|來源用40個訓練點的帶噪正弦資料,k=5;上圖等權,下圖距離加權。橘點是來源樣本,藍線是在500個查詢位置算出的預測;這500個位置沒有獨立的測試標籤,不是500筆測試成效。圖中的起伏屬來源實驗,本篇沒有重跑。來源:scikit-learn developers,Nearest Neighbors regression,BSD 3-Clause,原圖未改。

    一般的非負加權平均會落在所選鄰居目標的最小值與最大值之間。因此,基本KNN迴歸不擅長像線性模型那樣沿著趨勢往樣本範圍外外推。新的輸入離所有樣本很遠時,它仍可能交出一個看似正常的平均值;有數字不代表附近有足夠支持。

    距離由單位決定?先檢查尺度

    兩個數值特徵的歐氏距離可寫成:

    d(x, q) = √[(x₁−q₁)² + (x₂−q₂)²]
    

    假設一個欄位是幾公里,另一個是數十萬元。直接相加平方差時,數值較大的欄位很可能主導距離。把元改成萬元,又可能改變誰最近,雖然實際業務情況完全沒有變。

    標準化是常見起點:以訓練資料的平均與標準差,讓欄位轉成相對於該欄變動尺度的值。

    圖3|原始分布約以200為中心、標準差30,右側改以0為中心、標準差1;形狀沒有因此變成另一種關係。這是縮放示意,不是KNN準確率比較。來源:Google,Numerical data: Normalization,CC BY 4.0,原圖未改。

    圖4|偏斜資料經z-score轉換後仍然偏斜。標準化並不把所有分布變成常態,也不自動修正異常值或選出適合任務的距離。來源同圖3,原圖未改。

    平均與標準差只能用訓練資料估計,再用同一組值處理驗證與測試輸入;交叉驗證時,每個訓練折都要重估。先對全部資料fit scaler再切分,仍然是資料洩漏。

    類別欄位、經緯度與文字向量還有自己的相似性問題。把店家編號寫成1、2、3,不表示店家1與2比1與3更相似;經緯度也不應不加思考地當成任意平面座標。縮放能解決部分單位問題,不能代替特徵與距離的設計。

    也可以學距離,但這時就用到了標籤

    NCA,Neighborhood Components Analysis,是一種利用標籤學線性投影的方法。它嘗試讓投影後的鄰近關係更有利於分類,而不只是把各欄改成平均0、標準差1。

    圖5|關注編號3的紅色點;原空間裡有不同類別的候選鄰居。連線粗細表示來源隨機鄰居規則的相對權重,不是「越遠線就必然越粗」。來源:scikit-learn developers,Nearest Neighbors的NCA章節,BSD 3-Clause,原圖未改。

    圖6|投影後,3號點主要與紅色同類點建立較強的鄰近關係。這是同一組教學點的監督式投影,不能稱作一般StandardScaler前後,也不能據此保證新資料分類正確。來源同圖5,原圖未改。

    NCA的隨機鄰居權重使用投影後「負平方距離的指數」再正規化;它和先前手算的1/d加權不是同一個公式。它也需要在訓練折內學習,不能先看全部標籤投影再交叉驗證。

    這裡不必先實作NCA才能理解KNN。它帶來的提醒是:所謂「相近」,既可能來自人工選擇的表示,也可能來自另外學出的表示;兩者都應用獨立資料檢查。

    高維資料與預測成本,會讓直覺失效

    多加幾個欄位,不一定找得到更好的鄰居。當不相關維度很多,距離可能主要反映無關差異;在一些高維分布裡,最近與較遠樣本的相對距離也會變得不明顯。實際影響取決於資料結構與有效維度,不能只憑欄位超過某個數字就判死刑。

    KNN還把不少成本留在預測階段。對一個d維查詢與n筆樣本直接比較距離,基本工作量約隨n×d增加,還需選出最近的k個。KD Tree或Ball Tree可能在適合的結構下加速,但高維、較大k或特定資料分布可能讓它們失去優勢;沒有保證每次查詢都是log n。

    近似最近鄰搜尋可以在速度、記憶體與找回真鄰居的比例之間取捨。搜尋加速和預測品質仍是兩件事:找到近似鄰居後,分類或迴歸表現要再驗證,不是索引跑通就算模型好用。

    訓練資料還需要保存與維護。新增、刪除、隱私要求和分布漂移,都可能影響樣本與索引;不要因為沒有梯度下降,就認為不用管理模型生命週期。

    用一小段Python核對三個鄰居

    下面只用Python標準函式庫,重算本文的自訂三點例子;沒有安裝或重跑官方Iris、正弦或NCA實驗。所有數值都保留在正文,方便你先用紙筆檢查。

    query = 2.0
    rows = [(1.9, 1, 10), (2.2, 0, 20), (2.3, 0, 30)]
    near = sorted(rows, key=lambda row: abs(row[0] - query))[:3]
    distances = [abs(row[0] - query) for row in near]
    if any(d == 0 for d in distances):
        weights = [float(d == 0) for d in distances]
    else:
        weights = [1 / d for d in distances]
    
    uniform_share = sum(row[1] for row in near) / len(near)
    weighted_share = sum(w * row[1] for w, row in zip(weights, near)) / sum(weights)
    uniform_minutes = sum(row[2] for row in near) / len(near)
    weighted_minutes = sum(w * row[2] for w, row in zip(weights, near)) / sum(weights)
    print("distances:", [round(d, 4) for d in distances])
    print("uniform:", round(uniform_share, 4), round(uniform_minutes, 4))
    print("distance:", round(weighted_share, 4), round(weighted_minutes, 4))
    

    會得到距離0.1、0.2、0.3;等權延遲份額0.3333、分鐘20;距離加權延遲份額0.5455、分鐘16.3636。二元分類若以0.5作決策閾值,兩者分別預測未延遲與延遲;這只是例子,不是閾值選擇建議。

    這份程式刻意只處理目前的一維三點,讓每一步看得見;正式資料的缺值、類別特徵、切分、距離與效率,需要另外建立可驗證的流程。

    實務上先問五個問題

    • 這些特徵與距離真的代表任務上的相似嗎?換單位或加入無關欄位後,鄰居是否大幅改變?
    • k與加權方式是否只在開發資料上選擇?縮放與任何學到的投影是否都留在訓練折內?
    • 不同群體與稀少情境有足夠鄰居嗎?離訓練資料很遠的新輸入,要怎麼標示支持不足?
    • 與簡單基準模型相比,選擇KNN是否值得它的預測與儲存成本?
    • 預測是類別、局部份額還是可靠機率?如果拿來做決策,是否已驗證對應的錯誤與成本?

    能回答這幾個問題,比只記住「多數決」更接近真的會用KNN。

    來源與圖片授權

    本文的三鄰居數值、分類與迴歸對照為本站自訂教學;來源圖的實驗沒有由本站重跑。來源頁讀取時間為本系列研究期間2026-10-31,不把網站版本號當作歷史技術誕生時間。

    BSD 3-Clause License
    
    Copyright (c) 2007-2026 The scikit-learn developers.
    All rights reserved.
    
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:
    
    * Redistributions of source code must retain the above copyright notice, this
      list of conditions and the following disclaimer.
    
    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
    
    * Neither the name of the copyright holder nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.
    
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    

    封面沿用scikit-learn圖1,等比縮放並加白邊;手機圖1把左、右兩圖依序改為上、下排列,保留所有座標、標題、圖例與資料點。兩者依相同BSD 3-Clause條件使用,未重畫資料或改動數值。

    留言0

    登入後就能留言。

    登入
    sunny 桑尼
    sunny 桑尼

    AI 資料科學 · 產品經理 · 蒙奇 D 桑尼

    專注於 AI 工具應用與資料科學教育,致力於讓每個人都能用 AI 提升工作效率。曾任職於科技業,現為全職教育創作者。

    讀更多文章 →想自己動手試?領免費 Starter Kit →