ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

机器学习线性回归身高预测:从原理到实战的完整指南

2026/9/23 16:28:38 拓冰建站 浏览量
机器学习线性回归身高预测:从原理到实战的完整指南 简介这份资源面向机器学习入门者与需要掌握回归建模的开发者围绕线性回归在身高预测中的完整应用展开。包内共2个文件包含1个xlsx数据表与1个py脚本压缩包约80KB体量轻便适合快速上手练习。数据表用于记录身高、年龄、性别、体重等影响因素脚本则借助scikit-learn的LinearRegression类完成数据预处理、模型训练、评估与预测全流程并涉及MSE、RMSE、R²等指标的使用。读者可据此理解线性模型如何描述变量间依赖关系掌握分类变量编码、训练测试集划分等关键环节同时也能延伸思考多项式回归、岭回归及集成方法在复杂场景下的改进空间。目前已有114人学习适合作为课程实验或自学练手素材。1. 身高预测这件事为什么线性回归是最先该跑通的模型很多人第一次接触机器学习都是从「用身高预测体重」或者「用父母身高预测孩子身高」这类题目入门的。机器学习线性回归身高预测这个组合之所以经典是因为它把机器学习的完整流程压缩到了一个足够小、又能跑通的问题里有连续型输入特征有连续型输出目标有明确的误差度量还有可解释的参数含义。你不需要 GPU不需要大数据集一台普通笔记本就能把从数据构造到模型评估的全链路走一遍。这篇文章面向两类人一类是刚学完线性回归公式、但不知道代码怎么落地的新手另一类是想拿身高预测当教学案例或项目原型的从业者。我会把数据构造、模型训练、多项式扩展、正则化、评估指标、常见翻车点全部拆开讲每一步都给可复现的代码和参数说明。读完你应该能自己搭出一个预测误差在合理范围内的身高预测模型并且知道什么时候该换更复杂的模型。2. 从散点到模型身高预测的数据构造与线性回归原理2.1 身高预测问题到底在拟合什么先把问题定义清楚。假设我们有一组样本每个样本包含若干特征和一个目标值。身高预测最常见的设定有两种一种是用父母身高预测子女身高特征是两个连续变量另一种是用年龄、性别、营养指标等预测儿童身高特征更多。不管哪种线性回归要做的就是找到一组权重 w 和偏置 b使得预测值 ŷ w·x b 尽可能接近真实值 y。这里的关键假设是目标值和特征之间存在近似线性关系。如果真实关系是强非线性的比如身高随年龄先快后慢地增长直接用一条直线去拟合就会系统性偏差。所以第一步不是写代码而是画散点图。我一般会先用 matplotlib 把特征和目标的关系画出来肉眼判断线性假设是否成立。这一步花两分钟能省掉后面半小时的调参。从数学上看线性回归的求解有两种主流方式正规方程和梯度下降。正规方程直接解 w (XᵀX)⁻¹Xᵀy一步到位但要求矩阵可逆且特征维度不能太高。梯度下降是迭代逼近适合大样本和高维场景。身高预测这种小规模问题两种都能用但正规方程更容易验证结果对不对。2.2 用 numpy 手写一版最小可跑通的线性回归在调库之前我建议先用 numpy 手写一遍。这样你对每个参数的形状、每次更新的方向都会有直觉。下面是一个用正规方程求解的最小实现import numpy as np # 构造模拟数据父亲身高、母亲身高 - 子女身高 np.random.seed(42) n 200 father np.random.normal(172, 6, n) mother np.random.normal(160, 5, n) # 真实关系子女身高约等于父母均值加一点噪声 child 0.5 * father 0.4 * mother 20 np.random.normal(0, 3, n) # 组装特征矩阵加一列全1用于偏置 X np.column_stack([father, mother, np.ones(n)]) y child # 正规方程求解 w np.linalg.inv(X.T X) X.T y print(权重:, w) # 预测并计算均方误差 y_pred X w mse np.mean((y - y_pred) ** 2) print(MSE:, mse)这段代码的逻辑很直接先把父母身高拼成特征矩阵再补一列全 1 作为偏置项然后用正规方程公式一次性解出权重。参数说明上np.random.seed(42)保证每次运行数据一致方便你对照结果np.column_stack把三列拼在一起顺序要和后面权重的解读对应np.linalg.inv求逆如果矩阵接近奇异会报错这时候要么去掉冗余特征要么改用np.linalg.pinv求伪逆。跑完之后你会得到三个权重前两个分别对应父亲和母亲身高的贡献第三个是偏置。如果数据构造合理权重应该接近 0.5、0.4、20 附近。这就是线性回归可解释性的体现每个权重告诉你该特征每变化一个单位预测值平均变化多少。2.3 用 scikit-learn 落地标准流程手写版帮你理解原理实际项目里我一般直接用 scikit-learn因为它的接口统一、评估工具齐全、后续换模型也方便。下面是一个完整的训练和评估流程from sklearn.linear_model import LinearRegression from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error, r2_score import numpy as np # 沿用上面的 father、mother、child 数据 X np.column_stack([father, mother]) y child # 划分训练集和测试集 X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42 ) # 训练模型 model LinearRegression() model.fit(X_train, y_train) # 预测与评估 y_pred model.predict(X_test) print(系数:, model.coef_) print(截距:, model.intercept_) print(MSE:, mean_squared_error(y_test, y_pred)) print(R2:, r2_score(y_test, y_pred))这里有几个参数值得注意。test_size0.2表示留出 20% 做测试身高预测这种小数据集一般用 8:2 或 7:3不要用 9:1否则测试集太小评估结果波动大。random_state42固定划分保证你复现时结果一致。r2_score衡量模型解释了目标值多少方差越接近 1 越好但身高预测里能到 0.7 以上就算不错了因为身高受遗传、营养、环境等多因素影响父母身高只是其中一部分。如果你发现 R2 很低先别急着换模型检查三件事特征是否漏了关键变量、数据里有没有异常值、线性假设是否成立。这三件事比调模型参数重要得多。3. 多项式回归与正则化当直线不够用时怎么加料3.1 身高和年龄的关系为什么需要多项式用父母身高预测子女身高线性假设基本够用。但如果你做的是儿童身高预测特征里包含年龄线性模型就会翻车。因为身高随年龄的增长是典型的 S 型曲线婴儿期长得快儿童期平稳青春期又加速成年后停止。用一条直线去拟合低龄段会高估青春期中段会低估。这时候常见做法是加多项式特征。比如把年龄这一列扩展成年龄、年龄²、年龄³让模型自己去拟合曲线的不同弯曲程度。scikit-learn 提供了PolynomialFeatures来做这件事from sklearn.preprocessing import PolynomialFeatures from sklearn.pipeline import make_pipeline from sklearn.linear_model import LinearRegression # 假设 age 是年龄特征height 是身高目标 age np.random.uniform(2, 18, 300) height 75 12 * age - 0.4 * age ** 2 np.random.normal(0, 2, 300) X age.reshape(-1, 1) y height # 构造二次多项式并训练 poly_model make_pipeline( PolynomialFeatures(degree2, include_biasFalse), LinearRegression() ) poly_model.fit(X, y) print(R2:, poly_model.score(X, y))degree2表示扩展到二次项include_biasFalse是因为 LinearRegression 自己会处理截距不需要多项式再生成一列全 1。用make_pipeline把两步串起来预测时不用手动做特征转换少一个出错环节。但多项式次数不是越高越好。次数太高会过拟合训练集 R2 很漂亮测试集一塌糊涂。我一般会从 2 次开始试画学习曲线看训练和验证误差的差距差距大就降次数或者加正则化。3.2 岭回归和 Lasso 在身高预测里的选择正则化是解决过拟合的标准手段。岭回归在损失函数里加 L2 惩罚让权重整体变小但不为零Lasso 加 L1 惩罚会把不重要的特征权重压到零相当于自动做特征选择。身高预测里如果你扩展了很多多项式项和交互项Lasso 能帮你筛掉没用的项岭回归则更适合所有特征都有点用、但需要控制幅度的情况。from sklearn.linear_model import Ridge, Lasso from sklearn.preprocessing import StandardScaler # 多项式扩展后用岭回归 ridge_model make_pipeline( PolynomialFeatures(degree3, include_biasFalse), StandardScaler(), Ridge(alpha1.0) ) ridge_model.fit(X_train, y_train) print(Ridge R2:, ridge_model.score(X_test, y_test)) # Lasso 版本 lasso_model make_pipeline( PolynomialFeatures(degree3, include_biasFalse), StandardScaler(), Lasso(alpha0.1, max_iter10000) ) lasso_model.fit(X_train, y_train) print(Lasso R2:, lasso_model.score(X_test, y_test))alpha是正则化强度越大惩罚越重。岭回归的 alpha 一般从 0.1 到 10 之间调Lasso 的 alpha 更敏感通常从 0.001 到 1 之间试。StandardScaler不能省因为多项式项的数值范围差异很大不标准化的话正则化会偏向惩罚数值大的项结果不可信。Lasso 还要设max_iter默认迭代次数在特征多时可能不够会报收敛警告。选岭回归还是 Lasso我的经验是如果你不确定哪些特征有用先用 Lasso 看它把哪些权重压成零再用岭回归做最终模型。两者都试一遍对比测试集 R2花不了多少时间。3.3 特征标准化与交互项别让量纲毁了模型身高预测里如果特征只有父母身高量纲一致不标准化问题不大。但一旦加入年龄、体重、营养指数量纲差异就出来了。体重可能是几十年龄是个位数不标准化的话梯度下降会震荡正规方程虽然不受影响但正则化会失真。标准化的做法是减均值除标准差scikit-learn 的StandardScaler默认就是这么干的。注意标准化要在训练集上 fit然后 transform 测试集不能拿全体数据一起 fit否则测试集信息泄漏到训练过程评估结果会偏乐观。交互项是另一个容易被忽略的点。父母身高对子女身高的影响可能不是简单相加而是有交互父亲高且母亲高时子女可能比单纯相加预测的更高。加交互项可以让模型捕捉这种协同效应。PolynomialFeatures的interaction_onlyTrue参数可以只生成交互项不生成平方项适合你想控制特征数量的时候。4. 评估与调参身高预测模型到底准不准4.1 MSE、MAE、R2 三个指标各看什么训练完模型第一个问题就是「准不准」。回归问题常用的三个指标是 MSE、MAE 和 R2。MSE 是均方误差对大误差惩罚重适合你特别在意大偏差的场景MAE 是平均绝对误差单位跟目标值一致身高预测里 MAE 等于 3 就表示平均预测偏差 3 厘米直观好懂R2 是决定系数衡量模型比「直接猜平均值」好多少。我一般三个都看。MAE 用来跟业务方沟通比如「平均误差 2.8 厘米」MSE 用来对比不同模型因为它对误差更敏感R2 用来判断模型是否值得上线低于 0.5 基本说明特征不够或关系非线性。注意 R2 在测试集上可能为负表示模型比猜平均值还差这时候别怀疑指标直接回去检查数据和特征。4.2 交叉验证怎么做才不白跑单次划分训练测试集有个问题划分方式不同评估结果可能差很多。交叉验证能缓解这个问题。K 折交叉验证把数据分成 K 份每次拿 K-1 份训练、1 份验证循环 K 次取平均。身高预测这种小数据集我一般用 5 折或 10 折。from sklearn.model_selection import cross_val_score scores cross_val_score( ridge_model, X, y, cv5, scoringneg_mean_absolute_error ) print(MAE 各折:, -scores) print(平均 MAE:, -scores.mean())scoringneg_mean_absolute_error是因为 scikit-learn 的交叉验证默认分数越大越好而 MAE 越小越好所以取负。打印时再取负还原。cv5表示 5 折数据量少于 200 时用 5 折多于 1000 可以用 10 折。如果各折分数波动很大说明数据分布不均匀或者样本太少这时候要考虑增加数据或检查异常值。4.3 学习曲线告诉你该加数据还是加特征调参调到一定程度你会遇到瓶颈不管怎么调 alpha 或 degree测试集 R2 就是上不去。这时候该判断是数据不够还是特征不够。学习曲线能帮你做这个判断横轴是训练样本数纵轴是误差画两条线一条训练误差一条验证误差。如果两条线都高且接近说明欠拟合模型太简单该加特征或提高多项式次数。如果训练误差低、验证误差高且差距大说明过拟合该加数据或加正则化。如果验证误差还在下降但没到底说明加数据还有用。这个判断比盲目调参有效得多我一般会在项目初期就跑一次学习曲线确定后续投入方向。5. 避坑与排查身高预测里最容易翻车的五个地方5.1 现象模型在训练集上 R2 0.95测试集只有 0.3原因过拟合。多项式次数太高或者特征太多而样本太少模型把训练集的噪声也学进去了。解决先降多项式次数从 3 降到 2 或 1再加正则化岭回归 alpha 从 1 开始往上调最后检查样本量特征数是样本数的十分之一以下比较安全超了就减特征或加数据。5.2 现象预测出来的身高出现负数或者 250 以上原因特征量纲没统一或者测试集里有训练集没见过的极端值模型外推到了不合理区域。解决加StandardScaler做标准化检查训练集和测试集的特征分布用箱线图看有没有离群点对预测结果做业务裁剪比如身高限制在 100 到 220 之间超出就标记为异常而不是直接输出。5.3 现象交叉验证各折分数差距很大从 0.2 到 0.8原因数据划分不均匀某些折里集中了特殊样本或者样本量太小随机波动大。解决改用分层划分如果是分类问题用StratifiedKFold回归问题可以按目标值分箱后再分层增加样本量检查是否有重复样本或数据泄漏比如同一个人的多条记录被分到了不同折。5.4 现象Lasso 把所有权重都压成零了原因alpha 太大惩罚过重模型退化成只剩截距。解决减小 alpha从 0.001 开始试先做标准化否则量纲大的特征会被优先惩罚检查特征之间是否高度相关共线性严重时 Lasso 会随机保留一个而压掉其他这时候改用岭回归更稳。5.5 现象训练时没有报错但预测结果和手算对不上原因特征顺序搞错了。训练时特征矩阵的列顺序是 [父亲, 母亲]预测时传成了 [母亲, 父亲]模型照常输出但结果是错的。解决用 DataFrame 而不是裸 numpy 数组来管理特征列名跟着数据走或者在预测前打印model.feature_names_in_确认顺序把特征组装和预测封装成一个函数避免手动拼列。6. 把身高预测模型用起来从脚本到可复用的预测函数前面讲的都是训练和评估但实际用的时候你需要的是一个输入父母身高、输出预测身高的函数而不是每次重新跑训练脚本。我一般会把训练好的模型和标准化器一起保存然后写一个干净的预测接口。import joblib # 保存模型和标准化器 joblib.dump(ridge_model, height_model.pkl) # 加载并预测 def predict_height(father_cm, mother_cm): model joblib.load(height_model.pkl) X_new np.array([[father_cm, mother_cm]]) return model.predict(X_new)[0] print(predict_height(178, 165))joblib比 pickle 更适合保存 numpy 数组多的模型速度快、文件小。预测函数里把加载模型放在函数内部是为了演示实际服务里应该只加载一次常驻内存。输入参数用厘米输出也是厘米单位统一避免调用方混淆。如果你想进一步提升精度可以试三个方向一是加特征比如祖父母身高、出生体重、青春期启动年龄二是换模型梯度提升树或随机森林在表格数据上通常比线性回归强但可解释性下降三是做分性别建模男女性身高增长曲线不同分开训练往往比混在一起效果好。不过在做这些之前先把线性回归的基线跑稳知道基线在哪才知道复杂模型带来的提升值不值得。我自己在这个问题上踩过最深的坑是早期拿到数据直接上模型没画散点图结果特征和目标明显是曲线关系线性回归怎么调 R2 都上不去白白花了一下午调参。后来养成习惯任何回归任务先画图两分钟的事能省几小时。希望帮到你。本文还有配套的精品资源点击获取