Principal component analysis(PCA)主成分分析

PCA是将原始数据X通过数学方法降维,得到产生该形式数据的内在原因。

主要步骤为:

1)求原始数据X的协方差矩阵S

2)求S的最大特征值对应的K个特征向量并构成权重矩阵W

3)将W与X内积得到降维数据Z

注意:协方差矩阵计算的是不同属性之间的交互关系。so,如果数据集有2维属性,那么协方差矩阵就是2x2维;如果有4维属性,则协方差矩阵为4x4维。


本文以Iris数据为例,对其进行主成分分析,原始数据X.T为150x4:

[[ 5.1  3.5  1.4  0.2]
 [ 4.9  3.   1.4  0.2]
 [ 4.7  3.2  1.3  0.2]
 ..., 
 [ 6.5  3.   5.2  2. ]
 [ 6.2  3.4  5.4  2.3]
 [ 5.9  3.   5.1  1.8]]
由于python中numpy.cov()分解协方差矩阵默认以行中存储属性值(而不是列),所以在cov时要对数据进行转置,计算得到的协方差矩阵S为4x4:

[[ 0.68569351 -0.03926846  1.27368233  0.5169038 ]
 [-0.03926846  0.18800403 -0.32171275 -0.11798121]
 [ 1.27368233 -0.32171275  3.11317942  1.29638747]
 [ 0.5169038  -0.11798121  1.29638747  0.58241432]]
对S分解,得到最大两个特征值对应的特征向量构成的eVact为2x4:
[[ 0.36158968 -0.65653988 -0.58099728  0.31725455]
 [-0.08226889 -0.72971237  0.59641809 -0.32409435]]
将eVact(2x4)与原始数据X(4x150)做内积得到降维数据lowDData为2x150,转置后为:
[[-1.20372752 -2.20339819]
 [-0.94777551 -1.82208822]
 [-1.0933017  -2.01121873]
 ..., 
 [-2.00596351 -0.27069955]
 [-2.39807946 -0.51584852]
 [-2.2282685  -0.21616115]]
对应2维图为:


由2维数据可见,基本已经可分,但是只显示了2类,将得到的数据带入FCM聚类算法,得到的错分率和原始数据带入相同。

PCA代码如下:

# -*- coding: utf-8 -*-
"""
Created on Sat Oct  7 20:21:05 2017
@author: wjw
"""
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from FCM.fcm import fcm

def readText(filePath):
    
    lines = open(filePath,'r').readlines()
    data = []
    
    for line in lines:
        dataList = line.split(',')
        data.append([float(dataList[0]),float(dataList[1]),float(dataList[2]),
                     float(dataList[3])])
        
    return np.array(data).T #这里要把矩阵转置成行代表属性列,变成4x150的matrix

def pca(data):
    k=2
    meanVals = np.mean(data,axis=1) #对每一行(每个属性)求平均值,因为协方差的计算中需要减去均值
    # axis=0,求每一列的平均值;axis=1,求每一行的平均值 
    newMeanvals = []
    for meanVal in meanVals:
        newMeanvals.append([meanVal]) #单独构成list组成的list

    meanRemoved = data - newMeanvals # 这样才能对应相减
    covMat = np.cov(meanRemoved)
    print(covMat)
    print(covMat.shape)
    eigVals,eigVects = np.linalg.eig(np.mat(covMat))   

    #linalg中的eig方法,得到特征值和特征向量
    eig = list(zip(eigVals,eigVects)) # 将特征值特征向量压入一个eig
    dataframe = pd.DataFrame(eig,columns=['eigVals','eigVects'])#变成dataframe
    Ksorted = -np.sort(-dataframe.eigVals)[:k] # 降序排列取前k个
    index = []
    for i in range(dataframe.eigVals.size):
        for k in Ksorted:
            if dataframe.eigVals.iloc[i]==k: #iloc,iat,loc,at都是dataFrame中用来取值定位的方法,前者用index后者用行列名
                index.append(i)
    pickedata = dataframe.iloc[index,:] #得到特征值前k大对应的特征向量,并组合
    pickedeigVects =pickedata.eigVects
    array=[]
    for p in pickedeigVects:
        array.append(p.tolist()) #将matrix转换成list
    array = np.mat(np.array(array)) #list转换成matrix

    print(array)
    lowDdata = array * np.mat(data)#将原数据转换成维度较低的数据
    return lowDdata.T

def draw(data):
    plt.plot(data[:,0],data[:,1],'or')
    
    plt.show()

if __name__=="__main__":
    filePath = r"E:\data\iris.txt"
    data= readText(filePath)
    lowDdata = pca(data)
    print(lowDdata)
    draw(lowDdata)
    fmatrix = fcm(np.array(lowDdata),m=2,k=3)


猜你喜欢

转载自blog.csdn.net/ge_nious/article/details/78176592