摘要: 本文以knn算法為例簡要介紹如何使用分類算法來完成回歸任務。
關鍵字: knn算法,回歸任務。
之前的文章(K近鄰(knn)算法是如何完成分類的?)已經介紹了knn算法的思想以及如何使用sklearn去實現這個算法了,其實大多的分類算法也是可以做回歸的,特別是當訓練數據比較多的時候效果就更加明顯。下面讓我們看看如何使用分類算法來做回歸分析。
本文部分內容參考文獻[1]。
1 構建回歸分析的數據
為了仿真回歸分析,我們也不得不自己構造能夠滿足回歸分析的數據了。其構造如下:
import numpy as np
def makeRegressionData(n_samples=100):
rnd = np.random.RandomState(42) # 設置偽隨機狀態
x = rnd.uniform(-3, 3, size=n_samples) # 隨機生成范圍在[-3,3) n_samples個點的隨機數
y_no_noise = (np.sin(4 * x) + x) # 目標函數
y = (y_no_noise + rnd.normal(size=len(x))) / 2 # 加入滿足標注正太分布的隨機噪聲
return x.reshape(-1, 1), y
數據可視化:
import matplotlib.pyplot as plt
X, y = makeRegressionData(n_samples=40)
plt.plot(X, y, 'o')
plt.ylim(-3, 3)
plt.xlabel('Feature')
plt.ylabel('Target')
plt.show()
2 n鄰居預測結果
原理展示圖代碼:
from sklearn.metrics import euclidean_distances
from sklearn.neighbors import KNeighborsRegressor
def plot_knn_regression(X, y, X_test, n_neighbors=1):
dist = euclidean_distances(X, X_test) # 計算歐式距離
closest = np.argsort(dist, axis=0) # 對距離進行排序
plt.figure(figsize=(10, 6))
# knn回歸
reg = KNeighborsRegressor(n_neighbors=n_neighbors).fit(X, y)
# 預測值
y_pred = reg.predict(X_test) # 找出預測值
# 測試點與最近的n個點之間的連線
for x, y_, neighbors in zip(X_test, y_pred, closest.T):
for neighbor in neighbors[:n_neighbors]:
plt.arrow(x[0], y_, X[neighbor, 0] - x[0], y[neighbor] - y_, head_width=0, fc='k', ec='k')
# 各種數據繪制
train, = plt.plot(X, y, 'o', c='#0000aa')
test, = plt.plot(X_test, -3 * np.ones(len(X_test)), '*', c='#50ff50', markersize=20)
pred, = plt.plot(X_test, y_pred, '*', c='#0000aa', markersize=20)
# x, ymin, ymax
plt.vlines(X_test, -3.1, 3.1, linestyle="--")
# 顯示圖例
plt.legend([train, test, pred],
["training data/target", "test data", "test prediction"],
ncol=3, loc=(.1, 1.025))
# 坐標軸設置
plt.ylim(-3.1, 3.1)
plt.xlabel("Feature")
plt.ylabel("Target")
X_test = np.array([[-1.5], [0.9], [1.5]]) # 測試數據
plot_knn_regression(X,y,X_test) # k=1
plot_knn_regression(X,y,X_test, n_neighbors=3) # k=3
結果圖:
注: 特征只有一個,測試數據點與數據集之間的具體體現在x軸之間的距離
從上圖就可以很容易理解,k近鄰算法回歸分析的思路了,找到最近的幾個點,計算均值即可。
3 模型使用
有了之前的基礎,構建一個模型就簡單多了,如下:
from sklearn.model_selection import train_test_split
# 劃分數據集
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=40)
# 構建模型并訓練
reg = KNeighborsRegressor(n_neighbors=3)
reg.fit(X_train, y_train)
"""
KNeighborsRegressor(algorithm='auto', leaf_size=30, metric='minkowski',
metric_params=None, n_jobs=None, n_neighbors=3, p=2,
weights='uniform')
"""
# 模型預測
print("Test set predictions:n{}".format(reg.predict(X_test)))
"""
Test set predictions:
[ 0.82597372 -0.5856804 0.0836095 -1.02040464 0.41271285 -0.23052151
-1.62784743 -1.62784743 0.82597372 -0.23052151]
"""
print("Test set R^2:{:.2f}".format(reg.score(X_test, y_test)))
"""
Test set R^2:0.71
"""
需要說明的是:在sklearn中使用score來蘋果模型,在回歸問題上,返回的是R^2分數,也叫做決定系數,是回歸模型預測的優度度量,位于0與1之間。R^2等于1對應完美預測。
4 KNeighborsRegressor分析
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
line = np.linspace(-3, 3, 1000).reshape(-1, 1)
for n_neighbors, ax in zip([1, 3, 9], axes):
reg = KNeighborsRegressor(n_neighbors=n_neighbors) # 根據參數構建模型
reg.fit(X_train, y_train)
ax.plot(line, reg.predict(line)) # 繪制預測值
# 繪制訓練數據、測試數據
ax.plot(X_train, y_train, '^', c='#0000aa', markersize=8)
ax.plot(X_test, y_test, 'v', c='#ff5050', markersize=8)
ax.set_title("{} neightbor(s)n train score:{:.2f} test score:{:.2f}".format(n_neighbors, 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')
繪制結果如下:
結果總結:從結果圖可以看出,當僅使用1個鄰居時,訓練集的正確率為100%,測試集得分不高,隨著鄰居個數增多,擬合的曲線變得更加平滑,但訓練集得分降低,測試集得分先增高后降低。
總結
KNN模型容易理解,不需要過多的調節就可以得到不錯的結果,但如果訓練集數據比較多,預測速度就會變慢,并且還要有比較好的數據預處理。如果要解決的數據是稀疏數據,效果就不好了。當然本部分內容是參考《Python機器學習基礎教程》內容并結合自己的理解寫出,所以我還是推薦?一下這本書,或者可以在訂閱號“AIAS編程有道”中回復“Python機器學習基礎教程”獲取電子檔后決定?是否要購買,建議購買正版書籍。?