机器学习之k近邻回归算法实现与应用
在解决分类问题的过程中,K 近邻算法(简称:KNN)是一种简单而且实用的方法。但KNN不仅可以实现分类问题也可以实现回归问题
K-最近邻(K-Nearest Neighbors,KNN)算法是一种基本的分类和回归方法,它的工作原理非常直观:通过测量不同特征值之间的距离来进行预测。
基本概念
- 距离度量:KNN 算法通常使用欧氏距离来衡量样本之间的相似度,但也可以采用曼哈顿距离、切比雪夫距离等其他距离度量方式。
- K 值:K 值决定了在进行决策时考虑的最近邻居的数量。较小的 K 值意味着噪声对预测结果的影响更大,而较大的 K 值可能导致模型过于平滑,无法捕捉数据的局部变化。
分类问题中的 KNN
在分类问题中,KNN 的工作流程如下:
- 确定 K 值:选择一个正整数 K 作为邻居的数量。
- 计算距离:对于每个测试数据点,计算它与训练集中每个点的距离。
- 找到 K 个最近邻居:根据计算得到的距离,找出距离最近的 K 个训练数据点。
- 进行决策:在 K 个最近邻居中,根据多数投票原则(即出现次数最多的类别)来预测测试数据点的类别。
回归问题中的 KNN
在回归问题中,KNN 的工作流程略有不同:
- 确定 K 值:同样选择一个正整数 K。
- 计算距离:计算测试数据点与训练集中每个点的距离。
- 找到 K 个最近邻居:找出距离最近的 K 个训练数据点。
- 预测结果:计算这 K 个邻居的目标值的平均值(或加权平均值),作为测试数据点的预测结果。
优点
- 简单易懂:KNN 算法的原理简单,易于理解和实现。
- 无需训练:KNN 是一种惰性学习算法,所有的计算都是在预测时进行,不需要在训练阶段花费时间。
- 可用于非线性问题:KNN 不需要假设数据的分布,因此可以用于非线性问题的分类和回归。
缺点
- 计算成本高:由于在预测时需要计算测试数据点与所有训练数据点之间的距离,因此计算成本较高,尤其是在大数据集上。
- 存储成本高:KNN 需要存储全部数据集,因此存储成本较高。
- 对异常值敏感:KNN 算法对噪声和异常值敏感,这可能会影响模型的预测性能。
- 需要合适的距离度量和 K 值:选择合适的距离度量和 K 值对模型的性能至关重要,但找到最佳参数可能需要大量的实验。
实现
KNN 算法可以使用各种编程语言和库实现,如 Python 中的
scikit-learn
库提供了 KNeighborsClassifier
和
KNeighborsRegressor
类来分别处理分类和回归问题。
KNN 是一种非常灵活的算法,适用于多种类型的数据和问题,尽管它有其局限性,但在许多实际应用中仍然是一种有效的机器学习算法。
KNN算法实现
1 |
|
KNN解决分类问题:
使用sklearn库: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35from sklearn.neighbors import KNeighborsClassifier
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
# 得到 lilac 数据集中 feature 的全部序列: sepal_length,sepal_width,petal_length,petal_width
feature_data = lilac_data.iloc[:, :-1]
label_data = lilac_data["labels"] # 得到 lilac 数据集中 label 的序列
X_train, X_test, y_train, y_test = train_test_split(
feature_data, label_data, test_size=0.3, random_state=2
)
def sklearn_classify(train_data, label_data, test_data, k_num):
# 使用 sklearn 构建 KNN 预测模型
knn = KNeighborsClassifier(n_neighbors=k_num)
# 训练数据集
knn.fit(train_data, label_data)
# 预测
predict_label = knn.predict(test_data)
# 返回预测值
return predict_label
# 使用测试数据进行预测
y_predict = sklearn_classify(X_train, y_train, X_test, 3)
def get_accuracy(test_labels, pred_labels):
# 准确率计算函数
correct = np.sum(test_labels == pred_labels) # 计算预测正确的数据个数
n = len(test_labels) # 总测试集数据个数
accur = correct / n
return accur
get_accuracy(y_test, y_predict)
k值选择: 1
2
3
4
5
6
7
8
9
10
11
12
13normal_accuracy = [] # 建立一个空的准确率列表
k_value = range(2, 11)
for k in k_value:
y_predict = sklearn_classify(X_train, y_train, X_test, k)
accuracy = get_accuracy(y_test, y_predict)
normal_accuracy.append(accuracy)
plt.xlabel("k")
plt.ylabel("accuracy")
new_ticks = np.linspace(0.6, 0.9, 10) # 设定 y 轴显示,从 0.6 到 0.9
plt.yticks(new_ticks)
plt.plot(k_value, normal_accuracy, c="r")
plt.grid(True) # 给画布增加网格
KNN解决回归问题
1 |
|
1 |
|
其中: *
X_train,X_test, y_train, y_test
分别表示,切分后的特征的训练集,特征的测试集,标签的训练集,标签的测试集;其中特征和标签的值是一一对应的。
train_data,train_target
分别表示为待划分的特征集和待划分的标签集。test_size
:测试样本所占比例。random_state
:随机数种子,在需要重复实验时,保证在随机数种子一样时能得到一组一样的随机数
sklearn.neighbors.KNeighborsClassifier((n_neighbors=5, weights='uniform', algorithm='auto') * n_neighbors : k 值,表示邻近个数,默认为 5。
weights : 决策规则选择,多数表决或加权表决,可用参数('uniform','distance')
algorithm : 搜索算法选择(auto,kd_tree, ball_tree),包括逐一搜索,kd 树搜索或 ball 树搜索