机器学习 --- PCA

第1关:维数灾难与降维

任务描述
本关任务:根据本节课所学知识完成本关所设置的选择题。

相关知识
为了完成本关任务,你需要掌握维数灾难与降维的相关基础知识。

维数灾难
在机器学习中,我们不仅需要学习怎样进行分类、回归或者聚类,我们更要学习怎样对数据进行更好的处理,使得我们的数据能够更好地为我们的机器学习算法服务。而降维就是数据处理中的一环。

说到降维,那首先就要提到一个概念:维数灾难。维数灾难其实很好理解,举个例子。

我们现在玩个游戏,我告诉你一些信息,你猜一猜我所描述的是什么。

我:这个在地球上才有,而且是犬科动物。
您:……
如果您现在是一个动物的分类器,我相信您仅仅靠这两个特征(地球上才有,犬科动物)不大可能能够预测出我所说的是什么。也就是说,不管你用什么算法去分类,都很有可能发生欠拟合的现象。

我:这个是犬科动物,喜欢啃骨头,长得像狼, 比较二。
您:哈士奇!
我:猜的挺准。
当我给出的信息比较合适(这次有 4 个特征),您可能能够猜到所提供的特征数据所描述的是哈士奇。这个时候我们的分类算法能正常工作。

我:这个在地球上才有,是犬科动物,有毛,有爪子,体型大,耳尖呈圆形,尾巴喜欢上翘,长得像狼,喜欢啃骨头,有时比较二但挺忠诚。
您:哈士奇!
我:不,我说的是阿拉斯加。
您:……
这次我提供的信息比上面个两次都多(这次有 10 个特征),但是您可能将阿拉斯加误判成哈士奇。因为您可能看到长得像狼和比较二就认为是哈士奇了,也就是发生了过拟合的现象。这也说明了不是说数据的特征数量越多,我们的机器学习算法的效果就越强。当数据的特征数量变大时,可能会造成机器学习算法的模型变得非常复杂,从而导致过拟合。而且如果我所提供的特征数量越多,比如有 10000 个特征,那么模型训练过程中的时间成本会越大。

所以维数灾难通常是指对于已知样本数目,存在一个特征数目的最大值,当实际使用的特征数目超过这个最大值时,机器学习算法的性能不是得到改善,而是退化。

降维
既然维数太大可能引发维数灾难,那么如果能有算法能够自动地帮我们把重要性比较高的特征维度保留下来,把其他的维度过滤掉就好了。那这个过程我们称之为降维。

从维数灾难的概念出发,我们就能知道降维的作用了。

降低机器学习算法的时间复杂度;
节省了提取不必要特征的开销;
缓解因为维数灾难所造成的过拟合现象。
编程要求
根据本关所学习到的知识,完成所有选择题。

测试说明

开始你的任务吧,祝你成功!

1、下列说法正确的是

A、过拟合一定是维数灾难造成的

**B、降维能够缓解维数灾难的负面影响**

**C、使用原始数据训练出的回归器已经过拟合,可试试降维来提升性能**

D、使用原始数据训练出的回归器已经欠拟合,可试试降维来提升性能

2、下列说法错误的是

A、降维能够减小训练的时间复杂度

B、降维能够减小预测的时间复杂度

C、维数灾难不会引起过拟合

**D、根据原始数据挖掘出新特征后,特征数量较多,可能会引发维数灾难**

第2关:PCA算法流程

任务描述
本关任务:补充 python 代码,完成 PCA 函数,实现降维功能。

相关知识
为了完成本关任务,你需要掌握:

demean;
协方差;
特征值分解;
PCA 算法流程。
PCA与降维
降维的方法有很多,而最为常用的就是PCA(主成分分析)。 PCA 是将数据从原来的坐标系转换到新的坐标系,新的坐标系的选择是由数据本身决定的。第一个新坐标轴选择的是原始数据中方差最大的方向,第二个新坐标轴的选择和第一个坐标轴正交且方差最大的方向。然后该过程一直重复,重复次数为原始数据中的特征数量。最后会发现大部分方差都包含在最前面几个新坐标轴中,因此可以忽略剩下的坐标轴,从而达到降维的目的。

PCA的算法流程
PCA 在降维时,需要指定将维度降至多少维,假设降至 k 维,则 PCA 的算法流程如下:

demean;
计算数据的协方差矩阵;
计算协方差矩阵的特征值与特征向量;
按照特征值,将特征向量从大到小进行排序;
选取前 k 个特征向量作为转换矩阵;
demean 后的数据与转换矩阵做矩阵乘法获得降维后的数据。
其中demean ,协方差矩阵,特征值与特征向量的相关知识如下:

  1. demean
    demean 又称为零均值化,意思是将数据中每个维度上的均值变成 0。那为什么要这样做呢? PCA 实质上是找方差最大的方向,而方差的公式如下(其中μ为均值):

机器学习 --- PCA

如果将均值变成0,那么方差计算起来就更加方便,如下:

机器学习 --- PCA

在 numpy 中想要 demean 很简单,代码如下:

import numpy as np
#计算样本各个维度的均值
u = np.mean(data, axis=0)
#demean
after_demean = data - u
2. 协方差矩阵
协方差描述的是两个特征之间的相关性,当协方差为正时,两个特征呈正相关关系(同增同减);当协方差为负时,两个特征呈负相关关系(一增一减);当协方差为0时,两个特征之间没有任何相关关系。

协方差的数学定义如下(假设样本有 x 和 y 两种特征,而 X 就是包含所有样本的 x 特征的集合, Y 就是包含所有样本的 y 特征的集合):

机器学习 --- PCA

如果在算协方差之前做了 demean 操作,那么公式则为:

机器学习 --- PCA

假设样本只有 X 和 Y 这两个特征,现在把 X 与 X, X 与 Y, Y 与 X, Y 与 Y 的协方差组成矩阵,那么就构成了协方差矩阵。而协方差矩阵反应的就是特征与特征之间的相关关系。
机器学习 --- PCA

NumPy 提供了计算协方差矩阵的函数 cov,示例代码如下:

import numpy as np
#计算after_demean的协方差矩阵
#after_demean的行数为样本个数,列数为特征个数
#由于cov函数的输入希望是行代表特征,列代表数据的矩阵,所以要转置
cov = np.cov(after_demean.T)
3. 特征值与特征向量
特征值与特征向量的数学定义:如果向量v 与矩阵 A 满足 Av=λv ,则称向量 v 是矩阵A的一个特征向量, λ 是相应的特征值。

因为协方差矩阵为方阵,所以我们可以计算协方差矩阵的特征向量和特征值。其实这里的特征值从某种意义上来说体现了方差的大小,特征值越大方差就越大。而特征值所对应的特征向量就代表将原始数据进行坐标轴转换之后的数据。

numpy 为我们提供了计算特征值与特征向量的接口 eig,示例代码如下:

import numpy as np
#eig函数为计算特征值与特征向量的函数
#cov为矩阵,value为特征值,vector为特征向量
value, vector = np.linalg.eig(cov)
因此,PCA 算法伪代码如下:

#假设数据集为D,PCA后的特征数量为k
def pca(D, k):
after_demean=demean(D)
计算after_demean的协方差矩阵cov
value, vector = eig(cov)
根据特征值value将特征向量vector降序排序
筛选出前k个特征向量组成映射矩阵P
after_demean和P做矩阵乘法得到result
return result
编程要求
在 begin-end 之间填写pca(data, k)函数,实现 PCA 算法,要求返回降维后的数据。其中:

data :原始样本数据,类型为 ndarray;
k :需要降维至 k 维,类型为 int。
注意:为了顺利评测,计算协方差矩阵时请使用 NumPy 提供的 cov 函数。

测试说明
只需完成 pca 函数即可,程序内部会调用您所完成的 pca 函数来进行验证。以下为其中一个测试用例(其中 data 部分表示原始样本数据,k 表示需要降维至 k 维):

测试输入:
{‘data’:[[1, 2.2, 3.1, 4.3, 0.1, -9.8, 10], [1.8, -2.2, 13.1, 41.3, 10.1, -89.8, 100]],’k’:3}

预期输出:
[[-6.34212110e+01 6.32827124e-15 1.90819582e-17]
[ 6.34212110e+01 -6.32827124e-15 2.02962647e-16]]

开始你的任务吧,祝你成功!

import numpy as np

def meanX(dataX):
    return np.mean(dataX,axis=0)#axis=0表示按照列来求均值,如果输入list,则axis=1

def pca(data, k):
    '''
    对data进行PCA,并将结果返回
    :param data:数据集,类型为ndarray
    :param k:想要降成几维,类型为int
    :return: 降维后的数据,类型为ndarray
    '''

    #********* Begin *********#
    average = meanX(data)
    m, n = np.shape(data)
    data_adjust = []
    avgs = np.tile(average, (m, 1))
    data_adjust = data - avgs
    covX = np.cov(data_adjust.T)   #计算协方差矩阵
    featValue, featVec=  np.linalg.eig(covX)  #求解协方差矩阵的特征值和特征向量
    index = np.argsort(-featValue) #按照featValue进行从大到小排序
    finalData = []
    #注意特征向量时列向量,而numpy的二维矩阵(数组)a[m][n]中,a[1]表示第1行值
    selectVec = np.matrix(featVec.T[index[:k]]) #所以这里需要进行转置
    finalData = data_adjust * selectVec.T
    return finalData
    #********* End *********#

第3关:sklearn中的PCA

任务描述
本关任务:你需要调用 sklearn 中的 PCA 接口来对数据继续进行降维,并使用 sklearn 中提供的分类器接口(可任意挑选分类器)对癌细胞数据进行分类。

相关知识
为了完成本关任务,你需要掌握 sklearn 中的 PCA 类。

数据介绍
乳腺癌数据集,其实例数量是 569,实例中包括诊断类和属性,帮助预测的属性一共 30 个,各属性包括 radius 半径(从中心到边缘上点的距离的平均值), texture 纹理(灰度值的标准偏差)等等,类包括:WDBC-Malignant 恶性和 WDBC-Benign 良性。用数据集的 80% 作为训练集,数据集的 20% 作为测试集,训练集和测试集中都包括特征和诊断类。

sklearn 中已经提供了乳腺癌数据集的相关接口,想要使用该数据集可以使用如下代码:

from sklearn import datasets
#加载乳腺癌数据集
cancer = datasets.load_breast_cancer()
#X表示特征,y表示标签
X = cancer.data
y = cancer.target
数据集中部分数据与标签如下图所示(其中 0 表示良性,1 表示恶性):
机器学习 --- PCA

机器学习 --- PCA

PCA
PCA 的构造函数中有一个常用的参数可以设置:

n_components :表示想要将数据降维至 n_components 个维度。

PCA 类中有三个常用的函数分别为: fit 函数用于训练 PCA 模型; transform 函数用于将数据转换成降维后的数据,当模型训练好后,对于新输入的数据,也可以用 transform 方法来降维;fit_transform 函数用于使用数据训练 PCA 模型,同时返回降维后的数据。

其中 fit 函数中的参数:

X :大小为[样本数量,特征数量]的 ndarray ,存放训练样本。

transform 函数中的参数:

X :大小为[样本数量,特征数量]的 ndarray ,存放训练样本。

fit_transform 函数中的参数:

X :大小为[样本数量,特征数量]的 ndarray ,存放训练样本。

PCA 的使用代码如下:

from sklearn.decomposition import PCA
#构造一个将维度降至11维的PCA对象
pca = PCA(n_components=11)
#对数据X进行降维,并将降维后的数据保存至newX
newX = pca.fit_transform(X)
编程要求
在 begin-end 之间填写cancer_predict(train_sample, train_label, test_sample)函数实现降维并对癌细胞进行分类的功能,其中:

train_sample :训练样本,类型为 ndarray;
train_label :训练标签,类型为 ndarray;
test_sample :测试样本,类型为 ndarray。
测试说明
只需返回预测结果即可,程序内部会检测您的代码,预测 AUC 高于 0.9 视为过关。

开始你的任务吧,祝你成功!

from sklearn.decomposition import PCA
from sklearn.ensemble import RandomForestClassifier

def cancer_predict(train_sample, train_label, test_sample):
    '''
    使用PCA降维,并进行分类,最后将分类结果返回
    :param train_sample:训练样本, 类型为ndarray
    :param train_label:训练标签, 类型为ndarray
    :param test_sample:测试样本, 类型为ndarray
    :return: 分类结果
    '''

    #********* Begin *********#
    train_x = train_sample
    train_y = train_label
    clf = RandomForestClassifier()
    clf.fit(train_x, train_y)
    predictions = clf.predict(test_sample)
    #********* End *********#
    return predictions

欢迎大家加我微信学习讨论
机器学习 --- PCA

上一篇:9、主成分分析


下一篇:FE之DR之线性降维:PCA/白化、LDA算法的数学知识(协方差矩阵)、相关论文、算法骤、代码实现、案例应用等相关配图之详细攻略