错位的梦寐

PCA中协方差矩阵、矩阵特征值、特征向量的计算

2019-12-16

   

在 PCA 中用到协方差阵的计算以及特征值和特征向量的计算。

numpy.cov() 函数用来计算协方差

a, b = np.linalg.eig(x) 函数可以用来计算矩阵的特征值与特征向量

numpy.linalg.inv() 函数用来计算可逆矩阵的逆矩阵。

协方差矩阵

1. 协方差定义

X、Y 是两个随机变量,X、Y 的协方差 cov(X, Y) 定义为:

\[\operatorname{cov}(X, Y)=E\left[\left(X-\mu_{x}\right)\left(Y-\mu_{y}\right)\right]\]

其中:

\[E(X)=\mu_{x}, E(Y)=\mu_{y}\]

2. 协方差矩阵定义

矩阵中的数据按行排列与按列排列求出的协方差矩阵是不同的,这里默认数据是按行排列。即每一行是一个observation(or sample),那么每一列就是一个随机变量。

\[X_{m \times n}=\left[\begin{array}{cccc}{a_{11}} & {a_{12}} & {\cdots} & {a_{1 n}} \\ {a_{21}} & {a_{22}} & {\cdots} & {a_{2 n}} \\ {\vdots} & {\vdots} & {\vdots} & {\vdots} \\ {a_{m 1}} & {a_{m 2}} & {\cdots} & {a_{m n}}\end{array}\right]=\left[\begin{array}{llll}{c_{1}} & {c_{2}} & {\cdots} & {c_{n}}\end{array}\right]\]

协方差矩阵:

\[\text { covMatrix }=\frac{1}{m-1}\left[\begin{array}{cccc}{\operatorname{cov}\left(c_{1}, c_{1}\right)} & {\operatorname{cov}\left(c_{1}, c_{2}\right)} & {\cdots} & {\operatorname{cov}\left(c_{1}, c_{n}\right)} \\ {\operatorname{cov}\left(c_{2}, c_{1}\right)} & {\operatorname{cov}\left(c_{2}, c_{2}\right)} & {\cdots} & {\operatorname{cov}\left(c_{2}, c_{n}\right)} \\ {\vdots} & {\vdots} & {\vdots} & {\vdots} \\ {\operatorname{cov}\left(c_{n}, c_{1}\right)} & {\operatorname{cov}\left(c_{n}, c_{2}\right)} & {\cdots} & {\operatorname{cov}\left(c_{n}, c_{n}\right)}\end{array}\right]\]

协方差矩阵的维度等于随机变量的个数,即每一个 observation 的维度。在某些场合前边也会出现 $1 / m$ ,而不是 $1 / (m - 1)$ .

3. 求解协方差矩阵的步骤

举个例子,矩阵 X 按行排列:

\[X=\left[\begin{array}{lll}{1} & {2} & {3} \\ {3} & {1} & {1}\end{array}\right]=\left[\begin{array}{lll}{c_{1}} & {c_{2}} & {c_{3}}\end{array}\right]\]
  1. 求每个维度的平均值:

    \[\bar{c}=\left[\begin{array}{lll} {2} & {1.5} & {2} \end{array}\right]=\left[\begin{array}{lll} {\bar{c}_{1}} & {\bar{c}_{2}} & {\bar{c}_{3}} \end{array}\right]\]
  2. 将 X 的每一列减去平均值

    \[X=\left[\begin{array}{ccc} {-1} & {0.5} & {1} \\ {1} & {-0.5} & {-1} \end{array}\right]\]

    其中:

\[c_{i}=c_{i}-\bar{c}_{i}\]
  1. 计算协方差矩阵

    \[\operatorname{cov}=\frac{1}{m-1} X^{T} X=\frac{1}{2-1}\left[\begin{array}{ccc} {2} & {-1} & {-2} \\ {-1} & {0.5} & {1} \\ {-2} & {1} & {2} \end{array}\right]\]

4. 意义

协方差的为正,代表两个变量正相关;负,代表两个变量负相关

重点:协方差矩阵计算的是不同维度之间的协方差,而不是不同样本之间。

5. numpy.cov() 计算协方差矩阵

函数

numpy.cov() 的作用是计算协方差矩阵。

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),即使指定了fweightsaweights 参数;当ddof =0时,则返回简单平均值。
  • frequency weights :一维数组,代表每个观测要重复的次数(相当于给观测赋予权重)
  • analytic weights :一维数组,代表观测矢量权重。对于被认为“重要”的观察,这些相对权重通常很大,而对于被认为不太重要的观察,这些相对权重较小。如果ddof = 0,则可以使用权重数组将概率分配给观测向量。

Examples

In [1]: import numpy as np

In [2]: x = np.array([[0, 2], [1, 1], [2, 0]]).T

In [3]: x
Out[3]:
array([[0, 1, 2],
       [2, 1, 0]])

In [4]: np.cov(x)
Out[4]:
array([[ 1., -1.],
       [-1.,  1.]])

>>> x = [-2.1, -1,  4.3]
>>> y = [3,  1.1,  0.12]
>>> X = np.stack((x, y), axis=0)

>>> print(np.cov(X))
[[ 11.71        -4.286     ]
 [ -4.286        2.14413333]]

>>> print(np.cov(x, y))
[[ 11.71        -4.286     ]
 [ -4.286        2.14413333]]

>>> print(np.cov(x))
11.71
import numpy as np

# 计算协方差的时候,一行代表一个特征
# 下面计算cov(T, S, M)
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每行代表一个属性
#  每列代表一个示例,或者说观测
print(np.cov(X))

# [[ 47.71969697 122.9469697  129.59090909]
#  [122.9469697  370.08333333 374.59090909]
#  [129.59090909 374.59090909 399.        ]]

和方差的区别

>>> a = [1,2,3,4]  # 当a是一维向量时
>>> import numpy as np

>>> np.cov(a)  # 计算样本方差
array(1.66666667)

>>> np.var(a)  # 计算总体方差
1.25

# 下面是 cov(a) 和 var(a)的区别
>>> 1.666666666666666667*3/4
1.25
>>>

矩阵特征值、特征向量

函数

numpy.linalgeig() 函数可以用来计算矩阵的特征值与特征向量

a, b = np.linalg.eig(x) x 为矩阵 得到 a 为特征值,b 为特征向量

numpy.linalg.inv() 函数用来计算可逆矩阵的逆矩阵。

Examples

>>> import numpy as np
>>> x = np.mat([[1,2,3], [4,5,6], [7,8,9]])

# 计算矩阵特征值与特征向量
>>> e, v = np.linalg.eig(x)

# 根据特征值和特征向量得到原矩阵
>>> y = v * np.diag(e) * np.linalg.inv(v)
>>> y
matrix([[ 1.,  2.,  3.],
        [ 4.,  5.,  6.],
        [ 7.,  8.,  9.]])


numpy 返回的是矩阵的逆,而不是矩阵本身,特征提取有三个矩阵相乘,中间是对角矩阵,它左边的是逆,右边的是变化矩阵,习惯以为返回的是对角矩阵右边那个矩阵,实际返回的是左边那个,所以numpy 的写法是 $QBQ^{-1}$ 而不是教材里通常的写法$Q^{-1}BQ$

>>> from numpy import linalg as LA

>>> w, v = LA.eig(np.diag((1, 2, 3)))
>>> w; v
array([1., 2., 3.])
array([[1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])

>>> w, v = LA.eig(np.array([[1, -1], [1, 1]]))
>>> w; v
array([1.+1.j, 1.-1.j])
array([[0.70710678+0.j        , 0.70710678-0.j        ],
       [0.        -0.70710678j, 0.        +0.70710678j]])
       

参考

  1. 协方差矩阵计算方法
  2. np.cov详解
  3. Python使用numpy计算矩阵特征值、特征向量与逆矩阵

上一篇 朴素贝叶斯

Comments

Content