National Central University
Uedu Main Site
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try an AI Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

3

Local AI

--

Uedu Code

--

中央大學 AQI 80 24°C PM2.5 21
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 08

k 近鄰

用 numpy 寫:距離、尺度的影響、k 怎麼選
Interaction實作 30 minute(s)

Learning Objectives

  • 用 numpy 寫出 k 近鄰:算距離、排序、取最近的 k 筆、投票
  • 說明特徵尺度為什麼會影響 k 近鄰,並用 StandardScaler 標準化
  • 說明 scaler 為什麼只能用訓練資料 fit
  • 從訓練與測試準確率的變化,判斷 k 太小或太大

看看最像的幾筆資料

想知道一位同學這學期會不會及格,一個很直接的做法是:找過去資料裡和他最像的幾位同學,看那些人大多及格還是不及格。 這就是 k 近鄰(k-nearest neighbors,kNN):

  1. 算出要預測的這一筆,和每一筆訓練資料的距離;
  2. 取距離最近的 k 筆;
  3. 這 k 筆投票,票數最多的類別就是預測。

k 近鄰「訓練」時幾乎什麼都沒做,只是把資料存起來,真正的計算發生在預測的時候。 距離最常用歐氏距離,也就是把每個特徵的差平方、加總、再開根號:

距離 = √( (x1 − y1)² + (x2 − y2)² + … )

先用 numpy 親手寫一次,之後用 scikit-learn 時才知道它在做什麼。

逐步看:用 numpy 寫 k 近鄰

六筆訓練資料、兩個特徵、兩個類別,要預測 query 這一點。注意右邊的陣列:每一行都是對整個陣列一次算完,不需要自己寫迴圈(「資料分析」軌學過的向量化)。

尺度會決定誰說了算

距離是把每個特徵的差加起來,所以數字範圍大的特徵會主導距離。 小考分數相差 10 分,平方是 100;通勤時間如果用秒記,相差 10 分鐘就是 600,平方是 360,000。 這時候「最像的同學」幾乎就是「通勤時間最接近的同學」,小考分數再怎麼有用也發揮不了作用。

解決方法是先把每個特徵轉成相同的尺度。最常用的是標準化(standardization):減掉平均、除以標準差,轉換後每個特徵的平均是 0、標準差是 1。

scaler = StandardScaler().fit(X_train)     # 只用訓練資料算平均與標準差
X_train_s = scaler.transform(X_train)
X_test_s = scaler.transform(X_test)        # 測試資料用同一組平均與標準差

scaler 只能用訓練資料 fit。測試資料代表「模型還沒看過的資料」,如果平均與標準差是連測試資料一起算的,就等於偷看了答案的一部分,這叫資料洩漏(第 14 課會細談)。

靠距離或梯度下降的模型(k 近鄰、羅吉斯迴歸、支援向量機、神經網路)都要注意尺度;決策樹只比大小,不受尺度影響(第 9 課)。

逐步看:標準化前後差多少

這裡直接用亂數產生 300 筆模擬資料,讓現象清楚:及格與否由小考分數決定,通勤秒數和及格無關,但數字大得多。

互動練習:切換尺度,看鄰居換人

資料是 40 筆模擬資料:小考平均(標準差約 13)和通勤秒數(標準差約 1100),及格與否和通勤秒數幾乎沒有關係。紅點是要預測的新同學,黑框是找到的鄰居。

k 要選多大

k 控制模型的複雜度:

k 模型的樣子 問題
很小(例如 1) 只看最近的一筆,決策邊界彎來彎去 把訓練資料裡的雜訊也記住了:訓練準確率很高,測試準確率不好(過擬合)
適中 邊界平滑
很大(接近全部資料) 幾乎所有人都投票,預測接近「永遠猜最多的類別」 什麼規律都學不到(欠擬合)

k=1 時,每一筆訓練資料的最近鄰居就是自己,所以訓練準確率一定是 1.0,這個數字沒有意義。判斷模型好不好要看沒看過的資料。

逐步看:k 怎麼影響準確率

這次用 students.csv(程式產生的模擬資料,不是任何學校的真實資料)預測是否及格。看輸出的三欄:k、訓練準確率、測試準確率;最後畫成折線圖。

互動練習:k 怎麼改變決策邊界

把資料換成兩個維度的月牙形,就能把每個位置的預測畫出來。實心是訓練資料、空心是測試資料,背景顏色是 k 近鄰的預測。

可以用測試資料挑 k 嗎?

前面的折線圖看起來 k=5 最好,但要小心:如果用測試資料挑 k,測試資料就不再是「沒看過的資料」了,這個 0.809 會偏樂觀。 而且測試資料只有 94 筆,差一兩筆,準確率就差 1~2%,k=5 和 k=41 的差距可能只是運氣。 正確的做法是另外切出驗證資料,或用交叉驗證,第 14 課會教。

實作:寫一個 knn_predict 函數

完成 knn_predict(X, y, query, k):回傳 query 的預測類別。步驟同上面的逐步範例:算距離、argsort 取最近的 k 筆、bincount 加 argmax 投票。

你的輸出
預期輸出

小測驗:k 近鄰

1.

下面程式會印出什麼?

import numpy as np
dist = np.array([4.0, 1.0, 3.0, 2.0])
print(np.argsort(dist)[:2].tolist())
2.

k=1 時訓練準確率是 1.0,最恰當的解讀是?

3.

資料裡有「年收入(元)」和「年齡」兩個特徵,直接用 k 近鄰,最可能發生什麼?

4.

標準化時,下面哪一種寫法才正確?

5.

k 設成和訓練資料一樣多,預測會變成什麼樣子?

第 1 次作答

重點整理

  • k 近鄰:算距離、取最近的 k 筆、投票。訓練只是存資料,計算都在預測時發生,資料多時預測會變慢。
  • 距離會被數字範圍大的特徵主導,所以要先標準化;scaler 只用訓練資料 fit,否則是資料洩漏。
  • k 太小會過擬合(訓練高、測試低),k 太大會欠擬合(兩者都接近猜最多的類別)。
  • 不要用測試資料挑 k,第 14 課用交叉驗證解決。
  • 下一課的決策樹走另一條路:不算距離,而是問一連串「這個特徵大於某個值嗎?」,所以不受尺度影響。
這一課完成了!
Next lesson:決策樹
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。