协方差

  • 两个变量
    • 在变化过程中是同方向变化?
      • 你变大,同时我也变大,说明两个变量是同向变化的,这时协方差就是正的
    • 还是反方向变化?
      • 你变大,同时我变小,说明两个变量是反向变化的,这时协方差就是负的
    • 同向或反向程度如何?
      • 从数值来看,协方差的数值越大,两个变量同向程度也就越大。反之亦然
$$Cov(X,Y)=E[(X-\mu_{x})(Y-\mu_{y})]$$
  • 如果有$X,Y$两个变量
    • 每个时刻的“$X$值与其均值之差”乘以“$Y$值与其均值之差”得到一个乘积
    • 再对这每时刻的乘积求和求出均值求“期望”)(乘积加在一起,求平均)
  • 将每一时刻$(X-\mu_{x})$与$(Y-\mu_{y})$的乘积加在一起,其中的正负项就会抵消掉,最后求平均得出的值就是协方差
  • 通过协方差的数值大小,就可以判断这两个变量同向或反向的程度了

相关系数

$$\rho=\frac{Cov(X,Y)}{\sigma_{X} \sigma_{Y}}$$
  • 等于 $X、Y$ 的协方差,除以 $X$ 的标准差和 $Y$ 的标准差之积
  • 相关系数可以看成是 协方差剔除了两个变量量纲影响、标准化后的特殊协方差
    • 反映两个变量变化时是同向还是反向,如果同向变化就为正,反向变化就为负
    • 消除了两个变量变化幅度的影响,而只是单纯反应两个变量每单位变化时的相似程度

演示

In [25]:
import numpy as np

单个向量:样本方差

In [26]:
np.cov([4, 7, 2, 6])
Out[26]:
array(4.91666667)

两个向量:协方差矩阵

In [27]:
np.cov(
      [4, 7, 2,6]
    , [0, 0, 0,0]
)
Out[27]:
array([[4.91666667, 0.        ],
       [0.        , 0.        ]])
In [28]:
np.cov(
    [
          [4, 7, 2,6]
        , [4, 2, 9,8]
    ]
)
Out[28]:
array([[ 4.91666667, -4.41666667],
       [-4.41666667, 10.91666667]])

np.cov() 忽略了第3个向量

In [29]:
np.cov(
      [4, 7, 2, 6]
    , [4, 2, 9, 8]
    , [3, 6, 8, 2]
)
Out[29]:
array([[ 4.91666667, -4.41666667],
       [-4.41666667, 10.91666667]])

相当于cov([4, 7, 2,6],[4, 2, 9,8],ddof=0)

In [30]:
np.cov(
      [4, 7,  2, 6]
    , [4, 2,  9, 8]
    , [3, 6,  8, 2]
    , [4, 5, 10, 1]
)
Out[30]:
array([[ 3.6875, -3.3125],
       [-3.3125,  8.1875]])

cov处理了3个向量

In [31]:
np.cov(
    [
          [4, 7, 2, 6]
        , [4, 2, 9, 8]
        , [3, 6, 8, 2]
    ]
)
Out[31]:
array([[ 4.91666667, -4.41666667, -2.75      ],
       [-4.41666667, 10.91666667,  0.91666667],
       [-2.75      ,  0.91666667,  7.58333333]])

按列视为向量,有4个,所以产生4*4协方差矩阵

In [32]:
np.cov(
    [
         [4, 7, 2, 6]
        ,[4, 2, 9, 8]
        ,[3, 6, 8, 2]
    ]
    , rowvar=0
) 
Out[32]:
array([[ 0.33333333, -0.5       , -0.83333333,  1.66666667],
       [-0.5       ,  7.        , -7.5       , -5.        ],
       [-0.83333333, -7.5       , 14.33333333, -0.66666667],
       [ 1.66666667, -5.        , -0.66666667,  9.33333333]])

理解与说明

函数原型:def cov( m , y = None , rowvar = True , bias = False , ddof = None , fweights = None , aweights = None ) m: 一维或则二维的数组,默认情况下每一行代表一个变量(属性),每一列代表一个观测 y: 与m具有一样的形式的一组数据 rowvar: 默认为True,此时每一行代表一个变量(属性),每一列代表一个观测;为False时,则反之 bias: 默认为False,此时标准化时除以n-1;反之为n。其中n为观测数 ddof: 类型是int, 当其值非None时,bias参数作用将失效。 当ddof=1时,将会返回无偏估计(除以n-1),即使指定了fweights和aweights参数; 当ddof=0时,则返回简单平均值。 frequency weights: 一维数组,代表每个观测要重复的次数(相当于给观测赋予权重) analytic weights: 一维数组,代表观测矢量权重。 对于被认为“重要”的观察, 这些相对权重通常很大, 而对于被认为不太重要的观察, 这些相对权重较小。 如果ddof = 0, 则可以使用权重数组将概率分配给观测向量。

堆叠数组

  • np.vstack()
    • 按垂直方向(行顺序)堆叠数组构成一个新的数组
    • 堆叠的数组需要具有相同的维度
  • np.hstack()
    • 按水平方向(列顺序)堆叠数组构成一个新的数组
    • 堆叠的数组需要具有相同的维度
  • 计算协方差的时候,一行代表一个特征
  • 下面计算$Cov(T, S, M)$
In [33]:
T = np.array([9, 15, 25, 14, 10, 18, 0, 16, 5, 19, 16, 20])
S = np.array([39, 56, 93, 61, 50, 75, 32, 85, 42, 70, 66, 80])
M = np.asarray([38, 56, 90, 63, 56, 77, 30, 80, 41, 79, 64, 88])
X = np.vstack((T, S, M))
X
Out[33]:
array([[ 9, 15, 25, 14, 10, 18,  0, 16,  5, 19, 16, 20],
       [39, 56, 93, 61, 50, 75, 32, 85, 42, 70, 66, 80],
       [38, 56, 90, 63, 56, 77, 30, 80, 41, 79, 64, 88]])
  • $X$
    • 每行代表一个属性
    • 每列代表一个示例,或者说观测
In [34]:
np.cov(X)
Out[34]:
array([[ 47.71969697, 122.9469697 , 129.59090909],
       [122.9469697 , 370.08333333, 374.59090909],
       [129.59090909, 374.59090909, 399.        ]])
  • 协方差矩阵 计算的是不同维度之间的协方差,而不是不同样本之间
  • 拿到一个样本矩阵,首先要明确的就是行代表什么列代表什么

frequency weights

  • 一维数组,代表每个观测要重复的次数(相当于给观测赋予权重)
In [35]:
T = np.array([9, 15, 25, 14, 10, 18, 0, 16, 5, 19, 16, 20])
S = np.array([39, 56, 93, 61, 50, 75, 32, 85, 42, 70, 66, 80])
M = np.asarray([38, 56, 90, 63, 56, 77, 30, 80, 41, 79, 64, 88])
X = np.vstack((T, S, M))
print(np.cov(X, None, True, False, fweights=[2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]))
[[ 45.6025641  121.55769231 128.43589744]
 [121.55769231 381.42307692 389.30769231]
 [128.43589744 389.30769231 415.76923077]]
In [36]:
T = np.array([9, 15, 25, 14, 10, 18, 0, 16, 5, 19, 16, 20])
S = np.array([39, 56, 93, 61, 50, 75, 32, 85, 42, 70, 66, 80])
M = np.asarray([38, 56, 90, 63, 56, 77, 30, 80, 41, 79, 64, 88])
X = np.vstack((T, S, M))
print(np.cov(X, None, True, False, fweights=[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]))
[[ 47.71969697 122.9469697  129.59090909]
 [122.9469697  370.08333333 374.59090909]
 [129.59090909 374.59090909 399.        ]]

关于参数 y

In [37]:
T = np.array([9, 15, 25, 14, 10, 18, 0, 16, 5, 19, 16, 20])
S = np.array([39, 56, 93, 61, 50, 75, 32, 85, 42, 70, 66, 80])
M = np.asarray([38, 56, 90, 63, 56, 77, 30, 80, 41, 79, 64, 88])
X = np.vstack((T, S, M))
print(np.cov(X[0:1], X[1:])) # 你会惊奇发现,这个结果和上面的结果一致,这就是参数 m, y,不知道为什么要设置这样一个参数
[[ 47.71969697 122.9469697  129.59090909]
 [122.9469697  370.08333333 374.59090909]
 [129.59090909 374.59090909 399.        ]]
In [38]:
X
Out[38]:
array([[ 9, 15, 25, 14, 10, 18,  0, 16,  5, 19, 16, 20],
       [39, 56, 93, 61, 50, 75, 32, 85, 42, 70, 66, 80],
       [38, 56, 90, 63, 56, 77, 30, 80, 41, 79, 64, 88]])
In [39]:
X[0:1]
Out[39]:
array([[ 9, 15, 25, 14, 10, 18,  0, 16,  5, 19, 16, 20]])
In [40]:
X[1:]
Out[40]:
array([[39, 56, 93, 61, 50, 75, 32, 85, 42, 70, 66, 80],
       [38, 56, 90, 63, 56, 77, 30, 80, 41, 79, 64, 88]])

备注

方差

  • 方差是各个数据与平均数之差的平方的平均数
  • 在概率论和数理统计中,方差(英文Variance)用来度量随机变量和其数学期望(即均值)之间的偏离程度
  • 在许多实际问题中,研究随机变量和均值之间的偏离程度有着很重要的意义

标准差

  • 方差开根号

协方差

  • 在概率论和统计学中,协方差用于衡量两个变量的总体误差
  • 而方差是协方差的一种特殊情况,即当两个变量是相同的情况