有数据集={X,Y,Z},是三维度的数据,即此此数据集中的样例有3个特征
# -*- coding: utf-8 -*-
"""
@author: 蔚蓝的天空Tom
Talk is cheap, show me the code
Aim:计算两个维度的协方差covariance
"""
import numpy as np
class CCovariance(object):
'''计算X,Y这俩维度的协方差
'''
def __init__(self, X, Y):
self.X = X
self.Y = Y
self.Covariance_way1()
self.Covariance_way2()
self.Covariance_way3()
def Covariance_way1(self):
'''
协方差公式法计算两个等长向量的协方差convariance
'''
X,Y = np.array(self.X), np.array(self.Y)
meanX, meanY = np.mean(X), np.mean(Y)
n = np.shape(X)[0]
#按照协方差公式计算协方差,Note:分母一定是n-1
covariance = sum(np.multiply(X-meanX, Y-meanY))/(n-1)
print('协方差公式法求得的协方差:', covariance)
return covariance
def Covariance_way2(self):
'''
向量中心化方法计算两个等长向量的协方差convariance
'''
X,Y = np.array(self.X),np.array(self.Y)
n = np.shape(X)[0]
centrX = X-np.mean(X)
centrY = Y-np.mean(Y)
convariance = sum(np.multiply(centrX, centrY))/(n-1)
print('向量中心化方法求得协方差:', convariance)
return convariance
def Covariance_way3(self):
'''
numpy.conv(X,Y)提供的协方差函数求协方差
'''
conv = np.cov(self.X, self.Y)
print('np.cov(X,Y)求得的X的方差:', conv[0,0])
print('np.cov(X,Y)求得的Y的方差:', conv[1,1])
print('np.cov(X,Y)求得的X和Y的协方差:',conv[0,1])
if __name__=='__main__':
X = [10,15,23,11,42,9,11,8,11,21]
Y = [15,46,21,9,45,48,21,5,12,20]
c = CCovariance(X,Y)
runfile('C:/Users/tom/covariance.py', wdir='C:/Users/tom')
X: [10, 15, 23, 11, 42, 9, 11, 8, 11, 21]
Y: [15, 46, 21, 9, 45, 48, 21, 5, 12, 20]
协方差公式法求得的协方差: 74.5333333333
向量中心化方法求得协方差: 74.5333333333
np.cov(X,Y)求得的X的方差: 108.322222222
np.cov(X,Y)求得的Y的方差: 260.622222222
np.cov(X,Y)求得的X和Y的协方差: 74.5333333333
In [37]:
人肉出品,代码详见如下:
# -*- coding: utf-8 -*-
"""
@author: 蔚蓝的天空Tom
Talk is cheap, show me the code
Aim:计算一个多维度样本的协方差矩阵covariance matrix
Note:协方差矩阵是计算的样本中每个特征之间的协方差,所以协方差矩阵是特征个数阶的对称阵
"""
import numpy as np
class CCovMat(object):
'''计算多维度样本集的协方差矩阵
Note:请保证输入的样本集m×n,m行样例,每个样例n个特征
'''
def __init__(self, samples):
#样本集shpae=(m,n),m是样本总数,n是样本的特征个数
self.samples = samples
self.covmat1 = [] #保存方法1求得的协方差矩阵
self.covmat2 = [] #保存方法1求得的协方差矩阵
#用方法1计算协方差矩阵
self._calc_covmat1()
#用方法2计算协方差矩阵
self._calc_covmat2()
def _covariance(self, X, Y):
'''
计算两个等长向量的协方差convariance
'''
n = np.shape(X)[0]
X, Y = np.array(X), np.array(Y)
meanX, meanY = np.mean(X), np.mean(Y)
#按照协方差公式计算协方差,Note:分母一定是n-1
cov = sum(np.multiply(X-meanX, Y-meanY))/(n-1)
return cov
def _calc_covmat1(self):
'''
方法1:根据协方差公式和协方差矩阵的概念计算协方差矩阵
'''
S = self.samples #样本集
na = np.shape(S)[1] #特征attr总数
self.covmat1 = np.full((na, na), fill_value=0.) #保存协方差矩阵
for i in range(na):
for j in range(na):
self.covmat1[i,j] = self._covariance(S[:,i], S[:,j])
return self.covmat1
def _calc_covmat2(self):
'''
方法2:先样本集中心化再求协方差矩阵
'''
S = self.samples #样本集
ns = np.shape(S)[0] #样例总数
mean = np.array([np.mean(attr) for attr in S.T]) #样本集的特征均值
print('样本集的特征均值:\n',mean)
centrS = S - mean ##样本集的中心化
print('样本集的中心化(每个元素将去当前维度特征的均值):\n', centrS)
#求协方差矩阵
self.covmat2 = np.dot(centrS.T, centrS)/(ns - 1)
return self.covmat2
def CovMat1(self):
return self.covmat1
def CovMat2(self):
return self.covmat2
if __name__=='__main__':
'10样本3特征的样本集'
samples = np.array([[10, 15, 29],
[15, 46, 13],
[23, 21, 30],
[11, 9, 35],
[42, 45, 11],
[9, 48, 5],
[11, 21, 14],
[8, 5, 15],
[11, 12, 21],
[21, 20, 25]])
cm = CCovMat(samples)
print('样本集(10行3列,10个样例,每个样例3个特征):\n', samples)
print('按照协方差公式求得的协方差矩阵:\n', cm.CovMat1())
print('按照样本集的中心化求得的协方差矩阵:\n', cm.CovMat1())
print('numpy.cov()计算的协方差矩阵:\n', np.cov(samples.T))
runfile('C:/Users/tom/covariance_matrix.py', wdir='C:/Users/tom')
样本集(10行3列,10个样例,每个样例3个特征):
[[10 15 29]
[15 46 13]
[23 21 30]
[11 9 35]
[42 45 11]
[ 9 48 5]
[11 21 14]
[ 8 5 15]
[11 12 21]
[21 20 25]]
样本集的特征均值:
[ 16.1 24.2 19.8]
样本集的中心化(每个元素将去当前维度特征的均值):
[[ -6.1 -9.2 9.2]
[ -1.1 21.8 -6.8]
[ 6.9 -3.2 10.2]
[ -5.1 -15.2 15.2]
[ 25.9 20.8 -8.8]
[ -7.1 23.8 -14.8]
[ -5.1 -3.2 -5.8]
[ -8.1 -19.2 -4.8]
[ -5.1 -12.2 1.2]
[ 4.9 -4.2 5.2]]
按照协方差公式求得的协方差矩阵:
[[ 108.32222222 74.53333333 -10.08888889]
[ 74.53333333 260.62222222 -106.4 ]
[ -10.08888889 -106.4 94.17777778]]
按照样本集的中心化求得的协方差矩阵:
[[ 108.32222222 74.53333333 -10.08888889]
[ 74.53333333 260.62222222 -106.4 ]
[ -10.08888889 -106.4 94.17777778]]
numpy.cov()计算的协方差矩阵:
[[ 108.32222222 74.53333333 -10.08888889]
[ 74.53333333 260.62222222 -106.4 ]
[ -10.08888889 -106.4 94.17777778]]
发现那种方法都可以正确求得样本集的协方差矩阵。
最后总结:心中记住协方差矩阵是求一个样本集中的不同维度特征的协方差(不是不同样本集之间的协方差矩阵),然后再确定样本集的一行是特征,还是一列是特征维度。然后按照协方差矩阵的概念求解就可以了,最后发现求解过程很简单。重要是要把协方差的概念以及应用意义理解。
(end)