首页
/ 主成分分析(PCA)原理与实现详解

主成分分析(PCA)原理与实现详解

2025-07-10 07:18:16作者:尤辰城Agatha

引言

主成分分析(Principal Component Analysis,PCA)是数据降维中最常用的技术之一。本教程将深入讲解PCA的数学原理,并通过Python代码实现完整的PCA流程。我们将从协方差矩阵的特征分解开始,逐步展示如何通过投影数据到特征向量来实现降维。

理论基础

协方差矩阵与特征分解

PCA的核心思想是通过线性变换将原始数据投影到一个新的坐标系中,这个坐标系的基向量是数据协方差矩阵的特征向量。具体步骤如下:

  1. 计算协方差矩阵:对于中心化后的数据矩阵X,协方差矩阵Σ的计算公式为:

    Σ = (1/N) XᵀX

  2. 特征分解:对协方差矩阵进行特征分解,得到特征值λ和对应的特征向量v:

    Σv = λv

  3. 选择主成分:按照特征值从大到小排序,选择前k个特征向量作为新的基。

数据投影

将原始数据X投影到选定的特征向量上:

Y = XW

其中W是由前k个特征向量组成的矩阵。

代码实现

数据准备

首先我们生成二维高斯分布数据:

import numpy as np
import matplotlib.pyplot as plt

# 定义协方差矩阵参数
var_1 = 1
var_2 = 1
corr_coef = 0.8

# 计算协方差矩阵
cov = corr_coef * np.sqrt(var_1 * var_2)
cov_matrix = np.array([[var_1, cov], [cov, var_2]])

# 生成数据
mean = np.array([0, 0])
X = np.random.multivariate_normal(mean, cov_matrix, size=1000)

可视化原始数据

def plot_data(X):
    fig = plt.figure(figsize=[8, 4])
    # 绘制两个神经元的时序活动
    plt.subplot(1, 2, 1)
    plt.plot(X[:, 0], color='k')
    plt.plot(X[:, 1], color='r')
    plt.xlabel('Sample Number')
    plt.ylabel('Activity')
    
    # 绘制散点图
    plt.subplot(1, 2, 2)
    plt.plot(X[:, 0], X[:, 1], '.', color=[.5, .5, .5])
    plt.xlabel('Neuron 1 activity')
    plt.ylabel('Neuron 2 activity')
    plt.title(f'Sample corr: {np.corrcoef(X.T)[0,1]:.2f}')
    plt.show()

plot_data(X)

计算协方差矩阵和特征分解

# 计算样本协方差矩阵
cov_matrix_sample = np.cov(X.T)

# 特征分解
evals, evectors = np.linalg.eigh(cov_matrix_sample)

# 按特征值降序排列
evals, evectors = evals[::-1], evectors[:, ::-1]

print("特征值:", evals)
print("特征向量:\n", evectors)

可视化特征向量

def plot_basis_vectors(X, W):
    plt.figure(figsize=[6, 6])
    plt.plot(X[:, 0], X[:, 1], '.', color=[.5, .5, .5], alpha=0.5)
    plt.axis('equal')
    
    # 绘制特征向量
    colors = ['r', 'b']
    for i in range(2):
        plt.arrow(0, 0, W[0, i], W[1, i], 
                 color=colors[i], width=0.02, head_width=0.1)
        plt.text(W[0, i]*1.2, W[1, i]*1.2, f'PC{i+1}', color=colors[i])
    
    plt.xlabel('Neuron 1 activity')
    plt.ylabel('Neuron 2 activity')
    plt.show()

plot_basis_vectors(X, evectors)

数据投影与降维

# 投影到主成分空间
Y = X @ evectors

# 可视化投影后数据
def plot_projected_data(Y):
    plt.figure(figsize=[12, 4])
    
    # 绘制主成分时序
    plt.subplot(1, 2, 1)
    plt.plot(Y[:, 0], 'r', label='PC1')
    plt.plot(Y[:, 1], 'b', label='PC2')
    plt.xlabel('Sample number')
    plt.ylabel('Projection value')
    plt.legend()
    
    # 绘制主成分散点图
    plt.subplot(1, 2, 2)
    plt.plot(Y[:, 0], Y[:, 1], '.', color=[.5, .5, .5])
    plt.xlabel('Projection PC1')
    plt.ylabel('Projection PC2')
    plt.title(f'Sample corr: {np.corrcoef(Y.T)[0,1]:.2f}')
    plt.axis('equal')
    plt.show()

plot_projected_data(Y)

特征值分析(碎石图)

def plot_eigenvalues(evals):
    plt.figure(figsize=[6, 4])
    plt.plot(np.arange(1, len(evals)+1, evals, 'o-k')
    plt.xlabel('Principal Component')
    plt.ylabel('Eigenvalue')
    plt.title('Scree Plot')
    plt.xticks(np.arange(1, len(evals)+1)
    plt.show()

plot_eigenvalues(evals)

实际应用建议

  1. 数据标准化:在应用PCA前,通常需要对数据进行标准化处理(均值为0,方差为1),特别是当不同特征的量纲差异较大时。

  2. 主成分选择:可以通过以下方法选择保留的主成分数量:

    • 保留解释方差累计达到阈值(如95%)的成分
    • 选择特征值大于平均值的成分
    • 观察碎石图中"肘部"位置
  3. 解释性:主成分通常是原始特征的线性组合,可以分析特征向量中的权重来理解每个主成分的含义。

总结

本教程详细介绍了PCA的数学原理和实现步骤:

  1. 计算数据的协方差矩阵
  2. 对协方差矩阵进行特征分解
  3. 按特征值排序选择主成分
  4. 将数据投影到选定的主成分上

PCA是一种强大的降维工具,能够有效减少数据维度同时保留大部分信息。理解PCA的原理对于正确应用和解释结果至关重要。