PCA(主成分分析)python实现

回顾了下PCA的步骤,并用python实现。深刻的发现当年学的特征值、特征向量好强大。

Introduction to PCA

PCA是一种无监督的学习方式,是一种很常用的降维方法。在数据信息损失最小的情况下,将数据的特征数量由n,通过映射到另一个空间的方式,变为k(k<n)。

Sample Data

这里用一个2维的数据来说明PCA,选择2维的数据是因为2维的比较容易画图。
这是数据:

data
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])
data=np.matrix([[scaled_x[i],scaled_y[i]] for i in range(len(scaled_x))])

Step 1: 求平均值以及做normalization

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))])

画个图看看分布情况:

import matplotlib.pyplot as plt
plt.plot(scaled_x,scaled_y,'o')    
data distribution

Step 2: 求协方差矩阵(Covariance Matrix)

  • 协方差矩阵
    方差的定义为:
variance

协方差的定义为:

covariance

假设n为数据的特征数,那么协方差矩阵M, 为一个nn的矩阵,其中Mij为第i和第j个特征的协方差,对角线是各个特征的方差。
在我们的数据中,n=2,所以协方差矩阵是2
2的,
通过numpy我们可以很方便的得到:

cov=np.cov(scaled_x,scaled_y)

得到cov的结果为:
array([[ 0.61655556, 0.61544444],
[ 0.61544444, 0.71655556]])

  • 散度矩阵 Scatter Matrix
    另一种选择是用scatter matrix,定义为:
sactter matrix

由于我们之前已经做过normalization,因此对于我们来说,
这个矩阵就是 data*data的转置矩阵。

np.dot(np.transpose(data),data)

得到结果:
matrix([[ 5.549, 5.539],
[ 5.539, 6.449]])

我们发现,其实协方差矩阵和散度矩阵关系密切,散度矩阵 就是协方差矩阵乘以(总数据量-1)。因此他们的特征根特征向量是一样的。这里值得注意的一点就是,散度矩阵是SVD奇异值分解的一步,因此PCA和SVD是有很大联系的,他们的关系这里就不详细谈了,以后有机会再写下。

Step 3: 求协方差矩阵的特征根和特征向量

用numpy计算特征根和特征向量很简单,

eig_val, eig_vec = np.linalg.eig(cov)

但是他们代表的意义非常有意思,让我们将特征向量加到我们原来的图里:

plt.plot(scaled_x,scaled_y,'o',)
xmin ,xmax = scaled_x.min(), scaled_x.max()
ymin, ymax = scaled_y.min(), scaled_y.max()
dx = (xmax - xmin) * 0.2
dy = (ymax - ymin) * 0.2
plt.xlim(xmin - dx, xmax + dx)
plt.ylim(ymin - dy, ymax + dy)
plt.plot([eig_vec[:,0][0],0],[eig_vec[:,0][1],0],color='red')
plt.plot([eig_vec[:,1][0],0],[eig_vec[:,1][1],0],color='red')
data distribution with eig_vec

其中红线就是特征向量。有几点值得注意:

  • 特征向量之间是正交的,PCA其实就是利用特征向量的这个特点,重新构建新的空间体系

  • 特征向量代表着数据的pattern(模式),比如一条代表着y随着x的增大而增大的趋势,而另外一条,则是代表数据也有该方面的变化。所以特征向量的命名是很科学的,他代表着矩阵的特征。
    如果我们将数据直接乘以特征向量矩阵,那么其实我们只是以特征向量为基底,重新构建了空间,画个图,感受下吧:

    new_data=np.transpose(np.dot(eig_vec,np.transpose(data)))
    
new_data

蓝色的三角形就是经过坐标变换后得到的新点,其实他就是红色原点投影到红线、蓝线形成的。

Step 4: 选择主要成分

得到特征值和特征向量之后,我们可以根据特征值的大小,从大到小的选择K个特征值对应的特征向量。
这个用python的实现也很简单:

eig_pairs = [(np.abs(eig_val[i]), eig_vec[:,i]) for i in range(len(eig_val))]
eig_pairs.sort(reverse=True)

从eig_pairs选取前k个特征向量就行。这里,我们只有两个特征向量,选一个最大的。

feature=eig_pairs[0][1]

Step 5: 转化得到降维的数据

主要将原来的数据乘以经过筛选的特征向量组成的特征矩阵之后,就可以得到新的数据了。

new_data_reduced=np.transpose(np.dot(feature,np.transpose(data)))

output:

new_data

数据果然变成了一维的数据。
最后我们通过画图来理解下数据经过PCA到底发生了什么。

plt.plot(scaled_x,scaled_y,'o',color='red')
plt.plot([eig_vec[:,0][0],0],[eig_vec[:,0][1],0],color='red')
plt.plot([eig_vec[:,1][0],0],[eig_vec[:,1][1],0],color='blue')
plt.plot(new_data[:,0],new_data[:,1],'^',color='blue')
plt.plot(new_data_reduced[:,0],[1.2]*10,'*',color='green')
final_result

绿色的五角星是PCA处理过后得到的一维数据,为了能跟以前的图对比,将他们的高度定位1.2,其实就是红色圆点投影到蓝色线之后形成的点。这就是PCA,通过选择特征根向量,形成新的坐标系,然后数据投影到这个新的坐标系,在尽可能少的丢失信息的基础上实现降维。

总结

通过上述几步的处理,我们简单的实现了PCA第一个2维数据的处理,但是原理就是这样,我们可以很轻易的就依此实现多维的。

PCA的python3实现

import numpy as np
def pca(X,k):#k is the components you want
  #mean of each feature
  n_samples, n_features = X.shape
  mean=np.array([np.mean(X[:,i]) for i in range(n_features)])
  #normalization
  norm_X=X-mean
  #scatter matrix
  scatter_matrix=np.dot(np.transpose(norm_X),norm_X)
  #Calculate the eigenvectors and eigenvalues
  eig_val, eig_vec = np.linalg.eig(scatter_matrix)
  eig_pairs = [(np.abs(eig_val[i]), eig_vec[:,i]) for i in range(n_features)]
  # sort eig_vec based on eig_val from highest to lowest
  eig_pairs.sort(reverse=True)
  # select the top k eig_vec
  feature=np.array([ele[1] for ele in eig_pairs[:k]])
  #get new data
  data=np.dot(norm_X,np.transpose(feature))
  return data

用sklearn的PCA与我们的pca做个比较:

from sklearn.decomposition import PCA
X = np.array([[-1, 1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
pca=PCA(n_components=1)
pca.fit(X)
pca.transform(X)

得到结果:

array([[-0.50917706],
   [-2.40151069],
   [-3.7751606 ],
   [ 1.20075534],
   [ 2.05572155],
   [ 3.42937146]])

用我们的pca试试

pca(X,1)

得到结果:

array([[-0.50917706],
   [-2.40151069],
   [-3.7751606 ],
   [ 1.20075534],
   [ 2.05572155],
   [ 3.42937146]])

完全一致,完美~
值得一提的是,sklearn中PCA的实现,用了部分SVD的结果,果然他们因缘匪浅。

To Be Continued:

  1. The relationship between PCA and SVD
  2. The implementation of PCA, and the comparison between the results of my PCA and sklearn's PCA (completed)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,529评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,015评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,409评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,385评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,387评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,466评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,880评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,528评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,727评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,528评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,602评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,302评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,873评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,890评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,132评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,777评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,310评论 2 342

推荐阅读更多精彩内容

  • 前言 PCA是一种无参数的数据降维方法,在机器学习中很常用,这篇文章主要从三个角度来说明PCA是怎么降维的分别是方...
    WZFish0408阅读 51,312评论 6 36
  • 一前言 特征值 奇异值 二奇异值计算 三PCA 1)数据的向量表示及降维问题 2)向量的表示及基变换 3)基向量 ...
    Arya鑫阅读 10,478评论 2 43
  • 转自:主成分分析 - xiaoyu714543065的专栏 - 博客频道 - CSDN.NET 问题...
    horu阅读 1,180评论 1 3
  • 一.判别分析降维 LDA降维和PCA的不同是LDA是有监督的降维,其原理是将特征映射到低维上,原始数据的类别也...
    wlj1107阅读 11,882评论 0 4
  • PCA 算法主要是把高维度的数据降为低维度数据。典型地应用包括数据压缩和数据可视化。本文介绍 PCA 算法及其典型...
    kamidox阅读 4,932评论 6 12