4、最小二乘法原理:数学推导与斜截距求解

各位做嵌入式校准的同行,今天我们来啃一块硬骨头——最小二乘法。

说实话,我刚入行时也觉得这东西太数学了。直到有一次,我调试一台高精度万用表,发现ADC采集的数据总是飘。用最小二乘法一拟合,问题立马清晰了。从那以后,我就把这方法当成了吃饭的家伙。

4.1 最小二乘法的核心思想

先问大家一个问题:你有一堆测量点,想找一条直线来描述它们。怎么找?

最小二乘法的答案很简单——让所有点到直线的垂直距离的平方和最小。

为什么是平方?不是绝对值?

嗯,这里有个小故事。我刚开始做校准算法时,试过用绝对值距离。结果发现,绝对值函数在零点不可导,优化起来特别麻烦。而平方函数处处可导,用微积分就能轻松求解。这就是数学家的智慧——选一个好算的误差函数。

核心公式:

误差平方和 S = Σ(yᵢ - (a·xᵢ + b))²

其中 a 是斜率,b 是截距,我们要找到使 S 最小的 a 和 b。

4.2 数学推导:一步步来

推导过程其实不复杂。我习惯把它分成三步走:

  1. 写出误差函数——就是上面那个 S
  2. 对 a 和 b 分别求偏导——让导数等于0
  3. 解方程组——得到 a 和 b 的表达式

咱们一步步看。

首先,对 b 求偏导:

∂S/∂b = -2 Σ(yᵢ - a·xᵢ - b) = 0
→ Σyᵢ - a·Σxᵢ - n·b = 0
→ b = (Σyᵢ - a·Σxᵢ) / n

然后,对 a 求偏导:

∂S/∂a = -2 Σxᵢ·(yᵢ - a·xᵢ - b) = 0
→ Σxᵢ·yᵢ - a·Σxᵢ² - b·Σxᵢ = 0

把 b 的表达式代入第二个方程,整理后得到:

a = (n·Σxᵢ·yᵢ - Σxᵢ·Σyᵢ) / (n·Σxᵢ² - (Σxᵢ)²)
b = (Σyᵢ - a·Σxᵢ) / n

实战小技巧:

我在嵌入式平台上实现时,会先计算几个统计量:

  • Σx、Σy、Σx²、Σxy
  • n 是数据点数

这样只需要一次循环就能算出所有中间结果,效率很高。

4.3 斜率和截距的物理意义

在万用表校准中,这两个参数有明确的物理含义:

参数 物理意义 理想值
斜率 a 增益误差 1.0(无增益误差)
截距 b 偏移误差 0.0(无偏移误差)

举个例子。你测量一个标准电压源,得到一组数据:

标准值(V)  测量值(V)
1.000      1.002
2.000      2.005
3.000      3.008
4.000      4.011
5.000      5.014

用最小二乘法拟合,得到 a=1.003,b=-0.001。这说明什么?

斜率 a=1.003,意味着每1V的输入,测量值偏大0.003V,这是增益误差。截距 b=-0.001,意味着有-1mV的偏移。

我曾经踩过的坑:

有一次,我直接用原始ADC码值做拟合,结果斜率算出来是0.000几。后来才意识到,ADC码值和电压值量级差太多,导致数值计算精度丢失。我的建议是:

  • 先把数据归一化到同一量级
  • 或者用双精度浮点数计算

否则,在8位单片机上跑,结果可能完全不对。

4.4 嵌入式实现要点

在嵌入式系统里实现最小二乘法,有几个地方要特别注意:

  1. 数值稳定性——当数据点很多时,Σx² 可能非常大,容易溢出。我习惯用增量式更新,每来一个点就更新一次统计量。
  2. 定点数实现——如果MCU没有FPU,可以用Q15或Q31格式。但要注意,除法运算要特别小心。
  3. 异常处理——当所有x值相同时,分母为0。这种情况在现实中很少见,但代码里一定要处理。

推荐的数据类型:

对于12位ADC、16位MCU的系统:

  • 中间累加用32位整数
  • 最终结果用浮点数
  • 如果必须用定点,保留至少8位小数精度

4.5 一个完整的计算示例

咱们用手算一遍,加深理解。

假设有3个数据点:(1,2), (2,4), (3,6)

先算统计量:

n = 3
Σx = 1+2+3 = 6
Σy = 2+4+6 = 12
Σx² = 1+4+9 = 14
Σxy = 1×2 + 2×4 + 3×6 = 2+8+18 = 28

代入公式:

a = (3×28 - 6×12) / (3×14 - 6²)
  = (84 - 72) / (42 - 36)
  = 12 / 6
  = 2.0

b = (12 - 2.0×6) / 3
  = (12 - 12) / 3
  = 0.0

结果 a=2.0, b=0.0,完美拟合 y=2x 这条直线。

验证小技巧:

算完后,把第一个点和最后一个点代入直线方程,看看中间点是否在直线上。如果偏差很大,说明数据本身就不是线性关系,或者计算有误。

4.6 实际校准中的应用

在万用表校准中,我们通常这样做:

  1. 用标准源输出5~10个校准点
  2. 记录ADC的原始读数
  3. 用最小二乘法拟合出斜率和截距
  4. 将这两个参数存入EEPROM
  5. 正常测量时,用 y = (x - b) / a 反算真实值

你想想看,这个过程其实就是在做「反向校准」。我们不是去调整硬件,而是在软件里把测量值修正回来。

我个人习惯在出厂前做一次全量程校准,然后在关键温度点做二次校准。这样既能保证精度,又不会让校准时间太长。

好了,最小二乘法的原理和推导就讲到这里。下一章我们聊聊如何在嵌入式平台上高效实现这个算法,包括定点数优化和内存管理。到时候我会分享一个我在STM32上实际跑过的代码框架。