机器学习之主成分分析

127 阅读2分钟

本章数学公式太难了,作为初学者还是了解概念调包即可

主成分分析(PCA)

思想

  • 主要是利用 正交变换,把 线性相关变量的数据转化为 线性无关的数据。线性无关的数据称为 主成分,该算法因此得名。变换后的数据不仅是 线性无关的,而且是 相互独立(协方差Cov(X,Y)=0)
  • 新变量是正交变换中 方差和最大的,最大的称为 第一主成分,次大的是 第二主成分等等。

数学推导(todo)

  • 先占个坑,有空回来看数学推导,这里的结论是 xm维随机变量,x的协方差矩阵(xTx),降维后的PCA(X)=XW,其中W的前k个特征向量矩阵设x是m维随机变量,\sum是x的协方差矩阵(x^T * x),降维后的PCA(X) = X*W,其中W是\sum的前k个特征向量矩阵

实现

import numpy as np  
import matplotlib.pyplot as plt  
data = np.loadtxt('PCA_dataset.csv', delimiter=',')  
print(type(data))  
_,(ax1,ax2) = plt.subplots(1,2)  
print(type(ax1))  
ax1.scatter(data[:,0],data[:,1],color='red',s=10)  
def pca(x,k):  
    d,m = x.shape  
    if d < k:  
        print("k应该小于特征数")  
        return x,None  
    # 中心化  
    x = x - np.mean(x,axis=0)  
    # 计算协方差矩阵  
    cov = x.T @ x  
    # 计算特征值与特征向量  
    eig_val, eig_vec = np.linalg.eig(cov)  
    # 取最大的k个,因为加了负数,所以原本排序的规则颠倒过来  
    idx = np.argsort(-eig_val)[:k]  
    w = eig_vec[:,idx]  
    x = x @ w  
    return x,w  
x,w = pca(data,2)  
ax2.scatter(x[:,0],x[:,1],color='blue',s=10)  
x_min, x_max = min(data[:, 0].min(), x[:, 0].min()), max(data[:, 0].max(), x[:, 0].max())  
y_min, y_max = min(data[:, 1].min(), x[:, 1].min()), max(data[:, 1].max(), x[:, 1].max())  
  
# 设置两个子图的坐标轴范围一致  
ax1.set_xlim(x_min, x_max)  
ax1.set_ylim(y_min, y_max)  
ax2.set_xlim(x_min, x_max)  
ax2.set_ylim(y_min, y_max)  
  
# (可选)设置相同的刻度  
ax1.set_xticks(np.linspace(x_min, x_max, 10))  # 例如,在x轴范围内均匀设置5个刻度  
ax1.set_yticks(np.linspace(y_min, y_max, 10))  # 在y轴范围内均匀设置5个刻度  
ax2.set_xticks(np.linspace(x_min, x_max, 10))  # 与 ax1 设置相同的刻度  
ax2.set_yticks(np.linspace(y_min, y_max, 10))  # 与 ax1 设置相同的刻度  
plt.show()

实现之调包

from sklearn.decomposition import PCA  
# sklearn中调包使用  
x = data - np.mean(data,axis=0)  
data = np.loadtxt('PCA_dataset.csv', delimiter=',')  
pca = PCA(n_components=2).fit(x)  
w = pca.components_.T  
print('变换矩阵是: {}\n'.format(w))  
x_pca = x @ w  
ax = plt.subplot()  
ax.set_xticks(np.linspace(x_min, x_max, 5))  # 与 ax1 设置相同的刻度  
ax.set_yticks(np.linspace(y_min, y_max, 5))  # 与 ax1 设置相同的刻度  
ax.set_xlim(x_min, x_max)  
ax.set_ylim(y_min, y_max)  
ax.scatter(x_pca[:,0],x_pca[:,1])