PCA等降维算法真的能提升分类任务的性能吗?

简介: 本文验证分析了PCA算法对于分类任务性能的提升,结果出人意料。

       对于深度学习中的图像处理任务来说,很多研究人员都会用到降维处理技术,比如主成分分析(PCA)、稀疏自动编码器(SAE)、随机邻近嵌入(SNE)等,每种降维方法都有各自的侧重点,根据相应的任务需求选择合适的降维算法。在图像处理任务中,使用降维技术的原因主要有以下两个,一方面是通过降维能够降低计算复杂度,另外一方面受限于输入图像尺寸的大小,需要对其进行一些预处理,比如常用的卷积神经网络模型(CNN),输入图像的尺寸一般都不大。降维算法一般是选择最能代表数据集中的特征从而减少特征的数量,那么,降维算法能否对图像分类任务的性能有所提升?毕竟降维算法处理后的特征并不能完全表征图像的全部信息,下面就让我们一窥究竟吧。

降维算法

       本文主要以PCA降维算法为例分析,在直接编写代码验证之前,先来谈谈降维算法。维数降低一般有两种主要算法:一种是线性判别分析(LDA),另外一种是主成分分析(PCA)。二者之间的主要区别在于,LDA使用类别信息来查找新特征,以便最大化类别的可分性,而PCA使用每个特征的方差来做到这一点。在这种情况下,LDA可以被认为是有监督算法,而PCA是无监督算法。

谈谈PCA算法

       PCA的想法很简单,就是找到一组能概括数据集的低维坐标集。为什么我们需要概况数据呢?举一个例子:假设有一个包括一组汽车属性的数据集,这些属性通过其尺寸、颜色、形状、紧凑度、车身半径、座椅数量、门数以及行李箱尺寸等参数来描述每辆车。但是,许多属性之间是由关联的,所有部分属性是多余的。因此,我们应该根据描述每辆车的能力的高低来删除这些冗余属性,这就是PCA的目标。例如,考虑将车轮数量作为汽车和公共汽车的特征,几乎每个类别中每个样例都有四个轮子,因此,这个特征的差异度很小(一些罕见的公共汽车有六个轮子),所以这个特征无法区分公共汽车和汽车,但两种车辆实际上是非常不同。现在,考虑将高度作为特征,汽车和公共汽车具有不同的属性值,并且从最低的汽车到最高的公共汽车二者的高度差异具有很大的范围。显然,车辆的高度可以作为分离它们的良好特征。PCA算法不考虑类别的信息,它只是查看每个特征的方差,因为可以合理地假设,呈现高方差的特征更有可能在类别之间进行良好的区分。
       通常,人们会有一个误解,认为PCA算法会从数据集中选择某些特征并丢弃其他特征。实际上,该算法是基于旧的属性来组合构造新的属性集。从数学上讲,PCA执行线性变换,将原始特征集变换到由主成分组成的新空间。这些新特征对我们来说并没有任何的实际意义,只具有代数意义,因此不要认为PCA能够找到之前从未想过存在的新特征。许多人仍然相信机器学习算法是神奇的,他们直接将数以千计的输入投入到算法中,并希望机器学习算法能够为其业务找到所有的见解和解决方案,在这里声明一点,不要被一些夸张的报道所欺骗,机器学习目前的能力有限,数据科学家的工作是通过使用机器学习算法作为一组工具而并不是魔术棒,智能通过对数据进行良好的探索性分析来找到对业务的见解。

主成分空间

       在新的特征空间中,我们正在寻找一些在类别中存在很大差异的属性。正如之前举得例子所示,一些呈现出低方差的属性作用不大,无法很好的区分样例。另一方面,PCA寻找的属性可以尽可能多地显示类别,以构建出主成分空间。该算法使用方差矩阵、协方差矩阵、特征向量和特征值对的概念来实现PCA算法,从而提供一组特征向量及其各自的特征值。
那么,我们应该如何处理特征值和特征向量呢?答案非常简单,特征向量表示主成分空间的新坐标系,特征值带有每个特征向量具有的方差信息。因此,为了减小数据集的维数,将选择具有方差值大的那些特征向量,并丢弃具有方差值小的那些特征向量,具体实现步骤可以网上找下相关资源。下面将通过具体的例子和代码展示PCA算法是如何工作的。

实验代码

       本部分内容是比较有趣的部分,现在让我们看看PCA算法是否真的改善了分类任务的结果。
       为了验证它,采取的策略是在数据集上应用神经网络并查看其初始结果。之后,我将在分类之前执行PCA降维,之后在降维后得到的数据集上应用相同的神经网络,最后比较两个结果。
       该数据集源自名为“Statlog数据集”的UCI机器学习库,该数据集存储了四个车辆轮廓的一些度量,用于分类。它由946个示例和18个度量(属性)所有数值组成,可以在此链接中查看更多详细信息。神经网络结构是一个多层感知机,其具有四个隐藏节点和一个输出节点,所有的激活函数选择sigmoid函数,PCA的处理是通过R数据包完成。

准备数据集

       首先,准备二进制分类的数据集,仅从两个类别中选择示例以构成二进制分类。这些例子来自“bus(公共汽车)”和“saab(萨博汽车)”类。类别“saab”用类别0替换,类别“bus”用类别1替换。下一步是将数据集划分为训练数据集和测试数据集,其比例分别为占总类示例的60%和40%。
       在数据集准备好之后,一次性使用所有特征构建神经网络模型,然后对其应用测试数据集,看其性能。

# 加载库
library( dplyr )

# 读取数据集
data = read.csv( "../dataset/vehicle.csv", stringsAsFactor = FALSE )

# 变换数据格式
dataset = data %>% 
            filter( class == "bus" | class == "saab" ) %>%
            transform( class = ifelse( class == "saab", 0, 1 ) )
dataset = as.data.frame( sapply( dataset, as.numeric ) )

# 将数据集划分为训练集和测试集
index = sample( 1:nrow( dataset ), nrow( dataset ) * 0.6, replace = FALSE ) 

trainset = dataset[ index, ]
test = dataset[ -index, ]
testset = test %>% select( -class )

# 构建神经网络模型 (NN)
library( neuralnet )
n = names( trainset )
f = as.formula( paste( "class ~", paste( n[!n %in% "class"], collapse = "+" ) ) )
nn = neuralnet( f, trainset, hidden = 4, linear.output = FALSE, threshold = 0.01 )

plot( nn, rep = "best" )

1
多层感知机神经网络

# 测试结果输出
nn.results = compute( nn, testset )

results = data.frame( actual = test$class, prediction = round( nn.results$net.result ) )

# 混淆矩阵
library( caret )
t = table( results )
print( confusionMatrix( t ) )

## 输出结果
## 
##         prediction
## actual  0  1
##      0   79  0
##      1   79 16
##                                                 
##                Accuracy : 0.545977              
##                  95% CI : (0.4688867, 0.6214742)
##     No Information Rate : 0.908046              
##     P-Value [Acc > NIR] : 1                     
##                                                 
##                   Kappa : 0.1553398             
##  Mcnemar's Test P-Value : < 0.0000000000000002   
##                                                 
##             Sensitivity : 0.5000000             
##             Specificity : 1.0000000             
##          Pos Pred Value : 1.0000000             
##          Neg Pred Value : 0.1684211             
##              Prevalence : 0.9080460             
##          Detection Rate : 0.4540230             
##    Detection Prevalence : 0.4540230             
##       Balanced Accuracy : 0.7500000             
##                                                 
##        'Positive' Class : 0                     
##

无PCA处理的结果

       从上面的结果中首先可以看到,混淆矩阵(Confusion Matrix)表示有多少例子被分类,主对角线显示正确分类的示例,次对角线显示错误分类。这个结果中,分类器表示自己十分困惑,因为几乎所有来自“saab”类别的例子都被正确分类,但它也将大多数“bus”类别的样例分类为“saab”类别。此外,可以看出其精度值(Accuracy)约为50%,这对于分类任务来说是一个非常糟糕的结果,分类器本身就有一半一半的概率将新样例分类为“saab”或“bus”类别。因此,由神经网络构成的该分类器性能不好。

PCA处理后的结果

       现在,对数据集进行主成分分析PCA处理,得到特征值和特征向量。实际上,你会看到R数据包中的PCA函数提已经供了一组按降序排序的特征值,这意味着第一个分量是方差最大的一个,第二个分量是方差第二大的特征向量,以此类推。下面的代码展示了如何选择特征值的特征向量。

# PCA
pca_trainset = trainset %>% select( -class )
pca_testset = testset
pca = prcomp( pca_trainset, scale = T )

# 方差
pr_var = ( pca$sdev )^2 

# 方差占比
prop_varex = pr_var / sum( pr_var )

# 画出曲线
plot( prop_varex, xlab = "Principal Component", 
                  ylab = "Proportion of Variance Explained", type = "b" )

2
主成分

# 画出方差累积
plot( cumsum( prop_varex ), xlab = "Principal Component", 
                            ylab = "Cumulative Proportion of Variance Explained", type = "b" )

3
方差累积和


       来自R数据包中的“prcomp”函数执行PCA,该函数返回所需的所有特征值和特征向量。上面的第一张图显示每个特征的方差百分比。从图中可以看到,第一成分具有最高的方差,值约为50%,而第8个成分的方差约为0%。所以,这告诉我们。应该取其前八个组件作为主要成分。第二张图展示了方差的另外一个视角——方差的累积和。从图中可以看到,前八个特征值对应的方差累积和占所有方差的大约98%。实际上,这是一个非常好的数字,这意味着只有2%的信息丢失了,最大的好处是,从具有18维特征的空间转换到另外一个只有8维特征的空间,仅丢失了2%的信息,这就是降维的力量。
       当我们知道了构成新空间的特征数量时,就可以创建出新的数据集,然后再次对其构建神经网络模型,并用新的测试集测试其性能。
# 创建新的数据
train = data.frame( class = trainset$class, pca$x )
t = as.data.frame( predict( pca, newdata = pca_testset ) )

new_trainset = train[, 1:9]
new_testset =  t[, 1:8]

# 构建神经网络模型 (NN)
library( neuralnet )
n = names( new_trainset )
f = as.formula( paste( "class ~", paste( n[!n %in% "class" ], collapse = "+" ) ) )
nn = neuralnet( f, new_trainset, hidden = 4, linear.output = FALSE, threshold=0.01 )

# 画出 NN模型
plot( nn, rep = "best" )

4
新数据集的神经网络模型

# 测试输出
nn.results = compute( nn, new_testset )

# 结果
results = data.frame( actual = test$class, 
                      prediction = round( nn.results$net.result ) )

# 混淆矩阵
library( caret )
t = table( results ) 
print( confusionMatrix( t ) )

## 输出结果
## 
##       prediction
## actual  0  1
##      0 76  3
##      1  1 94
##                                                 
##                Accuracy : 0.9770115             
##                  95% CI : (0.9421888, 0.9937017)
##     No Information Rate : 0.5574713             
##     P-Value [Acc > NIR] : < 0.00000000000000022 
##                                                 
##                   Kappa : 0.9535318             
##  Mcnemar's Test P-Value : 0.6170751             
##                                                 
##             Sensitivity : 0.9870130             
##             Specificity : 0.9690722             
##          Pos Pred Value : 0.9620253             
##          Neg Pred Value : 0.9894737             
##              Prevalence : 0.4425287             
##          Detection Rate : 0.4367816             
##    Detection Prevalence : 0.4540230             
##       Balanced Accuracy : 0.9780426             
##                                                 
##        'Positive' Class : 0                     
##

       从上面可以看到,得到了非常好的结果。在这次实验中,混淆矩阵显示出神经网络在两个类别中都具有较少的错误分类次数,并且,出主对角线的值和精度值都在95%左右,这表明新的分类器有95%的机会正确分类一个新的样例,这个准确率对于分类问题而言,是一个非常不错的结果。

结论

       降维在机器学习中起着非常重要的作用,特别是当数据集具有数千种特征时。主成分分析是最优的降维算法之一,在实际项目中很容易被理解和使用。除了使得特征处理变得更加容易之外,这项技术还能够改善分类器的结果,从文中的实验对比来看,提升效果还是很大的。
最后,对于PCA降维算法能否提升分类任务的性能问题而言,其答案是肯定的,PCA降维算法有助于改善分类器的性能。

数十款阿里云产品限时折扣中,赶紧点击领劵开始云上实践吧!

作者信息

Meigarom Diego Fernandes,机器学习和数据科学研究者
个人主页:https://www.linkedin.com/in/meigarom/
本文由阿里云云栖社区组织翻译。
文章原标题《Dimensionality Reduction — Does PCA really improve classification outcome?》,译者:海棠,审校:Uncle_LLD。

相关文章
|
18天前
|
机器学习/深度学习 人工智能 算法
机器学习算法的优化与改进:提升模型性能的策略与方法
机器学习算法的优化与改进:提升模型性能的策略与方法
126 13
机器学习算法的优化与改进:提升模型性能的策略与方法
|
2月前
|
机器学习/深度学习 算法 数据挖掘
提高时钟置换算法的性能
【10月更文挑战第25天】通过上述一种或多种方法的综合应用,可以在不同程度上提高时钟置换算法的性能,使其更好地适应各种复杂的系统环境和应用场景,提高虚拟内存管理的效率和系统的整体性能。
129 62
|
2月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
83 1
|
2月前
|
机器学习/深度学习 算法 5G
基于MIMO系统的SDR-AltMin混合预编码算法matlab性能仿真
基于MIMO系统的SDR-AltMin混合预编码算法通过结合半定松弛和交替最小化技术,优化大规模MIMO系统的预编码矩阵,提高信号质量。Matlab 2022a仿真结果显示,该算法能有效提升系统性能并降低计算复杂度。核心程序包括预编码和接收矩阵的设计,以及不同信噪比下的性能评估。
71 3
|
3月前
|
机器学习/深度学习 算法 决策智能
【机器学习】揭秘深度学习优化算法:加速训练与提升性能
【机器学习】揭秘深度学习优化算法:加速训练与提升性能
|
4月前
|
机器学习/深度学习 人工智能 算法
【新闻文本分类识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
文本分类识别系统。本系统使用Python作为主要开发语言,首先收集了10种中文文本数据集("体育类", "财经类", "房产类", "家居类", "教育类", "科技类", "时尚类", "时政类", "游戏类", "娱乐类"),然后基于TensorFlow搭建CNN卷积神经网络算法模型。通过对数据集进行多轮迭代训练,最后得到一个识别精度较高的模型,并保存为本地的h5格式。然后使用Django开发Web网页端操作界面,实现用户上传一段文本识别其所属的类别。
136 1
【新闻文本分类识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
|
3月前
|
搜索推荐 Shell
解析排序算法:十大排序方法的工作原理与性能比较
解析排序算法:十大排序方法的工作原理与性能比较
109 9
|
3月前
|
存储 缓存 分布式计算
数据结构与算法学习一:学习前的准备,数据结构的分类,数据结构与算法的关系,实际编程中遇到的问题,几个经典算法问题
这篇文章是关于数据结构与算法的学习指南,涵盖了数据结构的分类、数据结构与算法的关系、实际编程中遇到的问题以及几个经典的算法面试题。
47 0
数据结构与算法学习一:学习前的准备,数据结构的分类,数据结构与算法的关系,实际编程中遇到的问题,几个经典算法问题
|
3月前
|
缓存 分布式计算 监控
算法优化:提升程序性能的艺术
【10月更文挑战第20天】算法优化:提升程序性能的艺术
|
3月前
|
移动开发 算法 前端开发
前端常用算法全解:特征梳理、复杂度比较、分类解读与示例展示
前端常用算法全解:特征梳理、复杂度比较、分类解读与示例展示
44 0

热门文章

最新文章