ML-For-Beginners 实战:用 Scikit-learn 逻辑回归预测南瓜颜色(二分类全流程指南)
2026/9/10 21:52:47 网站建设 项目流程

ML-For-Beginners 实战:用 Scikit-learn 逻辑回归预测南瓜颜色(二分类全流程指南)

【免费下载链接】ML-For-Beginners12 weeks, 26 lessons, 52 quizzes, classic Machine Learning for all项目地址: https://gitcode.com/GitHub_Trending/ml/ML-For-Beginners

导读

本指南基于 ML-For-Beginners 课程中“Logistic Regression”一课(2-Regression/4-Logistic/README.md),以南瓜数据集Color字段为切入点,完整演示如何用逻辑回归解决“白色还是非白色”的二分类问题。你将掌握 Seaborn 分类图与蜂群图的可视化技巧、OrdinalEncoder / OneHotEncoder / ColumnTransformer 的特征编码管线、LogisticRegression建模与train_test_split划分,以及用混淆矩阵、分类报告、ROC 曲线与 AUC 全面评估模型性能的完整方法论。

图片来源:课程正文配图,直观展示线性回归(连续值预测)与逻辑回归(类别预测)的本质差异。


一、为什么在“回归”单元讲分类:逻辑回归的本质

逻辑回归虽然名字里带“回归”,但从 Scikit-learn 官方文档的定位来看,它本质上是一种线性分类方法。课程将它与之前学过的线性回归并列讲述,只是为了教学组织的便利。两者能力边界不同:

  • 线性回归预测连续值。例如根据南瓜的产地与收获时间,估算“价格会上涨多少”。
  • 逻辑回归预测二元类别。例如“这块糖果是巧克力吗”“这种疾病会传染吗”“这位顾客会选择这个产品吗”。

二分类(Binary classification)

在本项目中,我们用南瓜数据集里的Color字段构造二分类问题:预测一个南瓜更可能是橙色(ORANGE)还是白色(WHITE)

信息图作者:Dasani Madipalli(课程原图标注)。

多分类变体:Multinomial 与 Ordinal

逻辑回归不止支持二分类,还有两种常见扩展:

  • Multinomial(多项):类别数大于两个,例如“橙色、白色、条纹色”。
  • Ordinal(有序):类别本身存在逻辑排序,例如按南瓜尺寸划分的等级(mini、sm、med、lg、xl、xxl)。

两个重要前提

  • 变量不必强相关:与“变量相关性越强效果越好”的线性回归相反,逻辑回归不要求特征之间对齐,这恰好适配南瓜数据集中相关性较弱的特征。
  • 需要大量干净数据:逻辑回归在更大数据集上表现更准确。课程明确提醒,约 1000 行的南瓜小数据集并非该任务的理想规模。

二、定义问题与准备数据

课程将问题框架为二元命题:“白色”还是“非白色”。数据集中原本还存在striped(条纹)类别,但实例极少,且在去除空值后自然消失,因此直接排除。有趣的是,白色南瓜常被戏称为“幽灵南瓜”(ghost pumpkin),所以问题也可以改写为“Ghost or Not Ghost”。

本课使用的启动笔记本位于 2-Regression/4-Logistic/notebook.ipynb,其首个代码单元通过pd.read_csv('../data/US-pumpkins.csv')加载原始数据(数据文件位于 2-Regression/data/US-pumpkins.csv),并构建full_pumpkins数据框。在此基础上,课程开始数据整理。

数据清洗:选列 + 去空值

columns_to_select = ['City Name','Package','Variety', 'Origin','Item Size', 'Color'] pumpkins = full_pumpkins.loc[:, columns_to_select] pumpkins.dropna(inplace=True)

清洗后可以随时预览新数据框:

pumpkins.info

最终保留的六列中,Color是我们要预测的标签(label),其余五列是特征(features)。


三、可视化:引入 Seaborn 分类图

本课引入新可视化库Seaborn,它构建在之前用过的 Matplotlib 之上。最直观的探索方式是使用catplotcount类型,按Variety(品种)统计Color的分布,并给两类南瓜指定配色:

import seaborn as sns palette = { 'ORANGE': 'orange', 'WHITE': 'wheat', } sns.catplot( data=pumpkins, y="Variety", hue="Color", kind="count", palette=palette, )

观察该图可以直观看出不同品种下橙色与白色南瓜的数量关系,这为后续特征选择提供了直觉依据。


四、数据预处理:特征编码与标签编码

南瓜数据集所有列都是字符串。人类对类别数据直觉友好,但机器学习算法只擅长数值,因此**编码(Encoding)**是预处理中至关重要的一步——它把类别数据无损地转换为数值数据,好的编码是构建好模型的前提。

1. 有序特征 → OrdinalEncoder

适合有序变量(ordinal),即类别存在逻辑顺序的列,例如Item Size。编码器按给定顺序把每个类别映射为一个数字:

from sklearn.preprocessing import OrdinalEncoder item_size_categories = [['sml', 'med', 'med-lge', 'lge', 'xlge', 'jbo', 'exjbo']] ordinal_features = ['Item Size'] ordinal_encoder = OrdinalEncoder(categories=item_size_categories)

注意categories参数显式指定了从小到大的完整顺序(sml → exjbo),确保编码后的数字真实反映尺寸的递增关系。

2. 名义特征 → OneHotEncoder

适合名义变量(nominal),即不存在逻辑顺序的列(本项目中除Item Size外的全部特征)。采用独热(one-hot)编码:每个类别对应一个二值列,南瓜属于该类别则为 1,否则为 0:

from sklearn.preprocessing import OneHotEncoder categorical_features = ['City Name', 'Package', 'Variety', 'Origin'] categorical_encoder = OneHotEncoder(sparse_output=False)

sparse_output=False让输出为密集矩阵(而非稀疏矩阵),便于后续转成 pandas DataFrame。

3. 用 ColumnTransformer 组装编码管线

ColumnTransformer将多个编码器合并为一步,并自动应用到各自指定的列上:

from sklearn.compose import ColumnTransformer ct = ColumnTransformer(transformers=[ ('ord', ordinal_encoder, ordinal_features), ('cat', categorical_encoder, categorical_features) ]) ct.set_output(transform='pandas') encoded_features = ct.fit_transform(pumpkins)

set_output(transform='pandas')使输出保留列名(如ord__Item Size),便于后续分析与可视化。

4. 标签编码 → LabelEncoder

标签侧使用 Scikit-learn 的LabelEncoder,把标签归一化为 0 到 n_classes-1 之间的整数(此处即 0 和 1):

from sklearn.preprocessing import LabelEncoder label_encoder = LabelEncoder() encoded_label = label_encoder.fit_transform(pumpkins['Color'])

5. 合并特征与标签

encoded_pumpkins = encoded_features.assign(Color=encoded_label)

encoded_pumpkins即后续建模使用的最终数据框。

思考题:对Item Size使用有序编码而非独热编码,优势在哪里?(提示:保留尺寸间的相对大小关系,避免维度爆炸。)


五、分析特征与标签的关系

预处理完成后,通过绘图分析特征与标签的关系,可以预估模型预测能力。这里再次使用 Seaborncatplot,以编码后的Item Size为横轴、Color为纵轴、按Variety分面绘制箱线图:

palette = { 'ORANGE': 'orange', 'WHITE': 'wheat', } pumpkins['Item Size'] = encoded_pumpkins['ord__Item Size'] g = sns.catplot( data=pumpkins, x="Item Size", y="Color", row='Variety', kind="box", orient="h", sharex=False, margin_titles=True, height=1.8, aspect=4, palette=palette, ) g.set(xlabel="Item Size", ylabel="").set(xlim=(0,6)) g.set_titles(row_template="{row_name}")

蜂群图(Swarm plot)

由于Color是二值类别,Seaborn 官方建议采用专门的可视化方式。试试蜂群图展示值的分布:

palette = { 0: 'orange', 1: 'wheat' } sns.swarmplot(x="Color", y="ord__Item Size", data=encoded_pumpkins, palette=palette)

⚠️ 注意:上述代码可能产生警告——当数据点过多时,Seaborn 难以在蜂群图中完整呈现每个点。可通过size参数调小标记尺寸缓解,但这会牺牲可读性。


六、逻辑回归的数学内核:Sigmoid 函数

逻辑回归依赖**最大似然(maximum likelihood)**与Sigmoid 函数。Sigmoid 函数的图像呈 “S” 形(又称逻辑曲线),它把任意输入值映射到 0 与 1 之间:

其中:曲线中点位于 x=0,L 是曲线的最大值,k 决定曲线陡峭程度。判定规则:若函数输出大于 0.5,则样本被归类为二分类中的 “1”;否则归类为 “0”。

这正是逻辑回归输出“概率”而非“连续值”的数学基础——模型的输出天然落在 [0,1] 区间,可直接解释为类别归属的概率。


七、构建并训练逻辑回归模型

在 Scikit-learn 中构建二分类模型非常直接。

1. 划分训练集与测试集

from sklearn.model_selection import train_test_split X = encoded_pumpkins[encoded_pumpkins.columns.difference(['Color'])] y = encoded_pumpkins['Color'] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

test_size=0.2表示 20% 数据留作测试,random_state=0固定随机种子以保证结果可复现。

2. 训练模型并输出评估报告

from sklearn.metrics import f1_score, classification_report from sklearn.linear_model import LogisticRegression model = LogisticRegression() model.fit(X_train, y_train) predictions = model.predict(X_test) print(classification_report(y_test, predictions)) print('Predicted labels: ', predictions) print('F1-score: ', f1_score(y_test, predictions))

LogisticRegression默认采用 L2 正则化与 liblinear/lbfgs 求解器,无需手动调参即可获得基线模型。

3. 模型表现

在仅约 1000 行数据的情况下,模型表现相当不错:

precision recall f1-score support 0 0.94 0.98 0.96 166 1 0.85 0.67 0.75 33 accuracy 0.92 199 macro avg 0.89 0.82 0.85 199 weighted avg 0.92 0.92 0.92 199 Predicted labels: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 0 0 0 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 1] F1-score: 0.7457627118644068

整体准确率 0.92;类别 0(非白色)的精确率/召回率均较高,类别 1(白色)召回率偏低(0.67),说明白色南瓜存在较多漏检——这正是后面混淆矩阵要深入剖析的问题。


八、用混淆矩阵深入理解模型

分类报告给出了汇总数字,而混淆矩阵(confusion matrix / error matrix)以表格形式对比真实与预测的正负例,能更直观地反映模型行为:

from sklearn.metrics import confusion_matrix confusion_matrix(y_test, predictions)

输出:

array([[162, 4], [ 11, 22]])

在 Scikit-learn 中,混淆矩阵的行(axis 0)代表真实标签列(axis 1)代表预测标签

预测 0预测 1
真实 0TNFP
真实 1FNTP

四类结果的含义(以“白色 / 非白色”为例):

  • True Negative(TN,真负例):模型预测“非白色”,实际也是“非白色”。
  • False Negative(FN,假负例):模型预测“非白色”,实际是“白色”。
  • False Positive(FP,假正例):模型预测“白色”,实际是“非白色”。
  • True Positive(TP,真正例):模型预测“白色”,实际也是“白色”。

理想状态下,我们希望 TP 与 TN 尽量多,FP 与 FN 尽量少。本例中array([[162, 4], [11, 22]])对应 TN=162、FP=4、FN=11、TP=22,即真负例数量充足,但仍存在少量假负例(白色被漏判)。

混淆矩阵与精确率、召回率的换算

前面分类报告中类别 1 的精确率为 0.85、召回率为 0.67,这两个数字正是由混淆矩阵算出来的:

Precision = tp / (tp + fp) = 22 / (22 + 4) = 0.8461538461538461 Recall = tp / (tp + fn) = 22 / (22 + 11) = 0.6666666666666666

九、分类报告指标速查表

  • Precision(精确率)= TP / (TP + FP):检索到的实例中真正相关的比例(例如:被判为白色的样本中,有多少确实为白色)。
  • Recall(召回率)= TP / (TP + FN):相关实例中被成功检索到的比例(例如:所有真实白色样本中,有多少被找出来了)。
  • F1-score = (2 × precision × recall) / (precision + recall):精确率与召回率的加权调和平均,最好为 1,最差为 0。
  • Support:每个标签在数据集中出现的次数。
  • Accuracy(准确率)= (TP + TN) / (TP + TN + FP + FN):样本中被正确预测标签的百分比。
  • Macro Avg(宏平均):对每个标签的指标取未加权平均,不考虑类别不平衡。
  • Weighted Avg(加权平均):以每个标签的 support(真实实例数)为权重计算的平均,考虑了类别不平衡。

思考题:如果你希望模型减少假负例(即尽量别漏掉白色南瓜),应该重点关注哪个指标?(提示:召回率。)


十、ROC 曲线与 AUC:模型判别能力的整体画像

最后用 ROC(Receiver Operating Characteristic,受试者工作特征)曲线对分类器做整体评估。ROC 曲线以**假正率(False Positive Rate)**为 X 轴、**真正率(True Positive Rate)**为 Y 轴,展示分类器在不同阈值下的表现;曲线越陡峭、越早越过对角线(随机猜测基线),模型判别力越强。

from sklearn.metrics import roc_curve, roc_auc_score import matplotlib import matplotlib.pyplot as plt %matplotlib inline y_scores = model.predict_proba(X_test) fpr, tpr, thresholds = roc_curve(y_test, y_scores[:,1]) fig = plt.figure(figsize=(6, 6)) plt.plot([0, 1], [0, 1], 'k--') plt.plot(fpr, tpr) plt.xlabel('False Positive Rate') plt.ylabel('True Positive Rate') plt.title('ROC Curve') plt.show()

predict_proba输出每个样本属于各类别的概率,y_scores[:,1]取类别 1(白色)的概率作为评分依据。本例中曲线初期存在少量假正例,随后迅速抬头越过对角线,表现良好:

最后用 Scikit-learn 的roc_auc_score计算曲线下面积(AUC):

auc = roc_auc_score(y_test,y_scores[:,1]) print(auc)

结果为0.9749908725812341。AUC 取值范围 0~1:完美模型的 AUC 为 1,本模型 AUC 接近 0.975,说明其排序能力“相当不错”。


十一、从 Python 到 R:同一课程的 tidymodels 实现

本课同时提供了完整的 R 语言版本(solution/R/lesson_4.Rmd,编译产物见 solution/R/lesson_4.html),便于不同技术栈的读者对照学习。R 版的流程与 Python 版一一对应,但工具链换成了 tidymodels 生态:

  • 数据清洗read_csv+clean_names()(janitor 包)+select()+drop_na(),并把color转为 factor。
  • 编码:通过recipes包的step_mutate(item_size = ordered(...))定义尺寸顺序,step_integer()做有序编码,step_dummy(one_hot = TRUE)做独热编码,再prep()+bake()提取预处理数据。
  • 建模logistic_reg()+set_engine("glm")定义模型规格,用workflow()recipe与模型捆绑,fit()训练。
  • 评估yardstick::conf_mat()生成混淆矩阵,metric_set(ppv, recall, spec, f_meas, accuracy)一次性计算多项指标,roc_curve()+roc_auc()绘制并量化 ROC 曲线。

R 版的 AUC 结果约为 0.975,与 Python 版(0.975)高度一致,可作为跨语言复现的交叉验证。课程还预告了后续如何处理不平衡数据以进一步优化分数。


十二、课后挑战与作业

课程的挑战任务鼓励动手实验:寻找一个适合逻辑回归分析的数据集,独立构建模型并总结学习收获。

配套作业见 2-Regression/4-Logistic/assignment.md:课程中只使用了南瓜数据的子集,作业要求回到原始数据(2-Regression/data/US-pumpkins.csv),清洗并标准化全部数据后重新构建逻辑回归模型,并提交一份模型解释充分、性能良好的 notebook。评分标准分三档:模型解释清晰且性能优秀为“Exemplary”,性能勉强达标为“Adequate”,性能不佳或缺失为“Needs Improvement”。


结语

至此,你已完整走通了“数据清洗 → 编码 → 可视化探索 → 建模 → 混淆矩阵 → 分类报告 → ROC/AUC”的逻辑回归全流程,也理解了它为何被归入线性模型家族却承担分类任务。后续课程将进入真正的分类算法专题,并学习如何通过迭代(如处理类别不平衡)进一步提升模型分数。

【免费下载链接】ML-For-Beginners12 weeks, 26 lessons, 52 quizzes, classic Machine Learning for all项目地址: https://gitcode.com/GitHub_Trending/ml/ML-For-Beginners

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询