PCA的Python实现

本文主要参考下面的文章,文中的代码基本是把第二篇文章的代码手写实现了一下。
- pca讲解:http://www.cnblogs.com/jerrylead/archive/2011/04/18/2020209.html
- python实现:http://blog.csdn.net/u012162613/article/details/42177327

总体代码

"""
总的代码.
Func: 对原始的特征矩阵进行降维, lowDataMat为降维之后返回新的特征矩阵。
Usage: lowDDataMat = pca(dataMat, k)
"""
# 零均值化
def zeroMean(dataMat):
    # 求各列特征的平均值
    meanVal = np.mean(dataMat, axis=0)
    newData = dataMat - meanVal
    return newData, meanVal
def pca(dataMat,k):  
    newData,meanVal=zeroMean(dataMat)  
    covMat=np.cov(newData,rowvar=0)    #求协方差矩阵,return ndarray;若rowvar非0,一列代表一个样本,为0,一行代表一个样本  

    eigVals,eigVects=np.linalg.eig(np.mat(covMat))#求特征值和特征向量,特征向量是按列放的,即一列代表一个特征向量  
    eigValIndice=np.argsort(eigVals)            #对特征值从小到大排序  
    k_eigValIndice=eigValIndice[-1:-(k+1):-1]   #最大的k个特征值的下标  
    k_eigVect=eigVects[:,k_eigValIndice]        #最大的k个特征值对应的特征向量  
    lowDDataMat=newData*k_eigVect               #低维特征空间的数据
    return lowDDataMat
#     reconMat=(lowDDataMat*k_eigVect.T)+meanVal  #重构数据  
#     return lowDDataMat,reconMat  

下面逐步来实现PCA

(0)先准备好数据

import numpy as np
# n维的原始数据,本例中n=2。
data = np.array([[2.5,2.4], [0.5, 0.7], [2.2, 2.9], [1.9, 2.2], [3.1, 3.0], [2.3, 2.7],\
                 [2, 1.6], [1, 1.1], [1.5, 1.6], [1.1, 0.9]])
print data
[[ 2.5  2.4]
 [ 0.5  0.7]
 [ 2.2  2.9]
 [ 1.9  2.2]
 [ 3.1  3. ]
 [ 2.3  2.7]
 [ 2.   1.6]
 [ 1.   1.1]
 [ 1.5  1.6]
 [ 1.1  0.9]]

(1)零均值化

# (1)零均值化
def zeroMean(dataMat):
    # 求各列特征的平均值
    meanVal = np.mean(dataMat, axis=0)
    newData = dataMat - meanVal
    return newData, meanVal
newData, meanVal = zeroMean(data)
print 'the newData is \n', newData
print 'the meanVal is \n', meanVal
the newData is 
[[ 0.69  0.49]
 [-1.31 -1.21]
 [ 0.39  0.99]
 [ 0.09  0.29]
 [ 1.29  1.09]
 [ 0.49  0.79]
 [ 0.19 -0.31]
 [-0.81 -0.81]
 [-0.31 -0.31]
 [-0.71 -1.01]]
the meanVal is 
[ 1.81  1.91]

(2)对各维特征的协方差矩阵

# (2)求协方差矩阵,rowvar=036表示每列对应一维特征
covMat = np.cov(newData, rowvar=0)
print covMat
# 若rowvar=1表示没行是一维特征,每列表示一个样本,显然咱们的数据不是这样的
# covMat2 = np.cov(newData, rowvar=1)
# print covMat2
[[ 0.61655556  0.61544444]
 [ 0.61544444  0.71655556]]

(3)求(2)中的协方差矩阵的特征值和特征向量

# (3)求协方差矩阵的特征值和特征向量,利用numpy中的线性代数模块linalg中的eig函数
eigVals, eigVects = np.linalg.eig(np.mat(covMat))
print '特征值为:\n', eigVals
print '特征向量为\n', eigVects
特征值为:
[ 0.0490834   1.28402771]
特征向量为
[[-0.73517866 -0.6778734 ]
 [ 0.6778734  -0.73517866]]

上面的结果中:
特征值为:

[ 0.0490834 1.28402771]

特征向量为

[[-0.73517866 -0.6778734 ]

[0.6778734 -0.73517866]]

特征值0.0490834对应的特征向量是第一列(-0.73517866 0.6778734)T

(4)降维到k维(k < n)

# (4)保留主要的成分,将特征值按照从大到小的顺序排序,选择其中最大的k个,然后将对应的k个特征向量分别作为列向量组成的特征向量矩阵。
# 比如本例子中保留1.28402771对应的特征向量(-0.6778734 -0.73517866)^T
k = 1 # 此例中取k = 1
eigValIndice = np.argsort(eigVals) # 从小到大排序
n_eigValIndice = eigValIndice[-1:-(k+1):-1] # 取值最大的k个下标
n_eigVect = eigVects[:, n_eigValIndice] # 取对应的k个特征向量
print n_eigVect
print n_eigVect.shape
lowDataMat = newData*n_eigVect # 低维特征空间的数据
reconMat = (lowDataMat * n_eigVect.T) + meanVal # 重构数据,得到降维之后的数据
print '将样本点投影到选取的低维特征向量上,实际使用的是这个结果作为新的特征:\n', lowDataMat
print '降维之后的样本:\n', reconMat
[[-0.6778734 ]
 [-0.73517866]]
(2L, 1L)

将样本点投影到选取的低维特征向量上,实际使用的是这个结果作为新的特征

[[-0.82797019]
 [ 1.77758033]
 [-0.99219749]
 [-0.27421042]
 [-1.67580142]
 [-0.9129491 ]
 [ 0.09910944]
 [ 1.14457216]
 [ 0.43804614]
 [ 1.22382056]]
降维之后的样本:
[[ 2.37125896  2.51870601]
 [ 0.60502558  0.60316089]
 [ 2.48258429  2.63944242]
 [ 1.99587995  2.11159364]
 [ 2.9459812   3.14201343]
 [ 2.42886391  2.58118069]
 [ 1.74281635  1.83713686]
 [ 1.03412498  1.06853498]
 [ 1.51306018  1.58795783]
 [ 0.9804046   1.01027325]]

降维之后的样本:

[[ 2.37125896 2.51870601]
[ 0.60502558 0.60316089]
[ 2.48258429 2.63944242]
[ 1.99587995 2.11159364]
[ 2.9459812 3.14201343]
[ 2.42886391 2.58118069]
[ 1.74281635 1.83713686]
[ 1.03412498 1.06853498]
[ 1.51306018 1.58795783]
[ 0.9804046 1.01027325]]
原始样本:
[[ 2.5 2.4]
[ 0.5 0.7]
[ 2.2 2.9]
[ 1.9 2.2]
[ 3.1 3. ]
[ 2.3 2.7]
[ 2. 1.6]
[ 1. 1.1]
[ 1.5 1.6]
[ 1.1 0.9]]
通过比较可以看出,通过降维之后我们成功地实现了特征从二维降到了一维,降维之后会和原始数据有一定的变化,
我们可以认为通过这种方式消除了一部分的噪声(当然实际上很可能损失了部分真实信息)。
——————————————-分割线———————————————————

利用sklearn实现PCA

# 原始数据
data = np.array([[2.5,2.4], [0.5, 0.7], [2.2, 2.9], [1.9, 2.2], [3.1, 3.0], [2.3, 2.7],\
                 [2, 1.6], [1, 1.1], [1.5, 1.6], [1.1, 0.9]])
# print data
# 好吧,就是这么简单
from sklearn.decomposition import PCA
pca = PCA(n_components=1)
new_feature = pca.fit_transform(data)
print new_feature

[[-0.82797019]
[ 1.77758033]
[-0.99219749]
[-0.27421042]
[-1.67580142]
[-0.9129491 ]
[ 0.09910944]
[ 1.14457216]
[ 0.43804614]
[ 1.22382056]]

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是关于 PLS 和 PCAPython 实现案例。 首先,我们需要导入必要的库,使用的是 scikit-learn 库: ```python from sklearn.cross_decomposition import PLSRegression from sklearn.decomposition import PCA from sklearn.datasets import load_diabetes from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error import numpy as np ``` 接下来,我们使用 PLS 和 PCA 对糖尿病数据集进行降维和建模,并计算均方误差(MSE): ```python # 加载糖尿病数据集 diabetes = load_diabetes() X = diabetes.data y = diabetes.target # 将数据集分为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 使用 PLS 进行建模并计算 MSE pls = PLSRegression(n_components=3) pls.fit(X_train, y_train) y_pred_pls = pls.predict(X_test) mse_pls = mean_squared_error(y_test, y_pred_pls) print("MSE with PLS: ", mse_pls) # 使用 PCA 进行建模并计算 MSE pca = PCA(n_components=3) pca.fit(X_train) X_train_pca = pca.transform(X_train) X_test_pca = pca.transform(X_test) pls.fit(X_train_pca, y_train) y_pred_pca = pls.predict(X_test_pca) mse_pca = mean_squared_error(y_test, y_pred_pca) print("MSE with PCA-PLS: ", mse_pca) ``` 输出结果如下: ``` MSE with PLS: 3413.036870501397 MSE with PCA-PLS: 3427.601194414032 ``` 可以看到,使用 PLS 和 PCA 进行降维后建模,均方误差非常接近。 希望这个示例对您有所帮助。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值