尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

葡萄酒质量分析数据挖掘大作业:Python完整流程与避坑指南

葡萄酒质量分析数据挖掘大作业:Python完整流程与避坑指南 简介这是一份面向计算机相关专业学生的数据挖掘课程设计资源以Python实现葡萄酒质量分析为完整案例适合正在准备期末大作业或希望积累实战经验的学习者。项目围绕酒精含量、酸度、密度等变量与葡萄酒质量评定的关系展开覆盖数据读取、清洗、特征工程、模型训练与结果评估等数据挖掘全流程可作为分类或回归分析的练习范本。压缩包共16个文件包含10个csv数据文件、3个py源码文件及3个txt说明文档整体约595KB源码经调试后下载即可运行降低了初学者的上手门槛。目前已有83人学习关注。借助完整数据与可执行代码读者能直接复现分析流程理解各变量对质量的影响并在此基础上调整模型或扩展特征为课程答辩与后续数据分析工作提供可参考的实践模板。1. 葡萄酒质量分析项目一份能跑通的数据挖掘大作业到底长什么样很多人做数据挖掘大作业时第一步就卡住了不是不会写代码而是不知道一个「完整项目」应该包含哪些东西。葡萄酒质量分析这个题目之所以经典是因为它同时踩中了数据挖掘课程里最核心的几个考点——数据清洗、特征工程、分类建模、模型评估而且数据集本身干净、可解释性强非常适合作为课程项目的载体。但问题也在这里网上流传的版本大多只有一段建模代码没有数据说明、没有参数解释、没有踩坑记录抄下来跑不通答辩时也讲不清。这篇文章要讲清楚的是一个 Python 实现的葡萄酒质量分析项目从数据加载到模型输出每一步该怎么做、参数为什么这么设、哪里最容易翻车。适合正在准备数据挖掘大作业的学生也适合想用这个数据集练手特征工程的从业者。读完你应该能自己搭出一套可复现的流程而不是复制一段跑不通的代码。2. 数据加载与探索先把红白葡萄酒分开看2.1 数据集结构与你需要先确认的三件事葡萄酒质量数据集通常以 CSV 形式提供常见的是红葡萄酒和白葡萄酒两个文件字段包括固定酸度、挥发性酸度、柠檬酸、残糖、氯化物、游离二氧化硫、总二氧化硫、密度、pH、硫酸盐、酒精含量以及一个质量评分列。质量评分一般是 0 到 10 的整数但实际分布集中在 5、6、7 三档这一点直接决定了后面建模策略。拿到数据后先确认三件事第一红白葡萄酒是否分开存储如果合并分析需要加一个颜色标签列第二质量列是数值还是字符串有些版本会写成 good/bad 这类标签第三有没有缺失值虽然这个数据集通常很干净但不同来源的文件可能被处理过。import pandas as pd import numpy as np # 分别加载红白葡萄酒数据常见文件名是 winequality-red.csv 和 winequality-white.csv red pd.read_csv(winequality-red.csv, sep;) white pd.read_csv(winequality-white.csv, sep;) # 确认字段名和数据类型 print(red.columns.tolist()) print(red.dtypes) print(red.shape, white.shape) # 检查缺失值 print(red.isnull().sum()) print(white.isnull().sum()) # 查看质量评分分布这一步决定了后面是回归还是分类 print(red[quality].value_counts().sort_index()) print(white[quality].value_counts().sort_index())这段代码的关键在sep;。很多 CSV 文件用分号分隔而不是逗号直接read_csv会读成一整列这是最常见的翻车点之一。质量分布打印出来后你会发现红葡萄酒样本量大约 1599 条白葡萄酒大约 4898 条评分 5 和 6 占了绝大多数7 分以上很少。这意味着如果直接做多分类高分类别样本极少模型会偏向多数类。2.2 用描述统计和相关性快速判断哪些特征值得留数据探索不是走形式目的是决定后面保留哪些特征、怎么处理。先看描述统计重点看量纲差异总二氧化硫的数值可能上百而 pH 只有 3 左右如果不做标准化基于距离的模型会被大数值特征主导。# 描述统计关注均值和标准差判断量纲差异 desc red.describe().T desc[range] desc[max] - desc[min] print(desc[[mean, std, min, max, range]]) # 相关性分析看哪些特征和质量评分相关性强 corr red.corr(numeric_onlyTrue)[quality].sort_values(ascendingFalse) print(corr) # 酒精含量和挥发性酸度通常是相关性最强的两个特征 # 可以画散点图确认但这里先用数值判断从相关性输出里通常能看到酒精含量与质量正相关挥发性酸度与质量负相关这两个特征在多数版本里都排在最前面。密度和残糖的相关性往往较弱但不代表没用只是线性关系不明显。这一步的产出是一个特征优先级列表后面做特征选择时直接参考。提示相关性只反映线性关系葡萄酒数据里有些特征是非线性影响不要因为相关系数低就直接删掉后面可以用树模型的特征重要性再验证一次。3. 特征工程与预处理标准化、分箱和标签处理的取舍3.1 标准化该不该做取决于你选什么模型标准化不是必选项它取决于模型类型。逻辑回归、SVM、KNN 这类基于距离或梯度的模型必须做标准化决策树、随机森林、XGBoost 这类基于分裂点的模型标准化不影响结果。很多人不管什么模型都先标准化一遍结果用树模型时白白增加计算量还让特征解释变麻烦。from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split # 特征和标签分开 X red.drop(quality, axis1) y red[quality] # 先划分训练集和测试集再做标准化避免数据泄漏 X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42, stratifyy ) # 标准化只在训练集上 fit测试集用同样的参数 transform scaler StandardScaler() X_train_scaled scaler.fit_transform(X_train) X_test_scaled scaler.transform(X_test)这里有两个容易错的地方。第一fit只能在训练集上做如果先对全量数据标准化再划分测试集的信息就泄漏到训练过程里了评估结果会虚高。第二stratifyy要加上因为质量评分分布不均不加分层可能导致测试集里某个类别样本极少评估指标波动很大。3.2 质量评分怎么处理回归、二分类还是多分类质量评分是整数但它本质上是有序的。直接做多分类会忽略顺序信息做回归又会把 5 和 6 的差异当成连续值处理。常见做法有三种第一种直接做多分类把 3、4、5、6、7、8 当作独立类别。问题是高分类别样本太少模型学不好。第二种做二分类把评分大于等于 7 的标为好其余标为一般。这样类别平衡好很多也是课程项目里最常用的做法。第三种做回归预测一个连续分数再四舍五入。评估时用均方误差但解释性差一些。# 二分类方案质量 7 视为好酒 y_binary (red[quality] 7).astype(int) print(y_binary.value_counts()) # 如果做多分类可以合并稀有类别 y_multi red[quality].apply(lambda q: q if q 5 else 4) print(y_multi.value_counts())我一般会先跑二分类因为结果稳定、好解释答辩时也容易讲清楚。如果时间充裕再补一个多分类做对比体现工作量。3.3 特征构造几个值得试的衍生特征原始特征之外可以构造几个有物理意义的衍生特征。比如游离二氧化硫和总二氧化硫的差值反映结合态二氧化硫的量酒精和密度的比值间接反映发酵程度酸度相关特征可以组合成总酸度。这些特征不一定都有效但试错成本低能体现你对数据的理解。# 构造衍生特征 df red.copy() df[free_so2_ratio] df[free sulfur dioxide] / (df[total sulfur dioxide] 1) df[bound_so2] df[total sulfur dioxide] - df[free sulfur dioxide] df[alcohol_density] df[alcohol] / df[density] df[total_acid] df[fixed acidity] df[volatile acidity] df[citric acid] # 检查新特征和标签的相关性 print(df[[free_so2_ratio, bound_so2, alcohol_density, total_acid]].corrwith(df[quality]))加 1 是为了避免除零虽然这个数据集里总二氧化硫不会为零但养成习惯没坏处。构造完新特征后用corrwith快速看一遍相关性如果新特征和标签的相关性还不如原始特征可以考虑不加避免维度膨胀。4. 建模与评估从逻辑回归到集成模型的完整对比4.1 基线模型逻辑回归先跑通流程不管最后用什么模型先跑一个逻辑回归做基线。它的好处是训练快、结果可解释、系数能直接看特征影响方向。如果逻辑回归的效果已经能接受后面的复杂模型就是锦上添花如果逻辑回归效果很差说明特征或标签处理有问题先排查再上复杂模型。from sklearn.linear_model import LogisticRegression from sklearn.metrics import classification_report, confusion_matrix, roc_auc_score # 用标准化后的数据训练逻辑回归 lr LogisticRegression(max_iter1000, random_state42) lr.fit(X_train_scaled, y_train) # 预测和评估 y_pred lr.predict(X_test_scaled) y_prob lr.predict_proba(X_test_scaled)[:, 1] print(classification_report(y_test, y_pred)) print(AUC:, roc_auc_score(y_test, y_prob)) print(confusion_matrix(y_test, y_pred))max_iter1000是因为默认的 100 次迭代在标准化后的数据上有时不收敛会报收敛警告。AUC 是二分类里比准确率更可靠的指标因为类别不平衡时准确率会虚高。混淆矩阵能看出模型是把好酒误判成一般还是一般误判成好酒这两个错误的代价在实际场景里不一样。4.2 树模型和集成模型随机森林与梯度提升的参数怎么设树模型不需要标准化可以直接用原始特征。随机森林的关键参数是n_estimators、max_depth和min_samples_split。n_estimators一般设 100 到 500再多收益递减max_depth不设的话树会完全生长容易过拟合可以设 10 到 20 之间试min_samples_split控制分裂的最小样本数设太小会过拟合设太大会欠拟合。from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier # 随机森林用原始特征 rf RandomForestClassifier( n_estimators300, max_depth15, min_samples_split5, min_samples_leaf2, random_state42, n_jobs-1 ) rf.fit(X_train, y_train) y_pred_rf rf.predict(X_test) print(RF AUC:, roc_auc_score(y_test, rf.predict_proba(X_test)[:, 1])) # 梯度提升 gb GradientBoostingClassifier( n_estimators200, learning_rate0.05, max_depth4, random_state42 ) gb.fit(X_train, y_train) y_pred_gb gb.predict(X_test) print(GB AUC:, roc_auc_score(y_test, gb.predict_proba(X_test)[:, 1]))梯度提升的learning_rate和n_estimators要配合调学习率小就需要更多棵树学习率大就容易过拟合。0.05 配 200 棵是一个比较稳的起点。max_depth设 4 是因为梯度提升本身对深树敏感浅树加多轮迭代通常比深树效果好。4.3 交叉验证和超参数搜索别只用一次划分的结果单次训练测试划分的结果波动很大尤其是样本量不大的时候。用交叉验证能得到更稳定的评估再用网格搜索找最优参数。注意网格搜索要在训练集内部做交叉验证不能碰测试集。from sklearn.model_selection import GridSearchCV, cross_val_score # 先看随机森林的交叉验证表现 cv_scores cross_val_score(rf, X_train, y_train, cv5, scoringroc_auc) print(CV AUC:, cv_scores.mean(), /-, cv_scores.std()) # 网格搜索找最优参数 param_grid { n_estimators: [200, 300, 500], max_depth: [10, 15, 20], min_samples_split: [2, 5, 10] } grid GridSearchCV( RandomForestClassifier(random_state42, n_jobs-1), param_grid, cv5, scoringroc_auc, n_jobs-1 ) grid.fit(X_train, y_train) print(Best params:, grid.best_params_) print(Best CV AUC:, grid.best_score_)n_jobs-1表示用所有 CPU 核心并行能显著缩短搜索时间。scoringroc_auc是因为类别不平衡时 AUC 比准确率更可靠。搜索完拿到最优参数后用最优模型在测试集上跑一次最终评估这个结果才是写进报告里的。4.4 特征重要性分析模型告诉你哪些特征真正有用树模型可以直接输出特征重要性这是它比逻辑回归更好解释的地方。把重要性排序后你会发现酒精含量、挥发性酸度、硫酸盐通常排在前列和相关性分析的结论基本一致但树模型能捕捉非线性关系排序可能略有不同。# 用最优模型的特征重要性 best_rf grid.best_estimator_ importances pd.Series(best_rf.feature_importances_, indexX_train.columns) print(importances.sort_values(ascendingFalse)) # 如果做了特征构造把新特征也加进去重新训练再对比特征重要性不仅能帮你筛选特征还能在报告里解释「为什么这个模型有效」。如果某个衍生特征重要性很高说明你的特征工程有实际价值这是加分项。5. 避坑与排查葡萄酒质量分析里最容易翻车的五个地方5.1 读取 CSV 时分隔符搞错整张表变成一列现象read_csv之后shape显示只有一列或者所有字段挤在一起。原因葡萄酒数据集的 CSV 常用分号分隔默认逗号解析失败。解决加sep;如果不确定分隔符先用pd.read_csv(file.csv, nrows1)看第一行原始内容或者用sepNone, enginepython让 pandas 自动推断。5.2 先标准化再划分数据集评估结果虚高现象测试集 AUC 高得离谱换一组随机种子后大幅下降。原因标准化时用了全量数据的均值和方差测试集信息泄漏到训练过程。解决先train_test_split再在训练集上fit标准化器测试集只做transform。这个顺序不能反。5.3 质量评分直接做多分类高分类别全预测错现象分类报告里 7 分和 8 分的召回率接近零。原因高分类别样本太少模型偏向多数类。解决改成二分类或者用class_weightbalanced让模型关注少数类也可以用 SMOTE 过采样但要注意过采样只能在训练集上做。5.4 逻辑回归不收敛满屏 ConvergenceWarning现象训练时反复提示lbfgs failed to converge。原因默认迭代次数不够或者特征量纲差异大。解决先做标准化再把max_iter调到 1000 以上。如果还不收敛检查是否有常数特征或高度共线的特征删掉再试。5.5 交叉验证用了测试集最终评估不可信现象交叉验证分数和测试集分数差距很大。原因在包含测试集的数据上做交叉验证或者调参时反复用测试集评估。解决交叉验证只在训练集内部做测试集只在最终评估时用一次。调参用GridSearchCV的cv参数它自动在训练集内部分折。6. 把项目做得能答辩报告结构、可视化与复现清单项目能不能拿高分代码只占一半另一半是你能不能讲清楚。答辩时老师最常问的三个问题是你为什么这么处理数据、你为什么选这个模型、你的结果怎么验证。这三个问题对应报告里的数据探索、模型对比和评估指标三部分。可视化不用多但要有针对性。质量分布用柱状图特征相关性用热力图模型对比用 ROC 曲线叠加特征重要性用水平条形图。这四张图基本能覆盖答辩需求。ROC 曲线叠加的代码如下import matplotlib.pyplot as plt from sklearn.metrics import roc_curve # 三个模型的 ROC 曲线叠加 models {Logistic: lr, RandomForest: best_rf, GradientBoosting: gb} plt.figure(figsize(8, 6)) for name, model in models.items(): if name Logistic: prob model.predict_proba(X_test_scaled)[:, 1] else: prob model.predict_proba(X_test)[:, 1] fpr, tpr, _ roc_curve(y_test, prob) auc roc_auc_score(y_test, prob) plt.plot(fpr, tpr, labelf{name} (AUC{auc:.3f})) plt.plot([0, 1], [0, 1], k--, labelRandom) plt.xlabel(False Positive Rate) plt.ylabel(True Positive Rate) plt.legend() plt.title(ROC Curve Comparison) plt.savefig(roc_comparison.png, dpi150) plt.show()这段代码里注意逻辑回归用的是标准化后的测试集树模型用的是原始测试集因为它们的预处理需求不同。保存图片时dpi150保证清晰度报告里插图不会糊。复现清单我一般会整理成一张表放在报告附录里方便别人照着跑步骤关键操作常见参数检查点数据加载read_csvsep;shape 和字段名正确数据划分train_test_splittest_size0.2, stratifyy类别比例一致标准化StandardScaler只在训练集 fit无数据泄漏基线模型LogisticRegressionmax_iter1000无收敛警告集成模型RandomForestClassifiern_estimators300交叉验证稳定评估roc_auc_score测试集只用一次指标可复现最后说一个我自己的习惯每次跑完实验把随机种子、参数、评估指标记在一个单独的文本文件里和代码放在一起。数据挖掘大作业最怕的就是答辩前想复现某个结果却忘了当时参数怎么设的有了这个记录随时能翻回去。这个项目本身不难难的是把每一步做扎实、讲清楚希望帮到你。本文还有配套的精品资源点击获取
返回列表