前些天發(fā)現(xiàn)了一個(gè)巨牛的人工智能學(xué)習(xí)網(wǎng)站,通俗易懂,風(fēng)趣幽默,忍不住分享一下給大家。點(diǎn)擊跳轉(zhuǎn)到網(wǎng)站。
簡(jiǎn)介
K近鄰(K Nearest Neighbors,KNN)算法是最簡(jiǎn)單的分類(lèi)算法之一,也就是根據(jù)現(xiàn)有訓(xùn)練數(shù)據(jù)判斷輸入樣本是屬于哪一個(gè)類(lèi)別。
“近朱者赤近墨者黑",所謂的K近鄰,也就是根據(jù)樣本相鄰最近的K個(gè)數(shù)據(jù)來(lái)進(jìn)行判斷,看K個(gè)鄰居中所屬類(lèi)別最多的是哪一類(lèi),則將該樣本分為這一類(lèi)。
算法原理很簡(jiǎn)單,如下圖,K取3時(shí),輸入數(shù)據(jù)為紅色點(diǎn),在它最近的3個(gè)鄰居點(diǎn)中,有2個(gè)黃色1個(gè)藍(lán)色,故應(yīng)把它分類(lèi)為黃色這一類(lèi)。
可以看出K的取值應(yīng)為奇數(shù),避免K近鄰中有相同個(gè)數(shù)的類(lèi)別,同時(shí)也不能為類(lèi)別數(shù)的倍數(shù),如3分類(lèi)中K取3時(shí),出現(xiàn)1:1:1無(wú)法分類(lèi)的情況。注意如果K過(guò)小可能造成過(guò)擬合。
此外距離的定義公式也有很多,這里不再贅述,根據(jù)實(shí)際場(chǎng)景進(jìn)行甄選,一般使用歐式距離更多,即 d i s t ( x , y ) = ∑ i = 1 n ( x i ? y i ) 2 dist(x,y)=\sqrt{\sum_{i=1}^n(x_i-y_i)^2} dist(x,y)=∑i=1n?(xi??yi?)2?
代碼復(fù)現(xiàn)
- 數(shù)據(jù)處理
采用典中典——鳶尾花數(shù)據(jù)集,Kaggle中有上傳鳶尾花數(shù)據(jù)(下載鏈接)
鳶尾花數(shù)據(jù)集包含四個(gè)特征,和三種鳶尾花標(biāo)簽類(lèi)別,共150條數(shù)據(jù)。
采用sepal length和petal width兩個(gè)特征,你也可以采用其他特征。
使用pandas讀取數(shù)據(jù),不懂pandas可以參考我這篇:Pandas光速入門(mén)-一文掌握數(shù)據(jù)操作
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
data = pd.read_csv("D:\\Iris_flower_dataset.csv")
x = np.array(data.iloc[:, [1, 4]])
y_tmp = np.array(data["Species"])
y = []
label = ["Iris-setosa", "Iris-virginica", "Iris-versicolor"]
for i in y_tmp: # 將英文壓為整型
if i == label[0]:
y.append(0)
elif i == label[1]:
y.append(1)
else:
y.append(2)
y = np.array(y)
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=2022)
# 訓(xùn)練集可視化
plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train)
plt.xlabel("sepal length[cm]") # 設(shè)置x軸名
plt.ylabel("petal width[cm]") # 設(shè)置y軸名
plt.show()
可視化可參考:Matplotlib光速入門(mén)-從安裝到繪圖實(shí)戰(zhàn)
(
插播反爬信息)博主CSDN地址:https://wzlodq.blog.csdn.net/
- KNN定義
只考慮兩個(gè)特征,就簡(jiǎn)單化處理了,即用 ( x 1 ? x 2 ) 2 + ( y 1 ? y 2 ) 2 \sqrt{(x_1-x_2)^2+(y_1-y_2)^2} (x1??x2?)2+(y1??y2?)2?
class KNN(object):
def __init__(self, k): # 初始化函數(shù)
self.k = k
def fit(self, x, y): # 載入訓(xùn)練集
self.x = x
self.y = y
def _distance(self, v1, v2): # 歐式距離
return np.sum(np.square(v1 - v2)) # (不開(kāi)根號(hào)節(jié)省算力,效果一致
def predict(self, x):
y_pre = []
for i in range(len(x)): # x是測(cè)試集,是一個(gè)n維特征數(shù)組
dist_arr = [self._distance(x[i], self.x[j]) for j in range(len(self.x))] # 計(jì)算距離
sorted_index = np.argsort(dist_arr) # 排序
top_k_index = sorted_index[:self.k] # 得到K近鄰
nearest = self._count(y_top_k=self.y[top_k_index]) # 根據(jù)K近鄰分類(lèi)做出預(yù)測(cè)
y_pre.append(nearest) # 加入預(yù)測(cè)答案
return np.array(y_pre)
def _count(self, y_top_k): # 統(tǒng)計(jì)各分類(lèi)數(shù)量
y_map = {}
for y in y_top_k:
if y not in y_map.keys():
y_map[y] = 1 # 首次不在字典則置1
else:
y_map[y] += 1 # 否則value++
sorted_vote_dict = sorted(y_map.items(), key=operator.itemgetter(1), reverse=True) # 排序
return sorted_vote_dict[0][0] # 返回?cái)?shù)量最多的分類(lèi)
- 測(cè)試
if __name__ == "__main__":
# 數(shù)據(jù)處理
data = pd.read_csv("D:\\Iris_flower_dataset.csv")
x = np.array(data.iloc[:, [1, 4]])
y_tmp = np.array(data["Species"])
y = []
label = ["Iris-setosa", "Iris-virginica", "Iris-versicolor"]
for i in y_tmp: # 將英文壓為整型
if i == label[0]:
y.append(0)
elif i == label[1]:
y.append(1)
else:
y.append(2)
y = np.array(y)
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=2022)
# 創(chuàng)建KNN對(duì)象
clf = KNN(5)
# 訓(xùn)練
clf.fit(x_train, y_train)
# 測(cè)試
pre_test = clf.predict(x_test)
# 計(jì)算正確率
correct = np.count_nonzero((pre_test == y_test) == True)
print("正確率:%.3f" % (correct / len(pre_test)))
- 結(jié)果可視化
# 結(jié)果可視化
plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train, alpha=0.3)
for i in range(len(x_test)):
if pre_test[i] == y_test[i]: # 正確標(biāo)綠
plt.scatter(x_test[i][0], x_test[i][1], color="green")
else: # 錯(cuò)誤標(biāo)紅
plt.scatter(x_test[i][0], x_test[i][1], color="red")
plt.xlabel("sepal length[cm]") # 設(shè)置x軸名
plt.ylabel("petal width[cm]") # 設(shè)置y軸名
plt.show()
半透明的是訓(xùn)練數(shù)據(jù),測(cè)試數(shù)據(jù)中,綠色是分類(lèi)正確的點(diǎn),紅色是分類(lèi)錯(cuò)誤的點(diǎn),可以看出上圖只錯(cuò)了一個(gè)。
sklearn庫(kù)調(diào)用
使用sklearn封裝函數(shù)可以非常方便的實(shí)現(xiàn):
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
# 載入數(shù)據(jù)
iris = datasets.load_iris() # 已經(jīng)內(nèi)置了鳶尾花數(shù)據(jù)集
x = iris.data # 輸入4個(gè)特征
y = iris.target # 輸出類(lèi)別
# 隨機(jī)劃分?jǐn)?shù)據(jù)集,默認(rèn)25%測(cè)試集75%訓(xùn)練集
x_train, x_test, y_train, y_test = train_test_split(x, y)
# 創(chuàng)建一個(gè)KNN分類(lèi)器對(duì)象,并設(shè)置K=5,
clf = KNeighborsClassifier(n_neighbors=5) # clf意為Classifier
# 訓(xùn)練
clf.fit(x_train, y_train) # 用訓(xùn)練數(shù)據(jù)擬合分類(lèi)器模型
# 測(cè)試
pre_test = clf.predict(x_test) # 得到測(cè)試集的預(yù)測(cè)結(jié)果
# 計(jì)算正確率
print('正確率:%.3f' % accuracy_score(y_test, pre_test))
# 由于數(shù)據(jù)集是隨機(jī)劃分,每次得到正確率自然不同,可以設(shè)置random_state讓隨機(jī)一致
直接調(diào)用庫(kù)函數(shù)簡(jiǎn)直不要太方便,蕪湖起飛(~ ̄▽?zhuān)?~文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-403223.html
原創(chuàng)不易,請(qǐng)勿轉(zhuǎn)載(
本不富裕的訪問(wèn)量雪上加霜)
博主首頁(yè):https://wzlodq.blog.csdn.net/
來(lái)都來(lái)了,不評(píng)論兩句嗎??
如果文章對(duì)你有幫助,記得一鍵三連?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-403223.html
到了這里,關(guān)于機(jī)器學(xué)習(xí)-KNN算法(鳶尾花分類(lèi)實(shí)戰(zhàn))的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!