一、K 近邻(回归)理论
(1)K 近邻回归原理
K 近邻算法( K-Nearest Neighbor ,KNN )不仅可以用于分类,还可以用于回归。思路与前面的 KNN 分类器类似,通过找出一个样本的 k 个最近邻居,将这些邻居的属性的平均值赋给该样本,就可以得到该样本的属性。更有用的方法是将不同距离的邻居对该样本产生的影响给予不同的权值( weight ),如权值与距离成反比(对 k 个近邻的贡献加权,权值为距离平方的倒数: wi=1/(d(xi,xj)^2 ,即距离越远,权值越小,距离越近,权值越大)。
平均回归:如果 K=3 ,就取附近三个点 y 的均值;如果 K=5 ,就取附近五个点 y 的均值。
加权回归(就是说距离越近,权重越大,权值与距离成反比):如果 K=3 ,就取附近三个点 y 的加权平均值;如果 K=5 ,就取附近五个点 y 的加权平均值。
(2)K 近邻加权法
K 近邻加权法是根据每个样本在整个样本空间中所处的不同位置,分别给出不同权重系数,以衡量每个样本点的重要程度。
如果一个样本点是很多点的 K 近邻,即这个样本点处于样本空间中密度高的位置,则说明这个点与其他点更为相似,更能代表这个样本空间的特征,因此,在考虑回归问题时,这个点对回归线的影响就应该大些,即在这个样本点之前加上一个比较大的权重;反之,若有一个样本点不是任何其他样本点的 K 近邻中的一员,那么它是离群点的可能性就非常大,可以说它在样本空间中的重要程度就弱些,那么在回归的过程中,在考虑它对回归线的影响就应该小一些,即在这个样本点之前给出一个比较小的权重系数。
设样本空间 X 中有 m 个样本点 x1,x2,…,xm 。用 K 近邻的方法来描述样本空间的局部结构,定义 K 近邻的权重矩阵为:
该矩阵为对称矩阵,求出它的每行或者每列的元素和记为 di (表示第 i 个样本点与其他样本点的 K 近邻数),从而通过引入权重对角矩阵给出了每个样本点在样本空间的权重系数。权重对角矩阵如下:
(3)算法流程
① 计算已知数据集中的点与当前点的距离;
② 按照距离递增依次排序;
③ 选取当前点距离最小的 k 个点;
④ 确定前 k 个点对应的 y 值;
⑤ 返回前 k 个点对应的 y 值的平均值或加权平均值别作为当前点 y 值的预测。
注意:距离计算常使用欧式距离或马氏距离
马氏距离定义如下:
d
i
s
t
=
(
x
−
μ
)
T
Σ
−
1
(
x
−
μ
)
dist=\sqrt{(x-\mu)^T\Sigma ^{-1}(x-\mu)}
dist=(x−μ)TΣ−1(x−μ)
(4)优缺点
优点:属于无参数模型( Nonparametric model ),没有参数训练过程,计算方法直观,精度高,对异常值不敏感,无数据输入假定且对离群点 outliner 不敏感。
缺点:计算复杂度高,空间复杂度高,难以处理样本不均衡样本(即:有时类样本很多,有时类样本很少),且需要大量内存。
二、K 近邻(回归)具体案例操作
# 从 sklearn.datasets 导入波士顿房价数据读取器。
from sklearn.datasets import load_boston
# 从读取房价数据存储在变量 boston 中。
boston = load_boston()
# 从sklearn.cross_validation 导入数据分割器。
from sklearn.model_selection import train_test_split
X = boston.data
y = boston.target
# 随机采样 25% 的数据构建测试样本,其余作为训练样本。
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=33, test_size=0.25)
# 从 sklearn.preprocessing 导入数据标准化模块。
from sklearn.preprocessing import StandardScaler
# 分别初始化对特征和目标值的标准化器。
ss_X = StandardScaler()
ss_y = StandardScaler()
# 分别对训练和测试数据的特征以及目标值进行标准化处理。
X_train = ss_X.fit_transform(X_train)
X_test = ss_X.transform(X_test)
y_train = ss_y.fit_transform(y_train.reshape(-1,1))
y_test = ss_y.transform(y_test.reshape(-1,1))
# 从 sklearn.neighbors 导入 KNeighborRegressor(K 近邻回归器)。
from sklearn.neighbors import KNeighborsRegressor
# 初始化 K 近邻回归器,并且调整配置,使得预测的方式为平均回归:weights='uniform'。
uni_knr = KNeighborsRegressor(weights='uniform')
uni_knr.fit(X_train, y_train)
uni_knr_y_predict = uni_knr.predict(X_test)
# 初始化 K 近邻回归器,并且调整配置,使得预测的方式为根据距离加权回归:weights='distance'。
dis_knr = KNeighborsRegressor(weights='distance')
dis_knr.fit(X_train, y_train)
dis_knr_y_predict = dis_knr.predict(X_test)
# 使用 R-squared、MSE 以及 MAE 三种指标对平均回归配置的 K 近邻模型在测试集上进行性能评估。
from sklearn.metrics import r2_score, mean_absolute_error, mean_squared_error
print('R-squared value of uniform-weighted KNeighorRegression:',
uni_knr.score(X_test, y_test))
print(
'The mean squared error of uniform-weighted KNeighorRegression:',
mean_squared_error(ss_y.inverse_transform(y_test),
ss_y.inverse_transform(uni_knr_y_predict)))
print(
'The mean absoluate error of uniform-weighted KNeighorRegression',
mean_absolute_error(ss_y.inverse_transform(y_test),
ss_y.inverse_transform(uni_knr_y_predict)))
# 使用 R-squared、MSE 以及 MAE 三种指标对根据距离加权回归配置的 K 近邻模型在测试集上进行性能评估。
print('R-squared value of distance-weighted KNeighorRegression:',
dis_knr.score(X_test, y_test))
print(
'The mean squared error of distance-weighted KNeighorRegression:',
mean_squared_error(ss_y.inverse_transform(y_test),
ss_y.inverse_transform(dis_knr_y_predict)))
print(
'The mean absoluate error of distance-weighted KNeighorRegression:',
mean_absolute_error(ss_y.inverse_transform(y_test),
ss_y.inverse_transform(dis_knr_y_predict)))
对比两种配置方式,由上面的输出结果可知,在本例中采用加权平均的方式回归房价具有更好的预测性能。结合前文的线性回归模型和支持向量回归模型看,性能从高到低为:SVR(高斯核函数)、K-NN(加权平均法回归预测)、线性回归模型(OLS)。
参考文献:
[1] 周志华. 机器学习[M]. 清华大学出版社, 北京, 2016.
[2] 范淼,李超.Python 机器学习及实践[M].清华大学出版社, 北京, 2016.