主成分分析算法

  • PCA的数学实现

主成分分析算法

PCA 减少 n 维到 k 维:

第一步是均值归一化。计算出所有特征的均值,然后令$x_j=x_j-\mu_j$。如果特征是在不同的数量级上,我们还需要将其除以标准差 $\sigma^2$。

第二步是计算协方差矩阵(covariance matrix)Σ

第三步是计算协方差矩阵 Σ 的特征向量(eigenvectors): 可以利用奇异值分解(singular value decomposition)来求解,[U, S, V]= svd(sigma)。

对于一个 n×n 维度的矩阵,上式中的 U 是一个具有与数据之间最小投射误差的方向向量构成的矩阵。如果我们希望将数据从 n 维降至 k 维,我们只需要从 U 中选取前 K 个向量,获得一个 n×k 维度的矩阵,我们用 $U_{reduce}$表示,然后通过如下计算获得要求的新特征向量$z^{(i)}$:

其中 x 是 n×1 维的,因此结果为 k×1 维度。注,我们不对方差特征进行处理。

牛刀小试

我们来实现PCA算法

import numpy as np

def covariance_matrix(X):
    """
    Args:
        X (ndarray) (m, n)
    Return:
        cov_mat (ndarray) (n, n):
            covariance matrix of X
    """
    m = X.shape[0]

    return (X.T @ X) / m


def normalize(X):
    """
        for each column, X-mean / std
    """
    X_copy = X.copy()
    m, n = X_copy.shape

    for col in range(n):
        X_copy[:, col] = (X_copy[:, col] - X_copy[:, col].mean()) / X_copy[:, col].std()

    return X_copy

def pca(x, keep_dims=None):
    if not keep_dims:
        keep_dims = x.shape[1] - 1
    # todo 进行归一化
    normalize_x = normalize(x)
    # todo 求出协方差矩阵
    cov_x = covariance_matrix(x)
    # todo 奇异值分解
    U, S, V = np.linalg.svd(cov_x)  # U: principle components (n, n)
    # todo 选取前 keep_dims 维特征
    reduction = U[:, :keep_dims]
    # todo 得到降维的结果
    return np.matmul(x, reduction)
x = np.random.uniform(size=(10, 10))
pca(x).shape

(10, 9)