【机器学习与实战】分类与聚类算法:KNN鸢尾花分类

【机器学习与实战】分类与聚类算法:KNN鸢尾花分类

配套视频课程:www.bilibili.com/video/BV1iS...

一、关于数据集

Iris 数据集是机器学习中常用的数据集之一,也是 scikit-learn 中自带的数据集之一,由 Fisher 1936 收集整理,也称鸢尾花数据集。Iris 数据集是一个经典的多分类问题数据集,被广泛用于分类算法的性能评估、特征选择、特征提取和可视化等方面的研究。

  • Iris 数据集包含了三种不同品种的鸢尾花 山鸢尾(Iris Setosa)、变色鸢尾(Iris Versicolour)和维吉尼亚鸢尾(Iris Virginica)
  • 每个品种的各 50 个样本,总共 150 个样本
  • 每个样本包含了**四个特征(花萼长度、花萼宽度、花瓣长度和花瓣宽度)**的测量值

利用Python代码加载数据集,并获取数据集相关信息:

python 复制代码
from sklearn.datasets import load_iris
# 获取鸢尾花数据集
iris = load_iris()
print("鸢尾花数据集的返回值:\n", iris)
# 返回值是一个继承自字典的Bench
print("鸢尾花的特征值:\n", iris["data"])
print("鸢尾花的目标值:\n", iris.target)
print("鸢尾花特征的名字:\n", iris.feature_names)
print("鸢尾花目标值的名字:\n", iris.target_names)
print("鸢尾花的描述:\n", iris.DESCR)

利用seaborn查看数据分布情况:

python 复制代码
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.datasets import load_iris
iris = load_iris()
# 把数据转换成dataframe的格式
iris_d = pd.DataFrame(iris['data'], columns = ['Sepal_Length', 'Sepal_Width', 'Petal_Length', 'Petal_Width'])
iris_d['Species'] = iris.target
col1 = 'Sepal_Width'
col2 = 'Sepal_Length'
sns.lmplot(x = col1, y = col2, data = iris_d, hue = "Species", fit_reg = False)
plt.xlabel(col1)
plt.ylabel(col2)
plt.show()
二、模型训练和评估
python 复制代码
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
# 1.获取数据集
iris = load_iris()
# 2.数据基本处理
# x_train,x_test,y_train,y_test为训练集特征值、测试集特征值、训练集目标值、测试集目标值
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2, random_state=22)
# 3.特征工程:标准化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)    # 测试数据不能调用fit_transform否则将会不准确
# 4.机器学习(模型训练)
estimator = KNeighborsClassifier(n_neighbors=9)
estimator.fit(x_train, y_train)
# 5.模型评估
# 方法1:比对真实值和预测值
y_predict = estimator.predict(x_test)
print("预测结果为:\n", y_predict)
print("比对真实值和预测值:\n", y_predict == y_test)
# 方法2:直接计算准确率
score = estimator.score(x_test, y_test)
print("准确率为:\n", score)

输出结果为:

python 复制代码
预测结果为:
 [0 2 1 2 1 1 1 1 1 0 2 1 2 2 0 2 1 1 1 1 0 2 0 1 2 0 2 2 2 2]
比对真实值和预测值:
 [ True  True  True  True  True  True  True False  True  True  True  True
  True  True  True  True  True  True False  True  True  True  True  True
  True  True  True  True  True  True]
准确率为:
 0.9333333333333333

尝试一下,将n_neighbors参数从9修改为12,准确率上升到 0.9666666666666667,那么如何知道这是否是最优K值呢?

三、模型调优
1、K折交叉验证

交叉验证:将拿到的训练数据,分为训练和验证集。以下图为例:将数据分成4份,其中一份作为验证集。然后经过4次(组)的测试,每次都更换不同的验证集。即得到4组模型的结果,取平均值作为最终结果。又称4折交叉验证。

交叉验证可以让模型更加可信,但是不一定就能提升模型预测的准确率,所以使用网格搜索,可以继续提升其准确率。

python 复制代码
kf = KFold(n_splits=5)
for train, test in kf.split(x, y):
    x_train, x_test = x[train], x[test]
    y_train, y_test = y[train], y[test]
    estimator = KNeighborsClassifier(n_neighbors=7)
    estimator.fit(x_train, y_train)
    y_predict = estimator.predict(x_test)
    score = estimator.score(x_test, y_test)
    print("准确率为:\n", score)
# 也可以计算平均准确率,进而确定K折和n_neighbors的最佳效果
2、网格搜索

通常情况下,有很多参数是需要手动指定的(如k-近邻算法中的K值),这种叫超参数。但是手动过程繁杂,所以需要对模型预设几种超参数组合。每组超参数都采用交叉验证来进行评估。最后选出最优参数组合建立模型。

sklearn.model_selection.GridSearchCV(estimator, param_grid=None,cv=None)

解释:对估计器的指定参数值进行详尽搜索

参数:

  • estimator:估计器对象
  • param_grid:估计器参数(dict){"n_neighbors":[1,3,5]}
  • cv:指定几折交叉验证

方法:

  • fit:输入训练数据
  • score:准确率

结果分析:

  • bestscore__:在交叉验证中验证的最好结果
  • bestestimator:最好的参数模型
  • cvresults:每次交叉验证后的验证集准确率结果和训练集准确率结果
3、K值调优

使用GridSearchCV构建估计器

python 复制代码
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
# 1、获取数据集
iris = load_iris()
# 2、数据基本处理 -- 划分数据集
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2, random_state=5)
# 3、特征工程:标准化
# 实例化一个转换器类
transfer = StandardScaler()
# 调用fit_transform
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
# 4、KNN预估器流程
# 4.1 实例化预估器类
estimator = KNeighborsClassifier()
# 4.2 模型选择与调优------网格搜索和交叉验证
# 准备要调的超参数
param_dict = {"n_neighbors": [1, 3, 5, 7, 9, 11]}
estimator = GridSearchCV(estimator, param_grid=param_dict, cv=5)
# 4.3 fit数据进行训练
estimator.fit(x_train, y_train)
# 5、评估模型效果
# 方法a:比对预测结果和真实值
y_predict = estimator.predict(x_test)
print("比对预测结果和真实值:\n", y_predict == y_test)
# 方法b:直接计算准确率
score = estimator.score(x_test, y_test)
print("直接计算准确率:\n", score)
print("在交叉验证中验证的最好结果:\n", estimator.best_score_)
print("最好的参数模型:\n", estimator.best_estimator_)
print("每次交叉验证后的准确率结果:\n", estimator.cv_results_)

输出结果为:

python 复制代码
比对预测结果和真实值:
 [ True  True  True  True  True  True  True  True  True  True  True False
  True  True  True  True  True  True  True  True  True  True  True False
  True  True  True  True  True  True]
直接计算准确率:
 0.9333333333333333
在交叉验证中验证的最好结果:
 0.975
最好的参数模型:
 KNeighborsClassifier(n_neighbors=9)    # 此处给出了最好的n_neighbors参数
每次交叉验证后的准确率结果:
 {'mean_fit_time': array([0.00060692, 0.00059123, 0.00059299, 0.00079851, 0.00040803,
       0.00060067]), 'std_fit_time': array([0.00049637, 0.00048293, 0.0004844 , 0.0003994 , 0.00049989,
       0.00049045]), 'mean_score_time': array([0.00278454, 0.00240145, 0.00259876, 0.00258627, 0.00259123,
       0.00219283]), 'std_score_time': array([0.00076474, 0.00049743, 0.00048247, 0.00049269, 0.00048831,
       0.00040145]), 'param_n_neighbors': masked_array(data=[1, 3, 5, 7, 9, 11],
             mask=[False, False, False, False, False, False],
       fill_value='?',
            dtype=object), 'params': [{'n_neighbors': 1}, {'n_neighbors': 3}, {'n_neighbors': 5}, {'n_neighbors': 7}, {'n_neighbors': 9}, {'n_neighbors': 11}], 'split0_test_score': array([1., 1., 1., 1., 1., 1.]), 'split1_test_score': array([1.        , 0.95833333, 0.95833333, 1.        , 1.        ,
       1.        ]), 'split2_test_score': array([0.95833333, 0.95833333, 0.95833333, 0.95833333, 0.95833333,
       0.95833333]), 'split3_test_score': array([0.95833333, 0.95833333, 0.95833333, 0.91666667, 0.95833333,
       0.95833333]), 'split4_test_score': array([0.91666667, 0.91666667, 0.91666667, 0.91666667, 0.95833333,
       0.95833333]), 'mean_test_score': array([0.96666667, 0.95833333, 0.95833333, 0.95833333, 0.975     ,
       0.975     ]), 'std_test_score': array([0.03118048, 0.02635231, 0.02635231, 0.0372678 , 0.02041241,
       0.02041241]), 'rank_test_score': array([3, 4, 4, 4, 1, 1])}

由上述输出结果可知,K设置为9时可以取得最好的效果。

相关推荐
憨憨爱编程6 小时前
机器学习-多因子线性回归
人工智能·机器学习·线性回归
悟乙己6 小时前
机器学习(MLOps)系统在线部署的基本指南
人工智能·机器学习·模型部署·mlops
林文韬32713 小时前
语义精炼技巧生成对抗网络(3)基于Wasserstein GAN 的特征生成
深度学习·机器学习·生成对抗网络
悟乙己14 小时前
机器学习常见的分类与回归模型目标变量系统性设计与实践(一)
机器学习·分类·回归
丰年稻香16 小时前
神经网络核心机制深度解析:链式法则驱动下的梯度流动与参数优化
深度学习·神经网络·机器学习
Thomas214317 小时前
MinMaxScaler Scikit-learn sparkml 稀疏向量
人工智能·机器学习·scikit-learn
饕餮怪程序猿17 小时前
(5)机器学习-模型训练的数学原理
人工智能·机器学习
字节高级特工17 小时前
蓝耘智算与DeepSeekR1:低成本高能AI模型
c++·人工智能·机器学习·计算机视觉
jie*18 小时前
小杰机器学习(seven)——贝叶斯分类
人工智能·python·深度学习·神经网络·机器学习·分类·scikit-learn