首页
/ ML-For-Beginners 回归实战指南:用 Scikit-learn 对 Linnerud 数据集做单变量回归并绘图

ML-For-Beginners 回归实战指南:用 Scikit-learn 对 Linnerud 数据集做单变量回归并绘图

2026-09-05 22:50:00作者:舒璇辛Bertina

本篇技术指南围绕 ML-For-Beginners 课程「回归(Regression)」模块第 1 课的工具类作业 assignment.md 展开:以 Scikit-learn 内置的 Linnerud 数据集为对象,完整演示如何创建回归模型并绘制"腰围 vs 仰卧起坐次数"等特征与生理指标之间的关系图。读完后,你可以独立复现课程作业的全部技术步骤,掌握数据集加载、训练/测试集划分、线性回归拟合、预测与可视化的标准工作流,并能将该流程推广到数据集中的所有特征-目标组合。

作业原文与考核标准

在动手之前,先完整理解作业要求。该作业位于 2-Regression/1-Tools/assignment.md,标题为 "Regression with Scikit-learn",原文要求如下:

查看 Scikit-learn 中的 Linnerud 数据集。该数据集包含多个 target(目标变量):'It consists of three exercise (data) and three physiological (target) variables collected from twenty middle-aged men in a fitness club'(它由 20 名健身俱乐部中年男性的 3 个运动类数据变量和 3 个生理类目标变量组成)。

用你自己的语言,描述如何创建一个回归模型,绘制腰围(waistline)与完成的仰卧起坐数量(situps)之间的关系。对该数据集中的其他数据点做同样的事情。

作业的评分标准(Rubric)原文为:

Criteria Exemplary(优秀) Adequate(合格) Needs Improvement(待改进)
Submit a descriptive paragraph(提交一段描述) Well-written paragraph is submitted(提交了撰写良好的段落) A few sentences are submitted(只提交了几句话) No description is supplied(未提供描述)

由此可见,作业考核的核心产出是一段你自己撰写的描述性文字,说明如何为每一组"运动量-生理指标"关系建立回归模型并绘图。下面从数据、代码两个层面,把这段话"写出来、跑出来"。

课程背景:本作业在回归模块中的位置

该作业是 2-Regression/1-Tools/README.md 所授"工具与上手"一课的课后练习。这一课的目标是:

  • 配置本地机器学习开发环境(Python、虚拟环境、Visual Studio Code);
  • 使用 Jupyter Notebook(.ipynb 文件)进行交互式建模;
  • 安装并上手 Scikit-learn;
  • 通过动手练习完成第一个线性回归实验(课程以内置 diabetes 数据集为例,完成了 BMI 与疾病进展指标的回归绘图)。

课程提供的练习骨架是 2-Regression/1-Tools/notebook.ipynb(空白笔记本),参考答案见 solution/notebook.ipynb。本作业则把同样的工作流迁移到另一个更小的内置数据集 Linnerud 上——样本更少、目标变量有多个,因此对"多目标回归"的表述要求更高。

Diabetes 数据集 BMI 与疾病进展的回归散点图,蓝色直线为模型预测结果

上图是课程主实验(diabetes 数据集,BMI 对疾病进展)的运行结果截图,出自 README 中 "your first Scikit-learn notebook" 练习:黑色散点为测试集数据,蓝色粗线为 LinearRegression 模型对测试集输入的预测值连线。Linnerud 作业的绘图逻辑与此完全一致,只是数据换成 20 名受试者的运动与生理指标。

Linnerud 数据集:结构与 Scikit-learn 加载方式

Scikit-learn 提供 sklearn.datasets.load_linnerud() 加载该数据集。根据作业引用与 Scikit-learn 官方文档的说明,其结构为:

  • 样本量:20 个样本(20 名健身俱乐部的中年男性);
  • 特征(data,3 列):3 个运动类变量——仰卧起坐次数(situps)、纵跳/跳跃(jumps)、折返跑(quests);
  • 目标(target,3 列):3 个生理类变量——腰围(waist,英寸)、脉搏(pulses,次/分钟)、胆固醇(cholesterol,mg/dl)。

加载代码:

import matplotlib.pyplot as plt
from sklearn import datasets, linear_model, model_selection

linnerud = datasets.load_linnerud()
X = linnerud.data      # 形状 (20, 3):situps, quests, jumps
y = linnerud.target    # 形状 (20, 3):waist, pulses, cholesterol

print(X.shape)   # (20, 3)
print(y.shape)   # (20, 3)

与课程主实验中 load_diabetes(return_X_y=True) 返回二维数值矩阵不同,Linnerud 的 target 本身就是一组并列的 3 个回归目标。这正是作业要求"描述如何对每一个数据点组合建模"的原因:你需要为 3 个运动特征 × 3 个生理目标组成的多组关系,分别建立单变量回归模型。

核心实操:绘制"腰围 vs 仰卧起坐"的回归关系

下面按照课程 solution 笔记本 中演示的标准五步(加载 → 拆分 → 拟合 → 预测 → 绘图)实现作业要求的主图。

1. 选出腰围与仰卧起坐两列

腰围是 target 的第 0 列,仰卧起坐是 data 的第 0 列。注意 Scikit-learn 的回归器要求输入 X 为二维数组,因此需要用 reshape(-1, 1) 把一维向量还原为列向量(课程 README 中对 diabetes 数据集选取第 3 列时使用了同样的技巧:X = X[:, 2]X.reshape((-1,1))):

X_situps = linnerud.data[:, 0].reshape(-1, 1)   # (20, 1)
y_waist  = linnerud.target[:, 0]                # (20,)

2. 划分训练集与测试集

沿用课程中的 model_selection.train_test_split(参考 solution 笔记本中的调用 train_test_split(X, y, test_size=0.33)):

X_train, X_test, y_train, y_test = model_selection.train_test_split(
    X_situps, y_waist, test_size=0.33)

从源码用法看,test_size=0.33 表示约三分之一样本划入测试集。Linnerud 只有 20 个样本,划出 33% 后测试集约 7 个样本、训练集约 13 个样本——样本极少,这直接决定了该模型只能用于教学演示层面的关系观察,而非严谨的统计推断(这一点建议在作业描述中如实写出)。

3. 拟合线性回归模型

model = linear_model.LinearRegression()
model.fit(X_train, y_train)

model.fit() 是 Scikit-learn(以及 TensorFlow 等库)通用的训练入口;solution 笔记本中执行该调用后返回的估计器表示即为 LinearRegression()

4. 对测试集做预测

y_pred = model.predict(X_test)

5. 散点 + 预测线绘图

完全复用课程 diabetes 实验的绘图模式:

plt.scatter(X_test, y_test, color='black')
plt.plot(X_test, y_pred, color='blue', linewidth=3)
plt.xlabel('Sit-ups (number)')
plt.ylabel('Waist (inches)')
plt.title('Linnerud: Waist vs. Sit-ups')
plt.show()

黑色散点是测试集真实数据,蓝色直线是模型对同一批 X 的预测值连成的拟合线。作业要求你用自己的语言解释这张图:例如"直线穿过了散点云,给定一个新样本的仰卧起坐次数,把它的横坐标代入这条直线,就能读出模型预测的腰围数值"。

推广到其余数据点:覆盖全部 3 × 3 组合

作业的后半句是"对该数据集中的其他数据点做同样的事情",即还要覆盖 quests、jumps 与 pulses、cholesterol 等组合。可以用双重循环把上述流程推广到全部组合:

feature_names = ['situps', 'quests', 'jumps']
target_names  = ['waist', 'pulses', 'cholesterol']

for fi, fname in enumerate(feature_names):
    for ti, tname in enumerate(target_names):
        X_f = linnerud.data[:, fi].reshape(-1, 1)
        y_t = linnerud.target[:, ti]

        X_train, X_test, y_train, y_test = model_selection.train_test_split(
            X_f, y_t, test_size=0.33)

        model = linear_model.LinearRegression()
        model.fit(X_train, y_train)
        y_pred = model.predict(X_test)

        plt.figure()
        plt.scatter(X_test, y_test, color='black')
        plt.plot(X_test, y_pred, color='blue', linewidth=3)
        plt.xlabel(fname)
        plt.ylabel(tname)
        plt.title(f'Linnerud: {tname} vs. {fname}')
        plt.show()

对每一组,作业描述段落中应说明三件事:

  1. 选列方式data[:, i] 取第 i 个运动特征、target[:, j] 取第 j 个生理目标,并用 reshape(-1, 1) 保证二维输入;
  2. 建模流程train_test_splittest_size=0.33)→ LinearRegression().fit(X_train, y_train)predict(X_test)plt.scatter + plt.plot
  3. 结果解读:直线斜率方向(正相关/负相关)反映该运动量与生理指标的直观关系,但 20 个样本、约 7 个测试点意味着拟合线对单点波动敏感,结论只宜作定性观察。

如果你愿意多走一步,LinearRegression 拟合后还可以读取 model.coef_model.intercept_ 属性,把每组关系的斜率与截距写进描述段落,让"用自己的语言描述"有具体数字支撑(注意:不要在作业中虚构未运行的数值,以实际运行为准)。

环境要求与运行前提

  • 需要 Python 3+,并已安装 Scikit-learn、matplotlib(课程 README 建议在虚拟环境中安装,M1 Mac 有专门的安装说明指引);
  • 作业在本课程文件夹的 notebook.ipynb 中完成,用 Visual Studio Code 打开后 Jupyter 内核会自动启动,代码块点"播放"图标即可执行,md 图标可添加 markdown 说明;
  • 课程同时提供 R 语言的对照版本,见 solution/R/lesson_1.html,可作为跨语言对照阅读。

自检清单:提交作业前的核对

  1. 是否用一句话说明了 Linnerud 数据集的来源与结构(20 名中年男性、3 运动特征、3 生理目标);
  2. 是否完整给出"选列 → 拆分(test_size=0.33)→ fitpredict → 散点+直线绘图"的代码流程,并至少展示了 waist vs situps 一张图;
  3. 是否用循环或分步说明覆盖了其余特征-目标组合,而不是只画了一张图;
  4. 描述段落是否达到 Rubric 中 "Exemplary" 档(一段撰写良好的完整描述,而非零散几句话),并如实注明小样本下的解释边界;
  5. 对照课程 diabetes 实验solution 笔记本 确认 fitpredicttrain_test_split 的调用方式与课程一致。

完成以上步骤,即同时满足了作业的两层要求:可运行的回归建模代码,以及一段能讲清"如何为 Linnerud 数据集每一组关系创建回归模型并绘图"的描述性文字。

登录后查看全文
热门项目推荐
相关项目推荐