ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Python机器学习SVM作业:Iris鸢尾花分类完整实战指南

Python机器学习SVM作业:Iris鸢尾花分类完整实战指南 简介面向机器学习初学与期末大作业场景这份Python机器学习SVM作业完整包含了Iris鸢尾花数据集上的SVM分类源码与实验报告。代码采用清晰注释从数据读取、特征标准化到模型训练和评估逐步展开适合快速上手支持向量机基础实践也适合课程设计或结课报告参考。资源包共16个文件、约620KB核心包括2个Python脚本、1份doc实验报告、7张png结果图片含分类效果图和ROC曲线以及项目目录配置文件。目录结构清楚读者可依据脚本复现完整实验对照图片检查分类结果与收敛情况。目前已有227人学习下载被广泛用于课程设计、期末大作业和入门练习。通过源码可掌握SVM分类的标准流程实验报告包含实验原理、步骤和结果分析可直接参考改写成高分作业部署简单下载后即可运行也可作为答辩讲解的支撑材料。1. Python机器学习SVM作业到底要交什么Iris分类案例的完整拆解老师这周刚把Python机器学习SVM作业的题目发下来用经典数据集Iris鸢尾花的数据样本实现SVM分类提交源码和实验报告。如果你正在为这个作业发愁或者想把这个案例彻底弄懂而不是抄完就忘这篇笔记就是冲着你来的。我会把SVM支持向量机在鸢尾花数据集上的完整落地路径拆开讲——从为什么Iris和SVM是作业界的黄金组合到怎么跑通一份能直接交差的Python源码再到实验报告里哪些数值和图表才是真正决定分数的东西。新手可以照着步骤一步步复现熟手建议直接跳到第5章的踩坑记录和第6章的呈现技巧能省下不少返工时间。2. 为什么Iris和SVM是作业界的黄金组合数据集特性与算法选型逻辑2.1 Iris数据集的三个硬特性150个样本、4个特征、3个类别Iris鸢尾花数据集是机器学习入门阶段几乎绕不开的基准数据。它由统计学家Ronald Fisher在1936年整理包含3个品种的鸢尾花各50个样本一共150条记录每条记录有4个数值特征花萼长度、花萼宽度、花瓣长度、花瓣宽度。类别标签是Setosa山鸢尾、Versicolor变色鸢尾和Virginica维吉尼亚鸢尾。这个数据集能在作业题里被反复使用靠的是三个硬特性。第一个是特征维度低4个特征不需要做降维就能直接喂给模型而且可视化方便——取两个特征就能在二维平面画出决策边界。第二个是样本量小但类别平衡每类恰好50条不存在类别不平衡导致的评分虚高问题。第三个是分布特性清晰Setosa这个类别与其他两类在花瓣长度、花瓣宽度上完全线性可分而Versicolor和Virginica之间存在部分重叠正好制造了一个“线性分类器能解决一部分但最优解需要一点技巧”的梯度空间。实际做作业的时候我一般会先跑一段数据探索代码打印出每个特征在不同类别下的均值和标准差。这一步看起来不起眼但实验报告里放一张特征分布表老师一眼就知道你理解数据。常见做法是直接用pandas的groupby加describe两行代码就能产出报告需要的统计量。注意Iris的标签是0、1、2三个整数对应setosa、versicolor、virginica不是字符串后面想显示品种名需要手动做映射。# explore_iris.py from sklearn.datasets import load_iris import pandas as pd # 加载数据集并组装成DataFrame iris load_iris() df pd.DataFrame(datairis.data, columnsiris.feature_names) df[species] iris.target # 按类别分组统计每个特征的均值、标准差、最小值、最大值 print(df.groupby(species).describe().T)这段代码输出的核心不是准确率而是让你快速建立对数据的直觉花瓣长度和花瓣宽度的类别差异最明显而花萼宽度在三个类别之间几乎重叠。说明如果把特征重要性写进实验报告花瓣相关的两个特征排名一定靠前这个结论后面SVM的决策边界图也能佐证。2.2 SVM凭什么在小样本高维数据上占优间隔最大化与核映射SVM支持向量机的核心思想不是“把点分开”这么简单而是找一个离两类样本都尽可能远的决策边界。这个“尽可能远”的数学表达是间隔最大化也就是说决策边界不是随便一条能把两类点分开的线而是到最近的样本点的距离之和最大的那条线。这些决定边界位置的样本点叫作支持向量整个模型的名字也由此而来。为什么要强调间隔最大化而不是单纯地分割正确因为间隔越大模型对样本的微小扰动越不敏感泛化能力越强。这个性质在小样本数据集上极其关键——Iris一共才150条样本测试集只有几十条如果决策边界贴着训练样本走换一批数据很可能翻车。SVM在这类场景下天然比KNN和决策树稳因为KNN依赖距离度量且计算量大决策树容易在小样本上过拟合而SVM只看离边界最近的那几个支持向量。作业里绕不开的另一个概念是核函数。当数据在当前维度线性不可分时SVM通过核函数把样本隐式映射到高维空间在高维空间里找一个线性超平面回到原空间观察就是一条弯曲的决策边界。常见的三个核函数是线性核linear、径向基核rbf和多项式核poly。周志华老师的《机器学习》第6章对这部分的数学推导讲得很细但作业落地不需要手动实现核函数scikit-learn里一个kernel参数就能切换。这里牵扯到两个必须理解的超参数C和gamma。C是误分类惩罚系数C越大越不愿意放过任何一个错分样本决策边界越复杂越容易过拟合C越小对错分越宽容边界越平滑。gamma只对rbf和poly核生效控制单个样本的影响力范围gamma越大每个样本只影响周围很小区域边界越曲折反之边界越平直。这两个参数是第4章网格搜索的主角先记住它们的定性含义调参时才知道数值该往哪个方向移动。3. 用sklearn跑通Iris SVM分类从环境配置到最小可运行代码3.1 环境准备python安装与依赖安装的推荐顺序网上python安装教程很多我默认你已经装好了Python 3.8以上的版本。做这个作业推荐的依赖是numpy、pandas、scikit-learn、matplotlib最多再加一个seaborn画分布图。我的建议是先用虚拟环境隔离项目再统一用pip安装避免和系统里其他Python项目互相污染。conda create -n svm_hw python3.10 -y conda activate svm_hw pip install numpy pandas scikit-learn matplotlib seaborn joblib如果是用原生Python环境用venv也完全够用。参数说明python3.10指定解释器版本scikit-learn在3.10上兼容性最稳joblib是sklearn并行计算的后端网格搜索时n_jobs-1依赖它生效。装完后跑一句python -c import sklearn; print(sklearn.version)确认版本常见做法是锁在1.2.x以上太老版本某些参数名对不上。3.2 数据加载与预处理train_test_split和标准化为什么不能省数据加载在sklearn里一行代码就完成真正的坑在预处理环节。很多第一次做作业的同学拿过原始数据直接训练准确率停在0.7左右然后开始怀疑算法有问题——实际上是被特征量纲坑了。花萼长度以厘米为单位数值范围在4.3到7.9之间花瓣宽度在0.1到2.5之间SVM计算样本距离时数值范围大的特征会主导间隔计算导致范围小但分类能力强的特征被淹没。# data_prepare.py from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler # 加载Iris数据集150个样本、4个特征、3个类别 iris load_iris() X, y iris.data, iris.target # 按7:3切分训练集和测试集stratify按类别比例分层抽样 X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.3, random_state42, stratifyy ) # 标准化让每个特征变成均值为0、方差为1的分布 scaler StandardScaler() X_train_scaled scaler.fit_transform(X_train) X_test_scaled scaler.transform(X_test)代码逻辑分三段解读。train_test_split负责数据划分7:3比例是SVM作业里的常规选择训练集105条、测试集45条random_state固定为42保证每次运行得到相同划分这个值本身没有特殊含义纯粹是约定俗成也可以换成任意整数stratifyy确保训练集和测试集里三种鸢尾花的比例都接近1:1:1Iris样本量小不加分层容易在随机切分时把某一类全部切进训练集。StandardScaler是新手最容易理解错的部分。fit_transform在训练集上计算每个特征的均值和标准差然后执行缩放transform是拿训练集算好的参数直接套到测试集上不在测试集上重新计算。测试集在这里扮演未来数据的角色不能参与任何统计量的估计否则就是信息泄漏第5章会专门讲这个事故。标准化之后4个特征处于同一个量级SVM的距离计算才有意义。3.3 第一个基线模型线性核SVC的完整代码与输出解读在调参之前先用一个最简单的线性核SVC跑通全流程拿到准确率基线。这一步的意义是确认数据、标签、模型、评估方式整条链路没有断点后面所有优化都建立在与这个基线的对比上。# svm_baseline.py from sklearn.svm import SVC from sklearn.metrics import accuracy_score, classification_report # 线性核SVM是最朴素的分类器C1.0是sklearn默认值 model SVC(kernellinear, C1.0, random_state42) model.fit(X_train_scaled, y_train) y_pred model.predict(X_test_scaled) acc accuracy_score(y_test, y_pred) print(fLinear SVM Test Accuracy: {acc:.4f}) print(classification_report(y_test, y_pred))输出里除了整体准确率一定要看classification_report的前几行precision代表查准率recall代表查全率f1-score是两者调和平均support是每个类别的样本数。Iris数据集上线性核SVM的测试准确率通常落在0.93到0.96之间错分样本几乎全部集中在Versicolor和Virginica的交界区域Setosa则是零错误。如果看到这个结果说明链路已经通了下面第4章的调参才有比较的价值。4. 把SVM准确率从0.95提到0.98核函数对比与网格搜索调参4.1 核函数对比实验linear、rbf、poly在Iris上的表现差异拿到基线准确率后第一件事是核函数对比实验。作业报告里这部分通常是核心数据来源也是老师判断你有没有真跑实验而不是抄结果的关键证据。写法上不要只列最终准确率要把每个核函数在交叉验证里的均值、标准差一并给出才能说明结论的稳定性。# kernel_compare.py from sklearn.svm import SVC from sklearn.model_selection import cross_val_score kernels [linear, rbf, poly] cv_results {} for kernel in kernels: model SVC(kernelkernel, C1.0, gammascale, random_state42) scores cross_val_score(model, X_train_scaled, y_train, cv5) cv_results[kernel] scores.mean() print(f{kernel:8s} CV Accuracy: {scores.mean():.4f} ± {scores.std():.4f}) best_kernel max(cv_results, keycv_results.get) print(fBest kernel: {best_kernel})这里有两个参数值得展开。gammascale是sklearn新版默认值它根据特征数量自动缩放gamma计算公式是1除以特征数与训练集方差的乘积对Iris这种4维小数据集通常落在0.2附近gammaauto则固定为1除以特征数等于0.25。两个值差别不大但在报告里显式写出来比留着默认值更像认真做过实验。cv5表示5折交叉验证训练集105条样本每折21条小数据集的折数不建议加到10折数越多每折样本越少估计方差反而变大。实际跑出来的结果通常是rbf略优于linearpoly在默认degree3下表现最差。原因是poly核的三次多项式映射对Iris这种低维数据来说过于复杂小样本上很容易过拟合。实验报告里可以写一句有根据的结论在样本量小、特征数少的数据集上rbf核是安全牌linear是基线poly不做精细调参一般不推荐。4.2 GridSearchCV参数搜索C和gamma的取值边界核函数确定之后调参目标落在C和gamma上。我见过不少同学直接写一个巨大的参数网格丢进GridSearchCV然后等半小时不出结果——这是典型的选参策略失误。正确做法是先粗后细第一轮用对数间隔的大范围网格锁定最优区域第二轮在最优区域附近用线性间隔加密。# grid_search.py from sklearn.model_selection import GridSearchCV # 第一轮粗搜索C和gamma都取10的幂次覆盖四个数量级 param_grid [ {kernel: [rbf], C: [0.1, 1, 10, 100], gamma: [0.01, 0.1, 0.5, scale]}, {kernel: [linear], C: [0.1, 1, 10, 100]}, ] grid_search GridSearchCV( SVC(random_state42), param_grid, cv5, scoringaccuracy, n_jobs-1, verbose1 ) grid_search.fit(X_train_scaled, y_train) print(fBest Params: {grid_search.best_params_}) print(fBest CV Score: {grid_search.best_score_:.4f}) print(fTest Score: {grid_search.score(X_test_scaled, y_test):.4f})GridSearchCV的scoring参数指定评估指标分类任务默认是accuracyIris类别平衡用accuracy没有问题如果是类别不平衡的数据集要换成f1_macro。n_jobs-1表示用满所有CPU核心并行搜索但如果本机内存小参数网格超过100组反而会因为进程间的内存竞争拖慢速度这在第5章的避坑里会细讲。verbose1的作用是输出搜索进度让你确认程序在跑而不是卡死。粗搜索跑完后把最优参数附近的值拿来做第二轮精搜。比如第一轮得出C10、gamma0.1最优第二轮就搜C在5、10、20gamma在0.05、0.1、0.2。第二轮结果才是写进报告的最终参数。这里有一个实际建议不要迷信网格搜索的全局最优如果多组参数的交叉验证得分只差0.001选C较小、gamma较小的那组模型更平滑泛化风险更低。4.3 决策边界可视化用matplotlib把分类结果画出来准确率数字只能说明模型好不好决策边界图才能展示模型学到了什么。SVM作业报告里放一两张可视化图整体观感会提升一大截。由于Iris有4个特征完整可视化需要画两两组合的散点图矩阵但最实用的做法是取前两个特征画一张决策区域图说明SVM的分类逻辑即可。# decision_boundary.py import numpy as np import matplotlib.pyplot as plt # 只取前两个特征做可视化单独训练一个模型 X_vis X_train_scaled[:, :2] y_vis y_train model_vis SVC(kernelrbf, C10, gamma0.5, random_state42) model_vis.fit(X_vis, y_vis) # 构造网格点用训练好的模型预测每个点的类别 h 0.02 x_min, x_max X_vis[:, 0].min() - 0.5, X_vis[:, 0].max() 0.5 y_min, y_max X_vis[:, 1].min() - 0.5, X_vis[:, 1].max() 0.5 xx, yy np.meshgrid( np.arange(x_min, x_max, h), np.arange(y_min, y_max, h) ) Z model_vis.predict(np.c_[xx.ravel(), yy.ravel()]) Z Z.reshape(xx.shape) # 绘制决策区域和训练样本散点 plt.contourf(xx, yy, Z, alpha0.3, cmapplt.cm.coolwarm) plt.scatter(X_vis[:, 0], X_vis[:, 1], cy_vis, cmapplt.cm.coolwarm, edgecolorsk) plt.xlabel(Sepal Length (Standardized)) plt.ylabel(Sepal Width (Standardized)) plt.title(SVM Decision Boundary (RBF Kernel)) plt.savefig(svm_decision_boundary.png, dpi150)代码里的网格间距h0.02控制决策边界曲线的光滑程度h越小边界越平滑但计算量越大二维平面下0.02足够。注意这里重新训练了一个只用两个特征的模型画出的边界和用全部4个特征的模型并不一致但特征投影到二维平面后的直观效果更好在报告图注里注明这一点就不算造假。彩色区域是模型预测的类别归属散点上的黑边让样本点在色块中更醒目。5. SVM作业避坑指南5条血泪经验与排查方法SVM作业的代码量不大真正的耗时往往不是写代码而是在小坑里反复横跳。下面这5个问题是我带过的学生和自己在重写案例时踩得最多的按现象、原因、解决的顺序写照着排查能省下大半天的调试时间。5.1 没做标准化线性核SVM准确率只有0.70现象数据加载后直接扔进SVC训练测试集准确率只有0.7左右比随机猜测0.33高不了太多但看网上的教程都写着Iris分类准确率能到0.95以上心态直接崩了。原因原始Iris数据里花萼长宽和花瓣长宽的量纲不同SVM计算样本间距离时数值范围大的特征直接压制了小范围特征决策边界被拉偏。说到底SVM不是决策树那种按阈值切分的模型它依赖样本在特征空间里的几何距离量纲不一致等于四个特征的投票权不一样。解决训练前做标准化代码就是第3章那个StandardScaler。铁律是只在训练集上fit_transform在测试集上只transform两个数据集必须用同一个scaler对象。提示标准化后准确率还是上不去检查你是不是对X_train和X_test分别调用了fit_transform那样会得到两套不同的均值方差等于测试集被独立缩放了一次。5.2 GridSearchCV加n_jobs-1笔记本直接卡死现象参数网格列了二十几组组合信心满满地加上n_jobs-1开跑结果CPU风扇狂转、内存占用逼近上限等了十分钟没输出最后把进程强杀。原因n_jobs-1意味着把所有CPU核心全部投入每个核在并行计算时都要复制一份数据和模型对象参数组合多、数据量不算小的时候内存带宽成为瓶颈并行反而比串行更慢甚至直接触发系统OOM。解决先缩小参数网格范围粗搜索阶段每组参数之间数量级拉开差距比如C取0.1、1、10、100gamma取0.01、0.1、0.5这样十几组组合既能覆盖大范围又不会撑爆内存。如果确实需要更大范围搜索改用RandomizedSearchCV从参数空间里随机采样固定次数开销小得多结果通常也够用。5.3 matplotlib图画出来中文标题全变成方块现象把图标题写成“决策边界与支持向量”保存的图里中文变成一排□□□□报告打印出来更没法看整个图直接废掉。原因matplotlib的默认字体库不包含中文字体绘图时遇到中文字符就替换为占位符方块。这个坑在不同操作系统上表现不一样Windows可能是SimHei缺省Linux服务器上大概率更严重。解决两种方案。一是绘图前设置中文字体常见写法是plt.rcParams[font.sans-serif] [SimHei]同时加上plt.rcParams[axes.unicode_minus] False处理负号显示二是直接用英文图题比如SVM Decision Boundary on Iris Dataset学术范更浓也能彻底绕开字体依赖。我后来交作业基本都用英文图题省心。5.4 同一份代码跑三次准确率三个数现象代码逻辑没变但每次运行的测试准确率都在0.95和0.97之间浮动实验报告里不知道该填哪个数答辩时被老师一问就想暴露对复现性的理解不够。原因train_test_split和SVC内部都有随机采样或随机初始化过程不固定种子每次运行结果天然不同。Iris只有150条样本测试集45条里错一个样本准确率就差两个百分点数字浮动格外明显。解决在所有引入随机性的地方固定random_state42——train_test_split里、SVC构造函数里、GridSearchCV的评估器里都要写。固定之后任何人任何机器跑同一份代码都会得到一致结果这也是实验报告里实验环境部分最该写清楚的细节。5.5 测试集准确率比交叉验证还高总觉得哪里不对现象网格搜索跑完一看测试集准确率0.98比交叉验证均值0.95还高第一反应是捡到宝了实际上概率上测试集分数通常不会显著超过验证分数。原因在数据集切分之前就做了全局标准化或特征选择。比如先用scaler拟合整个X再划分train_test_split这样测试集的分布信息已经通过scaler偷看到了模型在测试集上的表现虚高换一份新数据立刻现原形。解决流程上把数据切分放在任何数据变换之前所有预处理参数的估计都只能在训练集上完成测试集只在最后做一次性评估。这个原则叫数据泄漏防护是机器学习作业里老师最想看到你掌握的知识点之一。6. 实验报告怎么写出区分度结果表格、结论与分析技巧SVM作业的实验报告代码部分反而是配角老师真正看的是你能不能解释清楚三件事为什么选这个模型、参数怎么定下来的、结果意味着什么。写报告时我习惯用一组对比表格开头直接把结论放在显眼位置。核函数最优C最优gamma5折交叉验证准确率测试集准确率linear1-0.95240.9556rbf100.10.97140.9778poly1-0.94290.9333表格下面配三句话rbf核在交叉验证和测试集上均取得最高准确率更适合处理Versicolor和Virginica的重叠区域linear核作为基线表现良好说明两类重叠并非完全非线性poly核默认参数下过拟合明显支持向量数最多而泛化能力最弱。这三句话就是报告的分析核心比堆代码截图有用得多。报告里另一个容易被忽略的细节是支持向量数。通过len(model.support_)可以拿到写进报告能体现你对SVM原理的理解——支持向量越多说明间隔越小决策边界越复杂泛化风险越高。配合实验环境里的sklearn版本号、随机种子、Python版本整个报告的可复现性就完整了。我第一次写SVM实验报告时犯的最蠢错误是只贴代码和最终准确率没有任何过程数据。后来学乖了核函数对比表、交叉验证标准差、决策边界图三件套放上去老师打分时想给低分都得犹豫一下。如果你还在跟着吴恩达机器学习课程或者周志华老师的书补基础理论这个作业正好把理论侧的知识点串起来。希望这份作业的完整思路能帮到你少走我走过的弯路。本文还有配套的精品资源点击获取
返回列表