最近邻居法(KNN)

转载自:http://mmdays.com/2007/05/16/knn/

各位看到標題,如果沒有聽過KNN演算法,會不會覺得疑惑:KNN是甚麼呢?是不是CNN看久了,就變成DNN、ENN、最後變成KNN了呢?當然不是啦 XD!KNN全名是k-th nearest neighbor,中文意思是「第k位最接近的鄰居」。甚麼是「第k位最接近的鄰居」呢?假設在一個廣場上,有100個朋友,每位朋友都是你的鄰居,最接近你的鄰居,就是「第一位距離最近的鄰居」了,比第一位稍微遠一點的鄰居,就是「第二位距離最近的鄰居」了,以此類推,第10位距離最近的鄰居,就是k=10的時候了。

至於KNN演算法是甚麼,又有甚麼特別呢?之前提過了「人工智慧與機器學習」。KNN演算法就是一種機器學習的演算法。在進一步探討甚麼是KNN演算法之前,我們先介紹一下甚麼是演算法。演算法可以看成是一種「步驟」的集合。舉例來說:我們煮一道菜,第一步是先洗菜,第二步切菜,第三步放油,第四步快炒,第五步加點水悶幾分鐘,第六步再炒幾分鐘,最後第七步加鹽和味精,然後炒到菜煮熟為止。演算法就是這樣子,把工作分成詳細的步驟,有些步驟可能會重複執行,像是菜不夠鹹,就再加點鹽,一直到口味對了為止。有時候會依照情況的不同而有不同的步驟,像是過馬路的時候,如果是紅燈,我們重複「等待」的步驟,如果是綠燈,我們會進行「走路過斑馬線」的步驟。

由於電腦本身就是執行一道一道的指令,因此演算法詳細列出來的步驟,已經很接近電腦執行工作的語言。至於KNN演算法又是由哪些步驟所組成的呢?在這之前,我們再稍微提一下KNN演算法和機器學習之間的關係。之前在「人工智慧與機器學習」的文章中稍微提了一下,機器學習就是讓機器接收外界輸入的資料以後,依照某種演算法(一些步驟的集合),訓練出一種模型,這個模型是一種從資料學習出來的東西,有了這個東西,機器看到新的資料的時候,不會空空如也,而是有某種程度的經驗和智慧,可以了解新的資料了。

在這個過程中,有兩種訓練的方法:監督式和非監督式的學習。所謂監督式的學習,是指在訓練機器學出一個模型的之前,會先有一段訓練的時間,在這段時間裡面,每一筆資料會有一個正確答案,機器學習以後,會根據答案調整自己學習的方法。舉例來說:我們學習數學的時候,可能會練習一些題目,練習以後,會對一下答案,如果算錯了,就會調整自己的計算方式,或是檢查有沒有粗心算錯的地方。機器學習裡面的監督式學習正是如此,訓練之後,才開始有預測的階段,這個時候輸入機器的資料沒有正確答案,機器必須根據他之前學習的模型來判斷,預測新的資料應該輸出哪一個正確答案,而不像再訓練階段的時候,輸入的資料會有人類提供的正確答案了。

另外一種非監督式的學習,則是連訓練的階段都沒有。我們只給予機器簡單的學習方法,或是一個簡單的價值觀,然後就開始把資料輸入機器,讓機器自行判斷正確答案。舉例來說:我們還沒上小學之前,已經有了一些基本的說話能力。我們從嬰兒開始啞啞學語,我們並不曉得,甚麼是主詞、動詞、受詞。我們可能連注音符號都不曉得。但是我們的父母一直跟我們講話,我們有一天就突然蹦出一些詞,第一句可能是「媽媽」!第二句可能是「爸爸」!之後可能開始簡單的對話,最後在上小學之前,我們至少會問簡單的問題,老師講的句子也都聽的懂,才有辦法起立、立正、敬禮,還有學習注音符號,練習寫字了。非監督式的學習就是類似如此,我們給機器資料簡單的規則價值觀,剩下的就交給機器一邊學習一邊預測正確答案是甚麼了。

KNN就是一種非監督式的學習法。首先,我們要替每一筆資料定出一個位置,像是下圖:

我們的目標是要機器學會怎樣子分出紅點和藍點。每個點在平面上有個位置,分別用(x,y)來代表,舉個例子來說:紅點代表女生的大頭照,藍點代表男生的大頭照,x軸代表照片中頭髮的長度,y軸代表照片中臉面積的大小。現在機器已經知道某些點是男生的大頭照(藍色的點)、某些是女生的大頭照(紅色的點)。當一張新的大頭照輸入機器以後(圖片裡面打問號沒有顏色的點),KNN演算法就先計算這個點,和其他已經知道男生或女生的資料點之間的距離(圖裡面畫了幾條線代表在計算距離)。今天KNN的K如果設定成1,也就是(1-NN)的話,代表機器會找第一位距離最近的點,然後看這個點是男生(圖中藍色點)或是女生(圖中紅色點)。如果這個點是男生,那麼我們也預測剛才打問號的這個點(新的資料點)是男生的大頭照。之後這個問號點就變成藍色的,然後繼續反覆同樣的動作在下一個新輸入的資料點,預測新的問號點是男生或是女生。

如果k=3,也就是使用3-NN學習,情況會變成怎樣子呢?機器同樣先計算圖中打問號的點和各個顏色的點的距離,接著選出前三名距離最近的點,然後看看裡面紅色的點比較多(2個以上的點是紅色)還是藍色的點比較多(2個以上的點是藍色),如果藍色點比較多,就判斷這個新問號點,是男生的大頭照了。以此類推,會有5-NN,7-NN,9-NN學習法,端看問題的需要而定。

KNN學習法就是如此。他的好處是簡單,而且是一種非監督式學習方法,讓人們省去準備訓練資料(資料和對應的正確答案)的時間。然而KNN也有他困難的地方。首先是每個機器學習法都要面對的問題,就是選擇特徵,用剛才的例子,我們用頭髮長度和臉大小的面積來讓機器學習,如果遇到留長髮的男生或是輪廓比較大的女生,可能就判斷不大出來:或是說,如果我們改用膚色來判斷,比較白的是女生,比較黑的是男生,萬一這個規則拿來判斷歐洲人,可能也不大行。

另一個困難則是距離的訂定。剛才的例子中,頭髮長度如果用公分來算,差距1公分的頭髮長度,可能有辦法分辨男女。如果是用頭髮的顏色來判斷的話,那麼顏色的「距離」就不知道要怎麼定了,或許可以定成光線頻率的距離,那機器還可以學習,不然「紅色」和「黑色」兩種顏色之間的距離,可能就不知道要怎麼定了。這個問題在語意的問題上,也特別重要。如果我們要判斷兩個詞是否屬於同一類東西,但是只看兩個詞差別的字數,用相異字數的個數來當做座標上的距離,就會出現一些意想不到的狀況。譬如說:「巴黎鐵塔」、和「巴黎蛋塔」,只差了一個字,和「巴黎聖母院」差了三個字,所以「巴黎鐵塔」和「巴黎蛋塔」比較接近,屬於同一類,那麼機器學出來的東西,可能就不是我們想要的了。

因此,KNN是個好用的機器學習法,然而在某些問題上,仍然有改進的空間了!希望大家讀完這一篇以後,都能了解KNN演算法囉!

總結

  1. 演算法是一些步驟的集合,包含重覆部分與依條件執行的部分
  2. 機器學習可分為監督和非監督兩種學習法,差別在於有無訓練資料(訓練資料裡面有正確答案給機器參考)
  3. KNN是一種非監督式學習演算法,是參考最近k個鄰居的答案來做判斷
  4. 某些問題上(例如語意問題)以及特徵的選擇,是使用KNN需要注意的地方

參考資料

  1. KNN Algorithm (Wikipedia)
  2. 演算法Algorithm (Wikipedia
### KNN算法中交叉验证的应用与实现 #### 背景介绍 K最近邻(K-Nearest Neighbors, KNN)是一种基于实例的学习方,其核心思想是通过计算样本间的距离来进行分类或回归预测。然而,在实际应用中,选择合适的 \( k \) 值是一个重要的问题,因为不同的 \( k \) 值会对模型性能产生显著影响[^1]。 为了找到最佳的 \( k \) 值,可以利用交叉验证技术评估不同参数下的模型表现。这种方不仅能够有效减少过拟合的风险,还能帮助我们更科学地选取超参数。 --- #### 什么是交叉验证? 交叉验证是一种用于评估统计分析结果稳定性和泛化能力的技术。其中最常用的是 **K折交叉验证**(\( K \)-fold Cross Validation)。该方将数据集划分为 \( K \) 个子集(称为“折叠”,folds),每次训练时使用 \( K-1 \) 折作为训练集,剩下的那一折作为测试集。重复此过程 \( K \) 次后,最终取平均误差作为模型的整体评价指标[^2]。 --- #### 如何在KNN中应用交叉验证? 以下是具体的操作流程: 1. **准备数据**: 将原始数据随机打乱并分割成若干部分。 2. **定义候选 \( k \) 值范围**: 设定一系列可能的 \( k \) 值供后续比较,例如 \( k=[1, 3, 5, ..., 21] \)。 3. **执行K折划分**: 对于每种 \( k \),分别按照上述方式完成多次训练和测试。 4. **记录错误率/准确性得分**: 记录每一次实验的结果,并汇总得到每个 \( k \) 下的表现均值。 5. **选择最优 \( k \)**: 找到使目标函数最小化的那个 \( k \) 值。 下面给出一段Python代码示例展示这一过程的具体实施步骤: ```python from sklearn.model_selection import cross_val_score from sklearn.neighbors import KNeighborsClassifier import numpy as np # 初始化变量 X_train = ... # 特征矩阵 y_train = ... # 标签向量 k_values = range(1, 22, 2) best_k = None best_accuracy = 0 for k in k_values: knn_model = KNeighborsClassifier(n_neighbors=k) scores = cross_val_score(knn_model, X_train, y_train, cv=5, scoring='accuracy') mean_accuracy = np.mean(scores) if mean_accuracy > best_accuracy: best_accuracy = mean_accuracy best_k = k print(f"The optimal value of k is {best_k} with accuracy {best_accuracy:.4f}") ``` 以上脚本实现了自动寻找最佳邻居数的功能,同时借助`cross_val_score()`简化了手动拆分数据的工作负担。 --- #### 结果解释 当运行完毕后,程序会打印出最适合当前数据分布情况的那个整数值以及对应的精确度水平。这一步骤极大地提高了调参效率,减少了人为干预带来的偏差风险。 ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值