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))

KNN演算法python實現

繪製散點圖,更清楚可以看到這個資料庫帶有2個自變數,1個二分類的因變數,但也是因為他只有2個自變數,才能用二維影象畫出來。

2.KNN演算法圖解

plot1 = mglearn。plots。plot_knn_classification(n_neighbors=1)

plot2 = mglearn。plots。plot_knn_classification(n_neighbors=3)

KNN演算法python實現

KNN演算法python實現

我在改變了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)

KNN演算法python實現

可以看到,設定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演算法python實現

KNN演算法python實現

這裡對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’)

KNN演算法python實現

自然可以看出,如果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

KNN演算法python實現

看清楚資料結構之後,這次的任務是:對目標人物的消費金額進行預測,即預測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’)

KNN演算法python實現

這裡只畫了一張圖,我對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()

KNN演算法python實現

可以看到,不同的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,不能說這個一個非常正確的預測結果。