PCA降维,即主成分分析

主要过程为:先将数据标准化,然后求协方差矩阵,接着对协方差矩阵求特征向量和特征值,这些特征向量组成了新的特征空间。

标准化的方法一般有:

  • min-max
  • 均值
  • o-score 通过方差和均值来进行

求协方差矩阵:调用numpy中的cov方法即可计算

求特征向量和特征值:调用numpy中线性代数模块linalg中的eig函数,可以直接求得

保留主要成分:仅保留特征值前n大得维度即可

import random
import numpy as np

test_num = 20
test_vec = 5
test_data = [[random.randint(0, 100) for i in range(test_num)] for j in range(test_vec)]


class PCA:
    def __init__(self, dataset):
        self.dataset = dataset
        self.miu = [float(sum(i)) / len(i) for i in self.dataset]
        self.cov = None

    def avg_normalize(self):
        for j in range(len(self.dataset)):
            min_x = min(self.dataset[j])
            max_x = max(self.dataset[j])
            for i in range(len(self.dataset[j])):
                self.dataset[j][i] = (self.dataset[j][i] - self.miu[j]) / (max_x - min_x)

    def min_max_normalize(self):
        for j in range(len(self.dataset)):
            min_x = min(self.dataset[j])
            max_x = max(self.dataset[j])
            for i in range(len(self.dataset[j])):
                self.dataset[j][i] = (self.dataset[j][i] - min) / (max_x - min_x)

    def z_score_normalize(self):
        for j in range(len(self.dataset)):
            std = np.std(self.dataset[j], ddof=1)
            for i in range(len(self.dataset[j])):
                self.dataset[j][i] = (self.dataset[j][i] - self.miu[j]) / std

    # 获取协方差矩阵
    def get_cov(self):
        x = np.array(self.dataset)
        # 当数据存储为每个记录一个list需要转制
        # x = np.array(self.dataset).T
        self.cov = np.cov(x)
        return self.cov

    def get_svd(self):
        sigma, vt = np.linalg.eig(np.mat(self.cov))
        return sigma, vt

    def pca(self, n):
        self.get_cov()
        eig_vals, eig_vects = self.get_svd()  # 求特征值和特征向量,特征向量是按列放的,即一列代表一个特征向量
        eig_val_indice = np.argsort(eig_vals)  # 对特征值从小到大排序
        n_eig_val_indice = eig_val_indice[-1:-(n + 1):-1]  # 最大的n个特征值的下标
        n_eig_vect = eig_vects[:, n_eig_val_indice]  # 最大的n个特征值对应的特征向量
        low_d_data_mat = np.mat(self.dataset).T * n_eig_vect  # 低维特征空间的数据
        recon_mat = (low_d_data_mat * n_eig_vect.T)  # 重构数据
        return low_d_data_mat, recon_mat


pca = PCA(test_data)
pca.avg_normalize()
print(pca.pca(2))