葡萄酒质量分析Python实战:数据挖掘课程设计完整流程解析

发布时间:2026/10/11 19:03:48
葡萄酒质量分析Python实战:数据挖掘课程设计完整流程解析
简介面向数据挖掘课程设计及期末大作业场景这份基于Python的葡萄酒质量分析项目提供了一套可完整运行的实战案例覆盖数据读取、清洗、分析、可视化与建模流程。数据集包含酒精含量、酸度、密度等多项指标及对应质量评分可用于分类或回归模型训练适合计算机相关专业学生及希望上手数据挖掘的初学者参考。资源包共16个文件以10个csv数据文件为核心另有3个Python源码脚本和3个说明文档压缩包整体约595KB经过调试后下载即可直接运行。目前已有84人学习通过该项目可系统练习数据处理、特征工程、模型训练与结果评估等关键环节也可作为课程设计或期末大作业的整体范本。1. 数据挖掘大作业怎么拿高分先拆一遍葡萄酒质量分析源码的完整链路课程设计答辩时老师问得最多的不是「你准确率多少」而是「你这个流程为什么这么设计」。代码能跑但分数上不去多半是流程缺了环节。这份 Python 实现的葡萄酒质量分析项目正好是标准的加分结构红白葡萄酒两套数据的清洗、相关性分析、特征工程、三种分类模型对比以及分类报告和混淆矩阵可视化链路完整不是只丢给你一个训练脚本。它适合两类人一是数据挖掘期末大作业还没定题目的可以照这个结构直接改造成自己的题目二是想弄清楚课程设计怎么才不像应付差事的照着从头复现一遍比看十篇教程都管用。源码和全部数据都在一个包里先花十分钟把骨架摸透再动手改效率高得多。2. 摸清骨架再跑通主程序数据目录、环境安装与第一次运行输出这个资源不是把几十个文件堆在一个文件夹里让你自己猜而是按课程设计答辩逻辑拆好的工程目录。我拿到之后的第一件事是列文件清单搞清楚谁负责数据、谁负责建模、谁负责出图然后装环境、跑一次主程序确认输出数值和预期一致。这三步做完你才有资格去改代码否则后面所有改动都是盲改。2.1 源码包里有什么两个 CSV 数据文件与脚本分工文件/目录作用说明data/winequality-red.csv红葡萄酒数据集1599 条记录11 个理化特征加 1 个质量评分data/winequality-white.csv白葡萄酒数据集4898 条记录字段与红酒完全一致data_preprocess.py数据清洗与特征工程缺失值检查、相关性热力图、标签二值化train_model.py模型训练与评估逻辑回归 / 决策树 / 随机森林三组对比visualize.py可视化输出混淆矩阵、ROC 曲线、特征重要性柱状图main.py主入口脚本串联全流程支持命令行参数切换requirements.txt依赖清单pandas / numpy / matplotlib / seaborn / scikit-learn按阶段拆文件的好处答辩时能直接当讲稿用。老师问「每个文件干什么」你顺着列表把职责说清楚印象分先拿到一半。数据预处理单独一个文件也很关键因为清洗逻辑最具体、最好讲是最容易展示工作量的部分。这个项目的数据规模约 6500 条对课程设计来说非常合适——跑起来快又能展示出特征分布和类别不均衡这些真实问题不用自己造数据。2.2 环境准备Python 3.8 以上加五个库一条命令装完依赖没有整花活就是数据挖掘课上最常见的五个库。我用虚拟环境装的原因是课程设计中途一定会改模型、试新库虚拟环境能把这份项目的依赖和全局 Python 隔离项目删了也不影响其他作业。命令行操作如下cd wine_quality_project python -m venv venv source venv/bin/activate # Linux/macOSWindows 下用 venv\Scripts\activate pip install -r requirements.txtrequirements.txt 里的版本要注意两个边界pandas 2.x 起要求 Python 3.9 以上如果本机是 3.8要么升 Python 要么手动指定 pandas1.5.3scikit-learn 认准 1.0 以上即可1.x 的 API 基本稳定。装完后用一条命令验证环境没装错python -c import pandas, sklearn, matplotlib; print(pandas.__version__, sklearn.__version__, matplotlib.__version__)能打印出版本号说明依赖全部就位。这一步别跳过我见过太多人pip install结束就以为装好了实际 scikit-learn 装了一半后面 import 直接报错。2.3 先跑为敬主入口的参数设计与第一次输出的读法main.py 把整个流程串成了一条命令我用红葡萄酒加随机森林试跑python main.py --type red --model rf --target binary参数含义拆开说--type选数据集red 和 white 二选一--model选模型lr 是逻辑回归dt 是决策树rf 是随机森林--target选任务binary 表示二分类quality 大于等于 7 算好酒multi 表示按 38 分做多分类。第一次跑通之前我的建议是不要改任何代码。先看输出里的四个关键数字数据集形状是否为 1599 行 12 列、缺失值是否为 0、好酒和普通酒的样本数比例、交叉验证平均分和测试集分类报告。这几个数字就是后续所有修改的基准线。每次改完代码拿新输出和基准线对比出问题立刻能定位到是哪一步引入的。提示第一次跑完先别急着看模型分数先确认数据行数。red 应该是 1599white 应该是 4898。这个数对不上说明你手里的数据文件被改过或者 pandas 读取方式不对后面所有分析都建立在错误基础上。3. 数据预处理才是分水岭12 列葡萄酒数据的清洗、相关性与标签策略很多作业分数低低在预处理部分只写一句「数据没有缺失值所以不用处理」。这个数据集确实没有缺失值但它有偏态分布、有特征共线性、有标签不均衡这些才是预处理要展示的功夫。把这一章做厚答辩时你就有东西可讲而不是干巴巴地贴一张 describe 的表格。3.1 数据集结构盘点红白两份数据能不能合在一起用先用 pandas 把数据读进来这里有一个必须注意的细节——分隔符不是逗号import pandas as pd red pd.read_csv(data/winequality-red.csv, sep;) white pd.read_csv(data/winequality-white.csv, sep;) print(red.shape, white.shape) print(red.dtypes)sep;是这份数据的第一个坑。UCI 的葡萄酒质量数据集用分号做分隔符不带这个参数pandas 会把整行读成单列shape 直接变成 1599 行 1 列后面所有代码都会翻车。dtypes 输出显示全部是数值型没有类别变量需要编码这让预处理省了很多事。红白两份数据的字段完全一致但分布差异明显——白葡萄酒的残糖和二氧化硫整体偏高密度分布也不同。项目里默认分开建模不建议直接 concat 成一份答辩时老师问「为什么不合并」你可以理直气壮地说两类酒的理化指标分布不同合并会模糊决策边界。3.2 缺失值与异常值数据没缺失不代表不用处理缺失值检查跑一遍结果全是 0但这只是第一步。真正值得展示的是异常值分析for col in red.columns: q1, q3 red[col].quantile(0.25), red[col].quantile(0.75) iqr q3 - q1 outlier_count ((red[col] q1 - 1.5 * iqr) | (red[col] q3 1.5 * iqr)).sum() print(col, outlier_count)这段用经典的 IQR 方法统计每列异常值数量。残糖和总二氧化硫的异常值最多这符合葡萄酒工艺——个别甜型酒的残糖远高于干型酒。处理策略不是无脑删除对随机森林这类树模型异常值通常保留因为树模型按阈值切分不依赖尺度但逻辑回归对异常值敏感训练前要做 RobustScaler 稳健缩放避免个别极端值把系数拉偏。我一般的处理原则是只删「多列同时异常」的极端样本比如总二氧化硫超过 300 同时密度也异常的行而不是把所有 IQR 超限的样本全删掉那样会损失有效信息。3.3 相关性分析热力图要画但别只看热力图相关性热力图是课程设计的标配图也是答辩最容易被追问的地方import seaborn as sns import matplotlib.pyplot as plt corr red.corr() plt.figure(figsize(10, 8)) sns.heatmap(corr, annotTrue, fmt.2f, cmapcoolwarm, linewidths0.5) plt.title(Wine Quality Feature Correlation Matrix) plt.show()annotTrue把相关系数值标在格子里字体大小在字段多时可以调小。从热力图能看到两个关键结论酒精与质量正相关最高约 0.48挥发性酸度与质量负相关约 -0.39。这两个结论答辩时能讲出来说明你真的看过数据。但热力图有个陷阱密度和酒精高度负相关约 -0.50残糖和密度相关高达 0.84这些特征之间存在共线性。逻辑回归遇到共线性回归系数的解释会不稳定这属于数据挖掘课程里「多重共线性」的知识点。我的做法是建模时不完全依赖手工剔除而是用随机森林的特征重要性去验证如果做逻辑回归可以对高度相关的特征组做个 VIF 检查把 VIF 大于 10 的特征挑出来说明处理思路。3.4 标签策略二分类还是多分类答辩时怎么说数据里的 quality 是 3 到 8 的整数评分原始多分类任务并不好做。常见的处理是转成二分类阈值取 7import numpy as np red[label] np.where(red[quality] 7, 1, 0) print(red[label].value_counts())np.where把质量大于等于 7 的样本标成 1好酒其余标成 0。输出会显示正负样本大约 1:6 的比例这个不均衡比例在后面评估模型时非常关键。如果直接把 quality 当多分类的 y6 个类别里有几个类只有十几条样本模型很难学出规律答辩时还容易被追问「你处理的是不是有序分类问题」。我的课程设计建议主模型用二分类把多分类作为拓展实验放一页效果不理想也能解释成样本太少、类别有序至少展示了思考深度。注意阈值取 7 还是 6直接改变样本分布。改成 6正例比例升到约 45%模型准确率会好看很多但「质量 6 分算好酒」这个业务定义很难站住脚。高分作业的要点是先写清楚「为什么取 7」再谈模型结果。先定义问题再做实验顺序不能反。4. 建模评估别只看准确率逻辑回归、随机森林与交叉验证的正确打开方式准确率是课程设计里最容易虚高的指标。这个数据集上无脑把全部样本预测成「普通酒」准确率也有 87%。所以模型对比要讲「相对多数类基线提升了多少」而不是盯着绝对准确率自嗨。这一章按「选型理由 → 数据划分 → 评估指标 → 可视化输出」的顺序展开每一步都是答辩时可以展开讲的知识点。4.1 模型选型为什么是这三个模型而不是一个跑到底项目里默认的三组模型逻辑回归、决策树、随机森林。选型理由在答辩时要能一句话讲清逻辑回归是线性模型的代表可解释性强每个特征的系数直接对应正向还是负向影响决策树是单棵树的代表能画出树形图直观展示分裂依据随机森林是 Bagging 集成的代表通过多棵树投票降低方差效果通常最好。三者在复杂度上形成梯度正好对应课程里「线性模型 → 单树模型 → 集成模型」的教学顺序。课程设计不需要上 XGBoost 或深度学习一是数据量只有几千条二是这几个模型足够你把知识点串起来答辩时每一层都有话讲。4.2 训练集划分stratify 和 random_state 的坑数据划分的代码有几个参数不能乱填from sklearn.model_selection import train_test_split X red.drop(columns[quality, label]) y red[label] X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, stratifyy, random_state42 )stratifyy的作用是在切分时保持好酒和普通酒的比例和原始数据一致。正负样本 1:6 的数据如果不加这个参数随机切分可能把好酒样本集中到训练集或测试集导致测试结果失真。random_state42的作用是让结果可复现。这里有一个实操层面很要命的细节不设random_state每次跑出来的准确率都不一样答辩时老师让你现场再跑一次数字对不上体验极差。之后换模型时交叉验证也用分层策略from sklearn.model_selection import StratifiedKFold, cross_val_score cv StratifiedKFold(n_splits5, shuffleTrue, random_state42) scores cross_val_score(model, X_train, y_train, cvcv, scoringaccuracy) print(fCV mean: {scores.mean():.4f} (/- {scores.std():.4f}))交叉验证的均值比单次划分的结果更稳定报告里写这个数字比写单次测试集准确率更有说服力。n_splits5是课程设计常用的折数数据量不大5 折在稳定性和计算成本之间比较平衡。4.3 评估指标组合分类报告、混淆矩阵、ROC 曲线训练完成后先用classification_report看完整指标from sklearn.metrics import classification_report, confusion_matrix, roc_curve, auc y_pred model.predict(X_test) print(classification_report(y_test, y_pred, target_names[normal, good]))分类报告里的recall列比准确率更重要——它反映模型对少数类的识别能力。在这个数据集上好酒类别的召回率通常偏低你要重点比较随机森林是否比逻辑回归把好酒召回率提高了一截这个提升幅度才是报告的核心结论。混淆矩阵可视化是论文必备图cm confusion_matrix(y_test, y_pred) sns.heatmap(cm, annotTrue, fmtd, cmapBlues) plt.xlabel(Predicted Label) plt.ylabel(True Label) plt.show()ROC 曲线的代码也很短主要是把 predict_proba 输出的概率拿来做曲线fpr, tpr, _ roc_curve(y_test, model.predict_proba(X_test)[:, 1]) print(fAUC: {auc(fpr, tpr):.4f})AUC 对类别不均衡不敏感这个数据集上逻辑回归 AUC 通常在 0.85 上下随机森林能到 0.90 左右。答辩时把准确率、召回率、AUC 三个数一起摆出来说明你看过不止一个指标比单贴一个准确率高级得多。4.4 可视化输出特征重要性图与保存规范特征重要性图是随机森林特有的输出也是连接数据分析与模型解释的桥梁import pandas as pd importances pd.Series(model.feature_importances_, indexX.columns).sort_values() importances.plot(kindbarh, figsize(8, 6)) plt.xlabel(Importance) plt.tight_layout() plt.savefig(figures/feature_importance.png, dpi150)sort_values()让最重要的特征显示在顶部barh 是水平柱状图标签不容易截断。savefig要指定dpi150否则图片放进论文打印出来是糊的。特征重要性的结论通常与相关性分析一致酒精、挥发性酸度、密度排前三。这张图答辩时比模型分数更值得讲因为它把「数据理解」和「模型解释」接上了——你已经知道哪些特征和好酒有相关性现在模型又确认了一遍两条证据链互相印证。5. 避坑手册课程设计翻车现场的五类高频问题与排查思路这一章写的是复现这类课程设计项目时最常见的翻车现场每一条都是实际踩过的。现象、原因、解决三步写清楚你遇到类似报错可以直接按图索骥。5.1 CSV 读取出来只有一列现象pd.read_csv(winequality-red.csv)之后df.shape显示 1599 行 1 列所有字段挤在一个单元格里。原因这个数据集的分隔符是分号而 pandas 默认按逗号分隔。加了sep;就正常。这是 UCI 这套数据的经典陷阱。解决df pd.read_csv(data/winequality-red.csv, sep;, encodingutf-8)如果还乱码说明文件被 Excel 以其他编码另存过把encoding换成gbk或latin1逐个试。我习惯在代码开头加一个断言assert df.shape[1] 12列数不对直接报错避免数据读歪了还往下跑。5.2 准确率 0.87 但模型其实没用现象逻辑回归跑完了测试集准确率 0.87看起来很漂亮但看了混淆矩阵发现模型几乎把所有样本都判成普通酒。原因标签不均衡好酒只占约 13%。模型只要学会「全部说普通」准确率就有 87%这对模型来说是最省事的策略。解决别只盯着准确率。看分类报告里好酒类别的召回率或者直接算 AUC。报告里这样表述「多数类基线准确率为 87%随机森林在保持整体准确率 91% 的同时把好酒召回率从逻辑回归的 42% 提升到 65%。」用「相对基线提升多少」来陈述答辩老师一听就知道你理解这个数据的特点。5.3 图里中文全部变成方块现象plt.title(特征重要性)显示成一片方框。原因matplotlib 默认字体不包含中文字符。解决在绘图脚本开头加两行把字体改成系统自带的中文字体plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False第二行是修正负号显示异常的。另一个更省事的做法是图里全部用英文标签中文只出现在报告正文。课程设计论文本来就是要中英文混排的图注用英文反而看着规范。5.4 本机跑通换电脑就报错scikit-learn 版本差异现象在你自己电脑上训练好的模型换到实验室电脑重新跑剧本预测时报AttributeError或者大量 warning。原因scikit-learn 版本差异导致部分 API 行为不同。比如RandomForestClassifier的n_estimators默认值在 0.22 版本之前是 10之后是 100版本不对模型表现完全不同。跨版本加载保存的模型文件兼容性也差。解决课程设计不要保存训练好的模型文件只保存预测结果和图表。分析代码跟着走到哪台机器跑都是重新训练省掉序列化这一层麻烦。在 requirements.txt 里固定scikit-learn1.0换机器先pip install -r requirements.txt统一版本。5.5 随机森林训练慢跑一次四五分钟现象n_estimators500max_depthNone跑完一次交差验证小课间都不够。原因默认设置对这个只有 6500 条的数据集是高配。每棵树都长到完全生长500 棵树就是 500 次完整划分大部分收益是边际递减的。解决把n_estimators调到 100max_depth限制到 10效果几乎不变但速度快几倍。被老师问为什么这么调就答「数据量只有几千条树太多会导致训练时间线性增长而分类效果的提升在 100 棵树之后已经看不出来了。」这个回答本身就展示了对模型复杂度与数据规模关系的理解。6. 换个数据集照样用把葡萄酒分析改造成你的专属课程设计如果你不想交一份和别人撞车的作业最好的办法是保留这套代码框架换一个数据集。UCI 上常见的成人收入预测、心脏病分析、小麦种子分类字段结构都和葡萄酒数据兼容。改造的核心只有两件事字段映射和标签定义。假设换成成人收入预测代码里只需要改数据读取和字段名mapping { wine: { features: [alcohol, volatile acidity, density], label: quality 7 }, adult: { features: [age, education-num, hours-per-week], label: income 50K } } df pd.read_csv(data/adult.data, headerNone) df.columns [age, workclass, fnlwgt, education, education-num, marital-status, occupation, relationship, race, sex, capital-gain, capital-loss, hours-per-week, native-country, income]换成新数据集后需要连带确认四件事分隔符还是不是逗号有没有类别字段需要做编码缺失值是空字符串还是 NaN标签列要不要把50K和50K映射成 1 和 0。类别字段用pd.get_dummies做独热编码规模不大可以直接处理。新数据的相关性热力图和特征重要性图要重新跑一遍写报告时以新数据的结果为准葡萄酒的结论一律不能复用这是原则问题。从那以后我拿到任何新课程设计题目都会先花十五分钟把字段含义、分隔符、标签分布写在一张纸上再打开编辑器。这个习惯就是跑这份葡萄酒项目时养成的——当时我跳过了描述统计直接建模后来所有分析都建立在对数据结构的错误理解上返工了一整天。希望这篇拆解能帮你把同样的弯路省掉一次跑通。本文还有配套的精品资源点击获取