协方差、协方差矩阵、PCA的理解(附python代码)

您所在的位置:网站首页 用python求excel数据中方差 协方差、协方差矩阵、PCA的理解(附python代码)

协方差、协方差矩阵、PCA的理解(附python代码)

2023-12-08 19:58| 来源: 网络整理| 查看: 265

协方差、协方差矩阵、PCA的理解(附python代码) 均值、方差、标准差协方差协方差矩阵PCA特征值、特征向量协方差矩阵的特征值和特征向量选取前k个特征(降到k维度)将样本点投影到选取的特征向量上

均值、方差、标准差

均值: X ˉ = ∑ i = 1 n X i n \bar{X}=\frac{\sum_{i=1}^n{X_i}}{n} Xˉ=n∑i=1n​Xi​​ 标准差: S = ∑ i = 1 n ( X i − X ˉ ) 2 n − 1 S=\sqrt{\frac{\sum_{i=1}^n({X_i-\bar{X}})^2}{n-1}} S=n−1∑i=1n​(Xi​−Xˉ)2​ ​ 方差: S = ∑ i = 1 n ( X i − X ˉ ) 2 n − 1 S=\frac{\sum_{i=1}^n({X_i-\bar{X}})^2}{n-1} S=n−1∑i=1n​(Xi​−Xˉ)2​ 均值描述的是样本集合的中间点,标准差描述的是各个样本点到均值的距离之平均。方差则仅仅是标准差的平方。 以 [ 0 8 12 20 ] \begin{bmatrix} 0& 8& 12& 20\end{bmatrix} [0​8​12​20​]和 [ 8 9 11 12 ] \begin{bmatrix} 8& 9& 11& 12\end{bmatrix} [8​9​11​12​]为例: 均值都是10,但显然两个集合的差别是很大的。 计算两者的标准差,前者是8.3后者是1.8,显然后者较为集中,故其标准差小一些,标准差描述的就是这种“散布度”。

协方差

标准差和方差一般是用来描述一维数据的。 对于二维数据,协方差就产生了: 协方差: c o v ( X , Y ) = ∑ i = 1 n ( X i − X ˉ ) ( Y i − Y ˉ ) n − 1 cov(X,Y)=\frac{\sum_{i=1}^n({X_i-\bar{X}})({Y_i-\bar{Y}})}{n-1} cov(X,Y)=n−1∑i=1n​(Xi​−Xˉ)(Yi​−Yˉ)​ 从下面这个式子来看方差和协方差: c o v ( X , X ) = v a r ( X , X ) = ∑ i = 1 n ( X i − X ˉ ) ( X i − X ˉ ) n − 1 cov(X,X)=var(X,X)=\frac{\sum_{i=1}^n({X_i-\bar{X}})({X_i-\bar{X}})}{n-1} cov(X,X)=var(X,X)=n−1∑i=1n​(Xi​−Xˉ)(Xi​−Xˉ)​ 协方差的结果有什么意义呢? 如果结果为正值,则说明两者是正相关的。如果结果为负值, 就说明两者是负相关。如果为0,则两者之间没有关系,也就是“相互独立”。

协方差矩阵

协方差矩阵: C n × n = ( c i , j , c i , j = c o v ( D i m i , D i m j ) ) C_{n \times n} = (c_{i,j},\quad c_{i,j}=cov(Dim_{i}, Dim_{j})) Cn×n​=(ci,j​,ci,j​=cov(Dimi​,Dimj​)) 以三维为例: C = ( c o v ( X , X ) c o v ( X , Y ) c o v ( X , Z ) c o v ( Y , X ) c o v ( Y , Y ) c o v ( Y , Z ) c o v ( Z , X ) c o v ( Z , Y ) c o v ( Z , Z ) ) C=\begin{pmatrix} cov(X,X) & cov(X,Y) & cov(X,Z) \\ cov(Y,X) & cov(Y,Y) & cov(Y,Z) \\ cov(Z,X) & cov(Z,Y) & cov(Z,Z) \end{pmatrix} C=⎝⎛​cov(X,X)cov(Y,X)cov(Z,X)​cov(X,Y)cov(Y,Y)cov(Z,Y)​cov(X,Z)cov(Y,Z)cov(Z,Z)​⎠⎞​ 协方差矩阵的计算: (1)先让样本矩阵中心化,即每一维度减去该维度的均值,使每一维度上的均值为0; (2)然后直接新的样本矩阵乘上新的样本矩阵的转置(用转置相乘实现两两维度的相乘); (3)除以n-1。

现在有10个样例,每个样例有2个特征: X = [ 2.5 0.5 2.2 1.9 3.1 2.3 2 1 1.5 1.1 ] X=\begin{bmatrix} 2.5& 0.5& 2.2& 1.9& 3.1& 2.3& 2& 1& 1.5& 1.1\end{bmatrix} X=[2.5​0.5​2.2​1.9​3.1​2.3​2​1​1.5​1.1​] Y = [ 2.4 0.7 2.9 2.2 3 2.7 1.6 1.1 1.6 0.9 ] Y=\begin{bmatrix} 2.4& 0.7& 2.9& 2.2& 3& 2.7& 1.6& 1.1& 1.6& 0.9\end{bmatrix} Y=[2.4​0.7​2.9​2.2​3​2.7​1.6​1.1​1.6​0.9​] D a t a = [ 2.5 0.5 2.2 1.9 3.1 2.3 2 1 1.5 1.1 2.4 0.7 2.9 2.2 3 2.7 1.6 1.1 1.6 0.9 ] Data = \begin{bmatrix} 2.5& 0.5& 2.2& 1.9& 3.1& 2.3& 2& 1& 1.5& 1.1\\2.4& 0.7& 2.9& 2.2& 3& 2.7& 1.6& 1.1& 1.6& 0.9\end{bmatrix} Data=[2.52.4​0.50.7​2.22.9​1.92.2​3.13​2.32.7​21.6​11.1​1.51.6​1.10.9​] 矩阵去中心化之后: D a t a S = [ 0.69 − 1.31 0.39 0.09 1.29 0.49 0.19 − 0.81 − 0.31 − 0.71 0.49 − 1.21 0.99 0.29 1.09 0.79 − 0.31 − 0.81 − 0.31 − 1.01 ] Data_S = \begin{bmatrix} 0.69 & -1.31& 0.39& 0.09& 1.29&0.49& 0.19& -0.81& -0.31& -0.71\\0.49& -1.21& 0.99& 0.29& 1.09& 0.79& -0.31& -0.81& -0.31& -1.01\end{bmatrix} DataS​=[0.690.49​−1.31−1.21​0.390.99​0.090.29​1.291.09​0.490.79​0.19−0.31​−0.81−0.81​−0.31−0.31​−0.71−1.01​] 转置相乘除以 n − 1 n-1 n−1: C = D a t a S . D a t a S T / 9 C = Data_S. Data_S^T /9 C=DataS​.DataST​/9 得到协方差矩阵为: C = [ 0.61655556 0.61544444 0.61544444 0.71655556 ] C=\begin{bmatrix} 0.61655556 & 0.61544444 \\ 0.61544444 & 0.71655556 \end{bmatrix} C=[0.616555560.61544444​0.615444440.71655556​] 0.61655556为 X X X的方差,0.71655556为 Y Y Y的方差。 0.61544444为 X X X和 Y Y Y的协方差。 代码如下:

import numpy as np x = np.array([2.5, 0.5, 2.2, 1.9, 3.1, 2.3, 2, 1, 1.5, 1.1]) y = np.array([2.4, 0.7, 2.9, 2.2, 3, 2.7, 1.6, 1.1, 1.6, 0.9]) # 归一化数据 scaled_x = x-np.mean(x) scaled_y = y-np.mean(y) # 组成矩阵 data = np.matrix([[scaled_x[i], scaled_y[i]] for i in range(len(scaled_x))]) # 求协方差矩阵 cov_matrix= np.dot(data.T, data)/(len(x)-1)

等价于:

import numpy as np x = np.array([2.5, 0.5, 2.2, 1.9, 3.1, 2.3, 2, 1, 1.5, 1.1]) y = np.array([2.4, 0.7, 2.9, 2.2, 3, 2.7, 1.6, 1.1, 1.6, 0.9]) # 求协方差矩阵 cov_matrix= np.cov(x, y) PCA

先复习下矩阵的特征值和特征向量。

特征值、特征向量

定义1:设 A A A是 n n n阶方阵,若存在数 λ \lambda λ和非零向量 x x x,使得 A x = λ x ( x ≠ 0 ) Ax=\lambda x(x \neq 0) Ax=λx(x​=0) 则称 λ \lambda λ是 A A A的一个特征值, x x x是 A A A对应于特征值 λ \lambda λ的特征向量。 在几何学中,矩阵A的特征向量是指经过与矩阵A变换后方向保持不变的向量。而特征值为在这个变化中特征向量的比例因子。 方阵的特征值的个数等于矩阵的阶数。

协方差矩阵的特征值和特征向量

接着上文的例子,已经求出 D a t a Data Data的协方差矩阵 C C C: D a t a = [ 2.5 0.5 2.2 1.9 3.1 2.3 2 1 1.5 1.1 2.4 0.7 2.9 2.2 3 2.7 1.6 1.1 1.6 0.9 ] Data = \begin{bmatrix} 2.5& 0.5& 2.2& 1.9& 3.1& 2.3& 2& 1& 1.5& 1.1\\2.4& 0.7& 2.9& 2.2& 3& 2.7& 1.6& 1.1& 1.6& 0.9\end{bmatrix} Data=[2.52.4​0.50.7​2.22.9​1.92.2​3.13​2.32.7​21.6​11.1​1.51.6​1.10.9​]

C = [ 0.61655556 0.61544444 0.61544444 0.71655556 ] C=\begin{bmatrix} 0.61655556 & 0.61544444 \\ 0.61544444 & 0.71655556 \end{bmatrix} C=[0.616555560.61544444​0.615444440.71655556​]

# 求协方差矩阵的特征值和特征向量 eig_val, eig_vec = np.linalg.eig(cov)

得到特征值: e i g V a l u e = [ 0.0490834 1.28402771 ] eigValue=\begin{bmatrix} 0.0490834 & 1.28402771\end{bmatrix} eigValue=[0.0490834​1.28402771​] 特征向量: e i g V e c t M a t r i x = [ − 0.73517866 − 0.6778734 0.6778734 − 0.73517866 ] eigVectMatrix=\begin{bmatrix} -0.73517866&-0.6778734\\ 0.6778734&-0.73517866\end{bmatrix} eigVectMatrix=[−0.735178660.6778734​−0.6778734−0.73517866​]

选取前k个特征(降到k维度)

将特征值按照从大到小的顺序排序,选择其中最大的 k k k个,然后将其对应的 k k k个特征向量分别作为列向量组成特征向量矩阵。 这里特征值只有2个,我们选择其中最大的那个。 这里是1.28402771,对应的特征向量是 e i g V e c t = ( − 0.6778734 , − 0.73517866 ) eigVect=\begin{pmatrix} -0.6778734,&-0.73517866\end{pmatrix} eigVect=(−0.6778734,​−0.73517866​)。

将样本点投影到选取的特征向量上

获取低维特征空间的数据: l o w D a t a = e i g V e c t ⋅ D a t a s lowData= eigVect\cdot Data_s lowData=eigVect⋅Datas​ 我们来看下是如何降维的: [ 1 , 2 ] ⋅ [ 2 , 10 ] → [ 1 , 10 ] [1,2]\cdot [2,10]\to[1,10] [1,2]⋅[2,10]→[1,10]

完整代码如下:

# -*- coding: utf-8 -*- import numpy as np import matplotlib.pyplot as plt plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签 plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 x = np.array([2.5, 0.5, 2.2, 1.9, 3.1, 2.3, 2, 1, 1.5, 1.1]) y = np.array([2.4, 0.7, 2.9, 2.2, 3, 2.7, 1.6, 1.1, 1.6, 0.9]) # 归一化数据 mean_x = np.mean(x) mean_y = np.mean(y) scaled_x = x-mean_x scaled_y = y-mean_y data = np.matrix([[scaled_x[i], scaled_y[i]] for i in range(len(scaled_x))]) # 绘制散点图查看数据分布 plt.plot(x, y, 'r*', label='原始数据') plt.plot(scaled_x, scaled_y, 'go', label='去中心化后数据') # 求协方差矩阵 dot = np.dot(data.T, data) dott = dot/(len(x)-1) cov = np.cov(x, y) # 求协方差矩阵的特征值和特征向量 eig_val, eig_vec = np.linalg.eig(cov) # 求出特征向量后,我们需要选择降维后的数据维度 k(n 维数据降为 k 维数据),但我们的数据只有2维,所以只能降1维 eig_pairs = [(np.abs(eig_val[i]), eig_vec[:, i]) for i in range(len(eig_val))] eig_pairs.sort(reverse=True) feature = eig_pairs[0][1] # 转化得到降维后的数据 new_data_reduced = np.transpose(np.dot(feature, np.transpose(data))) new_y = np.zeros(len(x)) plt.plot(new_data_reduced, new_y, 'b.', label='降维后数据') plt.legend() plt.show()

结果: 在这里插入图片描述

附: 为什么要用协方差矩阵来算PCA?请看这篇,讲得很好。 https://blog.csdn.net/a10767891/article/details/80288463



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3