当前位置: 首页 > 資訊 >

Day 19 : KNN 與 K-means

今天進入演算法的介紹,首先打頭陣介紹的是 KNN 與 K-means,兩者不太一樣。

KNN 是監督式學習演算法;K-means 是非監督式學習演算法

KNN (K Nearest Neighbor, KNN)

屬於監督式學習演算法,主要是找尋最鄰近的 K 個鄰居,透過多數決的概念決定屬於哪一類

  • K 是參數,決定找幾個點
  • 計算每個鄰居與自己之間的距離
  • 多數決投票

K 會影響最後的結果

注意:通常會將數值進行正規化,讓計算出來的結果比較 robust

from sklearn import datasets
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import confusion_matrix, accuracy_score
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import train_test_split
import pandas as pd

iris_df = pd.DataFrame(iris.data, columns=iris.feature_names)
X = iris_df.drop(labels=['target_name', 'target'] ,axis=1)
y = iris_df['target'].values
X_train , X_test , y_train , y_test = train_test_split(X, y ,test_size=0.2 , random_state=55)

classifier = KNeighborsClassifier(n_neighbors=3)
classifier.fit(X_train, y_train)
y_pred = classifier.predict(X_test)

# 建立 KNN 的 K 串列
k_list = list(range(1, 50, 1))

# 實作 KNN 交叉驗證 
cv_scores = []
for k in k_list:
    knn = KNeighborsClassifier(n_neighbors=k)
    scores = cross_val_score(knn, X_train, y_train, cv=10, scoring='accuracy')
    cv_scores.append(scores.mean())
    
# 計算 MSE 
MSE = [1 - x for x in cv_scores]

plt.figure()
plt.figure(figsize=(15,10))
plt.title('The optimal number of neighbors', fontsize=20, fontweight='bold')
plt.xlabel('Number of Neighbors K', fontsize=15)
plt.ylabel('Misclassification Error', fontsize=15)
sns.set_style("whitegrid")
plt.plot(k_list, MSE)

plt.show()


透過這張圖可以找到 K 大約在 15~17 有最好的成效!

K-Means

屬於非監督式學習演算法,主要應用於分類,我們不會知道答案是什麼!

  • 決定 K 值
  • 隨機給定 K 個 中心點(初始化,不一定要是資料的點)
  • 計算每個樣本與各中心點的距離,並分配到不同的區域
  • 重新計算新的中心點到各樣本的距離,再度更新區域
  • 直到中心點不再變動

假設 K=2,然後我們隨機給兩個點,接著我們來計算每個樣本與各中心點的距離,並分配到不同區域

兩個點可以簡單用分割線來看最快

再度更新新的中心點,重新計算各中心點的距離,並更新區域

最後達到收斂(若再繼續分下去,中心點都會是一樣的)

注意: K-Means 不適合用於非數值型資料

from sklearn.cluster import KMeans
wcss = []

for i in range(1, 15):
    kmeans = KMeans(n_clusters = i, init = 'k-means++', max_iter = 300, n_init = 10, random_state = 0)
    kmeans.fit(x)
    wcss.append(kmeans.inertia_)
    
plt.plot(range(1, 15), wcss)
plt.title('The elbow method')
plt.xlabel('Number of clusters')
plt.ylabel('WCSS')
plt.show()

# Kmeans 的預測
kmeans = KMeans(n_clusters = 3, init = 'k-means++', max_iter = 300, n_init = 10, random_state = 0)
y_kmeans = kmeans.fit_predict(x)
plt.scatter(x[:, 0], x[:, 1], c=y_kmeans, cmap='rainbow')

# 原始數據的分類
plt.scatter(iris_df['sepal length (cm)'], iris_df['sepal width (cm)'], c=iris_df.target, cmap='rainbow')

github 程式碼

更詳細可以請參考連結