机器学习--无监督--PCA主成分分析

PCA, Principal Components Analysis主成分分析是针对高维复杂数据降维的常用算法。

1、简单理解

  • 针对有非常多特征变量的高维数据集往往会存在若干分析挑战:
    (1)一些变量之间存在较高的相关性(correlated);
    (2)有些变量的信息量较少,要找到关键信息比较难。
  • PCA就是旨在通过少数的主成分(Principal Components)来概括原始所有特征变量的信息;
    (1)主成分可以理解为新的特征变量,本质上为所有原始特征变量的线性加和;而对应的系数即表示特定原始特征标量与该主成分的相关性;
    (2)新的主成分之间不存在任何相关性(正交);
    (3)一般来说第一个主成分往往捕捉原始数据最多的方差。如果保留全部与原始特征向量相同数目的主成分,那么全部的方差和与等同于原始数据集的方差和。但后续的主成分往往提供的信息量很小,这就引出了后续主成分数目选择的问题。


2、代码实操

2.1 示例数据

  • 2000个消费者的购买商品内容:共涉及42件商品,若没有买,则标记为0
  • 目的是对于42个特征变量进行降维
url <- "https://koalaverse.github.io/homlr/data/my_basket.csv"
my_basket <- readr::read_csv(url)
dim(my_basket)
## [1] 2000 42
my_basket[1:4,1:8]
# A tibble: 4 x 8
# `7up` lasagna pepsi   yop red.wine cheese   bbq bulmers
# <dbl>   <dbl> <dbl> <dbl>    <dbl>  <dbl> <dbl>   <dbl>
# 1     0       0     0     0        0      0     0       0
# 2     0       0     0     0        0      0     0       0
# 3     0       0     0     0        0      0     0       0
# 4     0       0     0     2        1      0     0       0

2.2 分析R包

  • h2o
library(h2o) # performing dimension reduction
h2o::h2o.prcomp()

(1)分析的时候,需要将数据集转为特定的H2OFrame对象格式;
(2)在进行PCA分析时,需要对数据清洗:处理缺失值、分类变量转为数值变量(one-hot),以及标准化;
(3)相关重要参数:
pca_method设定主成分分析方法。默认为GramSVD,适合特征变量大多为数值型的数据;GLRM则适合特征变量大多为分类型的数据。
k表示保留多少个主成分。建议保留与原始特征变量相同数目的主成分(最多),到后面再挑选即可。
transform表示是否对数据标准化,默认为none。如需标准化,推荐使用STANDARDIZE。
impute_missing表示是否处理缺失值,如果为TRUE,则使用列均值代替。

2.3 分析实操

# run PCA
h2o.no_progress() # turn off progress bars for brevity
h2o.init(max_mem_size = "5g") # connect to H2O instance
# convert data to h2o object
my_basket.h2o <- as.h2o(my_basket)
my_pca <- h2o.prcomp(
  training_frame = my_basket.h2o,
  pca_method = "GramSVD",
  k = ncol(my_basket.h2o),
  transform = "STANDARDIZE",
  impute_missing = TRUE,
  max_runtime_secs = 1000
)
  • 查看主成分分析结果
    (1)每个主成分对应全部原始变量的系数(权重/载荷)
my_pca@model$eigenvectors[,c(1:4)]
#           pc1         pc2         pc3        pc4
# 7up      -0.007301550 -0.05311817 -0.27323018 -0.1827380
# lasagna  -0.114769325 -0.24694768  0.11432441  0.2226329
# pepsi    -0.002710653 -0.09608739 -0.29949758 -0.2326095
# yop       0.005479054 -0.06277877 -0.18666903 -0.1335696
# red.wine  0.272476523 -0.11728046  0.08847515 -0.2388557
# 
# ---
#               pc1        pc2        pc3         pc4
# soup         -0.08011242 -0.1508818 0.03499992  0.11826536
# toad.in.hole -0.04994771 -0.1329308 0.11074945  0.12391478
# coco.pops    -0.06154965  0.1633611 0.01836804 -0.11058194
# kitkat        0.18344895  0.2155878 0.08236436  0.09445834
# broccoli     -0.22706222  0.0835667 0.03656377 -0.11632245
# cigarettes    0.14824297  0.1998176 0.10945296  0.04793923

my_pca@model$eigenvectors %>%
  as.data.frame() %>%
  mutate(feature = row.names(.)) %>%
  ggplot(aes(pc1, reorder(feature, pc1))) +
  geom_point()

(2)每个主成分的重要性/方差解释度

my_pca@model$importance[,1:4]
#                             pc1        pc2        pc3        pc4
# Standard deviation     1.51391887 1.47376825 1.45911373 1.44063487
# Proportion of Variance 0.05457025 0.05171412 0.05069078 0.04941497
# Cumulative Proportion  0.05457025 0.10628436 0.15697514 0.20639012

data.frame(
  PC = my_pca@model$importance %>% seq_along(),
  PVE = my_pca@model$importance %>% .[2,] %>% unlist()
) %>%
  tidyr::gather(metric, variance_explained, -PC) %>%
  ggplot(aes(PC, variance_explained)) +
  geom_point() 

(3)计算每个消费者对于这些主成分的得分

pred = predict(my_pca, my_basket.h2o)
pred[1:4,1:4]
#     PC1      PC2         PC3         PC4
# 1  1.4129574 1.345266  1.68478079  0.38638015
# 2 -2.6380764 1.915549  0.04180579 -0.53584123
# 3 -0.9495209 2.173075 -0.46798305 -0.09323332
# 4  3.1338889 1.042791 -0.52911233 -0.47940245
  • 最后关于主成分数目的选择
    如上面展示主成分重要性的散点图,可以看到越靠后的主成分的方差解释度越小。
    那么到底选择前多少个主成分最合适呢?

The frank answer is that there is no one best method for determining how many components to use.

但也有几种思路可供参考,比如

cumulative variance explained (CVE)
# How many PCs required to explain at least 75% of total variability
cve = my_pca@model$importance[3,]
min(which(cve >= 0.75))
# [1] 27

data.frame(
  PC = my_pca@model$importance %>% seq_along(),
  CVE = my_pca@model$importance %>% .[3,] %>% unlist()
) %>%
  tidyr::gather(metric, variance_explained, -PC) %>%
  ggplot(aes(PC, variance_explained)) +
  geom_point() + geom_vline(aes(xintercept=27),colour="red")
Scree plot criterion:寻找主成分-PVE散点图的骤降点
data.frame(
  PC = my_pca@model$importance %>% seq_along,
  PVE = my_pca@model$importance %>% .[2,] %>% unlist()
) %>%
  ggplot(aes(PC, PVE, group = 1, label = PC)) +
  geom_point() +
  geom_line() +
  geom_text(nudge_y = -.002)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容