考虑如下几个问题:
比如我想要预估一下某篇文章的访问量。那么我可能会搜罗一些数据来帮我分析:
文章id | 访问量 | 点赞数 | 收藏数 | 评论数 | 粉丝数 | 编辑数 |
---|---|---|---|---|---|---|
1 | 2194 | 4 | 1 | 6 | 100 | 1 |
2 | 9308 | 10 | 4 | 10 | 200 | 1 |
3 | 36702 | 27 | 10 | 20 | 300 | 1 |
4 | ? | 8 | 3 | 8 | 150 | 1 |
如何预测文章4的访问量? 编辑数对于预测是否有作用? 其他几个成分对于预测访问量是否有作用,哪些成分对预测访问量有重要作用?
显然,如果我们使用编辑数来对文章的访问量进行预测是不合适的。为什么?因为编辑数在我们的采样中没有差异,无法进行数据的有效区分。所以,要牢记:差异才是信息!
再比如:R中的数据集USJudgeRatings包含了律师对美国高等法院法官的评分。数据框包含43个样本,12个变量!
这12个变量的介绍如下:
[,1] CONT Number of contacts of lawyer with judge. 律师与法官的联系数
[,2] INTG Judicial integrity. 司法诚信度
[,3] DMNR Demeanor. 风度/举止行为
[,4] DILG Diligence. 勤奋度
[,5] CFMG Case flow managing. 案件流程管理
[,6] DECI Prompt decisions. 果断决策
[,7] PREP Preparation for trial. 审判准备
[,8] FAMI Familiarity with law. 法律熟悉度
[,9] ORAL Sound oral rulings. 口头裁决
[,10] WRIT Sound written rulings. 书面裁决
[,11] PHYS Physical ability. 体能
[,12] RTEN Worthy of retention. 保留价值
在这个例子里面,我们拿到了这43个法官的12个信息,就可以通过这12个指标来对法官进行分类,但也许实际情况下收集其他法官的12个信息比较麻烦,所以我们希望只收集三五个信息即可,然后也想达到比较好的分类效果。或者至少也得剔除几个指标吧,这个时候主成分分析就能派上用场啦。这12个变量能得到12个主成分,如果前两个主成分可以揭示85%以上的变异度,也就是说我们可以用两个主成分来代替那12个指标。(所以说,降维也是聚类的一种前置手段。)
所以,
为什么要降维?
降维就是为了能更清楚的观测到数据之间的关系,降低运算难度。
在生物信息学领域,比如我们测了1000个病人的2万个基因的表达矩阵,同时也有他们的健康状态信息。那么我们想仔细研究这些数据,想得到基因表达与健康状态的某种关系。这样我就可以对其余几十亿的人检测基因表达来预测其健康状态。如果我们进行了主成分分析,就可以选择解释度比较高的主成分对应的基因,可能就几十上百个而已,大幅度的降低广泛的基因检测成本。
在许多领域的研究与应用中,通常需要对含有多个变量的数据进行观测,收集大量数据后进行分析寻找规律。多变量大数据集无疑会为研究和应用提供丰富的信息,但是也在一定程度上增加了数据采集的工作量。更重要的是在很多情形下,许多变量之间可能存在相关性,从而增加了问题分析的复杂性。如果分别对每个指标进行分析,分析往往是孤立的,不能完全利用数据中的信息,因此盲目减少指标会损失很多有用的信息,从而产生错误的结论。因此需要找到一种合理的方法,在减少需要分析的指标同时,尽量减少原指标包含信息的损失,以达到对所收集数据进行全面分析的目的。由于各变量之间存在一定的相关关系,因此可以考虑将关系紧密的变量变成尽可能少的新变量,使这些新变量是两两不相关的,那么就可以用较少的综合指标分别代表存在于各个变量中的各类信息。主成分分析与因子分析就属于这类降维算法。
降维就是一种对高维度特征数据预处理方法。降维是将高维度的数据保留下最重要的一些特征,去除噪声和不重要的特征,从而实现提升数据处理速度的目的。在实际的生产和应用中,降维在一定的信息损失范围内,可以为我们节省大量的时间和成本。降维也成为应用非常广泛的数据预处理方法。
降维具有如下一些优点:
- 使得数据集更易使用。
- 降低算法的计算开销。
- 去除噪声。
- 使得结果容易理解。
降维的算法有很多,比如奇异值分解(SVD)、主成分分析(PCA)、因子分析(FA)、独立成分分析(ICA)。
主成分分析(PCA)
主成分分析(principal component analysis,PCA)是一种降维技术,把多个变量化为能够反映原始变量大部分信息的少数几个主成分。
设X有p个变量,为n*p阶矩阵,即n个样本的p维向量。首先对X的p个变量寻找正规化线性组合,使它的方差达到最大(记住上面说的,差异才是信息。这一步就是通过旋转坐标系,使得落在X轴的投影最分散,这样在Y轴的差异很小,对于差异很小的成分,我们丢弃时,损失的信息就很少,就可以忽略了。这是核心思想。),这个新的变量称为第一主成分,抽取第一主成分后,第二主成分的抽取方法与第一主成分一样,依次类推,直到各主成分累积方差达到总方差的一定比例。
主成分分析的计算步骤:
设有m条n维数据:
- 将原始数据按列组成n行m列矩阵
- 将X的每一行(代表一个属性字段)进行零均值化,即减去这一行的均值
- 求出协方差矩阵:
- 求出协方差矩阵的特征值及对应的特征向量(特征值对应的特征向量就是理想中想取得正确的坐标轴,而特征值就等于数据在旋转之后的坐标上对应维度上的方差。)
- 将特征向量按对应特征值大小从上到下按行排列成矩阵,取前行组成矩阵
- 即为降维到维后的数据
主成分分析可以得到p个主成分,但是,由于各个主成分的方差是递减的,包含的信息量也是递减的,所以实际分析时,一般不是选取p个主成分,而是根据各个主成分累计贡献率的大小选取前k个主成分,这里贡献率就是指某个主成分的方差占全部方差的比重,实际也就是某个特征值占全部特征值总和的比重。贡献率越大,说明该主成分所包含的原始变量的信息越强。主成分个数k的选取,主要根据主成分的累积贡献率来决定,即一般要求累计贡献率达到85%以上,这样才能保证综合变量能包括原始变量的绝大多数信息。
基于R的PCA实现
例:对USArrests数据,使用PCA降维
手工实现:
- 中心化/标准化
所谓中心化就是将数据减去均值后得到的,比如有一组数据(1,2,3,4,5,6,7),它的均值是4,中心化后的数据为(-3,-2,-1,0,1,2,3)
而标准化则是在中心化后的数据基础上再除以数据的标准差。
如果变量的变化范围不一致,例如有的变量的变化范围是0~1,有的变化范围是1~+∞,那么就应该对变量进行中心化,使其变化范围一致;
如果变量的方差差别较大,其量纲不太一样,建议使用标准化,化为统一量纲,便于比较;
在R语言中可以通过scale函数直接进行数据的中心化和标准化,具体如下:
Scale(x,center,scale)
参数解释:
x—即需要标准化的数据
center—表示是否进行中心化
scale—表示是否进行标准化
USArrests_scale <- scale(USArrests, scale=TRUE)
- 求相关系数矩阵
dat_cor <- cor(USArrests_scale)
dat_cor
Murder Assault UrbanPop Rape
Murder 1.00000000 0.8018733 0.06957262 0.5635788
Assault 0.80187331 1.0000000 0.25887170 0.6652412
UrbanPop 0.06957262 0.2588717 1.00000000 0.4113412
Rape 0.56357883 0.6652412 0.41134124 1.0000000
- 求出协方差矩阵的特征值及对应的特征向量
dat_eigen <- eigen(dat_cor)
dat_eigen
eigen() decomposition
$values
[1] 2.4802416 0.9897652 0.3565632 0.1734301
$vectors
[,1] [,2] [,3] [,4]
[1,] -0.5358995 0.4181809 -0.3412327 0.64922780
[2,] -0.5831836 0.1879856 -0.2681484 -0.74340748
[3,] -0.2781909 -0.8728062 -0.3780158 0.13387773
[4,] -0.5434321 -0.1673186 0.8177779 0.08902432
dat_var <- dat_eigen$values
- 求主成分的贡献率和累积贡献率
pca_var <- dat_var / sum(dat_var)
pca_cvar <- cumsum(dat_var)/sum(dat_var)
pca_var
[1] 0.62006039 0.24744129 0.08914080 0.04335752
pca_cvar
[1] 0.6200604 0.8675017 0.9566425 1.0000000
一步法实现:
R语言有非常多的途径做主成分分析,比如自带的princomp()和prcomp()函数,还有psych包的principal()函数、gmodels包的fast.prcomp函数、FactoMineR包的PCA()函数、ade4包的dudi.pca()函数、amap包的acp()函数等。
一步法很简单,只需要使用上述函数中的任一一种,即可得到结果。我们以prcomp函数为例:
pca.out<-prcomp(USArrests,scale=TRUE)
pca.out
Standard deviations (1, .., p=4):
[1] 1.5748783 0.9948694 0.5971291 0.4164494
Rotation (n x k) = (4 x 4):
PC1 PC2 PC3 PC4
Murder -0.5358995 0.4181809 -0.3412327 0.64922780
Assault -0.5831836 0.1879856 -0.2681484 -0.74340748
UrbanPop -0.2781909 -0.8728062 -0.3780158 0.13387773
Rape -0.5434321 -0.1673186 0.8177779 0.08902432
注意,在使用该函数前,我们需要对数据进行一些初步判断。数据是否需要标准化?(各变量之间的均值、方差是否差别比较大?方差差差别比较大一般是因为量纲不同引致,因此要消除这种量纲的差别)
执行后,即可查看主成分分析后的结果
summary(pca.out)
Importance of components:
PC1 PC2 PC3 PC4
Standard deviation 1.5749 0.9949 0.59713 0.41645
Proportion of Variance 0.6201 0.2474 0.08914 0.04336
Cumulative Proportion 0.6201 0.8675 0.95664 1.00000
可以看到,通过函数计算出来的累积贡献率和我们之前手工计算出来的累积贡献率是一样的。
我们还可以通过崖底碎石图来对进行主成分贡献率进行可视化显示,以帮助我们选择合适的主成分数量。
#崖底碎石图
screeplot(pca.out,type="lines")
从上图可以看到,在第二个主成分之后,有个拐点,图像趋于平缓,因此我们可以采用前两个主成分来对原数据进行解释。
我们还可以查看各个变量的负载情况:
pca.out$rotation
PC1 PC2 PC3 PC4
Murder -0.5358995 0.4181809 -0.3412327 0.64922780
Assault -0.5831836 0.1879856 -0.2681484 -0.74340748
UrbanPop -0.2781909 -0.8728062 -0.3780158 0.13387773
Rape -0.5434321 -0.1673186 0.8177779 0.08902432
可以看到:第一个变量在Murder, Assault 以及Rape上有差不多的较高载荷,而在UrbanPop上的负载就小很多。因此第一个变量可以用来解释严重犯罪率;
第二个变量刚好相反:它的权重都分配在UrbanPop上,而其他三个变量的权重就小得多。因此第二个变量可以用来代表一个国家的城市化水平。
下面我们绘制双峰图来显示新的坐标系和原向量之间的关系:
#绘制双峰图,对各个变量的负载进行图形化展示:
biplot(pca.out,scale = 0, cex=0.65)
上面的双峰图显示了根据2个主成分映射的50个州。红色箭头代表变量,每个方向代表解释最大变化的方向。
第一主成分得分较高的州,如加利福尼亚州、内华达州和佛罗里达州,犯罪率较高,而北达科他州等,犯罪率较低。
加利福尼亚州在第二部分的得分也很高,表明城市化水平很高,而密西西比州则相反。
在这两个方面接近于零的州,如印第安纳州,犯罪率和城市化率都接近平均水平。
PCA的优劣:
优势:
- 直接利用原有变量建立新轴
- 新数据可直接投影
- 纯数学变换,计算量不大
劣势:
- 高维到低维可能非线性
- 分类变量处理
- 降低维数需要人工判断
[参考文献]: