機器學習入門-主成分分析(PCA)

 

主成分分析:ide

                用途:降維中最經常使用的一種方法ui

                目標:提取有用的信息(基於方差的大小)spa

                存在的問題:降維後的數據將失去本來的數據意義3d

向量的內積:A*B = |A|*|B|*cos(a) 若是|B| = 1,那麼A*B = |A| * cos(a) 即在B的方向上對A作投影code

 

基變化: 若是向量爲(3, 2)那麼它能夠有(1, 0)和(0, 1)一組基進行表示,這兩個基是正交的component

在基變化過程當中,每個基都是正交的即線性無關orm

數據與第一個基進行內積,造成一個新的份量,數據與第二個基作內積,造成第二個份量,因爲基是正交的,而內積表示的是投影,所以這兩個份量也是正交的blog

即 1/m ai.dot(bi) = 0。排序

方差:變量的方差越大,其分散程度也就越大,方差 (ai-ui).dot((ai-ui).T) ui表示的是樣本的均值ip

協方差:兩個向量的內積,協方差越小,表示兩個向量越不類似cov(a, b) = 1/m*(a.dot(b.T))

 引入協方差的目的:

                 若是單純只看變化後的方差大小,那麼求得的基可能都在方差最大的方向附件進行徘徊,由於咱們爲了使變換後的特徵儘量的表示原始信息,咱們使得變化後的特徵是正交的狀況,即特徵之間線性無關,協方差cov=0 

 

結合上述的兩個條件:第一:變換後的矩陣的方差最大1/m ai.dot(ai.T)

                                     第二:變換後的矩陣的協方差等於0  1/m ai.dot(bi.T)

 

 

咱們引入了協方差矩陣,協方差矩陣對角線是方差,非對角線上是協方差 

公式: 1/m X.dot(X.T)

1/m * Y.dot(Y.T) = 1/m PX.dot((PX).T) = 1/m(P* X * X^T * P^T)

令上面的式子中的 X*X^T等於C,那麼上面的式子就是 1/m * Y.dot(Y.T) = 1/m(P* C * P^T)

咱們須要使得1/m * Y.dot(Y.T) 知足上述兩個條件,即對C作一個對角化變化,使得變化後的矩陣對角線上的表示方差(從大到小排列), 非對角線上等於0 

 

這個問題前人已經研究了很透,即上述變化的P就是C的特徵向量,而C等於X*X^T 

 

咱們只須要求得X*X^T的特徵向量便可

上述的過程的實現步驟:

                          1.對特徵進行標準化

                          2.去均值

                          3.求協方差矩陣 X*X^T 

                          4.協方差矩陣的特徵向量

                          5.使用前幾維的特徵向量與特徵進行內積,實現特徵降維

 

代碼: 

第一步:導入數據, 進行列名賦值

第二步:提取特徵和標籤

第三步:對每個特徵進行物體類別畫直方圖,研究不一樣變量對特徵分佈的影響

第四步:對樣本特徵進行標準化操做

第五步:對樣本去均值並構造協方差矩陣X.dot(X.T)

 

第六步:對構造好的協方差矩陣求特徵值和特徵向量

第七步:將求得的特徵值和特徵向量進行組合, 對組合的特徵進行排序操做,將排序後的特徵進行使用np.cumsum對特徵值進行加和

第八步:使用條形圖和步進圖對特徵值和加和後的特徵進行做圖操做

第九步:選取前兩個特徵向量與標準化後的特徵進行內積操做,得到降維後的特徵

第十步:對降維後的特徵畫出散點圖

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt


# 第一步 數據讀取
data = pd.read_csv('iris.data')

data.columns = ['sepal_len', 'sepal_wid', 'petal_len', 'petal_wid', 'classes']

# 第二步 提取特徵
X = data[['sepal_len', 'sepal_wid', 'petal_len', 'petal_wid']].values
y = data['classes'].values

feature_names = ['sepal_len', 'sepal_wid', 'petal_len', 'petal_wid']
label_names = data['classes'].unique()

# 第三步 對每個特徵的樣品類別作直方圖
for feature in range(len(feature_names)):
    plt.subplot(2, 2, feature+1)
    for label in label_names:
        plt.hist(X[y==label, feature], bins=10, alpha=0.5, label=label)
    plt.legend(loc='best')
plt.show()

                           不一樣變量對類別分佈的影響

# 第四步 對特徵進行標準化操做
from sklearn.preprocessing import StandardScaler

std_feature = StandardScaler().fit_transform(X)

# 第五步 對特徵去除均值, 並構造協方差矩陣, 也可使用np.conv進行構造
mean_fea = std_feature.mean(axis=0)
cov_matrix = (std_feature - mean_fea).T.dot(std_feature-mean_fea)

# 第六步 使用np.linalg.eig 求出協方差矩陣的特徵值和特徵向量

eig_val, eig_vector = np.linalg.eig(cov_matrix)

# 第七步:咱們將特徵值和特徵向量進行組合

eig_paries = [(eig_val[j], eig_vector[:, j]) for j in range(len(eig_val))]

# 得到對組合的特徵值進行排序,得到重要性的佔比
sum_val = np.sum(eig_val)
feature_importance = [eig_v[0]/sum_val * 100 for eig_v in sorted(eig_paries, key=lambda x:x[0], reverse=True)]
print(feature_importance)
# 使用np.cumsum進行兩兩的先後加和
su_feature_importance = np.cumsum(feature_importance)
# 第八步:對特徵重要性進行做圖操做
figure = plt.figure(figsize=(8, 6))
plt.bar(range(4), feature_importance, align='center', label='identity explain variance', alpha=0.5)
# plt.step表示的是步進圖, where表示的線條的表示方式
plt.step(range(4), su_feature_importance, where='mid', label='cumidentity explain variance')
plt.xlabel('PC component')
plt.ylabel('variance importance')
plt.show()

                               特徵值重要比例圖

# 第九步:使用前兩個特徵向量進行矩陣的變換

eig_vector_two = np.vstack([eig_paries[0][1], eig_paries[1][1]])
trans_std_X = std_feature.dot(eig_vector_two.T)

# 第十步: 對變化後的數據進行畫圖操做

figure = plt.figure(figsize=(8, 6))
for label, c in zip(label_names, ['red', 'green', 'black']):
    plt.scatter(std_feature[y==label][:, 0], std_feature[y==label][:, 1], c=c, label=label, alpha=0.6, s=20)
    leg = plt.legend(loc='best')
    leg.get_frame().set_alpha(0.6)
    plt.xlabel(feature_names[0])
    plt.ylabel(feature_names[1])
plt.show()


figure = plt.figure(figsize=(8, 6))
for label, c in zip(label_names, ['red', 'green', 'black']):
    plt.scatter(trans_std_X[y==label][:, 0], trans_std_X[y==label][:, 1], c=c, label=label, alpha=0.6, s=20)
    leg = plt.legend(loc='best')
    leg.get_frame().set_alpha(0.6)
    plt.xlabel('PC1')
    plt.ylabel('PC2')
plt.show()

                           原始特徵圖                                                               降維後的特徵圖

相關文章
相關標籤/搜索