最小二乘拟合从入门到实战:十个典型场景与踩坑指南
2026/8/31 22:22:29 网站建设 项目流程

简介:本资源是一套面向本科及以上层次学习者与工程实践者的MATLAB最小二乘拟合实战案例集,聚焦函数建模、参数估计与曲线拟合核心问题,适用于数值分析、数据处理、信号建模及科研实验等场景。压缩包共含完整可运行代码、配套实测数据文件及详细中文注释,涵盖线性与非线性模型的10类典型拟合任务(如多项式、指数、对数、三角函数等公式拟合),结构清晰、模块独立,便于理解原理、调试验证与二次扩展。资源为RAR格式,总大小351.99MB,主要包含.m源码文件、.mat数据文件及说明文档,所有案例均通过MATLAB R2018a及以上版本实测。目前已有734人下载学习,提供私信答疑支持,并可根据具体需求定制创新改进或适配新模型,是掌握最小二乘法工程实现的高实用性教学与开发参考包。 最近我在整理实验室的数据时又翻出最小二乘拟合这套老工具,发现它真的是被低估了。给新人培训的时候,我让大家说说对最小二乘拟合的理解,十个人里有九个回答是“画一条直线”。可实际上,传感器标定、光谱峰面积计算、房价影响因素分析、设备校准曲线……这些都是最小二乘拟合的变体。它不是一个算法,而是一整套从数据里提炼规律的思想框架。

这篇文章我想换个讲法:不堆推导,直接给你十个我实际处理过或者日常工作中非常典型的案例。从直线到曲线,从普通最小二乘到加权、非线性、鲁棒拟合,每个案例我都会给出具体数据、计算思路和踩坑记录。不管你是做科研数据处理、工程测量,还是商业数据分析,这十个案例基本覆盖了你日常能遇到的大部分拟合场景,可以直接对照着手上的数据去套。

1. 为什么需要十种案例:最小二乘不是一种“算法”

先说清楚一个认知:最小二乘拟合的核心思想其实只有一个——找到一组参数,让模型预测值和实际观测值之间的误差平方和最小。平方这个操作有两个实实在在的好处:一是避免正负误差相互抵消,二是对大误差施加更重的惩罚,让结果更倾向于照顾那些偏离较多的点。

但思想简单,落地千变万化。同样是“最小化误差平方和”,直线拟合有解析解,多项式拟合也能直接算,可一旦碰到指数函数、高斯峰形、正弦周期,问题就变成非线性优化,得靠迭代求解。而这还没完,如果你的数据点有的可信、有的不可信,那就得加权;如果数据里混入几个异常值,普通最小二乘就会被严重带偏。这些不是同一个问题,却都叫“最小二乘拟合”。

所以我才说要看案例。只有把各种场景都见一遍,你才能形成一种直觉:拿到数据后,第一步不是套公式,而是先判断这组数据适合用哪一类拟合。

下面这张表是我对十个案例的总体梳理:

案例模型形式典型应用场景最容易踩的坑
一、线性拟合y = kx + b身高体重关系、简单趋势分析盲目外推、忽略残差结构
二、多项式拟合y = ax² + bx + c温度曲线、非单调趋势阶数过高导致过拟合
三、指数拟合y = A·e^(-t/τ)电容放电、放射性衰变线性化后误差结构被改变
四、幂律拟合y = a·x^b文件大小分布、排名规模关系双对数直线掩盖原始误差
五、多元线性回归y = β0 + β1x1 + β2x2房价、销量多因素分析自变量共线性导致系数失真
六、加权最小二乘min Σ wᵢ(yᵢ - ŷᵢ)²不等精度测量数据不会估计权重σᵢ
七、高斯峰拟合y = A·exp(-(x-μ)²/2σ²) + C光谱峰、色谱峰分析初值敏感、约束不足
八、正弦周期拟合y = A·sin(ωt + φ) + C昼夜温度、季节波动频率未知时参数全乱
九、鲁棒拟合Huber、RANSAC传感器异常值、脏数据一个离群点毁掉整条直线
十、标定与反演仪器响应曲线压力、温度传感器标定忽略自变量误差、正反拟合混用

接下来一个一个拆。

2. 案例一:线性拟合也可以充满陷阱

2.1 我先给你看一组原始数据

假设你拿到一组学生身高和体重的统计数据:

身高(cm)160165170175180
体重(kg)5562687279

看起来身高越高体重越大,是不是直接画一条直线就行?对,模型就是 y = kx + b,其中 x 是身高,y 是体重。目标函数是:

min Σᵢ (yᵢ - kxᵢ - b)²

这里的关键在于“为什么最小二乘能求出 k 和 b”。思路很简单:把目标函数看成关于 k 和 b 的二元二次函数,它是个开口向上的“碗”,最低点处偏导数为零,于是得到两个正规方程:

∂S/∂k = -2Σ xᵢ(yᵢ - kxᵢ - b) = 0 ∂S/∂b = -2Σ (yᵢ - kxᵢ - b) = 0

解这个二元一次方程组,得到最常用的公式:

k = Σ(xᵢ - x̄)(yᵢ - ȳ) / Σ(xᵢ - x̄)²,b = ȳ - kx̄

2.2 手算一遍和一个重要的检查

拿上面的数据验证。x̄ = 170,ȳ = 67.2。分母是各身高减去均值后的平方和:(−10)² + (−5)² + 0² + 5² + 10² = 250。分子是身高偏差乘体重偏差:(−10)(−12.2) + (−5)(−5.2) + 0(0.8) + 5(4.8) + 10(11.8) = 290。因此 k = 290 / 250 = 1.16,b = 67.2 − 1.16×170 = −130。

得到的模型是:体重 = 1.16×身高 − 130。用 Python 一行也能做出来:

import numpy as np x = np.array([160, 165, 170, 175, 180]) y = np.array([55, 62, 68, 72, 79]) k, b = np.polyfit(x, y, 1) print(k, b) # 1.1599999999999997 -129.99999999999994

但算出斜率不等于完事。真正专业的人会紧接着算决定系数 R² 和残差,判断这 1.16 的斜率到底可不可信。把拟合值代回原数据,预测值分别是 55.6、61.4、67.2、73、78.8,残差是 −0.6、0.6、0.8、−1、0.2,残差平方和约 2.4;总平方和约 338.8,R² = 1 − 2.4/338.8 ≈ 0.993。这个结果说明直线解释了 99.3% 的波动,拟合质量非常高。

2.3 这个案例背后的“坑”

很多人到这里就停了,但我想多提醒一句:线性拟合的系数再漂亮,也不代表两个变量之间真的存在线性因果关系。身高和体重只在某个区间内近似线性,如果你拿这条直线去预测一个 220 cm 的人,得到的体重是 125 kg,显然不符合实际。最小二乘拟合只是“在给定模型和数据下求最优参数”,它不会告诉你模型本身是不是正确。

所以线性拟合后,务必画残差图。如果残差随 x 呈喇叭形或弯曲状,说明这组数据根本不适合直线,需要换后面的多项式或非线性模型。

3. 案例二:多项式拟合不是次数越高越好

3.1 数据的形状决定了“次方”

再看一个场景:你在户外放了一个温度记录仪,每两小时记录一次气温:

时间(h)8910111213141516
温度(℃)17.820.523.125.226.827.627.526.424.3

把点画出来,显然不是直线,而是一条先升后降的抛物线。这时用二次多项式 y = ax² + bx + c 就很自然。在 Python 里依然是一句话:

coeff = np.polyfit(x, y, 2) print(coeff) # [-0.23 6.12 -13.6] 大约

这组结果代表温度在 13 点前后达到峰值,大约 27.6℃,和观测一致。

3.2 阶数越高的教训

很多新手看到二次能拟合得很好,就想试三次、四次甚至八次是不是“更准”。这是多项式拟合里最容易翻车的点。

以这组 9 个数据点为例,如果用 8 次多项式去拟合,模型可以做到残差几乎为零,但它会像蛇一样在数据点之间剧烈震荡,在端点附近甚至会出现完全不符合物理的“大弯”。这就是经典过拟合,也就是数值分析里常说的龙格现象。拟合本身不是目的,拟合出数据背后的趋势才是目的。

我的经验是:没有物理依据时,多项式阶数不要超过三次,超过四次要非常谨慎。每加一阶,你就给模型多一个自由弯曲的机会,而数据往往只有一个真实趋势。“模型更复杂”不代表“模型更正确”,它只是更会钻空子。

3.3 残差分析代替盲目加阶

判断多项式阶数够不够,不看拟合的 R²,看残差结构。做完二次拟合后,把残差按时间顺序画出来,如果残差大致随机分布在零附近,说明二次已经吃掉了主要趋势;如果残差还有明显的弧线形状,那就说明确实需要加三次项。用这个标准去判断,比单纯比较 R² 从 0.98 涨到 0.99 靠谱得多。

4. 案例三:指数拟合——线性化的诱惑与代价

4.1 电容放电的测量数据

做电路实验时,电容通过电阻放电,电压随时间的关系是指数衰减:v(t) = V₀·e^(−t/τ)。手头有一组实测数据:

时间 t(s)00.51.01.52.02.53.03.54.0
电压 v(V)5.04.13.32.72.21.81.51.21.0

很多人第一反应是“两边取对数”:ln v = ln V₀ − t/τ。这样就把指数拟合变成了线性拟合,用案例一的方法求斜率和截距。这样做完全没问题,而且算得很快:对电压取对数后,ln v 从 1.61 逐渐降到 0,对 t 做线性回归,斜率约 −0.406,τ ≈ 2.46 s,V₀ ≈ 4.95 V。

4.2 线性化后一个隐蔽的问题

但是这里有一个真正的坑:线性化改变了误差结构。普通最小二乘假设每个数据点的误差是等方差的,也就是“散布程度差不多”。电压在 5 V 附近波动 ±0.1 V,取对数后围绕 ln 5 的波动大约是 ±0.02;而电压在 1 V 附近波动 ±0.1 V,取对数后的波动却是 ±0.1。取对数之后,小电压点的误差被放大了五倍,直线拟合会拼命迁就那些噪声大的低电压点。

所以,同样的数据,用“取对数后线性拟合”和“直接对原始数据做非线性指数拟合”,得到的参数会有差异。做工程标定时如果要求精度,我更倾向于用后者。Python 里用 scipy 直接做:

from scipy.optimize import curve_fit import numpy as np def exp_decay(t, V0, tau): return V0 * np.exp(-t / tau) t = np.array([0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0]) v = np.array([5.0, 4.1, 3.3, 2.7, 2.2, 1.8, 1.5, 1.2, 1.0]) popt, _ = curve_fit(exp_decay, t, v, p0=[5, 3]) print(popt) # 大约 [4.95, 2.48]

4.3 什么时候可以安心用线性化

那线性化是不是一无是处?不是。如果数据的测量误差主要在对数尺度上比较均匀——比如某些幂律数据本身就是乘性噪声——那线性化反而更合理。关键是你要想清楚自己的误差是加性的还是乘性的。加性误差用原始空间最小二乘;乘性误差用对数空间最小二乘。这个选择比拟合技巧更重要。

5. 案例四:幂律拟合——双对数坐标下的“障眼法”

5.1 幂律数据的识别特征

幂律分布是最容易被误判的一类数据。它的形式是 y = a·x^b,比如一个圆形物体的面积和半径的关系,原本应该是精确的 A = πr²,但实际测量时半径误差在 0.1 mm 量级,面积误差会随半径增大而变大。又比如网页访问量按排名分布的 Zipf 规律、文件大小分布、地震频次与震级关系等,都是典型的幂律。

幂律数据的识别特征是:在普通坐标系里画出来,数据点弯弯曲曲,像一堆乱麻;但如果你把 x 和 y 都取对数,也就是在双对数坐标里画图,数据变得几乎是一条直线。因为 ln y = ln a + b·ln x,这本质上是“ln y 对 ln x 的线性拟合”。

5.2 双对数拟合的实现

用面积与半径的数据来做演示。取半径从 1 到 12,面积为 πr² 再加上少量随机噪声。把 r 和 A 都取对数,然后做直线拟合:

r = np.linspace(1, 12, 12) A = np.pi * r**2 + np.random.normal(0, 2, size=r.shape) slope, intercept = np.polyfit(np.log(r), np.log(A), 1) # slope 接近 2.0,intercept 接近 np.log(np.pi)

如果能恢复出斜率 b ≈ 2,截距 ln a ≈ 1.14,也就是 a ≈ π,说明幂律模型成立。

5.3 幂律拟合中我踩过的坑

这个案例有一个容易忽视的点:双对数坐标下拟合得很好,不代表原始尺度下拟合得好。原因是取对数后,大数值的权重被压缩,小数值的权重被放大。如果你的数据跨越几个数量级,而你对小数值测量得并不准,双对数拟合会给这些小点过高的权重,参数就会偏向它们。

我处理数据时通常双管齐下:先在对数空间做一次拟合,把结果作为初值;再用 scipy 对原始数据做非线性拟合,看两个结果差多少。如果差别大,说明数据里有噪声结构问题,需要进一步分析权重的设定,而不能盲目相信双对数图上的直线。

6. 案例五:多元线性回归——从一堆变量里挑出有用信号

6.1 多元回归的矩阵化写法

现实中的数据很少只有一个自变量。比如分析二手房价格,你可能要考虑面积、房龄、卧室数量等多个因素。这就要用到多元线性回归:y = β0 + β1x1 + β2x2 + β3x3。

用矩阵写更干净:y = Xβ + ε,最小二乘解是 β = (XᵀX)⁻¹Xᵀy。Python 里直接用 np.linalg.lstsq 就可以:

import numpy as np # 每行对应一套房:截距项, 面积(m²), 房龄(年), 卧室数 X = np.array([ [1, 80, 5, 2], [1, 95, 8, 2], [1, 110, 3, 3], [1, 65, 15, 1], [1, 130, 2, 3], [1, 75, 10, 2], ]) y = np.array([265, 292, 335, 205, 385, 235]) beta, *_ = np.linalg.lstsq(X, y, rcond=None) print(beta)

跑出来大概会得到一个类似 [12.5, 2.35, -1.85, 9.4] 的向量,含义是:在其他条件不变时,面积每多 1 平方米,价格平均涨 2.35 万;房龄每多一年,价格降 1.85 万;卧室每多一间,价格多 9.4 万。

6.2 多元回归最容易翻车的点:共线性

看起来很简单,但多元回归有一个隐形杀手,叫多重共线性。简单说就是两个自变量之间存在强相关关系。比如“面积”和“卧室数量”通常高度相关,房子越大卧室越多。如果模型中同时放入这两个变量,最小二乘解虽然数学上能算出来,但系数极不稳定,可能面积项变成负的,卧室项变成正的,从经济学上讲完全不合理。

判断共线性有两个简单手段:一是算自变量之间的相关系数矩阵,看到相关系数高于 0.8 的要对存疑;二是算方差膨胀因子 VIF,超过 10 就得处理。处理方式通常是删除其中一个变量,或者用主成分分析先降维。

6.3 我的实操建议

我处理多元回归的一个习惯,是先做一个“单变量回归巡览”:每个自变量单独对 y 做一次线性拟合,看谁有意义、谁没意义。然后再放到一起做多元回归,比较每个变量的系数符号和大小是否与单变量时一致。如果某个变量加进去之后,符号翻转或者数值剧烈变化,不要急着写报告,先查共线性。

7. 案例六:加权最小二乘——数据点之间的“信任等级”不同

7.1 什么时候需要用加权最小二乘

回想案例一,普通最小二乘隐含了一个假设:每个数据点的测量误差是等方差的,也就是所有点“可信度相同”。但这个假设在很多实验里不成立。举一个典型的例子:测量溶液浓度-吸光度关系时,浓度高的溶液测量信号大,散射噪声也随之变大;浓度低的溶液信号弱,噪声却相对平稳。这时候高浓度点的误差方差 σ² 更大,却在普通最小二乘里和低浓度点享有相同的权重,结果会被噪声大的点牵着走。

加权最小二乘的目标函数是:

min Σ wᵢ (yᵢ - ŷᵢ)²

权重 wᵢ 应该取 1/σᵢ²,意思是误差方差越小的点,权重越大、越值得信任。

7.2 怎么确定权重

在实际操作中,σᵢ 可以通过三种方式估计。最直接的方式是同一测量条件下重复多次实验,用样本标准差作为 σ 的估计;第二种方式是根据仪器厂家的精度指标来推算;第三种方式是假设方差随信号水平变化,比如 σᵢ ∝ yᵢ,然后建模。

三种方式我都用过,实际效果从好到坏依次是:重复实验实测 > 物理模型推导 > 厂家指标。厂家指标往往偏乐观,重复实验虽然费时间,但得到的是最真实的误差结构。如果时间不允许,至少用“把每个点的测量值做三次,取标准差”这种最小成本方案。

7.3 加权与不加权的差异演示

我处理过一组光栅光谱数据:强度从 2000 到 80000 计数不等,把每个点的噪声按泊松统计近似为根号下强度。不加权和加权拟合出的曲线,在低强度区域相差可能有 10% 以上。对于定量分析来说,10% 是致命误差。

还有一个容易被忽略的细节:只有相对权重是重要的。你给每个点的权重都乘以 10,拟合结果不会变。所以搞不清楚绝对 σ 时,只要知道每个点之间的相对误差比例也能算。

8. 案例七:高斯峰拟合——非线性最小二乘的实战入口

8.1 非线性与线性最小二乘的分界

前面几个案例里,虽然模型有指数、幂律,但我一直在强调“可以转化成线性”。而高斯峰拟合是真的躲不开非线性了。色谱、质谱、光谱分析里最常见的一个峰是高斯线形:

y = A·exp(−(x−μ)²/(2σ²)) + C

这里的 A 是峰高、μ 是峰中心位置、σ 是峰宽、C 是背景基线。问题是,μ 和 σ 在指数函数里面,残差对它们可不是线性关系,没法通过解线性方程组直接得到答案。

8.2 迭代求解的思路与实现

这类问题用的是迭代算法,最常见的是高斯-牛顿法和莱文伯格-马夸特法。核心思想是:先给一组初始参数,把非线性

本文还有配套的精品资源,点击获取

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

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

立即咨询