🌼案例:鸢尾花种类预测 — 流程实现🥰

🎯学习目标

  • 🎯目标

    • 熟悉:机器学习从数据获取到评估的完整流程
    • 掌握:KNeighborsClassifier的使用及参数设置
    • 理解:归一化和标准化原理、区别及适用场景
    • 明晰:交叉验证和网格搜索概念及作用
    • 运用:交叉验证和网格搜索优化模型

🔍K - 近邻算法 API

sklearn.neighbors.KNeighborsClassifier(n_neighbors=5, algorithm='auto')

📋参数说明

  • n_neighbors:int,可选(默认 = 5),k_neighbors 查询默认使用的邻居数
  • algorithm:{‘auto’,‘ball_tree’,‘kd_tree’,‘brute’},快速 k 近邻搜索算法,默认参数为 auto,可以理解为算法自己决定合适的搜索算法。除此之外,用户也可以自己指定搜索算法:
    • brute:蛮力搜索,也就是线性扫描,当训练集很大时,计算非常耗时。
    • kd_tree:构造kd树存储数据以便对其进行快速检索的树形数据结构,kd树也就是数据结构中的二叉树。以中值切分构造的树,每个结点是一个超矩形,在维数小于20时效率高。
    • ball_tree:是为了克服kd树高维失效而发明的,其构造过程是以质心C和半径r分割样本空间,每个节点是一个超球体。

💡预处理归一化和标准化的精髓✨

🔢归一化

  • 核心定义:将原始数据通过变换映射到指定范围,通常是[0,1]区间。
  • 公式本质:每一列数据,通过减去最小值,除以极差(最大值与最小值的差)

    再乘以指定区间长度并加上区间下限,实现数据的缩放。

  • 主要作用:消除特征之间的量纲差异,使不同特征在模型中具有相同的“地位”,便于进行比较和分析,有助于提高某些对特征范围敏感的机器学习算法的性能。
  • API要点:使用 sklearn.preprocessing.MinMaxScaler类,通过 fit_transform方法对 numpy array格式的数据进行转换,可通过 feature_range参数指定映射范围。
  • 应用局限:最大值和最小值易受异常点影响,导致归一化结果不稳定,鲁棒性较差,适用于传统精确小数据场景。

🌟标准化

  • 核心定义:对原始数据进行变换,使数据转换到均值为0、标准差为1的范围内。
  • 公式本质:

    针对每一列数据,减去该列的均值,再除以该列的标准差,从而使数据符合标准正态分布。

  • 主要作用:在消除量纲影响的同时,能让数据具有稳定的均值和标准差,使模型更加稳定和高效,尤其适用于对数据分布有一定要求的算法。
  • API要点:利用 sklearn.preprocessing.StandardScaler类的 fit_transform方法处理 numpy array格式的数据,处理后每列数据都聚集在均值0附近,标准差为1。
  • 应用优势:在样本数据足够多的情况下比较稳定,少量异常点对平均值和方差的影响较小,适合现代嘈杂大数据场景。

🌸案例:鸢尾花种类预测🌼

📊数据集介绍

Iris数据集是常用的分类实验数据集,由Fisher, 1936收集整理。Iris也称鸢尾花卉数据集,是一类多重变量分析的数据集。关于数据集的具体介绍:
Alt text

🚀步骤分析

  • 获取数据集
  • 数据基本处理
  • 特征工程
  • 机器学习 (模型训练)
  • 模型评估

💻代码过程

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
# 导入必要的库
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)

# 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)

🔄什么是交叉验证 (cross validation)🌟

交叉验证是一种用于评估模型性能的重要技术。它将拿到的训练数据,进一步细分为训练集和验证集。例如,把数据分成 4 份,其中一份作为验证集。然后经过 4 次(组)的测试,每次都更换不同的验证集,即得到 4 组模型的结果,取平均值作为最终结果,这也被称为 4 折交叉验证。

🧐分析

我们之前了解到数据分为训练集和测试集,但为了让从训练得到的模型结果更加准确,我们做如下处理:

  • 训练集:进一步拆分为训练集和验证集
  • 测试集:保持不变

🤔为什么需要交叉验证

交叉验证的目的是为了让被评估的模型更加准确可信。不过,这只是提升了模型评估的准确性,那如何选择或者调优参数呢?这就引出了网格搜索。

🔍什么是网格搜索 (Grid Search)🌈

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

🛠交叉验证,网格搜索(模型选择与调优)API📚

sklearn.model_selection.GridSearchCV(estimator, param_grid=None, cv=None) 用于对估计器的指定参数值进行详尽搜索。

📋参数说明

  • estimator:估计器对象
  • param_grid:估计器参数(字典形式),例如 {"n_neighbors": [1, 3, 5]}
  • cv:指定几折交叉验证
  • fit:输入训练数据
  • score:计算准确率

📈结果分析

  • best_score_:在交叉验证中验证的最好结果
  • best_estimator_:最好的参数模型
  • cv_results_:每次交叉验证后的验证集准确率结果和训练集准确率结果

🌺鸢尾花案例增加 K 值调优💐

以下是使用 GridSearchCV 构建估计器的完整代码:

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
35
36
37
38
39
40
41
42
43
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, random_state=22)

# 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]}
estimator = GridSearchCV(estimator, param_grid=param_dict, cv=3)

# 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_)

💻代码运行输出结果👇

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
比对预测结果和真实值:
[ 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 True True True True True True
True True]
直接计算准确率:
0.947368421053
在交叉验证中验证的最好结果:
0.973214285714
最好的参数模型:
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
metric_params=None, n_jobs=1, n_neighbors=5, p=2,
weights='uniform')
每次交叉验证后的准确率结果:
{'mean_fit_time': array([ 0.00114751, 0.00027037, 0.00024462]), 'std_fit_time': array([ 1.13901511e-03, 1.25300249e-05, 1.11011951e-05]), 'mean_score_time': array([ 0.00085751, 0.00048693, 0.00045625]), 'std_score_time': array([ 3.52785082e-04, 2.87650037e-05, 5.29673344e-06]), 'param_n_neighbors': masked_array(data = [1 3 5],
mask = [False False False],
fill_value = ?), 'params': [{'n_neighbors': 1}, {'n_neighbors': 3}, {'n_neighbors': 5}], 'split0_test_score': array([ 0.97368421, 0.97368421, 0.97368421]), 'split1_test_score': array([ 0.97297297, 0.97297297, 0.97297297]), 'split2_test_score': array([ 0.94594595, 0.89189189, 0.97297297]), 'mean_test_score': array([ 0.96428571, 0.94642857, 0.97321429]), 'std_test_score': array([ 0.01288472, 0.03830641, 0.00033675]), 'rank_test_score': array([2, 3, 1], dtype=int32), 'split0_train_score': array([ 1. , 0.95945946, 0.97297297]), 'split1_train_score': array([ 1. , 0.96 , 0.97333333]), 'split2_train_score': array([ 1. , 0.96, 0.96]), 'mean_train_score': array([ 1. , 0.95981982, 0.96876877]), 'std_train_score': array([ 0. , 0.00025481, 0.0062022 ])}

📝总结🎉

本文围绕鸢尾花种类预测案例,详细介绍了机器学习从数据获取到模型评估的完整流程,以及相关的数据预处理、模型调优等重要技术,具体内容总结如下:

🚀机器学习流程与核心算法

  • 完整流程:涵盖获取数据集、数据基本处理、特征工程、模型训练和模型评估等环节,清晰展示了运用机器学习解决实际分类问题的步骤。
  • K - 近邻算法KNeighborsClassifier 是常用的分类算法,可通过设置 n_neighborsalgorithm 等参数进行灵活调整。不同的 algorithm 选项(如 autoball_treekd_treebrute)适用于不同的数据规模和维度场景。

💾数据预处理

  • 归一化:将数据映射到指定范围(通常是 [0,1]),能消除特征量纲差异,但易受异常点影响,鲁棒性较差,适用于传统精确小数据场景。使用 sklearn.preprocessing.MinMaxScaler 类实现。
  • 标准化:把数据变换到均值为 0、标准差为 1 的范围内,在处理大数据时更为稳定,受异常点影响较小,适合现代嘈杂大数据场景。使用 sklearn.preprocessing.StandardScaler 类实现。

📊模型评估与调优

  • 交叉验证:通过将训练数据划分为多个子集进行多次验证,取结果平均值,可使模型评估结果更加准确可信,提高模型的泛化能力。
  • 网格搜索:针对超参数(如 K - 近邻算法中的 n_neighbors)预设多种组合,利用交叉验证评估每组参数的效果,从而选出最优参数组合,优化模型性能。使用 sklearn.model_selection.GridSearchCV 类实现。

通过鸢尾花种类预测案例,我们不仅掌握了 KNeighborsClassifier 算法的使用,还学会了如何运用数据预处理、交叉验证和网格搜索等技术,提升模型的准确性和稳定性。这些方法和技术在解决各类机器学习分类问题中具有广泛的应用价值。