柚子快報邀請碼778899分享:人工智能 機(jī)器學(xué)習(xí)2-KNN
柚子快報邀請碼778899分享:人工智能 機(jī)器學(xué)習(xí)2-KNN
KNN算法簡介
KNN(K-Nearest Neighbor)最鄰近分類算法是數(shù)據(jù)挖掘分類(classification)技術(shù)中最簡單的算法之一,其指導(dǎo)思想是”近朱者赤,近墨者黑“,即由你的鄰居來推斷出你的類別。
原理
以所有已知類別的樣本作為參照,計(jì)算未知樣本與所有已知樣本的距離,從中選取與未知樣本距離最近的K個已知樣本,根據(jù)少數(shù)服從多數(shù)的投票法則(majority-voting),將未知樣本與K個最鄰近樣本中所屬類別占比較多的歸為一類。
?如下圖所示,如何判斷綠色圓應(yīng)該屬于哪一類,是屬于紅色三角形還是屬于藍(lán)色四方形?如果K=3,由于紅色三角形所占比例為2/3,綠色圓將被判定為屬于紅色三角形那個類,如果K=5,由于藍(lán)色四方形比例為3/5,因此綠色圓將被判定為屬于藍(lán)色四方形類。
核心點(diǎn)
?(1) 樣本的所有特征都要做可比較的量化
? ? ? ? ? ?若是樣本特征中存在非數(shù)值的類型,必須采取手段將其量化為數(shù)值。例如樣本特征中包含顏色,可通過將顏色轉(zhuǎn)換為灰度值來實(shí)現(xiàn)距離計(jì)算。
?(2) 樣本特征要做歸一化處理
? ? ? ? ? ?樣本有多個參數(shù),每一個參數(shù)都有自己的定義域和取值范圍,他們對距離計(jì)算的影響不一樣,如取值較大的影響力會蓋過取值較小的參數(shù)。所以樣本參數(shù)必須做一些 scale 處理,最簡單的方式就是所有特征的數(shù)值都采取歸一化處置。
(3) 需要一個距離函數(shù)以計(jì)算兩個樣本之間的距離
? ? ? ? ? ?通常使用的距離函數(shù)有:歐氏距離、余弦距離、漢明距離、曼哈頓距離等,一般選歐氏距離作為距離度量,但是這是只適用于連續(xù)變量。在文本分類這種非連續(xù)變量情況下,漢明距離可以用來作為度量。通常情況下,如果運(yùn)用一些特殊的算法來計(jì)算度量的話,K近鄰分類精度可顯著提高,如運(yùn)用大邊緣最近鄰法或者近鄰成分分析法。
(4) 確定K的值
? ? ? ? ? ?K值選的太大易引起欠擬合,太小容易過擬合,需交叉驗(yàn)證確定K值。
算法實(shí)現(xiàn)
主要有以下三個步驟:
? ? ? ? ? ?算距離:給定待分類樣本,計(jì)算它與已分類樣本中的每個樣本的距離;
? ? ? ? ? ?找鄰居:圈定與待分類樣本距離最近的K個已分類樣本,作為待分類樣本的近鄰;
? ? ? ? ? ?做分類:根據(jù)這K個近鄰中的大部分樣本所屬的類別來決定待分類樣本該屬于哪個分類;
KNN算法
# 定義KNN分類器類
class KNNClassifier:
def __init__(self, k=3):
self.k = k
def fit(self, X_train, y_train):
self.X_train = X_train
self.y_train = y_train
def predict(self, X_test):
y_pred = []
for x in X_test:
# 計(jì)算測試樣本與所有訓(xùn)練樣本的距離
distances = [np.sqrt(np.sum((x - x_train)**2)) for x_train in self.X_train]
# 根據(jù)距離排序,并取出前k個最近鄰
nearest_neighbors = np.argsort(distances)[:self.k]
# 獲取最近鄰的標(biāo)簽
labels = [self.y_train[i] for i in nearest_neighbors]
# 統(tǒng)計(jì)最近鄰的標(biāo)簽,選擇出現(xiàn)次數(shù)最多的標(biāo)簽作為預(yù)測結(jié)果
y_pred.append(max(set(labels), key=labels.count))
return np.array(y_pred)
處理數(shù)據(jù)集:
# 導(dǎo)入數(shù)據(jù)集
def load_data():
# 這里使用一個簡單的示例數(shù)據(jù)集
X_train = np.array([[1, 2], [2, 3], [3, 4], [4, 5], [5, 6]])
y_train = np.array([0, 0, 1, 1, 1])
X_test = np.array([[2, 2], [3, 3], [4, 4]])
return X_train, y_train, X_test
? ? ? ? ?
在這個示例中,我使用了一個簡單的二維數(shù)據(jù)集,其中每個數(shù)據(jù)點(diǎn)包含兩個特征。數(shù)據(jù)集的加載過程分為兩個部分:訓(xùn)練集和測試集。
訓(xùn)練集(Training Set):
???X_train:訓(xùn)練集的特征矩陣,是一個二維數(shù)組,每一行代表一個訓(xùn)練樣本,每一列代表一個特征。例如,X_train[i] 表示訓(xùn)練集中第 i 個樣本的特征向量。
? ? y_train:訓(xùn)練集的標(biāo)簽向量,是一個一維數(shù)組,每個元素代表相應(yīng)訓(xùn)練樣本的標(biāo)簽。例如,y_train[i] 表示訓(xùn)練集中第 i 個樣本的標(biāo)簽
可視化
? ? ? ?
# 可視化結(jié)果
def visualize(X_train, y_train, X_test, y_pred):
plt.figure(figsize=(10, 6))
# 繪制訓(xùn)練集數(shù)據(jù)點(diǎn)
plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap='viridis', label='訓(xùn)練集')
# 繪制測試集數(shù)據(jù)點(diǎn)及預(yù)測結(jié)果
plt.scatter(X_test[:, 0], X_test[:, 1], c=y_pred, cmap='viridis', marker='x', label='測試集預(yù)測')
# 添加標(biāo)簽和圖例
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.title('KNN Classification Visualization')
plt.legend()
plt.show()
? ? ? k=3時:
具體解釋如下:
訓(xùn)練集數(shù)據(jù)點(diǎn):用散點(diǎn)圖表示,每個數(shù)據(jù)點(diǎn)在二維平面上的位置由其特征確定,點(diǎn)的顏色表示該樣本的真實(shí)類別。在示例中,用不同的顏色表示兩個不同的類別。 測試集數(shù)據(jù)點(diǎn)及預(yù)測結(jié)果:同樣用散點(diǎn)圖表示,測試集的數(shù)據(jù)點(diǎn)以叉號('x')標(biāo)識,點(diǎn)的顏色表示模型對該樣本的預(yù)測類別。使用模型對測試集的數(shù)據(jù)點(diǎn)進(jìn)行預(yù)測,并將預(yù)測結(jié)果用不同的顏色表示。
完整代碼
import numpy as np
import matplotlib.pyplot as plt
# 定義KNN分類器類
class KNNClassifier:
def __init__(self, k=3):
self.k = k
def fit(self, X_train, y_train):
self.X_train = X_train
self.y_train = y_train
def predict(self, X_test):
y_pred = []
for x in X_test:
# 計(jì)算測試樣本與所有訓(xùn)練樣本的距離
distances = [np.sqrt(np.sum((x - x_train)**2)) for x_train in self.X_train]
# 根據(jù)距離排序,并取出前k個最近鄰
nearest_neighbors = np.argsort(distances)[:self.k]
# 獲取最近鄰的標(biāo)簽
labels = [self.y_train[i] for i in nearest_neighbors]
# 統(tǒng)計(jì)最近鄰的標(biāo)簽,選擇出現(xiàn)次數(shù)最多的標(biāo)簽作為預(yù)測結(jié)果
y_pred.append(max(set(labels), key=labels.count))
return np.array(y_pred)
# 導(dǎo)入數(shù)據(jù)集
def load_data():
# 這里使用一個簡單的示例數(shù)據(jù)集
X_train = np.array([[1, 2], [2, 3], [3, 4], [4, 5], [5, 6]])
y_train = np.array([0, 0, 1, 1, 1])
X_test = np.array([[2, 2], [3, 3], [4, 4]])
return X_train, y_train, X_test
# 可視化結(jié)果
def visualize(X_train, y_train, X_test, y_pred):
plt.figure(figsize=(10, 6))
# 繪制訓(xùn)練集數(shù)據(jù)點(diǎn)
plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap='viridis', label='訓(xùn)練集')
# 繪制測試集數(shù)據(jù)點(diǎn)及預(yù)測結(jié)果
plt.scatter(X_test[:, 0], X_test[:, 1], c=y_pred, cmap='viridis', marker='x', label='測試集預(yù)測')
# 添加標(biāo)簽和圖例
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.title('KNN Classification Visualization')
plt.legend()
plt.show()
# 主函數(shù)
def main():
# 加載數(shù)據(jù)集
X_train, y_train, X_test = load_data()
# 初始化KNN分類器0
knn = KNNClassifier(k=20)
# 訓(xùn)練模型
knn.fit(X_train, y_train)
# 測試模型
y_pred = knn.predict(X_test)
# 可視化結(jié)果
visualize(X_train, y_train, X_test, y_pred)
if __name__ == "__main__":
main()
柚子快報邀請碼778899分享:人工智能 機(jī)器學(xué)習(xí)2-KNN
文章來源
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。