PCA全稱Principal Component Analysis,即主成分分析,是一種經常使用的數據降維方法。它能夠經過線性變換將原始數據變換爲一組各維度線性無關的表示,以此來提取數據的主要線性份量。javascript
z=wTx
其中,z爲低維矩陣,x爲高維矩陣,w爲二者之間的映射關係。假如咱們有二維數據(原始數據有兩個特徵軸——特徵1和特徵2)以下圖所示,樣本點分佈爲斜45°的藍色橢圓區域。css
PCA算法認爲斜45°爲主要線性份量,與之正交的虛線是次要線性份量(應當捨去以達到降維的目的)。html
劃重點:html5
相應的,PCA解釋方差並對離羣點很敏感:少許原遠離中心的點對方差有很大的影響,從而也對特徵向量有很大的影響。java
一個矩陣與一個列向量A相乘,等到一個新的列向量B,則稱該矩陣爲列向量A到列向量B的線性變換。node
咱們但願投影后投影值儘量分散,而這種分散程度,能夠用數學上的方差來表述。python
即尋找一個一維基,使得全部數據變換爲這個基上的座標表示後,方差值最大。jquery
解釋:方差越大,說明數據越分散。一般認爲,數據的某個特徵維度上數據越分散,該特徵越重要。linux
對於更高維度,還有一個問題須要解決,考慮三維降到二維問題。與以前相同,首先咱們但願找到一個方向使得投影后方差最大,這樣就完成了第一個方向的選擇,繼而咱們選擇第二個投影方向。若是咱們仍是單純只選擇方差最大的方向,很明顯,這個方向與第一個方向應該是「幾乎重合在一塊兒」,顯然這樣的維度是沒有用的,所以,應該有其餘約束條件——就是正交android
解釋:從直觀上說,讓兩個字段儘量表示更多的原始信息,咱們是不但願它們之間存在(線性)相關性的,由於相關性意味着兩個字段不是徹底獨立,必然存在重複表示的信息。
字段在本文中指,降維後的樣本的特徵軸
數學上能夠用兩個字段的協方差表示其相關性:
當協方差爲0時,表示兩個字段線性不相關。
總結一下,PCA的優化目標是:
將一組N維向量降爲K維(K大於0,小於N),其目標是選擇K個單位正交基,使得原始數據變換到這組基上後,各字段兩兩間協方差爲0,而字段的方差則儘量大。
因此如今的重點是方差和協方差
在統計學上,協方差用來刻畫兩個隨機變量之間的相關性,反映的是變量之間的二階統計特性。考慮兩個隨機變量Xi 和 Xj ,它們的協方差定義爲:
協方差矩陣:
假設有m個變量,特徵維度爲2,a1表示變量1的a特徵。那麼構成的數據集矩陣爲:
再假設它們的均值都是0,對於有兩個均值爲0的m維向量組成的向量組,
能夠發現對角線上的元素是兩個字段的方差,其餘元素是兩個字段的協方差,二者都被統一到了一個矩陣——協方差矩陣中。
回顧一下前面所說的PCA算法的目標:方差max,協方差min!!
要達到PCA降維目的,等價於將協方差矩陣對角化:即除對角線外的其餘元素化爲0,而且在對角線上將元素按大小從上到下排列,這樣咱們就達到了優化目的。
設原始數據矩陣X對應的協方差矩陣爲C,而P是一組基按行組成的矩陣,設Y=PX,則Y爲X對P作基變換後的數據。設Y的協方差矩陣爲D,咱們推導一下D與C的關係:
解釋:想讓原始數據集X =>pca成數據集Y,使得Y的協方差矩陣是個對角矩陣。
有上述推導可得,如有矩陣P能使X的協方差矩陣對角化,則P就是咱們要找的PCA變換。
優化目標變成了尋找一個矩陣P,知足是一個對角矩陣,而且對角元素按從大到小依次排列,那麼P的前K行就是要尋找的基,用P的前K行組成的矩陣乘以X就使得X從N維降到了K維,並知足上述優化條件。
首先,原始數據矩陣X的協方差矩陣C是一個實對稱矩陣,它有特殊的數學性質:
P是協方差矩陣的特徵向量單位化後按行排列出的矩陣,其中每一行都是C的一個特徵向量。若是設P按照中特徵值的從大到小,將特徵向量從上到下排列,則用P的前K行組成的矩陣乘以原始數據矩陣X,就獲得了咱們須要的降維後的數據矩陣Y。
小例子:
https://www.jianshu.com/u/1ebb0a071a9f
import numpy as np
import pandas as pd
df = pd.read_csv('D:\\mlInAction\\iris.data')
df.head()
df.columns = ['sepal_len', 'sepal_wid', 'petal_len', 'petal_wid', 'class']
df.head()
# split data table into data X and class labels y
X = df.iloc[:, 0:4].values
y = df.iloc[:, 4].values
from sklearn.preprocessing import StandardScaler
X_std = StandardScaler().fit_transform(X)
print(X_std)
mean_vec = np.mean(X_std, axis=0)
cov_mat = (X_std - mean_vec).T.dot((X_std - mean_vec)) / (X_std.shape[0] - 1)
# 協方差和方差都是除以n-1
print('Covariance matrix \n%s' % cov_mat)
print('NumPy covariance matrix: \n%s' % np.cov(X_std.T))
# 重點:協方差矩陣計算的是不一樣維度之間的協方差,而不是不一樣樣本之間。
# 拿到一個樣本矩陣,首先要明確的就是行表明什麼,列表明什麼。
cov_mat = np.cov(X_std.T)
eig_vals, eig_vecs = np.linalg.eig(cov_mat) # 利用numpy求特徵值和特徵向量
print('Eigenvectors \n%s' % eig_vecs)
print('\nEigenvalues \n%s' % eig_vals)
# Make a list of (eigenvalue, eigenvector) tuples
eig_pairs = [(np.abs(eig_vals[i]), eig_vecs[:, i]) for i in range(len(eig_vals))]
print(eig_pairs)
print('----------')
# Sort the (eigenvalue, eigenvector) tuples from high to low
eig_pairs.sort(key=lambda x: x[0], reverse=True)
# Visually confirm that the list is correctly sorted by decreasing eigenvalues
print('Eigenvalues in descending order:')
for i in eig_pairs:
print(i[0])
tot = sum(eig_vals)
var_exp = [(i / tot) * 100 for i in sorted(eig_vals, reverse=True)]
print(var_exp)
cum_var_exp = np.cumsum(var_exp)
cum_var_exp
a = np.array([1, 2, 3, 4])
print(a)
print('-----------')
print(np.cumsum(a))
matrix_w = np.hstack((eig_pairs[0][1].reshape(4, 1),
eig_pairs[1][1].reshape(4, 1)))
print('Matrix W:\n', matrix_w)
Y = X_std.dot(matrix_w)
Y
from matplotlib import pyplot as plt
plt.figure(figsize=(6, 4))
for lab, col in zip(('Iris-setosa', 'Iris-versicolor', 'Iris-virginica'),
('blue', 'red', 'green')):
plt.scatter(X[y == lab, 0],
X[y == lab, 1],
label=lab,
c=col)
plt.xlabel('sepal_len')
plt.ylabel('sepal_wid')
plt.legend(loc='best')
plt.tight_layout()
plt.show()
plt.figure(figsize=(6, 4))
for lab, col in zip(('Iris-setosa', 'Iris-versicolor', 'Iris-virginica'),
('blue', 'red', 'green')):
plt.scatter(Y[y == lab, 0],
Y[y == lab, 1],
label=lab,
c=col)
plt.xlabel('Principal Component 1')
plt.ylabel('Principal Component 2')
plt.legend(loc='lower center')
plt.tight_layout()
plt.show()
進一步討論 根據上面對PCA的數學原理的解釋,咱們能夠了解到一些PCA的能力和限制。PCA本質上是將方差最大的方向做爲主要特徵,而且在各個正交方向上將數據「離相關」,也就是讓它們在不一樣正交方向上沒有相關性。
所以,PCA也存在一些限制,例如它能夠很好的解除線性相關,可是對於高階相關性就沒有辦法了,對於存在高階相關性的數據,能夠考慮Kernel PCA,經過Kernel函數將非線性相關轉爲線性相關,關於這點就不展開討論了。另外,PCA假設數據各主特徵是分佈在正交方向上,若是在非正交方向上存在幾個方差較大的方向,PCA的效果就大打折扣了。
最後須要說明的是,PCA是一種無參數技術,也就是說面對一樣的數據,若是不考慮清洗,誰來作結果都同樣,沒有主觀參數的介入,因此PCA便於通用實現,可是自己沒法個性化的優化。