np.cov()容易忽略的地方/坑

本文探讨使用numpy的np.cov函数计算协方差时遇到的困惑,即为何二维特征数据计算出的协方差矩阵为5x5而非预期的2x2。通过调整数据的转置方式解决了这一问题,并详细解释了np.cov函数参数rowvar的默认值如何影响计算结果,以及为何实际应用中需注意数据的组织方式。

五个样本,每个样本二维特征
import numpy as np
a = np.array([(2.5, 2.3), (1.5, 1.3), (2.2, 2.9), (2.1, 2.7), (1.7, 1.9)])

用np.cov(a)得到的结果 是一个shape为(5, 5)的array
array([[ 0.02 ,  0.02 , -0.07 , -0.06 , -0.02 ],
       [ 0.02 ,  0.02 , -0.07 , -0.06 , -0.02 ],
       [-0.07 , -0.07 ,  0.245,  0.21 ,  0.07 ],
       [-0.06 , -0.06 ,  0.21 ,  0.18 ,  0.06 ],
       [-0.02 , -0.02 ,  0.07 ,  0.06 ,  0.02 ]])
      
觉得很奇怪,两个特征维度,为什么计算结果是5*5的矩阵?

搜了一下协方差,网上的几个例子,跟理解中大部分是一样的。但为什么实际算出来的会完全不一样?
协方差计算的是 特征维度之间 变化方向同异问题,这里只有两个特征,问题在哪?

发现转置一下,计算出来是预期的样子了:(或者np.cov(a, rowvar=False))
np.cov(a.T)
array([[ 0.16 ,  0.195],
       [ 0.195,  0.412]])

看一下代码注释:
它这里的variable, observation跟常用的描述角度不一样, 初看时很晕,花了好多个小时才弄清。。。(主要原因有两个,第一个错估计很少人犯,第二个坑 可能较多人会没注意: 转置了我们通常的方向 )

通常情况下, 我们用来训练的数据,一行是一个样本,一列是一个特征。

它这里的variable是特征,  observation是样本。个人没接受这种说法前,觉得 也可以是: 样本是变化的变量, 观测是对于某个特征 或某一列 集中观察结果 (a single observation of all those variables)? 。。。 
有个挺大的坑是: 按照rowvar的默认值, 会把一行当成一个特征,一列当成一个样本。。这跟我们常用的数据位置方向 应该是反的 。。。 也解释了为什么 五个样本,每个样本二维特征 用np.cov()得到的结果 是一个shape为(5, 5)的array

    Parameters
    ----------
    m : array_like
        A 1-D or 2-D array containing multiple variables and observations.
        Each row of `m` represents a variable, and each column a single
        observation of all those variables. Also see `rowvar` below.
    y : array_like, optional
        An additional set of variables and observations. `y` has the same form
        as that of `m`.
    rowvar : bool, optional
        If `rowvar` is True (default), then each row represents a
        variable, with observations in the columns. Otherwise, the relationship
        is transposed: each column represents a variable, while the rows
        contain observations.


网上搜的讲协方差的例子,很多都是用matlab算的。matlab跟我们平时用的数据位置方向是一样的,所以看那些例子,都是顺着 自然的。np.cov默认值 为啥是这样的呢。。。有大侠知道的欢迎指点

import numpy as np # 已知点坐标 coords_known = { 'A': np.array([-14063.675, 93526.066, 7431.515]), 'B': np.array([-13316.387, 97044.422, 2942.687]) } # 待定点近似坐标 coords_approx = { 'P1': np.array([-14679.619, 95545.981, 4346.910]), 'P2': np.array([-18592.569, 95226.358, 3105.897]) } # 基线观测向量 baselines = { 'A-P1': np.array([-615.9439, 2019.9151, -3084.6049]), 'P1-B': np.array([1363.2325, 1498.4417, -1404.2228]), 'P2-A': np.array([4528.9347, -1700.3398, 4325.6152]), 'P2-P1': np.array([3912.9908, 319.5758, 1241.0104]), 'P2-B': np.array([5276.2233, 1818.0175, -163.2124]), 'A-B': np.array([747.2886, 3518.3567, -4488.8277]) } # 协方差矩阵 cov_matrices = { 'A-P1': np.array([ [0.0000072900, -0.0000098502, -0.0000067366], [-0.0000098502, 0.0000184900, 0.0000115488], [-0.0000067366, 0.0000115488, 0.0000096100] ]), 'P1-B': np.array([ [0.0000422500, -0.0000300539, -0.0000278659], [-0.0000300539, 0.0000532900, 0.0000332169], [-0.0000278659, 0.0000332169, 0.0000291600] ]), 'P2-A': np.array([ [0.0000067600, -0.0000090516, -0.0000062859], [-0.0000090516, 0.0000168100, 0.0000107230], [-0.0000062859, 0.0000107230, 0.0000090000] ]), 'P2-P1': np.array([ [0.0000057600, -0.0000077617, -0.0000057600], [-0.0000077617, 0.0000144400, 0.0000089046], [-0.0000052109, 0.0000089046, 0.0000072900] ]), 'P2-B': np.array([ [0.0000057600, -0.0000077595, -0.0000054089], [-0.0000077595, 0.0000144400, 0.0000092365], [-0.0000054089, 0.0000092365, 0.0000078400] ]), 'A-B': np.array([ [0.0000067600, -0.0000090779, -0.0000062899], [-0.0000090779, 0.0000168100, 0.0000106849], [-0.0000062899, 0.0000106849, 0.0000090000] ]) } # 基线顺序 baseline_order = [ 'P2-A', 'P2-P1', 'P2-B', 'A-P1','A-B', 'P1-B'] def build_adjustment_model(use_error=False): n_obs = 6 * 3 n_params = 6 B = np.zeros((n
最新发布
12-18
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值