import pandas as pd
import matplotlib。pyplot as plt
import numpy as np
import scipy as sp
import IPython
import sklearn
import sys
import mglearn
使用sklearn自帶的資料,forge資料庫帶有2個自變數,一個二分類因變數
1.第一步自然是看清楚資料結構
X, y = mglearn。datasets。make_forge() #二分類因變數,自變數帶有兩個引數
mglearn。discrete_scatter(X[:, 0], X[:, 1], y) #繪製散點圖
plt。legend([‘Class 0’, ‘Class 1’], loc=‘best’) #新增圖例
plt。title(“Two type of number”)
plt。xlabel(‘First Feature’)
plt。ylabel(‘Second Feature’)
print(“Shape of X: {}”。format(X。shape))
繪製散點圖,更清楚可以看到這個資料庫帶有2個自變數,1個二分類的因變數,但也是因為他只有2個自變數,才能用二維影象畫出來。
2.KNN演算法圖解
plot1 = mglearn。plots。plot_knn_classification(n_neighbors=1)
plot2 = mglearn。plots。plot_knn_classification(n_neighbors=3)
我在改變了K值,就是搜尋臨近點的個數時候,可以簡單地看到KNN演算法大概是如何運作的:
透過歐幾里得距離找到K個臨近點,對這K個臨近點的分類結果進行彙總,那麼目標點在這個模型中學習到的結果就是K個臨近點分類彙總最大的那個分類。
3.KNN模型學習
#設定測試集與預測集
from sklearn。model_selection import train_test_split
X, y = mglearn。datasets。make_forge()
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
print(“Shape of X_train: {}”。format(X_train。shape))
#設定KNN模型
from sklearn。neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=3)
knn。fit(X_train, y_train)
#測試資料集
print(“Test set prediction: {}”。format(knn。predict(X_test)))
print(“Tese set accuracy: {:。2f}”。format(clf。score(X_test, y_test)))
========================================================================================
Shape of X_train: (19, 2)
Test set prediction: [1 0 1 0 1 0 0]
Tese set accuracy: 0。86
透過我們設定K值為3進行的KNN演算法,對預測集進行計算準確率,得到86%的正確率,說明模型擬合效果“還可以”。
4.K值改變結果影響
#繪製決策邊界,多個近鄰比較(多圖合併)
fig, axes = plt。subplots(1, 3, figsize=(10, 3)) #繪製多個畫板
for neighbors, ax in zip([1, 3, 9], axes):
knn = KNeighborsClassifier(n_neighbors=neighbors)
knn。fit(X, y)
mglearn。plots。plot_2d_separator(knn, X, fill=True, eps=0。5, ax=ax, alpha=。4) #繪製分界線
mglearn。discrete_scatter(X[:, 0], X[:, 1], y, ax=ax)
ax。set_title(“{} neighbor(s)”。format(neighbors))
ax。set_xlabel(“feature 0”)
ax。set_ylabel(“feature 1”)
axes[0]。legend(loc=3)
可以看到,設定K為1時,決策邊界緊貼著資料點,而隨著K指變為9,決策邊界離資料點的距離越來越遠,當然,我們最後想得到的模型,不想過擬合,也不要欠擬合,因為模型過於複雜(如K=1)或者過於簡單(K=9),都對我們的泛化結果產生影響。
5.KNN迴歸
X, y = mglearn。datasets。make_wave()
plt。plot(X, y, ‘o’)
plt。ylim(-3, 3)
plt。xlabel(“Feature”)
plt。ylabel(“Target”)
#K近鄰迴歸
mglearn。plots。plot_knn_regression(n_neighbors=1)
mglearn。plots。plot_knn_regression(n_neighbors=3)
from sklearn。neighbors import KNeighborsRegressor
X, y = mglearn。datasets。make_wave(n_samples=40)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
reg = KNeighborsRegressor(n_neighbors=3)
reg。fit(X, y)
print(“Test set prediction: {}”,format(reg。predict(X_test)))
print(“Test set R^2: {:。2f}”。format(reg。score(X_test, y_test)))
=============================================================================
Test set prediction: {} [ 0。03885648 0。41779483 1。19926374 -1。98183861 -1。18120831 -1。55460707
0。49062028 0。6597075 -0。47777954 -0。9859799 ]
Test set R^2: 0。84
這裡對KNN迴歸不再贅述,我們這裡只是想看一下K值改變對精度和泛化能力的影響。
fig, axes = plt。subplots(1, 3, figsize=(15, 4))
line = np。linspace(-3, 3, 1000)。reshape(-1, 1)
for neighbor, ax in zip([1, 3, 9], axes):
reg = KNeighborsRegressor(neighbor)
reg。fit(X_train, y_train)
ax。plot(line, reg。predict(line))
ax。plot(X_train, y_train, ‘v’, c=mglearn。cm2(0), markersize=8)
ax。plot(X_test, y_test, ‘v’, c=mglearn。cm2(1), markersize=8)
ax。set_title(
“{} neighbors(s)\n train score: {:。2f} test score: {:。2f}”。format(
neighbor, reg。score(X_train, y_train),
reg。score(X_test, y_test)))
ax。set_xlabel(“Feature”)
ax。set_ylabel(“Target”)
axes[0]。legend([“Model predictions”, “Training data/target”,
“Test data/target”], loc=‘best’)
自然可以看出,如果K值過小,我們的模型太過於複雜,幾乎所有點都穿進了迴歸曲線,導致訓練集中每個點都對預測結果產生了顯著影響。在考慮更多的近鄰後,會讓迴歸曲線更加平滑,但是有很多預測集的資料離迴歸線還是較遠,說明擬合效果並不好。
總結:
KNN演算法預設歐幾里得距離,在實際操作過程中,應該不斷地改變引數K,以獲取最佳的模型。
雖然KNN模型簡單易懂,不需要過多的調參就能獲得較好的結果。但是一旦資料集很大,包括資料量很大,或者特徵值很多(類別多),這個模型效果往往不好,特別是對於大多數特徵取值為0時尤其不好(歐幾里得距離差距會非常小),因此在實踐中很少運用到。可能寫作業用的比較多吧haha。
KNN具體演算法不再贅述,無非就是求歐式距離,自己翻翻書看吧。
補充,對自己的資料進行分析,以後所有的模型,在透過已知資料庫跑完之後,都會在自己的資料集上跑,加深印象。
import pandas as pd
import matplotlib。pyplot as plt
import numpy as np
import scipy as sp
import IPython
import sklearn
import sys
import mglearn
1。載入資料
data = pd。read_csv(“Accounts。csv”)
data = pd。DataFrame(data)
print(“Data keys: {}”。format(data。columns))
data
看清楚資料結構之後,這次的任務是:對目標人物的消費金額進行預測,即預測Perchase amount資料,運用KNN演算法。
2。視覺化
#繪圖
X = []
for i in range(len(data)):
x = [data[‘Age’][i], data[‘Perchase amount’][i]]
X。append(x)
X = np。array(X)
bins = [500, 700, 1000, 1300, 1500]
t = np。array(data[‘Perchase amount’])
group = [0, 1, 2, 3]
y = np。array(pd。cut(t, bins, labels=group))
mglearn。discrete_scatter(X[1:150, 0], X[1:150, 1], y[1:150])
plt。legend(loc=2)
plt。xlabel(‘Age’)
plt。ylabel(‘Perchase amount’)
這裡只畫了一張圖,我對Perchase amount這個資料進行切分,這樣自然可以對最後的資料進行更加清楚的分類,我們從上圖可以看出,年齡跟消費金額並沒有什麼關係(主要是看KNN演算法的預測結果,視覺化不再贅述)。
3。模型擬合
#KNN演算法模擬
from sklearn。neighbors import KNeighborsClassifier
from sklearn。model_selection import train_test_split
X = []
for i in range(len(data)):
x = [data[‘Age’][i], data[‘Discount card type’][i], data[‘Gender’][i],
data[‘Marital Status’][i], data[‘Membership ’][i]]
X。append(x)
X = np。array(X)
bins = [500, 700, 1000, 1300, 1500]
t = np。array(data[‘Perchase amount’])
group = [0, 1, 2, 3]
y = np。array(pd。cut(t, bins, labels=group))
#設定訓練集與測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
在做預測之前,我們想知道K值不同會對我們的模型造成什麼影響,先視覺化看下對不同的K值造成的訓練集精度與測試集泛化能力的影響
#測試不同K值的訓練集與測試集精度
training_accuracy = []
test_accuracy = []
#將K值設定為1-7
neighbors_setting = range(1, 8)
for n_neighbors in neighbors_setting:
clf = KNeighborsClassifier(n_neighbors=n_neighbors)
clf。fit(X_train, y_train)
training_accuracy。append(clf。score(X_train, y_train)) #記錄訓練集精度
test_accuracy。append(clf。score(X_test, y_test))
plt。plot(neighbors_setting, training_accuracy, label=“training accuracy”)
plt。plot(neighbors_setting, test_accuracy, label=“test accuracy”)
plt。ylabel(“Accuracy”)
plt。xlabel(“n_neighbors”)
plt。legend()
可以看到,不同的K值造成的影響,對測試集泛化影響不大,但是對訓練集影響就有了,在K=2時形成轉折點,因此我們最好選擇K=3,這樣造成的影響較小(但是這個模型不得不的說擬合的很爛)。
knn = KNeighborsClassifier(n_neighbors=3)。fit(X_train, y_train)
print(“Train set accuracy: {:。2f}”。format(knn。score(X_train, y_train)))
print(“Test set accuracy: {:。2f}”。format(knn。score(X_test, y_test)))
X_new = np。array([[27, 3, 1, 1, 0]])
print(“Prediction: {}”。 format(knn。predict(X_new)))
============================================================================================
Train set accuracy: 0。57
Test set accuracy: 0。30
Prediction: [1]
我們最後想知道一位27歲,擁有第3類信用卡,已婚,沒有和家人一起的女性會消費多少金額,選擇K值為3,雖然精度不高,但是我們還是得出她會消費第二個等級,即700-1000的類別之中。
總結:仍然為之前所說,KNN演算法簡單,但是精度很可能不高,在這種情況下,精度只能達到0。5,不能說這個一個非常正確的預測結果。