新闻详情

新闻详情

首页 / 资讯中心 / 详情

葡萄酒品质预测实战:从数据预处理到模型评估全流程

发布时间:2026/9/29 1:30:35来源:尧图网络
葡萄酒品质预测实战:从数据预处理到模型评估全流程
不知道你有没有遇到过这种情况手里拿到一份真实数据集课程学了一堆机器学习算法真到自己动手做项目时却不知道从哪一步开始。葡萄酒品质预测就是那个能帮你把“课本知识”串成“完整流程”的经典项目。它来自UCI机器学习库公开的wine quality数据集核心任务是利用葡萄酒的化学成分指标酸度、糖分、酒精含量等预测品酒师给出的品质评分。这个项目我反复带过很多次也被好几个学生写进求职作品集因为它足够简单、足够完整而且每一环都有真实业务含义——不是那种拍脑袋造的玩具数据而是实实在在的品酒记录。这篇文章不打算讲空洞的概念而是按我实际做项目的节奏走一遍从数据概况、问题定义、预处理讲到模型选型、训练评估和踩坑记录。无论你是正在复习机器学习期末、准备实验报告还是想找第一个实战项目练手这套流程都可以直接参考甚至照抄。我尽量写得像现场记录而不是教科书因为很多关键经验真的只有亲手跑过才会发现。1. 项目概况与核心设计思路1.1 为什么选择葡萄酒品质数据集葡萄酒品质数据集能在机器学习入门项目里长期“霸榜”不是没有原因的。先说数据规模红葡萄酒样本1599条、白葡萄酒4898条这个体量对于教学和实验来说特别合适——太小了学不到规律太大了又需要优化训练效率这个数据集正好卡在“机器学习都能跑得动”的甜区。再说特征设计每条样本包含11个输入特征固定酸度、挥发酸度、柠檬酸、残糖、氯化物、游离二氧化硫、总二氧化硫、密度、pH值、硫酸盐、酒精含量。这些不是抽象的数字而是真实葡萄酒理化检测会测的指标。目标变量quality是品酒师打的分数范围从3到8整数。换句话说这个项目的本质是用化学检测结果预测人的主观评价这是一个非常典型的“客观数据预测主观评分”业务场景。这种场景在现实中非常常见比如电商用商品参数预测好评率平台用用户行为预测满意度。所以这个项目练的不只是调库而是练一种思维方式怎么把领域里看似杂乱的指标变成机器学习能用的特征和目标。这也是我带学生做这个项目时最想让他们理解的东西。1.2 回归还是分类先把问题定义清楚很多人拿到这个项目第一反应是quality是3到8的整数那不是分类问题吗直接跑个多分类模型不就行了这个思路不能说错但实际做下来会发现很多问题。先看类别分布红葡萄酒数据里5分和6分占了绝大多数3分只有10条8分只有18条。如果做6分类3分到8分模型会被5分和6分主导3分和8分这种小类别的F1值会惨不忍睹。另一个问题是3到8不是纯粹的无序类别而是有顺序的等级。你预测成5分和预测成7分对4分的样本来说误差性质完全不同——前者接近后者离谱。所以实际项目中我更推荐两条路。第一条是把问题当作回归任务处理用线性回归、随机森林回归去预测一个连续的品质分数最后四舍五入取整评估。第二条是把分数做二值化处理比如7分及以上算“好酒”6分及以下算“普通”把问题转化成经典二分类。这两种做法各有取舍回归保留了原始信息但评估指标不太直观二分类牺牲了细粒度却能让模型效果和评估都清晰很多。我自己的习惯是实验报告和面试里优先展示二分类方案。因为二分类能更清楚地讲评估指标也能把类别不平衡、阈值调整这些机器学习核心知识点串起来讲解观看者更容易听懂面试时也更好展开。2. 数据探索与预处理实战2.1 数据集长什么样动手建模之前先花10分钟把数据看明白这一步看似简单但往往能省掉后面好几个小时的排查时间。我第一次做这个项目就吃过亏没看数据直接标准化丢进模型后来发现数据集里有两列的名字容易混淆——free sulfur dioxide和total sulfur dioxide——还有个density特征的数值范围明显和其他列不在一个量级。先看读取语句import pandas as pd df pd.read_csv(winequality-red.csv, sep;) print(df.shape) print(df.head()) print(df.info())这个数据集有个小坑分隔符是分号;而不是逗号用默认的read_csv会报错或读成一整列。读取之后第一步就是检查缺失值print(df.isnull().sum())红葡萄酒数据集没有缺失值这是它适合入门的原因之一。但不用高兴太早紧接着就要看描述性统计print(df.describe().T)观察一下就能发现sulphates的最大值达到2左右density集中在0.99到1.00之间alcohol跨度从8.4到14.9。不同特征之间的尺度差异非常大这对稍后选择模型会有直接影响。还有一个值得做的操作是看特征之间的相关性尤其要看density和alcohol的关系。事实上酒精含量越高密度通常越低这两列存在较强的负相关。这种共线性不一定会毁掉树模型但对线性模型会有影响后面讲模型选型时会再提。2.2 预处理三步走缺失值、标准化、特征相关性数据探索做完正式进入预处理。这个项目里预处理可以拆成三步每一步都有明确的“为什么”。第一步是处理缺失值和异常值。这个数据集没有缺失值但要注意极端值比如某些样本的residual sugar特别高或者chlorides异常。树模型对极端值不敏感但逻辑回归和SVM很敏感所以我会用百分位法或者IQR四分位距方法去识别离群点必要时做截尾处理。不过因为酒精含量等指标本身天然存在宽范围别一看到大数值就删得结合业务判断这点初学者最容易犯错。第二步是标准化。标准化不是对所有模型都必要但当你准备对比多个模型时标准化能让公平性更高。StandardScaler是默认选择它把每个特征变换成均值0、方差1的标准正态分布。from sklearn.preprocessing import StandardScaler scaler StandardScaler() X_scaled scaler.fit_transform(features)为什么逻辑回归和SVM必须标准化因为它们的目标函数里有距离计算或者正则化项如果某个特征的数值范围特别大它会主导损失函数模型学到的权重也会失真。树模型不受影响因为树的分裂只看特征顺序不看数值大小。所以我通常在Pipeline里统一做标准化这样不管后面用什么模型对比都公平。第三步是特征相关性检查。我一般会画一个相关性热力图重点看特征之间相关系数超过0.7的对。红葡萄酒数据里density和fixed acidity的相关系数在0.47左右不算太高但density和alcohol的负相关需要留意。如果后续用逻辑回归可以考虑去掉density或者单独做一个消融实验看看不去掉时模型权重有什么变化。import seaborn as sns import matplotlib.pyplot as plt corr_matrix df.corr() plt.figure(figsize(12, 10)) sns.heatmap(corr_matrix, annotTrue, fmt.2f, cmapcoolwarm) plt.show()这里还想分享一个实际项目的体会EDA探索性数据分析不是交差用的流程化动作而是帮你建立“模型预期”的过程。你在预处理阶段形成的对每一个特征的认知在之后看特征重要性、解释模型为什么这么预测时都会变成重要的判断依据。3. 模型选型从逻辑回归到随机森林3.1 三个模型的适用性拆解机器学习项目里最常见的纠结就是“这个数据该用什么模型”。我也不例外刚做这个项目时把所有能想到的模型都塞进去跑了一遍包括KNN、朴素贝叶斯、逻辑回归、SVM、决策树、随机森林甚至XGBoost。跑完发现真正值得深挖的其实就三个逻辑回归、SVM、随机森林。逻辑回归是当之无愧的baseline。它不是最强的模型但它是一个解释性极好、训练极快的参考线。如果连逻辑回归都能达到可接受的分数说明数据里的线性规律已经足够强不需要上复杂模型。另外逻辑回归的系数直接反映特征方向——正系数意味着这个特征值越大酒品越可能是好酒——这一点对报告总结非常有价值。SVM擅长处理特征维度适中、存在非线性边界的数据。葡萄酒数据集只有11个特征、1599条样本符合SVM的舒适区。但SVM对特征尺度极其敏感必须标准化而且核函数的选择线性核还是RBF核对结果影响很大。如果数据量大SVM训练时间长这个数据集倒不存在这个问题。随机森林是我在这个项目里的主力模型。理由有三个第一它对表格数据的非线性关系拟合能力强第二能容忍特征共线性和小规模缺失值第三自带特征重要性评估这对解释项目很有帮助。随机森林的本质是多个决策树的“投票”每棵树都用不同的随机子集训练最后综合结果所以抗过拟合能力比单棵决策树强很多。3.2 基线模型先跑通逻辑回归我把逻辑回归放在项目流程的第一步因为它的训练结果能帮我对任务难度有个快速判断。from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.pipeline import make_pipeline # 构造二分类目标quality 7 为好酒 df[good] (df[quality] 7).astype(int) X df.drop([quality, good], axis1) y df[good] # 分层抽样保证训练测试集的类别比例一致 X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, stratifyy, random_state42 ) model make_pipeline(StandardScaler(), LogisticRegression(max_iter1000)) model.fit(X_train, y_train) print(train acc:, model.score(X_train, y_train)) print(test acc:, model.score(X_test, y_test))这里最关键的细节是stratifyy也就是分层抽样。因为好酒在总样本里占比不到14%如果不分层随机切分很可能导致测试集里根本没有好酒或者训练集里好酒太少模型学不到。分层抽样能保证训练集和测试集的类别比例和总体一致这是不平衡分类任务里新手最容易忽略的一步。逻辑回归跑完一般准确率在85%左右看起来还不错对吧但这里有个陷阱如果模型把所有样本都预测成“非好酒”准确率也能到86%因为数据集里好酒本来就只有14%。所以单看accuracy是没有意义的必须看precision、recall和F1这个我在下一节会详细展开。3.3 主力模型随机森林的参数选择随机森林有四个参数值得花时间去调n_estimators树的数量、max_depth最大深度、min_samples_split节点分裂所需最小样本数、class_weight类别权重。先说原则n_estimators不是越大越好100到500之间收益最高超过500后计算量涨但效果几乎不变。max_depth如果不加限制随机森林可能会长得过深虽然随机性本身能抵御过拟合但当特征很少时比如只有11个特征深度太大仍然可能记住训练集噪声。min_samples_split设为5或10是个比较安全的起点。class_weight是关键。因为好酒的样本少如果不对少数类做额外约束随机森林会倾向于把边界上的样本都判成多数类。设置class_weightbalanced模型会根据类别频率自动调整权重让少数类样本的错误被放得更大。from sklearn.ensemble import RandomForestClassifier rf RandomForestClassifier( n_estimators300, max_depthNone, min_samples_split5, class_weightbalanced, random_state42 ) rf.fit(X_train, y_train)跑完之后建议输出一下混淆矩阵而不是只看准确率。我实测下来随机森林在测试集上准确率能到86%到90%关键是从混淆矩阵里能看清到底有多少好酒被漏掉了这比一个孤零零的准确率数字有用得多。4. 训练评估与模型对比4.1 层交叉验证别满足于一次切分只做一次train_test_split实际上有运气成分。如果切分的随机种子不好测试集恰好是比较容易或比较难的样本模型分数就会偏高或偏低。为了更稳定地评估模型我习惯在项目报告里加上交叉验证。from sklearn.model_selection import cross_val_score scores cross_val_score(rf, X_train, y_train, cv5, scoringf1) print(F1 scores:, scores) print(mean F1:, scores.mean())这里用scoringf1而不是默认的accuracy是因为我们关注少数类好酒的识别能力。5折交叉验证把训练数据切成5份每次用4份训练、1份验证轮流做5次最后取均值能有效避免单次切分的偶然性。交叉验证的另一个价值是判断模型稳定性。如果5次验证的F1分数方差很大比如一次0.8一次0.5说明模型对数据的某些子集很不稳定这往往意味着特征或样本有问题需要回退到数据探索阶段排查。如果分数稳定才有信心去调参和上线。4.2 评估指标别被准确率骗了我反复强调准确率不可靠是因为这个项目的类别分布太容易制造“虚假繁荣”。如果模型完全放弃预测好酒只把所有样本判为普通酒准确率也有86%左右。但从业务角度看这个模型毫无价值——品酒师想知道的恰恰是那14%的好酒。所以真正需要看的是这四个指标precision查准率、recall查全率、F1分数、AUC值。先把这个数据集的现实对照说清楚precision回答的问题是“模型说是好酒的那些样品真的好的比例有多高”recall回答的问题是“真正的好酒中模型找回来了多少”。两者天然矛盾精确率提高了召回率往往会下降所以用F1这个调和平均来综合衡量。from sklearn.metrics import classification_report, confusion_matrix, roc_auc_score y_pred rf.predict(X_test) print(classification_report(y_test, y_pred, target_names[普通酒, 好酒])) print(AUC:, roc_auc_score(y_test, rf.predict_proba(X_test)[:, 1]))我实测随机森林的F1大概在0.75到0.8之间AUC能达到0.9以上。AUC的含义是随机抽一个好酒样本和一个普通酒样本模型给好酒打更高分概率是0.9。这个数字用来衡量排序能力更直观也是面试里经常被追问的指标。4.3 特征重要性模型学到了什么随机森林最吸引人的地方是自带特征重要性输出importance pd.DataFrame({ feature: X_train.columns, importance: rf.feature_importances_ }).sort_values(importance, ascendingFalse) print(importance)运行结果通常显示alcohol酒精和volatile acidity挥发酸是排名靠前的两个特征。这个结论和品酒常识是吻合的酒精含量高一般意味着酒体更醇厚而挥发酸过高通常会让酒闻起来有醋味。模型在没有任何葡萄酒知识的前提下从数据中自己学到了这些规律这就是机器学习项目最有说服力的部分。不过要小心一件事特征重要性不代表因果也不代表特征独立有效。如果两个特征高度相关比如density和alcohol树模型可能在两个特征之间随机分配重要性导致单次输出不稳定。遇到这种情况可以多次训练取均值或者用permutation importance置换重要性做辅助验证。5. 常见问题与排查心得5.1 类别不平衡的三个对策这个项目里类别不平衡是绕不开的核心问题也是最值得讲给新手听的内容。好酒占比约14%如果不处理模型天然倾向于预测多数类。主流对策有三招我全部试过。第一招是调整class_weight用class_weightbalanced让少数类在损失函数中获得更高权重这是成本最低的方案。第二招是上采样少数类用imblearn库的SMOTE算法合成好酒样本让训练集类别比例接近。第三招是下采样多数类随机丢弃部分普通酒样本但会损失数据信息一般不做首选。实测下来SMOTE对随机森林的提升没有想象中大因为树模型本身对不均衡有一定免疫力。但对逻辑回归和SVM来说SMOTE或class_weight会带来明显改善。如果把三个模型放在一张表里对比这种差异会看得非常清楚。5.2 过拟合的识别与处理树类模型最容易被质疑的就是过拟合。判断方法很简单如果训练集的F1是0.95测试集只有0.7差距过大说明模型把训练集记住而不是学会了。这个时候不要急着加数据加不了先调整max_depth限制树深或者调高min_samples_split让树更难分裂到细分样本上。另外要注意随机种子。同一份数据random_state不同排名和结果可能会有小幅波动这不代表模型不稳定只能说明模型对训练划分敏感。写报告的时候最好固定random_state42并且在结果里注明方便复现。5.3 我踩过的具体问题第一次做这个项目时我把quality直接当作连续值预测用均方误差评估结果模型预测的分数全部集中在5到6之间方差很小。后来才明白这本质上是多数类均值回归效应的体现——模型发现预测“平庸”比预测“极端”损失更低所以学成了“老好人”。这也是我后来倾向二分类方案的原因。还有一次排查了很久的诡异现象模型在交叉验证里分数很高但应用到另一个批次的预测时效果暴跌。最后发现是数据分布不一致训练集来自红葡萄酒测试数据里混进了白葡萄酒样本。红葡萄酒和白葡萄酒的理化指标分布差异很大如果混合训练模型很难找到共同规律。这个教训告诉我任何预测项目先确认训练数据和应用场景的属性一致再谈模型效果。最后一个经验分享给做实验报告的同学这个项目最大的价值不是跑出一个高准确率而是能把整个机器学习流程串起来讲清楚——业务理解、数据探索、预处理、模型选择、训练调参、评估分析、结论沉淀。哪怕最后效果差一点点只要每个环节都能说清楚“为什么这么做、遇到了什么问题、怎么解决的”这就是一份能打动老师的实验报告也能成为你履历里值得讲的项目经历。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

[智能体-538]:Coze、Dify、Hermes、LangChain 四者完整对比:TaoToken 统一 Key 接入配置骨架 2026/9/29 6:57:50

[智能体-538]:Coze、Dify、Hermes、LangChain 四者完整对比:TaoToken 统一 Key 接入配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Harness 对标 Claude Code 和 Cursor:差距与优势拆解,附 TaoToken 统一 Key 配置骨架 2026/9/29 6:57:50

Harness 对标 Claude Code 和 Cursor:差距与优势拆解,附 TaoToken 统一 Key 配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Node 版本升级后 opencode 与 Claude Code 报错?用 nvm 配 TaoToken 一次修好 2026/9/29 6:57:50

Node 版本升级后 opencode 与 Claude Code 报错?用 nvm 配 TaoToken 一次修好

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
OpenAI Codex(二)——编程需求理解技术剖析与TaoToken配置实战 2026/9/29 6:57:50

OpenAI Codex(二)——编程需求理解技术剖析与TaoToken配置实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Codex 额度重置周期变化:TaoToken 统一 Key 接入 AI 编程工具的配置骨架 2026/9/29 6:57:50

Codex 额度重置周期变化:TaoToken 统一 Key 接入 AI 编程工具的配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
从Notebook到生产:AI工程化落地的完整实战指南 2026/9/29 6:57:43

从Notebook到生产:AI工程化落地的完整实战指南

做AI这几年,我最大的体会是:能跑通一个模型的人很多,能把模型稳稳当当跑上生产、持续迭代、出了问题还能快速定位的人,少之又少。市面上大多数教程都在教你怎么用PyTorch搭一个网络、怎么调loss,但很少有人告诉你&…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉