Kang's Blog

Kang's Blog

12 Nov 2022

使用在线算法求解样本方差 - 算法 (第 4 版) 1.2.18 练习题详解

本文是对 算法 (第 4 版)习题 1.2.18 分析,分析为什么题目中给出的代码可以求解方差。

名词解释

  • 方差(variance):是描述一组数据的离散程度。比如比较两个班级的身高差异度,就可以使用方差。方差大的班级,高的更高,矮的更矮。计算方法为:先算出数据的平均值,在求每个数据与平均值差的平方的和,最后除以数据总量。

    既然有了总体方差,那为什么还有一个样本方差?那是因为统计全部数据难度高。比如计算全国身高的方差,就不可能把全国每一个人的身高都统计一遍。

  • 标准差(standard deviation):标准差的平方是方差。方差可以描述一组数据的离散程度,但其单位与数据的单位不一致。这也是标准差出现的原因。比如,一个班级升高的身差的方差是 $ 100 cm^2 $,标准差就是 $ 10 cm $。

  • 在线算法:在输入的过程中就能完成的一系列算法。比如插入排序,它可以在输入的过程中进行排序,输入完毕也就排好序了。

求解

n 组数据的样本方差的公式为:

$$ S_{n} = \frac{1}{n-1} \sum_{i=1}^{n} (x_i - m_n)^{2} $$

其中:

  • $S_{n}$ 为样本方差
  • $x_i$ 为第 i 个数据
  • $m_n$ 为样本的平均值,即: $ m_n = \frac{1}{n} \sum_{i=1}^{n} x_i $

根据 Kevin Wayne 在 algs4 中的提示知道可以用 1962 年 B. P. Welford 在 Technometrics 发表的 Note on a method for calculating corrected sums of squares and products 来解释。

前提准备

n 个数据的平均值与 n-1 个数据的平均值的关系为(其中 $x_n$ 为第 n 个数据):

$$ m_n = \frac{1}{n} ((n-1) m_{n-1}+ x_n) $$

简化一下:

$$ m_n = \frac{n-1}{n} m_{n-1} + \frac{1}{n} x_n $$

这样就可以得出 $x_i - m_n$ 和 $x_n - m_n$ 的表达式:

$$ \begin{split} x_i - m_n &= x_i - (\frac{n-1}{n} m_{n-1} + \frac{1}{n} x_n ) \\ &= x_i - m_{n-1} + \frac{1}{n} m_{n-1} - \frac{1}{n} x_n \\ &= x_i - m_{n-1} - \frac{1}{n} (x_n - m_{n-1}) \\ \end{split} $$

$$ \begin{split} x_n - m_n &= x_n - (\frac{n-1}{n} m_{n-1} + \frac{1}{n} x_n ) \\ &= x_n - \frac{1}{n} x_n - \frac{n-1}{n} m_{n-1} \\ &= \frac{n-1}{n} (x_n - m_{n-1}) \\ \end{split} $$

开始证明

由公式可得:

$$ S_{n} = \frac{1}{n-1} \sum_{i=1}^{n} (x_i - m_n)^{2} $$

把 (n-1) 放到左边,将 $(n-1)S_n$ 看成一个整体:

$$ (n-1)S_n = \sum_{i=1}^{n} (x_i - m_n)^2 $$

拆分下,让其等于 (n-1) 的和加上最后一项:

$$ (n-1)S_n = \sum_{i=1}^{n-1} (x_i - m_n)^2 + (x_n - m_n)^2 $$

将上述的 $x_i - m_n$ 和 $x_n - m_n$ 代入:

$$ (n-1)S_n = \sum_{i=1}^{n-1} \left [(x_i - m_{n-1}) - \frac{1}{n}(x_n - m_{n-1}) \right ]^2 + \left [(\frac{n-1}{n})(x_n - m_{n-1}) \right ]^2 $$

求和公式满足分配律和结合律,且可直接提取常量。故可将式子拆分成:

$$ (n-1)S_n = \sum_{i=1}^{n-1} (x_i - m_{n-1})^2 - 2 (x_n - m_{n-1}) \sum_{i=1}^{n-1} (x_i - m_{n-1}) \\ + \frac{1}{n^2} \sum_{i=1}^{n-1} (x_n - m_{n-1})^2 + (\frac{n-1}{n})^2(x_n - m_{n-1})^2 $$

其中 $x_n$ 和 $m_{n-1}$ 为常量,可以分解下第二个和第三个式子:

$$ \begin{split} \sum_{i=1}^{n-1} (x_i - m_{n-1}) &= \sum_{i=1}^{n-1} x_i - \sum_{i=1}^{n-1} m_{n-1} \\ &= \sum_{i=1}^{n-1} x_i - (n-1) m_{n-1} \\ &= \sum_{i=1}^{n-1} x_i - (n-1) \frac{1}{n-1} \sum_{i=1}^{n-1} x_i\\ &= 0 \end{split} $$

$$ \frac{1}{n^2} \sum_{i=1}^{n-1} (x_n - m_{n-1})^2 = \frac{n-1}{n^2} (x_n - m_{n-1})^2 $$

代入上式可得:

$$ \begin{split} (n-1)S_n &= \sum_{i=1}^{n-1} (x_i - m_{n-1})^2 + \left [ \frac{n-1}{n^2} + \frac{(n-1)^2}{n^2} \right ](x_n - m_{n-1})^2 \\ &= S_{n-1} + (\frac{n-1}{n})(x_n - m_{n-1})^{2} \end{split} $$

所以下列等式成立:

$$ \begin{split} S_{n} &= \frac{1}{n-1} \sum_{i=1}^{n} (x_i - m_n)^{2} \\ &= S_{n-1} + (\frac{n-1}{n})(x_n - m_{n-1})^{2} \\ \end{split} $$

其中 $S_{0} = S_{1} = 0$

这样就得到的 $S_{n}$ 与 $S_{n-1}$ 之间的关系。这样就可以在每读一个数据时,都可以使用之前的方差($S_{n-1}$)加上 $(\frac{n-1}{n})(x_n - m_{n-1})^{2}$ 来计算当前的方差。达到来在线算法的标准。