背景
维数灾难是机器学习中常见的现象,具体是指随着特征维数的不断增加,需要处理的数据相对于特征形成的空间而言比较稀疏,由有限训练数据拟合的模型可以很好的适用于训练数据,但是对于未知的测试数据,很大几率距离模型空间较远,训练的模型不能处理这些未知数据点,从而形成“过拟合”的现象。
方案
既然维数灾难严重影响模型的泛化,那么如何解决呢?容易想到的解决办法是增加数据量,但是如果特征维数比较多,需要很大的数据量才能将整个特征空间“填满”,代价太大;还有一种比较容易实现而且效果还不错的解决办法就是特征的降维。特征的降维的主要思想是:过滤掉一些不重要的特征,或者把一些相关的特征进行合并,在减少特征维数的同时尽量保留原始数据的信息。
PCA主要包含以下几个步骤:
1、标准化样本矩阵中的原始数据;(通常每列是一个维度,按列进行标准化,不可整体标准化,每列都是相互独立的)
2、获取标准化矩阵的协方差矩阵;
3、计算协方差矩阵的特征值和特征向量;
4、依照特征值的大小,挑选主要的特征向量;
5、生成新的特征。
工具
本文使用工具为:Anaconda、PyCharm、python语言、sklearn
Python代码实现
from numpy import * from numpy import linalg as LA from sklearn.preprocessing import scale from sklearn.decomposition import PCA import pandas as pd data = {'a': [1,2,3,40], 'b': [5,6,17,8], 'c': [9,10,81,12]} x = pd.DataFrame(data) #x_s = (x-x.mean())/x.std() # 对矩阵按列进行标准化,每列是一个维度 x_s = scale(x, with_mean=True, with_std=True, axis=0) print("标准化之后的矩阵为:{}".format(x_s)) # 获取标准化矩阵的协方差矩阵 x_cov = cov(x_s.transpose()) # 计算协方差矩阵的特征值和特征向量 e,v = LA.eig(x_cov) print("特征值:{}".format(e)) print("特征向量:\n{}".format(v)) # 依照特征值的大小,挑选主要的特征向量 pca = PCA(2) pca.fit(x_s) # 输出变换后的数据矩阵 print("方差(特征值): ", pca.explained_variance_) print("主成分(特征向量)", pca.components_) print("变换后的样本矩阵:",pca.transform(x_s)) print("信息量: ", pca.explained_variance_ratio_)
代码运行结果
标准化之后的矩阵为:[[-0.63753558 -0.84327404 -0.6205374 ] [-0.5768179 -0.63245553 -0.58787754] [-0.51610023 1.68654809 1.73097275] [ 1.73045371 -0.21081851 -0.52255781]] 特征值:[2.72019876e+00 1.27762876e+00 2.17247549e-03] 特征向量: [[ 0.2325202 -0.96356584 0.13219394] [-0.67714769 -0.25795064 -0.68915344] [-0.69814423 -0.07072727 0.71245512]] 方差(特征值): [2.72019876 1.27762876] 主成分(特征向量) [[-0.2325202 0.67714769 0.69814423] [ 0.96356584 0.25795064 0.07072727]] 变换后的样本矩阵: [[-0.85600578 -0.8757195 ] [-0.7045673 -0.76052331] [ 2.4705145 0.06017659] [-0.90994142 1.57606622]] 信息量: [0.68004969 0.31940719]