摘要:
本文對(duì)KNN算法做一個(gè)通俗易懂的介紹,值得收藏!
古語(yǔ)云:“近水樓臺(tái)先得月”,意思是臨近在水邊的樓臺(tái)就能優(yōu)先得到月亮的光芒,也比喻由于接近某些人或事物而搶先得到某種利益或便利。還有一句類(lèi)似的話:“遠(yuǎn)親不如近鄰”,說(shuō)的是人在有需要時(shí),鄰居比遠(yuǎn)處的親戚更加能獲得支持和幫助。在人工智能領(lǐng)域,有一種算法,非常貼近上述的形象比喻,這就是KNN算法,即K最近鄰算法(K-NearestNeighbors,簡(jiǎn)稱KNN),它是一個(gè)比較簡(jiǎn)單的機(jī)器學(xué)習(xí)算法,也是一個(gè)理論上比較成熟的、運(yùn)用基于樣本估計(jì)的最大后驗(yàn)概率規(guī)則的判別方法。本文對(duì)KNN算法做一個(gè)通俗易懂的介紹,并通過(guò)python進(jìn)行編碼示范,讓讀者朋友對(duì)該算法有較好的理解。
K最近鄰算法的比較貼近的一個(gè)比喻場(chǎng)景是:一個(gè)牧場(chǎng)里,放養(yǎng)著許多牛和羊,它們交叉聚集生活在一起,有時(shí)某只動(dòng)物自己都可能分不清自己是牛還是羊。按照K最近鄰算法,它判別自己是?;蛘哐虻囊罁?jù)是——“我”周邊離“我”最近的類(lèi)別(?;蛘哐颍?,且在一定范圍內(nèi)是數(shù)量最多的類(lèi)別,那“我”就是這個(gè)類(lèi)別。歸結(jié)到K最近鄰算法中,就是在一個(gè)數(shù)據(jù)集中,新的數(shù)據(jù)點(diǎn)離哪一類(lèi)最近且一定范圍內(nèi)最多,就和這一類(lèi)屬于同一類(lèi)。
其中,這個(gè)一定范圍就是鄰居們(Neighbors)的數(shù)量,也就是K最近鄰算法的“K”這個(gè)字母代表的數(shù)量(最近鄰的個(gè)數(shù))。在人工智能領(lǐng)域,大家所熟知的scikit-learn庫(kù)中,K最近鄰算法的K值可以通過(guò)n_neighbors參數(shù)來(lái)調(diào)節(jié)的,默認(rèn)值是5。
“近水樓臺(tái)”——KNN預(yù)測(cè)實(shí)戰(zhàn)
“近水樓臺(tái)先得月”可以很好地詮釋KNN算法,下面我們進(jìn)行一個(gè)KNN算法的實(shí)際應(yīng)用,以方便讀者更好地理解KNN算法。
當(dāng)今每屆大學(xué)生在畢業(yè)前一年都非常關(guān)注研究生考試,能進(jìn)入碩士級(jí)別進(jìn)一步深造,也是大多數(shù)學(xué)生所渴望的,本文將模擬某年部分碩士研究生的入學(xué)考試數(shù)據(jù)集,通過(guò)python編程演練一個(gè)KNN算法機(jī)器學(xué)習(xí)的建模、訓(xùn)練、預(yù)測(cè)過(guò)程,展示KNN算法的效果。
其中,2、3、4、5,分別是研究生入學(xué)考試的基礎(chǔ)課程、政治課程、外語(yǔ)課程、專(zhuān)業(yè)課程的分?jǐn)?shù)。
6是考試學(xué)生的本科學(xué)校分類(lèi),分類(lèi)粗略的分為三級(jí):3-超一流(如清北)、2-雙一流、1-普通高校。
7是考試學(xué)生的目標(biāo)碩士高校學(xué)校的分類(lèi),分類(lèi)粗略的分為四級(jí):3-超一流(如清北)、2-雙一流、1-普通高校、0-表示未被錄取。
二、導(dǎo)入和查看、準(zhǔn)備數(shù)據(jù)集
#使用pandas加載碩士研究生入學(xué)成績(jī)信息數(shù)據(jù)集
data= pd.read_csv('Graduate_Admission.csv')
#查看數(shù)據(jù)特征的統(tǒng)計(jì)信息
上表說(shuō)明:這個(gè)數(shù)據(jù)集總共有500條記錄,其中基礎(chǔ)課程的最高分和最低分是125.7和67.1,政治課程的最高分和最低分是91.8和41.1,外語(yǔ)課的最高分和最低分是91.7和42.2,專(zhuān)業(yè)課程的最高分和最低分是133.4和29.2。
下面的代碼針對(duì)數(shù)據(jù)集做預(yù)處理:
data.drop(['SerialNo'], axis = 1, inplace = True)
#把去掉預(yù)測(cè)目標(biāo)Chanceof Class后的數(shù)據(jù)集作為訓(xùn)練數(shù)據(jù)集X
X= data.drop(['Chance of Class'], axis = 1)
y= data['Chance of Class'].values
三、生成訓(xùn)練集和測(cè)試集、使用KNN算法建模并評(píng)估模型分?jǐn)?shù)
fromsklearn.model_selection import train_test_split
#將數(shù)據(jù)集拆分為訓(xùn)練數(shù)據(jù)集和測(cè)試數(shù)據(jù)集
X_train,X_test, y_train, y_test = train_test_split(X, y, random_state=0)
fromsklearn.neighbors import KNeighborsClassifier
Clf_KNN= KNeighborsClassifier()
#用模型對(duì)數(shù)據(jù)進(jìn)行擬合
Clf_KNN.fit(X_train,y_train)
KNeighborsClassifier(algorithm='auto',leaf_size=30, metric='minkowski', metric_params=None, n_jobs=None,n_neighbors=5, p=2, weights='uniform')
print('驗(yàn)證數(shù)據(jù)集得分:{:.2f}'.format(Clf_KNN.score(X_test,y_test)))
print('訓(xùn)練數(shù)據(jù)集得分:{:.2f}'.format(Clf_KNN.score(X_train,y_train)))
驗(yàn)證數(shù)據(jù)集得分:0.81
訓(xùn)練數(shù)據(jù)集得分:0.87
可以看出模型的訓(xùn)練集和驗(yàn)證集的評(píng)估分值都在0.80分以上,模型訓(xùn)練的效果還算不錯(cuò)。
四、預(yù)測(cè)新成績(jī)的分類(lèi)
現(xiàn)在有A、B、C三位同學(xué)都進(jìn)行了研究生入學(xué)模擬考試,他們的成績(jī)和本科學(xué)校分別是:
我們可以利用上面步驟建立的KNN模型來(lái)預(yù)測(cè)一下,看看他們目前的考試成績(jī)能夠進(jìn)入研究生高校的類(lèi)別是哪些:是成功登上清華北大的超一流神圣殿堂或者普通高校,還是遺憾地鎩羽而歸。經(jīng)過(guò)這樣的預(yù)測(cè)后,相信他們也會(huì)有一定的信心或者更加強(qiáng)化自身的學(xué)習(xí)力度,力爭(zhēng)能考入心儀的理想學(xué)校。
下面使用python代碼利用前面已經(jīng)建好的KNN模型,對(duì)三位同學(xué)的研究生成績(jī)的入學(xué)結(jié)果進(jìn)行預(yù)測(cè):
#輸入A同學(xué)的考試成績(jī)和學(xué)校分類(lèi)數(shù)據(jù)
X_A= np.array([[90.5, 80.6, 67.7, 80, 2]])
#使用.KNN模型對(duì)A同學(xué)的入學(xué)可能分類(lèi)進(jìn)行預(yù)測(cè)
pred_A= Clf_KNN.predict(X_A)
#輸入B同學(xué)的考試成績(jī)和學(xué)校分類(lèi)數(shù)據(jù)
X_B= np.array([[120.5, 90.8, 76.5, 98, 3]])
#使用.KNN模型對(duì)B同學(xué)的入學(xué)可能分類(lèi)進(jìn)行預(yù)測(cè)
pred_B= Clf_KNN.predict(X_B)
#輸入C同學(xué)的考試成績(jī)和學(xué)校分類(lèi)數(shù)據(jù)
X_C= np.array([[60.5, 50.2, 87.3, 65, 1]])
#使用.KNN模型對(duì)C同學(xué)的入學(xué)可能分類(lèi)進(jìn)行預(yù)測(cè)
pred_C= Clf_KNN.predict(X_C)
print("K最近鄰算法模型預(yù)測(cè)分類(lèi)結(jié)果如下:")
print("A同學(xué)的分類(lèi)結(jié)果:{}".format(pred_A))
print("B同學(xué)的分類(lèi)結(jié)果:{}".format(pred_B))
print("C同學(xué)的分類(lèi)結(jié)果:{}".format(pred_C))
K最近鄰算法模型預(yù)測(cè)分類(lèi)結(jié)果如下:
A同學(xué)的分類(lèi)結(jié)果:[1]
B同學(xué)的分類(lèi)結(jié)果:[3]
C同學(xué)的分類(lèi)結(jié)果:[0]
以上結(jié)果說(shuō)明,如果按他們的模擬考試成績(jī),A同學(xué)分類(lèi)預(yù)測(cè)結(jié)果為“1-普通高校”,即KNN模型預(yù)測(cè)他能夠考入一般的普通高校的研究生;B同學(xué)分類(lèi)預(yù)測(cè)結(jié)果為“3-超一流高校(如清北)”,即KNN模型預(yù)測(cè)他能進(jìn)入清北超一流殿堂,值得慶祝;C同學(xué)分類(lèi)預(yù)測(cè)結(jié)果為“0-未被錄取”,很遺憾,KNN模型預(yù)測(cè)他成績(jī)不理想,無(wú)法考上研究生。
通過(guò)這個(gè)數(shù)據(jù)集和例子可以得出一定的推論:考試成績(jī)好且在超一流高校讀本科的學(xué)生,更容易被超一流的高校(如清北)的碩士學(xué)位錄取,超一流高校(如清北)的學(xué)生可以說(shuō)是“近水樓臺(tái)”,比其他學(xué)生更容易“先得月”,也比較好地詮釋了KNN算法的工作原理。
K最近鄰算法(KNN)可以說(shuō)是一個(gè)非常經(jīng)典、原理十分容易理解的算法。本文利用KNN算法解決了一個(gè)研究生入學(xué)考試成績(jī)的被錄取高校的分類(lèi)預(yù)測(cè)問(wèn)題,其實(shí),K最近算法不僅能夠進(jìn)行分類(lèi)預(yù)測(cè),也可以用于回歸,原理和其用于分類(lèi)是相同的。
另外,利用KNN算法進(jìn)行機(jī)器學(xué)習(xí)的過(guò)程中,對(duì)K值(Neighbors的數(shù)量)的選擇會(huì)對(duì)算法的結(jié)果產(chǎn)生重大影響。K值較小意味著只有與輸入實(shí)例較近的訓(xùn)練實(shí)例才會(huì)對(duì)預(yù)測(cè)結(jié)果起作用,但容易發(fā)生過(guò)擬合;如果K值較大,優(yōu)點(diǎn)是可以減少學(xué)習(xí)的估計(jì)誤差,但缺點(diǎn)是學(xué)習(xí)的近似誤差增大。有興趣的讀者朋友可以在上述Python代碼中修改K值,看看是否能得到不同的預(yù)測(cè)結(jié)果。