机器学习exp1——基于sklearn的鸢尾花分类
一、项目简介
1.鸢尾花数据集:
150朵
4个特征:花萼长度,花萼宽度,花瓣长度,花瓣宽度(cm)
3个类别:Setosa,Versicolor,Virginica
2.实验流程
加载数据集
划分数据集
选择3种分类模型,进行训练
输出测试集上的精度,对比不同分类模型的结果
要求:多次划分数据集,得到多个精度
3.个人建议
数据集分析和结果分析在报告中要讲述清楚
二、实验前的基础知识
1.数据集
data= load_iris():获取鸢尾花数据集对象,此对象类似字典的特殊对象(Bunch),包含了数据集的所有信息(特征的数据,特征的名子,标签,对数据集的描述)
datas = data.data:从鸢尾花数据集中提取特征数据(具体值),提取结果为二维数组。形状为 (150, 4)),意思是有 150 个样本,每个样本有 4 个特征值。比如 datas[0] 就是第一个鸢尾花样本的 4 个特征值:[5.1, 3.5, 1.4, 0.2]
labels = data.target:从鸢尾花数据集中提取标签的数据。0(山鸢尾)、1(变色鸢尾)、2(维吉尼亚鸢尾)。labels 是一个一维数组(形状为 (150,)),每个元素对应 datas 中相同位置样本的品种。比如 labels[0] = 0,表示第一个样本是山鸢尾。
描述性说明:

| 属性名 | 具体说明什么 |
|---|---|
target_names |
标签(target)的实际含义名称(而非数字 0/1/2)。比如:['setosa', 'versicolor', 'virginica'],对应标签 0 = 山鸢尾,1 = 变色鸢尾,2 = 维吉尼亚鸢尾。 |
feature_names |
特征(data)的实际含义名称(而非单纯的第 1/2/3/4 列)。比如:['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)'],即花萼长度、花萼宽度、花瓣长度、花瓣宽度(单位厘米)。 |
DESCR |
数据集的详细描述文档(最核心的 “说明”)。包含:1. 数据集来源、作者、发表背景;2. 样本数量、特征数量、标签类别;3. 数据集的用途、经典应用场景;4. 相关参考文献等。 |
filename |
数据集文件在你本地 Python 环境中的存储路径(方便定位原始数据文件)。 |
frame |
数据集是否基于 DataFrame 存储(iris 数据集为 None,代表是纯数组形式)。 |
data_module |
数据集加载的模块路径(内部实现相关,对新手无实际使用价值)。 |
2.X和y
X 和 y 是约定俗成的变量命名,分别代表特征和标签(也叫目标变量)。
X(特征 / 输入):通常是一个二维数组 / 矩阵,决定y的因素。
y(标签 / 输出 / 目标):你最终要预测的结果
| 变量 | 含义 |
|---|---|
X_train |
训练集的特征(80% 样本的特征数据) |
X_test |
测试集的特征(20% 样本的特征数据) |
y_train |
训练集的标签(80% 样本的目标结果) |
y_test |
测试集的标签(20% 样本的目标结果) |
用 X_train 训练模型,让模型学习 “特征→标签” 的规律,用 X_test 喂给训练好的模型,得到预测结果,再和 y_test 对比,验证模型准不准。
| 变量 | 作用 | 阶段 |
|---|---|---|
y_train |
给模型当 “标准答案”,教模型学习 | 训练阶段 |
y_test |
验证模型学的好不好,不参与学习 | 测试阶段 |
简而言之:y_train用于训练模型,y_test用于检验模型性能。
3.随机种子
test_size 只规定了划分的 “比例”,但 “哪些样本进训练集 / 测试集” 是由随机种子控制的。
4.K 折交叉验证
数据分为K块,每一块都当一次测试集
kf = KFold(n_splits=5, shuffle=True, random_state=40)
| 部分 | 通俗解释(用 “切蛋糕” 类比) |
|---|---|
KFold(...) |
调用 sklearn 的 “切分工具”,专门用来做 K 折划分 |
n_splits=5 |
把数据集(150 个鸢尾花样本)平均切成 5 块,每块 30 个样本(150÷5=30) |
shuffle=True |
切蛋糕前先把 150 个样本 “打乱顺序”(避免样本按类别排序,比如前 50 个全是 setosa) |
random_state=40 |
固定 “打乱的规则”—— 每次都按同一顺序打乱,保证切分结果不变(可复现) |
kf = ... |
把这个 “切分工具” 保存到变量kf里,后续直接用这个工具切分数据 |
5.cv_scores = []
这行是创建一个空列表,作用是 “记录每一次折的测试精度”。
6.分类模型
逻辑回归模型:画多条直线分类
迭代(max_iter):迭代是逻辑回归模型的核心。每一次迭代都是机器在学习如何分类鸢尾花,并且获取经验,调整学习参数,得到最优的参数来接受最终的分类检验任务。
核心循环代码:
for fold, (train_idx, test_idx) in enumerate(kf.split(X)):
X_train_cv, X_test_cv = X[train_idx], X[test_idx]
y_train_cv, y_test_cv = y[train_idx], y[test_idx]
| 英文部分 | 中文翻译 | 通俗解释 |
|---|---|---|
for |
循环 / 遍历 | 就是 “重复做某件事”,比如循环 5 次就做 5 次 |
fold |
折 / 轮次 | 表示 “第几次验证”,比如 5 折交叉验证,fold 就是 0、1、2、3、4(从 0 开始数) |
train_idx |
训练集索引 | “idx” 是 index(索引 / 行号)的缩写,train_idx 就是 “训练数据的行号列表” |
test_idx |
测试集索引 | test_idx 就是 “测试数据的行号列表” |
in |
在... 里面 | 固定语法,比如 “在苹果堆里挑苹果” |
enumerate() |
枚举 / 给序号 | 给每一次循环的内容加一个 “编号”,比如第 1 次循环编号 0,第 2 次编号 1 |
kf |
K 折交叉验证对象 | 提前定义好的 “K 折拆分工具”(比如分成 5 份) |
kf.split(X) |
拆分 X 数据 | split 是 “拆分”,kf.split (X) 就是 “用 K 折工具把 X 数据的行号拆分成训练 / 测试两组” |
| 循环轮次(fold) | train_idx(训练行号) | test_idx(测试行号) | X_train_cv(取 X 的哪些行) | X_test_cv(取 X 的哪些行) |
|---|---|---|---|---|
| 0 | [1,2,3,4] | [0] | X 的 1、2、3、4 行 | X 的 0 行 |
| 1 | [0,2,3,4] | [1] | X 的 0、2、3、4 行 | X 的 1 行 |
| 2 | [0,1,3,4] | [2] | X 的 0、1、3、4 行 | X 的 2 行 |
SVM模型(可以非线性分类)
model = SVC(random_state=40, kernel='rbf', gamma='scale')
| 参数 | 中文解释 | 核心作用(结合鸢尾花) |
|---|---|---|
SVC |
支持向量分类器 | Scikit-learn 中专门用于分类的 SVM 模型(区别于用于回归的 SVR) |
random_state=40 |
随机种子 | 固定模型的随机初始化过程,保证每次运行结果完全一致(比如你跑 10 次,精度都是 1.0);如果不设,每次运行结果可能略有差异(比如一次 0.99,一次 1.0) |
kernel='rbf' |
核函数为高斯核(径向基函数) | 让 SVM 从 “只能画直线” 变成 “能画任意曲线”,适配鸢尾花中 1 类和 2 类的轻微非线性重叠;(如果设kernel='linear',SVM 就退化成线性模型,和逻辑回归效果接近) |
gamma='scale' |
高斯核的带宽参数(自动缩放) | 控制 “曲线的弯曲程度”:✅ gamma='scale'(默认):自动根据特征尺度计算 gamma(1/(特征数×特征方差)),适配鸢尾花的 4 个 cm 级特征,不用手动调;❌ 如果 gamma 太小:曲线太平缓,和线性模型没区别;❌ 如果 gamma 太大:曲线太弯曲,会过拟合(把噪声当规律) |
随机森林模型
model_cv = RandomForestClassifier(random_state=40, n_estimators=100, max_depth=5)
| 参数 | 中文解释 | 核心作用(结合鸢尾花) |
|---|---|---|
RandomForestClassifier |
随机森林分类器 | 基于 “多棵决策树投票” 的集成模型,不是单棵 “随机树” 哦~ |
random_state=40 |
随机种子 | 固定模型的随机过程(比如树的生成、特征采样),保证 5 折交叉验证中每一轮的结果可复现;如果不设,不同轮次的精度可能忽高忽低,对比无意义 |
n_estimators=100 |
决策树数量 | 随机森林里包含 100 棵独立的决策树,最终分类结果由 100 棵树 “投票” 决定;✅ 100 是行业默认值:树太少(比如 10 棵)→ 结果不稳定;树太多(比如 500 棵)→ 训练变慢,精度提升微乎其微;对鸢尾花来说,100 棵树足够覆盖所有特征组合 |
max_depth=5 |
每棵树的最大深度 | 限制单棵决策树最多长 5 层(比如 “花瓣长度> 5cm→花瓣宽度 > 1.8cm→判定为 2 类”,最多 5 个判断步骤);✅ 核心作用:防止过拟合!鸢尾花数据简单,若不限制深度,单棵树会 “死抠” 个别样本的噪声(比如异常的花瓣长度),导致泛化能力下降;5 层对鸢尾花来说 “刚好够用”—— 既能捕捉核心特征规律,又不会过度拟合 |
三、代码
逻辑回归
#coding:utf-8
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split, KFold
from sklearn.metrics import accuracy_score
#1.加载数据集
#取出鸢尾花数据集
data=load_iris()
#取出鸢尾花的特征数据
X=data.data
#取出鸢尾花的类别标签
y=data.target
#2.划分数据集
print("方法1,普通划分")
#分成训练集和测试集(0.7train,0.3test)
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.3,random_state=40)
print("训练集样本数:",len(X_train),"测试集样本数:", len(X_test))
print("方法2,5折交叉实验")
kf=KFold(n_splits=5,shuffle=True,random_state=40)
#存储5次测试精度
cv_scores=[]
#3.选择分类模型
#3.1逻辑回归
model=LogisticRegression(random_state=40,max_iter=500)
# 训练模型
model.fit(X_train,y_train)
#用测试集预测
y_pred=model.predict(X_test)
#4输出测试集精度
accuracy=accuracy_score(y_test,y_pred)
print(f"普通划分 - 测试集精度:{accuracy:.4f}")
#3.25折交叉实验
for fold, (train_index, test_index) in enumerate(kf.split(X)):
X_train_cv, X_test_cv = X[train_index], X[test_index]
y_train_cv, y_test_cv = y[train_index], y[test_index]
#初始化模型
model_cv = LogisticRegression(random_state=40, max_iter=200)
# 训练模型
model_cv.fit(X_train_cv, y_train_cv)
#用测试集预测
y_pred_cv = model_cv.predict(X_test_cv)
fold_accuracy = accuracy_score(y_test_cv, y_pred_cv)
cv_scores.append(fold_accuracy)
print(f"第{fold + 1}折 测试精度:{fold_accuracy:.4f}")
avg_accuracy = sum(cv_scores) / len(cv_scores)
print(f"5折交叉验证 - 平均测试精度:{avg_accuracy:.4f}")
SVM
#coding:utf-8
from sklearn.datasets import load_iris
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split, KFold
from sklearn.metrics import accuracy_score
#1.加载数据集
#取出鸢尾花数据集
data=load_iris()
#取出鸢尾花的特征数据
X=data.data
#取出鸢尾花的类别标签
y=data.target
#2.划分数据集
print("方法1,普通划分")
#分成训练集和测试集(0.7train,0.3test)
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.3,random_state=40)
print("训练集样本数:",len(X_train),"测试集样本数:", len(X_test))
print("方法2,5折交叉实验")
kf=KFold(n_splits=5,shuffle=True,random_state=40)
#存储5次测试精度
cv_scores=[]
#3.选择分类模型
#3.1逻辑回归
model=SVC(random_state=40, kernel='rbf', gamma='scale')
# 训练模型
model.fit(X_train,y_train)
#用测试集预测
y_pred=model.predict(X_test)
#4输出测试集精度
accuracy=accuracy_score(y_test,y_pred)
print(f"普通划分 - 测试集精度:{accuracy:.4f}")
#3.25折交叉实验
for fold, (train_index, test_index) in enumerate(kf.split(X)):
X_train_cv, X_test_cv = X[train_index], X[test_index]
y_train_cv, y_test_cv = y[train_index], y[test_index]
#初始化模型
model_cv = SVC(random_state=40, kernel='rbf', gamma='scale')
# 训练模型
model_cv.fit(X_train_cv, y_train_cv)
#用测试集预测
y_pred_cv = model_cv.predict(X_test_cv)
fold_accuracy = accuracy_score(y_test_cv, y_pred_cv)
cv_scores.append(fold_accuracy)
print(f"第{fold + 1}折 测试精度:{fold_accuracy:.4f}")
avg_accuracy = sum(cv_scores) / len(cv_scores)
print(f"5折交叉验证 - 平均测试精度:{avg_accuracy:.4f}")
随机森林
#coding:utf-8
from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split, KFold
from sklearn.metrics import accuracy_score
#1.加载数据集
#取出鸢尾花数据集
data=load_iris()
#取出鸢尾花的特征数据
X=data.data
#取出鸢尾花的类别标签
y=data.target
#2.划分数据集
print("方法1,普通划分")
#分成训练集和测试集(0.7train,0.3test)
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.3,random_state=60)
print("训练集样本数:",len(X_train),"测试集样本数:", len(X_test))
print("方法2,5折交叉实验")
kf=KFold(n_splits=5,shuffle=True,random_state=60)
#存储5次测试精度
cv_scores=[]
#3.选择分类模型
#3.1逻辑回归
model = RandomForestClassifier(random_state=40, n_estimators=100, max_depth=5, min_samples_split=2)
# 训练模型
model.fit(X_train,y_train)
#用测试集预测
y_pred=model.predict(X_test)
#4输出测试集精度
accuracy=accuracy_score(y_test,y_pred)
print(f"普通划分 - 测试集精度:{accuracy:.4f}")
#3.25折交叉实验
for fold, (train_index, test_index) in enumerate(kf.split(X)):
X_train_cv, X_test_cv = X[train_index], X[test_index]
y_train_cv, y_test_cv = y[train_index], y[test_index]
#初始化模型
model_cv = RandomForestClassifier(random_state=40, n_estimators=100, max_depth=5)
# 训练模型
model_cv.fit(X_train_cv, y_train_cv)
#用测试集预测
y_pred_cv = model_cv.predict(X_test_cv)
fold_accuracy = accuracy_score(y_test_cv, y_pred_cv)
cv_scores.append(fold_accuracy)
print(f"第{fold + 1}折 测试精度:{fold_accuracy:.4f}")
avg_accuracy = sum(cv_scores) / len(cv_scores)
print(f"5折交叉验证 - 平均测试精度:{avg_accuracy:.4f}")
数据集分析
from sklearn.datasets import load_iris
data=load_iris()
print(data.DESCR)
import numpy as np
print("\n===== 特征描述性统计 =====")
stats = {
"均值": np.mean(data.data, axis=0),
"标准差": np.std(data.data, axis=0),
"最小值": np.min(data.data, axis=0),
"最大值": np.max(data.data, axis=0)
}
for key, value in stats.items():
print(f"{key}:", value.round(2))
四、实验总结
逻辑回归适用:因为鸢尾花近似线性可分,数据简单,线性模型足够高效准确。
SVM 适用:因为数据存在少量非线性重叠,高斯核 SVM 能更好地分割边界。
随机森林适用:因为数据特征区分度高、干扰的没用的数据少,集成树模型能稳定学习分类规则且不易过拟合
五、致谢
感谢豆包,感谢小红书老师们
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)