k近邻回归算法python_K近邻算法用作回归的使用介绍(使用Python代码)
介紹
在我遇到的所有機(jī)器學(xué)習(xí)算法中,KNN是最容易上手的。盡管它很簡(jiǎn)單,但事實(shí)上它其實(shí)在某些任務(wù)中非常有效(正如你將在本文中看到的那樣)。
甚至它可以做的更好?它可以用于分類和回歸問題!然而,它其實(shí)更擅長(zhǎng)用于分類問題。我很少看到KNN在任何回歸任務(wù)上實(shí)現(xiàn)。我在這里的目的是說明并強(qiáng)調(diào),當(dāng)目標(biāo)變量本質(zhì)上是連續(xù)的時(shí),KNN是如何有效的運(yùn)作的。
在本文中,我們將首先了解KNN算法背后的思維,研究計(jì)算點(diǎn)與點(diǎn)之間距離的不同方法,然后最終在Big Mart Sales數(shù)據(jù)集上用Python實(shí)現(xiàn)該算法。讓我們動(dòng)起來吧
1.用簡(jiǎn)單的例子來理解KNN背后的邏輯
讓我們從一個(gè)簡(jiǎn)單的例子開始。請(qǐng)考慮下表 - 它包含10人的身高,年齡和體重(目標(biāo))值。如你所見,缺少ID11的重量值。我們需要根據(jù)他們的身高和年齡來預(yù)測(cè)這個(gè)人的體重。
注意:此表中的數(shù)據(jù)不代表實(shí)際值。它僅用作一個(gè)例子來解釋這個(gè)概念。
為了更清楚地了解這一點(diǎn),下面是上表中高度與年齡的關(guān)系圖:
在上圖中,y軸表示人的身高(以英尺為單位),x軸表示年齡(以年為單位)。這些點(diǎn)是根據(jù)ID值進(jìn)行編號(hào)。黃點(diǎn)(ID 11)是我們的測(cè)試點(diǎn)。
如果我要求你根據(jù)圖來確定ID11的重量,你的答案會(huì)是什么?你可能會(huì)說,因?yàn)镮D11 更接近第 5點(diǎn)和第1點(diǎn),所以它必須具有與這些ID類似的重量,可能在72-77千克之間(表中ID1和ID5的權(quán)重)。這實(shí)際上是有道理的,但你認(rèn)為算法會(huì)如何預(yù)測(cè)這些值呢?讓我們?cè)谙逻呥M(jìn)行試驗(yàn)討論。
2. KNN算法是怎樣工作的
如上所述,KNN可用于分類和回歸問題。該算法使用“ 特征相似性 ”來預(yù)測(cè)任何新數(shù)據(jù)點(diǎn)的值。這意味著新的點(diǎn)將根據(jù)其與訓(xùn)練集中的點(diǎn)的接近程度而進(jìn)行分配。從我們的例子中,我們知道ID11的高度和年齡類似于ID1和ID5,因此重量也大致相同。
如果這是一個(gè)分類問題,我們會(huì)采用該模式作為最終預(yù)測(cè)。在這種情況下,我們有兩個(gè)重量值--72和77.猜猜最終值是如何計(jì)算的?是取兩個(gè)重量的平均值來作為最終的預(yù)測(cè)值。
以下是該算法的逐步說明:首先,計(jì)算新的點(diǎn)與每個(gè)訓(xùn)練點(diǎn)之間的距離。選擇最接近的k個(gè)數(shù)據(jù)點(diǎn)(基于距離)。在我們演示的例子中,如果k的值為3,則將選擇點(diǎn)1,5,6。我們將在本文后面進(jìn)一步探索選擇正確的k值的方法。這些數(shù)據(jù)點(diǎn)的平均值是新點(diǎn)的最終預(yù)測(cè)值。在這里,我們的ID11的重量為 =(77 + 72 + 60)/ 3 = 69.66千克。
在接下來的幾節(jié)中,我們將詳細(xì)討論這三個(gè)步驟中的每一個(gè)。
3.點(diǎn)與點(diǎn)之間距離的計(jì)算方法
所述第一步驟是計(jì)算新點(diǎn)和每個(gè)訓(xùn)練點(diǎn)之間的距離。計(jì)算該距離有多種方法,其中最常見的方法是 - 歐幾里德,曼哈頓(用于連續(xù))和漢明距離(用于分類)。歐幾里德距離:歐幾里德距離計(jì)算為新點(diǎn)(x)和現(xiàn)有點(diǎn)(y)之間的差的平方和的平方根。
曼哈頓距離:這是實(shí)際向量之間的距離,使用它們的絕對(duì)差值之和表示。漢明距離:用于分類變量。如果值(x)和值(y)相同,則距離D將等于0。否則D = 1。
一旦一個(gè)新的觀測(cè)值與我們訓(xùn)練集中的點(diǎn)之間的距離被測(cè)量出來,下一步就是要選擇最近的點(diǎn)。要考慮的點(diǎn)的數(shù)量由k的值定義。
4.如何選擇k因子
第二個(gè)步驟是選擇k值。這決定了我們?cè)跒槿魏涡碌挠^察值賦值時(shí)所要考慮到的鄰居的數(shù)量。
在我們的示例中,k值 = 3,最近的點(diǎn)是ID1,ID5和ID6。
ID11的重量預(yù)測(cè)將是:
ID11 =(77 + 72 + 60)/ 3 ID11 = 69.66千克
如果k的值 = 5的話,那么距離最近的點(diǎn)將是ID1,ID4,ID5,ID6,ID10。
那么ID11的預(yù)測(cè)將是:
ID 11 =(77 + 59 + 72 + 60 + 58)/ 5 ID 11 = 65.2千克
我們注意到,基于k值,最終結(jié)果將趨于變化。那我們?cè)鯓硬拍苷页鰇的最優(yōu)值呢?讓我們根據(jù)我們的訓(xùn)練集和驗(yàn)證集的誤差計(jì)算來決定它(畢竟,最小化誤差是我們的最終目標(biāo)!)。
請(qǐng)看下面的圖表,了解不同k值的訓(xùn)練誤差和驗(yàn)證誤差。
對(duì)于非常低的k值(假設(shè)k = 1),模型過度擬合訓(xùn)練數(shù)據(jù),這導(dǎo)致驗(yàn)證集上的高錯(cuò)誤率。另一方面,對(duì)于k的高值,該模型在訓(xùn)練集和驗(yàn)證集上都表現(xiàn)不佳。如果仔細(xì)觀察,驗(yàn)證誤差曲線在k = 9的值處達(dá)到最小值。那么該k值就是是模型的最佳K值(對(duì)于不同的數(shù)據(jù)集,它將有所不同)。該曲線稱為“ 肘形曲線 ”(因?yàn)樗哂蓄愃浦獠康男螤?,通常用于確定k值。
你還可以使用網(wǎng)格搜索技術(shù)來查找最佳k值。我們將在下一節(jié)中實(shí)現(xiàn)這一點(diǎn)。
5.處理數(shù)據(jù)集(Python代碼)
到目前為止,你應(yīng)該清楚的了解這個(gè)算法。我們現(xiàn)在將繼續(xù)在數(shù)據(jù)集上實(shí)現(xiàn)該算法。我使用Big Mart銷售數(shù)據(jù)集來進(jìn)行代碼實(shí)現(xiàn),你可以從此鏈接下載它,邀請(qǐng)碼為b543。
1.閱讀文件
import pandas as pd df = pd.read_csv('train.csv') df.head()
2.計(jì)算缺失值
df.isnull().sum() #輸入Item_weight和Outlet_size中缺少的值 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)
3.處理分類變量并刪除id列
df.drop(['Item_Identifier', 'Outlet_Identifier'], axis=1, inplace=True) df = pd.get_dummies(df)
4.創(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']
5.預(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)
6.查看不同K值的錯(cuò)誤率
#導(dǎo)入所需要的包 from sklearn import neighbors from sklearn.metrics import mean_squared_error from math import sqrt import matplotlib.pyplot as plt %matplotlib inline rmse_val = [] #存儲(chǔ)不同K值的RMSE值 for K in range(20): K = K+1 model = neighbors.KNeighborsRegressor(n_neighbors = K) model.fit(x_train, y_train) #合適的模型 pred=model.predict(x_test) #對(duì)測(cè)試集進(jìn)行測(cè)試 error = sqrt(mean_squared_error(y_test,pred)) #計(jì)算RMSE值 rmse_val.append(error) #存儲(chǔ)RMSE值 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
#根據(jù)K值繪制RMSE值 curve = pd.DataFrame(rmse_val) #elbow curve curve.plot()
正如我們所討論的,當(dāng)我們?nèi) = 1時(shí),我們得到一個(gè)非常高的RMSE值。隨著我們?cè)黾觡值,RMSE值不斷減小。在k = 7時(shí),RMSE約為1219.06,并且隨著K值在進(jìn)一步增加,RMSE值會(huì)迅速上升。我們可以有把握地說,在這種情況下,k = 7會(huì)給我們帶來最好的結(jié)果。
這些是使用我們的訓(xùn)練數(shù)據(jù)集進(jìn)行的預(yù)測(cè)。現(xiàn)在讓我們預(yù)測(cè)測(cè)試數(shù)據(jù)集的值并進(jìn)行提交。
7.對(duì)測(cè)試數(shù)據(jù)集的預(yù)測(cè)
#閱讀測(cè)試和提交文件 test = pd.read_csv('test.csv') submission = pd.read_csv('SampleSubmission.csv') submission['Item_Identifier'] = test['Item_Identifier'] submission['Outlet_Identifier'] = test['Outlet_Identifier'] #預(yù)處理測(cè)試數(shù)據(jù)集 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) #預(yù)測(cè)測(cè)試集并創(chuàng)建提交文件 predict = model.predict(test) submission['Item_Outlet_Sales'] = predict submission.to_csv('submit_file.csv',index=False)
在提交此文件后,我得到的RMSE為1279.5159651297。
8.實(shí)現(xiàn)GridsearchCV
為了確定k的值,每次繪制肘部曲線是一個(gè)繁瑣且繁瑣的過程。你只需使用gridsearch即可簡(jiǎn)單的找到最佳值。
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.結(jié)束語(yǔ)和其他資源
在本文中,我們介紹了KNN算法的工作原理及其在Python中的實(shí)現(xiàn)。它是最基本但最有效的機(jī)器學(xué)習(xí)技術(shù)之一。并且在本文中,我們是直接調(diào)用了Sklearn庫(kù)中的KNN模型,如果你想更仔細(xì)的研究一下KNN的話,我建議你可以手敲一下有關(guān)KNN的源代碼。
本文作者介紹了如何使用KNN算法去進(jìn)行完成回歸任務(wù),大家如果感興趣的話,可以跟著本文敲一遍代碼,進(jìn)行練習(xí),畢竟看10篇文章也不如去敲一遍代碼,畢竟看文章看看也就過去了,如果敲一遍代碼的話,就會(huì)加深自己的印象,如果想深入的去了解KNN算法的話,可以自己去研究一下KNN的源代碼,然后敲一遍,我們后邊也會(huì)放出有關(guān)KNN源代碼的文章,當(dāng)然其他算法的文章我們也會(huì)發(fā)布,請(qǐng)大家到時(shí)候多多捧場(chǎng)。
A Practical Introduction to K-Nearest Neighbors Algorithm for Regression (with Python code)
總結(jié)
以上是生活随笔為你收集整理的k近邻回归算法python_K近邻算法用作回归的使用介绍(使用Python代码)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 动态网站的技术路线_简单动态网站搭建
- 下一篇: python 导入模型h20_【机器学习