干货 :送你一份使用k近邻算法实现回归的实用指南(附代码、链接)
作者:AISHWARYA SINGH, AUGUST 22, 2018;翻譯:趙雪堯;校對(duì):張玲
本文約4200字,建議閱讀10分鐘。
本文解釋了在k近鄰算法工作原理的基礎(chǔ)上,簡(jiǎn)單介紹三種計(jì)算點(diǎn)距離方法。
簡(jiǎn)介
?
在我遇到的所有機(jī)器學(xué)習(xí)算法中,KNN是最容易學(xué)會(huì)的。盡管它很簡(jiǎn)單,但事實(shí)證明它在某些任務(wù)中非常有效(我們將在本文中看到)。
?
甚至于在某種情況下它是更好的選擇,畢竟它可以同時(shí)用于分類(lèi)和回歸問(wèn)題!不過(guò),它更常用來(lái)解決分類(lèi)問(wèn)題,很少看到在回歸任務(wù)中使用KNN。提起KNN可以被用于回歸任務(wù),只是想說(shuō)明和強(qiáng)調(diào)一下當(dāng)目標(biāo)變量是自然連續(xù)的時(shí)候,KNN也會(huì)同樣有效。
在本文中,我們將首先理解KNN算法背后的直觀解釋,看看計(jì)算點(diǎn)之間距離的不同方法,然后在Big Mart Sales數(shù)據(jù)集上用Python實(shí)現(xiàn)KNN算法。讓我們開(kāi)始吧!
目錄
1.?一個(gè)簡(jiǎn)單的例子來(lái)理解KNN背后的直觀解釋
2.?KNN算法是如何工作的?
3.?點(diǎn)之間距離的計(jì)算方法
4.?如何選擇k因子?
5.?應(yīng)用在一個(gè)數(shù)據(jù)集上
6.?額外的資源
1. 一個(gè)簡(jiǎn)單的例子來(lái)理解KNN背后的直觀解釋
讓我們從一個(gè)簡(jiǎn)單的例子開(kāi)始。考慮下表——它包括10個(gè)人的身高、年齡和體重(目標(biāo))。如圖所示,ID11的體重值丟失了。下面,我們需要根據(jù)這個(gè)人的身高和年齡來(lái)預(yù)測(cè)他的體重。
?
注意:該表中的數(shù)據(jù)不代表實(shí)際值。它只是作為一個(gè)例子來(lái)解釋這個(gè)概念
為了更清楚地了解這一點(diǎn),下面是從上表得出的身高與年齡的關(guān)系圖:
在上圖中,y軸代表一個(gè)人的身高(以英尺為單位),x軸代表年齡(以年為單位)。這些點(diǎn)是根據(jù)ID值編號(hào)的。黃色點(diǎn)(ID 11)是我們的測(cè)試點(diǎn)。
?
如果讓你根據(jù)上圖來(lái)確定編號(hào)ID11這個(gè)人的體重,你的答案會(huì)是什么?你可能會(huì)說(shuō),因?yàn)镮D11更接近于點(diǎn)5和點(diǎn)1,所以這個(gè)人的體重應(yīng)該與這些id相似,可能在72-77公斤之間(表中ID1和ID5的體重)。這是有道理的,但是算法是如何預(yù)測(cè)這些值的呢?我們會(huì)在這篇文章里找到答案。
?
2. KNN算法是如何工作的?
?
如上所述,KNN可以用于分類(lèi)和回歸問(wèn)題。該算法使用“特征相似度”來(lái)預(yù)測(cè)任何新數(shù)據(jù)點(diǎn)的值。這意味著,根據(jù)與訓(xùn)練集中點(diǎn)的相似程度為新點(diǎn)賦值。從我們的示例中,我們知道ID11的高度和年齡與ID1和ID5相似,所以重量也大致相同。
?
如果這是一個(gè)分類(lèi)問(wèn)題,我們會(huì)把眾數(shù)作為最終的預(yù)測(cè)。在本例中,我們有兩個(gè)體重值——72和77。誰(shuí)能猜到最終值是如何計(jì)算的?我們會(huì)將兩個(gè)取值的平均值作為最終的預(yù)測(cè)結(jié)果。
下面是這個(gè)算法的具體步驟:
首先,計(jì)算新點(diǎn)與訓(xùn)練集中每一個(gè)點(diǎn)的距離。
選出與新點(diǎn)最接近的K個(gè)點(diǎn)(根據(jù)距離)。在這個(gè)例子中,如果K=3,點(diǎn)1,5,6將會(huì)被選擇。在本文后續(xù)部分,我們會(huì)進(jìn)一步探索選擇正確K值的方法。
將所有點(diǎn)的均值作為新點(diǎn)的最終預(yù)測(cè)值。在這個(gè)例子中,我們可以得到ID11的體重=(77+72+60)/3 = 69.66kg。
?
接下來(lái)的幾個(gè)小節(jié)里,我們將討論以上三個(gè)步驟的具體細(xì)節(jié)。
?
3. 點(diǎn)之間距離的計(jì)算方法
?
第一步是計(jì)算新點(diǎn)與訓(xùn)練集中每個(gè)點(diǎn)之間的距離。計(jì)算這個(gè)距離的方法有很多種,其中最常見(jiàn)的方法是歐幾里得法、曼哈頓法(連續(xù)的)和漢明距離法(離散的)。
?
歐幾里得距離:歐幾里得距離是新點(diǎn)(x)和現(xiàn)有點(diǎn)(y)之間的平方差之和的平方根。
曼哈頓距離:這是實(shí)向量之間的距離,用它們差的絕對(duì)值之和來(lái)計(jì)算。
漢明距離:用于離散變量,如果(x)和(y)值相等,距離D就等于0。否則D = 1。
一旦計(jì)算完成新觀測(cè)點(diǎn)與訓(xùn)練集中點(diǎn)之間的距離,下一步就是挑選最近的點(diǎn)。點(diǎn)的數(shù)量由K值決定。
4. 如何選擇k因子?
第二步是確定K值。在為新觀測(cè)點(diǎn)賦值時(shí),K值決定了需要參考的鄰點(diǎn)數(shù)量。
?
在我們的例子里,對(duì)于K=3,最近的點(diǎn)就是ID1、ID5和ID6。
ID11的預(yù)測(cè)體重是:
ID11 = (77+72+60)/3?
ID11 = 69.66 kg
對(duì)于k=5,最近的點(diǎn)是ID1、ID4、ID5、ID6和ID10。
ID11的預(yù)測(cè)體重是:
ID 11 =? (77+59+72+60+58)/5?
ID 11 = 65.2 kg
我們注意到,基于k值,最終結(jié)果往往會(huì)改變。那么如何求出k的最優(yōu)值呢?讓我們根據(jù)訓(xùn)練集和驗(yàn)證集的誤差計(jì)算來(lái)決定(畢竟,最小化誤差是我們的最終目標(biāo)!)
請(qǐng)看下面的圖表,不同k值的訓(xùn)練錯(cuò)誤和驗(yàn)證錯(cuò)誤。
K值很低時(shí)(假設(shè)k = 1),該模型過(guò)擬合訓(xùn)練數(shù)據(jù),從而導(dǎo)致驗(yàn)證集的錯(cuò)誤率很高。另一方面,k取較大值時(shí),模型在訓(xùn)練集和驗(yàn)證集上表現(xiàn)都很差。如果你仔細(xì)觀察,驗(yàn)證誤差曲線的值在k = 9時(shí)達(dá)到最小值,此時(shí)k值是模型的最優(yōu)值(根據(jù)不同的數(shù)據(jù)集會(huì)有所不同)。這條曲線被稱(chēng)為“手肘曲線”(因?yàn)樗男螤詈芟袷种?#xff09;,通常用于確定k值。
?
我們還可以使用網(wǎng)格搜索技術(shù)來(lái)確定k值。在下一個(gè)小節(jié)里我們將會(huì)介紹它。
5. 應(yīng)用在一個(gè)數(shù)據(jù)集上
讀到現(xiàn)在,你應(yīng)當(dāng)對(duì)算法有一個(gè)清晰的理解。如果你還有問(wèn)題,請(qǐng)給我們的公眾號(hào)留言,我們很樂(lè)意回答。現(xiàn)在,我們將在數(shù)據(jù)集中實(shí)現(xiàn)該算法。我已經(jīng)使用了Big Mart sales數(shù)據(jù)集來(lái)展示算法實(shí)現(xiàn)的過(guò)程,大家可以從這個(gè)鏈接下載它。
讀取文件
import pandas as pd
df = pd.read_csv('train.csv')
df.head()
計(jì)算缺失值
df.isnull().sum()
#missing values in Item_weight and Outlet_size needs to be imputed
mean = df['Item_Weight'].mean() #imputing item_weight with mean
df['Item_Weight'].fillna(mean, inplace =True)
mode = df['Outlet_Size'].mode() #imputing outlet size with mode
df['Outlet_Size'].fillna(mode[0], inplace =True)
處理分類(lèi)變量,刪除id列
df.drop(['Item_Identifier', 'Outlet_Identifier'], axis=1, inplace=True)
df = pd.get_dummies(df)
創(chuàng)建訓(xùn)練和測(cè)試集
from sklearn.model_selection import train_test_split
train , test = train_test_split(df, test_size = 0.3)
?
x_train = train.drop('Item_Outlet_Sales', axis=1)
y_train = train['Item_Outlet_Sales']
?
x_test = test.drop('Item_Outlet_Sales', axis = 1)
y_test = test['Item_Outlet_Sales']
預(yù)處理——擴(kuò)展特征
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler(feature_range=(0, 1))
?
x_train_scaled = scaler.fit_transform(x_train)
x_train = pd.DataFrame(x_train_scaled)
?
x_test_scaled = scaler.fit_transform(x_test)
x_test = pd.DataFrame(x_test_scaled)
?
看看不同K值的錯(cuò)誤率
#import required packages
from sklearn import neighbors
from sklearn.metrics import mean_squared_error?
from math import sqrt
import matplotlib.pyplot as plt
%matplotlib inline
rmse_val = [] #to store rmse values for different k
for K in range(20):
????K = K+1
????model = neighbors.KNeighborsRegressor(n_neighbors = K)
?
????model.fit(x_train, y_train) ?#fit the model
????pred=model.predict(x_test) #make prediction on test set
????error = sqrt(mean_squared_error(y_test,pred)) #calculate rmse
????rmse_val.append(error) #store rmse values
????print('RMSE value for k= ' , K , 'is:', error)
輸出:
RMSE value for k = 1 is: 1579.8352322344945
RMSE value for k = 2 is: 1362.7748806138618
RMSE value for k = 3 is: 1278.868577489459
RMSE value for k = 4 is: 1249.338516122638
RMSE value for k = 5 is: 1235.4514224035129
RMSE value for k = 6 is: 1233.2711649472913
RMSE value for k = 7 is: 1219.0633086651026
RMSE value for k = 8 is: 1222.244674933665
RMSE value for k = 9 is: 1219.5895059285074
RMSE value for k = 10 is: 1225.106137547365
RMSE value for k = 11 is: 1229.540283771085
RMSE value for k = 12 is: 1239.1504407152086
RMSE value for k = 13 is: 1242.3726040709887
RMSE value for k = 14 is: 1251.505810196545
RMSE value for k = 15 is: 1253.190119191363
RMSE value for k = 16 is: 1258.802262564038
RMSE value for k = 17 is: 1260.884931441893
RMSE value for k = 18 is: 1265.5133661294733
RMSE value for k = 19 is: 1269.619416217394
RMSE value for k = 20 is: 1272.10881411344
?
#plotting the rmse values against k values
curve = pd.DataFrame(rmse_val) #elbow curve?
curve.plot()
正如我們所討論的,當(dāng)k=1時(shí),我們得到一個(gè)非常高的RMSE值。RMSE值隨著k值的增加而減小。在k= 7時(shí),RMSE約為1219.06,并進(jìn)一步增加k值。我們可以有把握地說(shuō),在k=7這種情況下,會(huì)得到最好的結(jié)果。
這些是使用訓(xùn)練數(shù)據(jù)集得到的預(yù)測(cè)結(jié)果。現(xiàn)在讓我們預(yù)測(cè)測(cè)試數(shù)據(jù)集的值并提交。
在測(cè)試集上得到預(yù)測(cè)值
#reading test and submission files
test = pd.read_csv('test.csv')
submission = pd.read_csv('SampleSubmission.csv')
submission['Item_Identifier'] = test['Item_Identifier']
submission['Outlet_Identifier'] = test['Outlet_Identifier']
#preprocessing test dataset
test.drop(['Item_Identifier', 'Outlet_Identifier'], axis=1, inplace=True)
test['Item_Weight'].fillna(mean, inplace =True)
test = pd.get_dummies(test)
test_scaled = scaler.fit_transform(test)
test = pd.DataFrame(test_scaled)
#predicting on the test set and creating submission file
predict = model.predict(test)
submission['Item_Outlet_Sales'] = predict
submission.to_csv('submit_file.csv',index=False)
提交這個(gè)文件,我得到了一個(gè)RMSE 1279.5159651297。
?
實(shí)現(xiàn)網(wǎng)格搜索(Gridsearch)
為了確定k值,每次繪制手肘曲線是一個(gè)繁瑣的過(guò)程。我們可以簡(jiǎn)單地使用gridsearch來(lái)找到最佳值。
from sklearn.model_selection import GridSearchCV
params = {'n_neighbors':[2,3,4,5,6,7,8,9]}
knn = neighbors.KNeighborsRegressor(
model = GridSearchCV(knn, params, cv=5)
model.fit(x_train,y_train)
model.best_params
?
輸出:
{'n_neighbors': 7}
6. 額外的資源
在本文中,我們介紹了KNN算法的工作原理及其在Python中的實(shí)現(xiàn)。這是最基本也是最有效的機(jī)器學(xué)習(xí)技術(shù)之一。對(duì)于在R中實(shí)現(xiàn)KNN,您可以瀏覽這篇文章:使用R的KNN算法。
在本文中,我們直接使用sklearn庫(kù)中的KNN模型。您還可以從頭實(shí)現(xiàn)KNN(我建議這樣做!),這篇文章將對(duì)此進(jìn)行介紹:KNN simplified。
如果你認(rèn)為你很了解KNN,并且對(duì)該技術(shù)有扎實(shí)的掌握,在這個(gè)MCQ小測(cè)驗(yàn)中測(cè)試你的技能:關(guān)于KNN算法的30個(gè)問(wèn)題。祝你好運(yùn)!
?
譯者附:注冊(cè)下載數(shù)據(jù)集流程
1、注冊(cè)一個(gè)賬號(hào),然后注冊(cè)這個(gè)比賽
2、點(diǎn)擊data
就可以愉快的下載運(yùn)行并測(cè)試?yán)瞺
譯者的分?jǐn)?shù)是:
歡迎留言自己的分?jǐn)?shù)和心得~
「送你一份使用k近鄰算法實(shí)現(xiàn)回歸的實(shí)用指南(附代碼、鏈接):
鏈接: https://pan.baidu.com/s/1eMd2cqDD1YljBdS8zv3W8Q 提取碼: 6mx1」
原文標(biāo)題:
A Practical Introduction to K-Nearest Neighbors Algorithm for Regression (with Python code)
原文鏈接:?
https://www.analyticsvidhya.com/blog/2018/08/k-nearest-neighbor-introduction-regression-python/
譯者簡(jiǎn)介:趙雪堯,北郵研三在讀,京東見(jiàn)習(xí)算法工程師,目前研究強(qiáng)化學(xué)習(xí)廣告競(jìng)價(jià)模型。相信數(shù)據(jù)和算法將為企業(yè)發(fā)展賦能,希望跟志同道合的小伙伴一起追尋前沿消息,深入探索算法的極限。在玄學(xué)調(diào)參的道路上,一路狂奔。
「完」
本次轉(zhuǎn)自:THU數(shù)據(jù)派 微信公眾號(hào);
版權(quán)聲明:本號(hào)內(nèi)容部分來(lái)自互聯(lián)網(wǎng),轉(zhuǎn)載請(qǐng)注明原文鏈接和作者,如有侵權(quán)或出處有誤請(qǐng)和我們聯(lián)系。
關(guān)聯(lián)閱讀
原創(chuàng)系列文章:
1:從0開(kāi)始搭建自己的數(shù)據(jù)運(yùn)營(yíng)指標(biāo)體系(概括篇)
2 :從0開(kāi)始搭建自己的數(shù)據(jù)運(yùn)營(yíng)指標(biāo)體系(定位篇)
3 :從0開(kāi)始搭建自己的數(shù)據(jù)運(yùn)營(yíng)體系(業(yè)務(wù)理解篇)
4 :數(shù)據(jù)指標(biāo)的構(gòu)建流程與邏輯
5 :系列 :從數(shù)據(jù)指標(biāo)到數(shù)據(jù)運(yùn)營(yíng)指標(biāo)體系
6: ??實(shí)戰(zhàn) :為自己的公號(hào)搭建一個(gè)數(shù)據(jù)運(yùn)營(yíng)指標(biāo)體系
7:??從0開(kāi)始搭建自己的數(shù)據(jù)運(yùn)營(yíng)指標(biāo)體系(運(yùn)營(yíng)活動(dòng)分析)
數(shù)據(jù)運(yùn)營(yíng)?關(guān)聯(lián)文章閱讀:??
運(yùn)營(yíng)入門(mén),從0到1搭建數(shù)據(jù)分析知識(shí)體系? ??
推薦 :數(shù)據(jù)分析師與運(yùn)營(yíng)協(xié)作的9個(gè)好習(xí)慣
干貨 :手把手教你搭建數(shù)據(jù)化用戶(hù)運(yùn)營(yíng)體系
推薦 :最用心的運(yùn)營(yíng)數(shù)據(jù)指標(biāo)解讀
干貨 : 如何構(gòu)建數(shù)據(jù)運(yùn)營(yíng)指標(biāo)體系
從零開(kāi)始,構(gòu)建數(shù)據(jù)化運(yùn)營(yíng)體系
干貨 :解讀產(chǎn)品、運(yùn)營(yíng)和數(shù)據(jù)三個(gè)基友關(guān)系
干貨 :從0到1搭建數(shù)據(jù)運(yùn)營(yíng)體系
數(shù)據(jù)分析、數(shù)據(jù)產(chǎn)品?關(guān)聯(lián)文章閱讀:
干貨 :數(shù)據(jù)分析團(tuán)隊(duì)的搭建和思考
關(guān)于用戶(hù)畫(huà)像那些事,看這一文章就夠了
數(shù)據(jù)分析師必需具備的10種分析思維。
如何構(gòu)建大數(shù)據(jù)層級(jí)體系,看這一文章就夠了
干貨 : 聚焦于用戶(hù)行為分析的數(shù)據(jù)產(chǎn)品
如何構(gòu)建大數(shù)據(jù)層級(jí)體系,看這一文章就夠了
80%的運(yùn)營(yíng)注定了打雜?因?yàn)槟銢](méi)有搭建出一套有效的用戶(hù)運(yùn)營(yíng)體系
從底層到應(yīng)用,那些數(shù)據(jù)人的必備技能
讀懂用戶(hù)運(yùn)營(yíng)體系:用戶(hù)分層和分群
做運(yùn)營(yíng)必須掌握的數(shù)據(jù)分析思維,你還敢說(shuō)不會(huì)做數(shù)據(jù)分析
合作請(qǐng)加qq:365242293??
更多相關(guān)知識(shí)請(qǐng)回復(fù):“ 月光寶盒 ”;
數(shù)據(jù)分析(ID :?ecshujufenxi?)互聯(lián)網(wǎng)科技與數(shù)據(jù)圈自己的微信,也是WeMedia自媒體聯(lián)盟成員之一,WeMedia聯(lián)盟覆蓋5000萬(wàn)人群。
總結(jié)
以上是生活随笔為你收集整理的干货 :送你一份使用k近邻算法实现回归的实用指南(附代码、链接)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: linux查看照片命令,php 及 li
- 下一篇: HTML第七章作业