1、理解KNN算法
K-最近邻(K-Nearest Neighbors,KNN)算法是一种基本且易于实现的机器学习算法,广泛应用于分类和回归问题。它是一种基于实例的学习(Instance-based learning),或者称为懒惰学习(Lazy learning),因为它不会从训练数据中学习一个固定的模型,而是使用整个数据集进行预测。其工作原理包括:首先计算测试数据点与每个训练数据点之间的距离,接着选取距离最近的K个邻居。在分类问题中,测试点的类别由这些邻居中最常见的类别决定;在回归问题中,则通常是这些邻居值的平均值。
KNN的效能在很大程度上取决于K值的选择和距离度量的方式。选取合适的K值是至关重要的,太小的K值会使模型对噪声敏感,而太大的K值可能使模型无法捕捉到数据的特性。此外,由于KNN对特征的尺度敏感,特征缩放(如标准化或归一化)通常是预处理步骤的一部分。虽然KNN易于实现且通常不需要太多调优,但它在处理大数据集或维度很高的数据集时效率不高,且对噪声和异常值比较敏感。适用于多分类问题。
2、scikit-learn
scikit-learn 是 Python 中一个强大的机器学习库,它提供了各种常用机器学习算法的简单易用的实现。使用 scikit-learn,可以快速进行数据预处理、模型训练、评估和预测,从而进行有效的机器学习分析。
1)安装命令
pip install scikit-learn
2)导入所需模块
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import classification_report, confusion_matrix
from sklearn.datasets import load_iris
3、数据集
使用scikit-learn自带的鸢尾花(Iris)数据集,鸢尾花数据集是机器学习领域经典的入门数据集,由英国统计学家 R. A. Fisher 于 1936 年首次提出。该数据集包含 150 个样本,每个样本代表一朵鸢尾花,并包含 4 个特征:花萼长度 (Sepal_Length)、花萼宽度 (Sepal_Width)、花瓣长度 (Petal_Length)、花瓣宽度 (Petal_Width)。通过 4 个特征可以用来描述鸢尾花的形状和大小。数据集还包含每个样本的类别标签,鸢尾花有 3 个品种:山鸢尾 (Iris-setosa)、变色鸢尾 (Iris-versicolor)、维吉尼亚鸢尾 (Iris-virginica)。
使用 scikit-learn 加载鸢尾花数据集代码如下,
from sklearn.datasets import load_iris
iris = load_iris()
# 查看数据信息
print(iris.DESCR)
# 查看数据
print(iris.data)
# 查看目标
print(iris.target)
4、划分数据集
使用train_test_split
函数将数据集划分为训练集和测试集,train_test_split
函数是Scikit-Learn库中一个非常重要的工具。常用参数如下,
参数名 | 描述 |
arrays | 需要划分的数据,通常是特征集和标签集。 例如: X_train, X_test, y_train, y_test = train_test_split(X, y) |
test_size | 测试集所占的比例或数量。 例如: train_test_split(X, y, test_size=0.2) 表示测试集占总数据集的20%。 |
train_size | 训练集所占的比例或数量。 例如: train_test_split(X, y, train_size=0.8) 表示训练集占总数据集的80%。 |
random_state | 控制随机数生成器的种子。 例如: train_test_split(X, y, random_state=42) 确保每次划分结果相同。 |
shuffle | 是否在划分前随机打乱数据。 例如: train_test_split(X, y, shuffle=True) 默认会打乱数据。 |
stratify | 确保训练集和测试集具有相同的类比例。 例如: train_test_split(X, y, stratify=y) 确保类别分布均衡。 |
使用代码:
from sklearn.model_selection import train_test_split
from sklearn import datasets
# 加载示例数据集,如鸢尾花数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target
# 使用train_test_split函数划分数据集
# 测试集占比30%,保持类别比例,设置随机种子为42以确保结果一致性
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42, stratify=y)
# 输出划分后的训练集和测试集的信息
print("训练集特征大小:", X_train.shape)
print("测试集特征大小:", X_test.shape)
print("训练集标签大小:", y_train.shape)
print("测试集标签大小:", y_test.shape)
5、训练KNN模型
KNeighborsClassifier
是scikit-learn中用于分类的K-近邻算法实现。使用KNeighborsClassifier
时,通常需要对n_neighbors
和weights
参数进行调整,以达到最佳的分类效果。选择合适的参数取决于具体的数据集和应用场景。常用参数如下,
参数名 | 描述 |
n_neighbors | 选择最近邻的数量(即K的值)。 默认值: 示例:
|
weights | 邻居的权重函数。 默认值: 'uniform'。 示例:
|
algorithm | 计算最近邻的算法。 默认值: 'auto'。示例:
|
leaf_size |
|
p | Minkowski距离的幂参数。 默认值: 示例:
|
metric | 距离度量方式。 默认值: 'minkowski'。 示例:
常用:'euclidean'(欧几里得距离),'manhattan'(曼哈顿距离)等。 |
使用代码:
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import classification_report, confusion_matrix
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score
# 加载示例数据集,如鸢尾花数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target
# 使用train_test_split函数划分数据集
# 测试集占比30%,保持类别比例,设置随机种子为42以确保结果一致性
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42, stratify=y)
# 创建KNN分类器实例
knn = KNeighborsClassifier(
n_neighbors=3, # 设置邻居的数量为3
weights='distance', # 设置权重为距离的倒数
algorithm='kd_tree', # 使用KD树算法
leaf_size=40, # 设置KD树/球树的叶子大小
p=1, # 设置Minkowski距离的幂参数为1(曼哈顿距离)
metric='euclidean' # 使用欧氏距离作为距离度量
)
knn.fit(X_train, y_train)
# 预测和评估
y_pred = knn.predict(X_test)
print("Accuracy:", accuracy_score(y_test, y_pred))
6、调整参数
实践中可能需要调整KNN模型的参数(如K的值)来获得更好的性能。可以通过交叉验证等方法来找到最佳的参数。
n_neighbors
参数选择最近邻的数量。增加n_neighbors
会使模型更稳定,但可能导致欠拟合;减少n_neighbors
可能导致过拟合。weights
参数确定邻居的权重。可以选择 'uniform' 使所有邻居具有均等权重,或者选择 'distance' 赋予距离较近的邻居更大的权重。algorithm
参数指定了计算最近邻的方法,可选项包括 'auto', 'ball_tree', 'kd_tree', 'brute',其中'auto'会自动选择最适合数据的算法。最后,metric
参数用于定义距离度量,常用的有欧几里得距离('euclidean')和曼哈顿距离('manhattan')。通过适当调整这些参数,可以大幅提升KNN模型在特定数据集上的表现。
7、欧几里得距离(Euclidean Distance)和 曼哈顿距离(Manhattan Distance)
K-近邻(K-Nearest Neighbors,KNN)算法是一种常用的分类和回归方法。KNN算法的核心思想是找出测试数据在特征空间中的K个最近邻居,并根据这些邻居的信息来预测测试数据的标签或值。KNN算法中一个重要的概念是距离度量,它用于计算特征空间中点之间的距离。Scikit-learn的KNN实现支持多种距离度量,其中最常用的是“欧几里得距离”(Euclidean distance)和“曼哈顿距离”(Manhattan distance)。
1)欧几里得距离(Euclidean Distance)
欧几里得距离是最常见的距离度量方法,定义为两点间的直线距离。在二维空间中,它就是两点间的直线距离。
def euclidean_distance(point1, point2):
"""计算欧几里得距离"""
return sum((p1 - p2) ** 2 for p1, p2 in zip(point1, point2)) ** 0.5
# 示例点
point1 = (1, 2)
point2 = (4, 6)
# 计算两点之间的欧几里得距离
eu_dist = euclidean_distance(point1, point2)
print(eu_dist)
2)曼哈顿距离,也称为城市街区距离,是另一种常用的距离度量方法。它是两点在标准坐标系上的绝对轴距总和。
def manhattan_distance(point1, point2):
"""计算曼哈顿距离"""
return sum(abs(p1 - p2) for p1, p2 in zip(point1, point2))
# 示例点
point1 = (1, 2)
point2 = (4, 6)
# 计算两点之间的曼哈顿距离
man_dist = manhattan_distance(point1, point2)
print(man_dist)