在机器学习领域,分类算法是解决众多实际问题的重要工具。K 最近邻(K-Nearest Neighbors,KNN)算法作为一种简单且有效的分类算法,在模式识别、数据挖掘等诸多领域广泛应用。鸢尾花数据集是机器学习中常用的经典数据集,非常适合用来演示和理解分类算法的原理与实现。本文将详细介绍如何使用 KNN 算法对鸢尾花数据集进行分类,并通过 Python 代码实现整个过程。
KNN 算法是一种基于实例的学习算法,属于有监督学习范畴。其核心思想是:对于一个新的待分类样本,在训练集中找到与它距离最近的 K 个样本,这 K 个样本中出现次数最多的类别,就作为该新样本的预测类别。
在 KNN 算法中,常用的距离度量方式有欧氏距离、曼哈顿距离等。以二维空间为例,假设样本点 A (x1, y1) 和样本点 B (x2, y2),欧氏距离计算公式为:
d(A,B)=(x2−x1)2+(y2−y1)2
曼哈顿距离计算公式为:
d(A,B)=∣x2−x1∣+∣y2−y1∣
K 值的选择对 KNN 算法的性能影响较大。如果 K 值过小,模型对局部数据敏感,容易过拟合;如果 K 值过大,模型对全局数据更关注,可能导致欠拟合。通常需要通过交叉验证等方法来确定一个合适的 K 值。
鸢尾花数据集由著名统计学家 Fisher 收集整理,包含 150 个样本,分为三个类别:山鸢尾(Iris setosa)、变色鸢尾(Iris versicolor)和维吉尼亚鸢尾(Iris virginica),每个类别各 50 个样本。每个样本有四个特征:花萼长度(sepal length)、花萼宽度(sepal width)、花瓣长度(petal length)、花瓣宽度(petal width),单位为厘米。该数据集可从多种途径获取,如著名的机器学习库 Scikit-learn 中就内置了鸢尾花数据集。
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
import numpy as np
# 加载鸢尾花数据集
iris = load_iris()
X = iris.data
y = iris.target
# 将数据集划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.3, random_state = 42)
# 创建KNN分类器,这里K取5,可根据实际情况调整
k = 5
knn = KNeighborsClassifier(n_neighbors = k)
# 训练模型
knn.fit(X_train, y_train)
# 进行预测
y_pred = knn.predict(X_test)
# 计算模型准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"KNN分类器在鸢尾花数据集上的准确率为:{accuracy * 100:.2f}%")
加载数据集:通过load_iris()
函数从 Scikit-learn 库中加载鸢尾花数据集,将特征数据存储在X
中,标签数据存储在y
中。
数据集划分:使用train_test_split()
函数将数据集按 70% 训练集、30% 测试集的比例进行划分,random_state
参数设置为 42 是为了保证每次运行代码时划分结果的一致性。
创建 KNN 分类器:实例化KNeighborsClassifier
类,设置n_neighbors
参数为 K 值,这里设置为 5。
训练模型:调用fit()
方法,使用训练集数据对 KNN 分类器进行训练。
进行预测:使用训练好的模型对测试集数据进行预测,得到预测结果y_pred
。
计算准确率:通过accuracy_score()
函数计算模型预测结果与真实标签的准确率,并打印输出。
除了准确率外,还可以使用其他指标如精确率(Precision)、召回率(Recall)、F1 值等对模型进行更全面的评估。在 Scikit-learn 中,可以通过classification_report
函数方便地获取这些指标:
from sklearn.metrics import classification_report
print(classification_report(y_test, y_pred))
通过交叉验证寻找最优的 K 值,例如使用GridSearchCV
进行 K 值搜索:
from sklearn.model_selection import GridSearchCV
param_grid = {'n_neighbors': np.arange(1, 21)}
grid_search = GridSearchCV(KNeighborsClassifier(), param_grid, cv = 5)
grid_search.fit(X_train, y_train)
best_k = grid_search.best_params_['n_neighbors']
print(f"通过网格搜索得到的最优K值为:{best_k}")
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import GridSearchCV
import numpy as np
# 加载鸢尾花数据集
iris = load_iris()
X = iris.data
y = iris.target
# 将数据集划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 定义要搜索的 K 值范围
param_grid = {'n_neighbors': np.arange(1, 21)}
# 创建 KNN 分类器
knn = KNeighborsClassifier()
# 使用网格搜索进行超参数调优
grid_search = GridSearchCV(knn, param_grid, cv=5)
grid_search.fit(X_train, y_train)
# 获取最优的 K 值
best_k = grid_search.best_params_['n_neighbors']
print(f"通过网格搜索得到的最优 K 值为:{best_k}")
# 使用最优的 K 值创建新的 KNN 分类器
best_knn = KNeighborsClassifier(n_neighbors=best_k)
# 训练最优模型
best_knn.fit(X_train, y_train)
# 进行预测
y_pred = best_knn.predict(X_test)
# 计算模型准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"使用最优 K 值的 KNN 分类器在鸢尾花数据集上的准确率为:{accuracy * 100:.2f}%")
代码解释:
加载数据集:使用 load_iris
函数从 sklearn
库中加载鸢尾花数据集,将特征数据存储在 X
中,标签数据存储在 y
中。
划分数据集:使用 train_test_split
函数将数据集划分为训练集和测试集,测试集占比为 30%。
定义超参数搜索范围:使用 param_grid
定义要搜索的 K 值范围,这里是从 1 到 20。
创建 KNN 分类器:实例化 KNeighborsClassifier
类。
网格搜索:使用 GridSearchCV
进行超参数调优,通过 5 折交叉验证找到最优的 K 值。
获取最优 K 值:从 grid_search
的结果中获取最优的 K 值。
创建并训练最优模型:使用最优的 K 值创建新的 KNN 分类器,并使用训练集进行训练。
预测和评估:使用训练好的模型对测试集进行预测,并计算准确率。
通过这种方式,可以找到更适合鸢尾花数据集的 K 值,从而提高模型的性能。