Spark and Sparklyr

Hadoop和Spark

Apache Hadoop是一个开源软件库,可以跨计算机集群分布式处理大型数据集。它具有高度可扩展性,可以加载到单个服务器上,也可以分布在数千台不同的机器上。它包括几个模块,包括用于分布式文件存储的Hadoop分布式文件系统(HDFS),用于大数据集并行处理的Hadoop MapReduce,以及用于大规模数据处理(包括统计学习)的通用引擎Spark

sparklyr

学习使用Hadoop和Spark可能非常复杂。他们使用自己的编程语言来指定函数和执行操作。在本课程中,我们将与Spark进行交互,sparklyr来自Rt的一个包来自RStudio的同一作者和tidyverse。这允许我们:

  • 使用dplyr界面从R连接到Spark

  • 与存储在Spark群集上的SQL数据库进行交互

  • 实施分布式统计 学习算法

有关设置和使用的详细说明,请参见此处sparklyr。

安装

首先你需要安装sparklyr:

install.packages("sparklyr")

您还需要安装本地版本的Spark才能在您的计算机上运行它:

连接到Spark

您可以连接到Spark的本地实例以及远程Spark群集。让我们使用该spark_connect()函数连接到我们计算机上构建的本地集群:

用Spark学习机器

您可以sparklyr在Apache Spark中使用适合各种机器学习算法。caret::train()您可以ml_根据要使用的算法使用一组函数,而不是使用它们。

加载数据

让我们继续使用泰坦尼克号数据集。首先,titanic将包含我们用于过去统计学习练习的数据文件的包加载到本地Spark集群中:

 library(titanic)

(titanic_tbl <- copy_to(sc, titanic::titanic_train, "titanic", overwrite = TRUE)) 

整理数据

您可以使用dplyr语法在Spark中整理和重塑数据,以及Spark机器学习库中的专用函数。

Spark SQL转换

这些是使用Spark SQL的功能转换(也就是对列/行进行改变或过滤)。这允许您在仍然使用dplyr语法的同时创建新列并修改现有列。这里让我们修改4列:

  1. Family_Size - 创造一些兄弟姐妹和父母

  2. Pclass - 将乘客类格式化为字符而不是数字

  3. Embarked - 删除少量丢失的记录

  4. Age - 估计平均年龄的失踪年龄

我们sdf_register()在操作结束时使用将表存储在Spark集群中。

Spark ML转换

Spark还包括几个转换功能的功能。我们可以直接sparklyr访问其中几个。例如,要转换Family_Sizes为垃圾箱,请使用ft_bucketizer()。因为这个函数来自Spark,所以它在内部使用sdf_mutate(),而不是mutate()

titanic_final_tbl <-  titanic2_tbl %>%

 mutate(Family_Size =  as.numeric(Family_size)) %>%

 sdf_mutate(

 Family_Sizes =  ft_bucketizer(Family_Size, splits =  c(1,2,5,12))

) %>%

 mutate(Family_Sizes =  as.character(as.integer(Family_Sizes))) %>%

 sdf_register("titanic_final")

> ft_bucketizer()等同cut()于R.

数据拆分

随机将数据划分为训练/测试集。

训练模型

Spark ML包括几种类型的机器学习算法。我们可以使用这些算法来使用训练数据拟合模型,然后使用测试数据评估模型性能。

逻辑回归

Model survival as a function of several predictors

ml_formula <- formula(Survived ~ Pclass + Sex + Age + SibSp +

                        Parch + Fare + Embarked + Family_Sizes)

# Train a logistic regression model

(ml_log <- ml_logistic_regression(train_tbl, ml_formula))

其他机器学习算法

使用其他机器学习算法运行相同的公式。请注意,方法之间的培训时间差异很大。

验证数据

比较结果

要选择最佳模型,请通过检查性能指标(电梯,精度和曲线下面积(AUC))来比较测试集结果。

模型升降机

Lift比较模型与随机猜测相比预测生存的程度。下面的函数计算测试数据中每个评分十分位数的模型升力

# Lift function

calculate_lift <-  function(scored_data) {

scored_data %>%

 mutate(bin =  ntile(desc(prediction), 10)) %>%

 group_by(bin) %>%

 summarize(count =  sum(Survived)) %>%

 mutate(prop = count /  sum(count)) %>%

 arrange(bin) %>%

 mutate(prop =  cumsum(prop)) %>%

 select(-count) %>%

 collect() %>%

 as.data.frame()

}

Initialize results

ml_gains <-  data_frame(

 bin =  seq(from =  1, to =  10),

 prop =  seq(0, 1, len =  10),

 model =  "Base"

)

Calculate lift

for(i in  names(ml_score)){

  ml_gains <-  ml_score[[i]] %>%

 calculate_lift %>%

 mutate(model = i) %>%

 bind_rows(ml_gains, .)

}

Plot results

ggplot(ml_gains, aes(x = bin, y = prop, color = model)) +

 geom_point() +

 geom_line() +

 scale_color_brewer(type =  "qual") +

 labs(title =  "Lift Chart for Predicting Survival",

 subtitle =  "Test Data Set",

 x =  NULL,

 y =  NULL)
image.png

提升图表显示基于树的模型(随机森林,梯度提升树和决策树)提供了最佳预测。

准确性和AUC

接收器操作特性(ROC)曲线是说明二元分类器性能的图形图。他们可视化真阳性率(TPR)与假阳性率(FPR)之间的关系。

image.png

理想模型将所有正面结果完美地归类为真假,并将所有负面结果归类为假(即TPR = 1且FPR = 0)。第二个图上的线是通过计算不同切点阈值(即.1,.2,.5,.8)的预测结果而得出的。0.1,0.2,0.5,0.8并连接点。如果您随机猜测,对角线表示预期的真/假阳性率。曲线下面积(AUC)总结了模型同时在这些阈值点上的良好程度。面积为1表示对于任何阈值,模型总是做出完美的前奏。这几乎不会发生在现实生活中。良好的AUC值介于.6之间0.6和.80.8。虽然我们无法使用Spark绘制ROC图,但我们可以根据预测提取AUC值。

Function for calculating accuracy

calc_accuracy <-  function(data, cutpoint =  0.5){

data %>%

 mutate(prediction =  if_else(prediction >  cutpoint, 1.0, 0.0)) %>%

 ml_classification_eval("prediction", "Survived", "accuracy")

}

Calculate AUC and accuracy

perf_metrics <-  data_frame(

 model =  names(ml_score),

 AUC =  100  *  map_dbl(ml_score, ml_binary_classification_eval, "Survived", "prediction"),

 Accuracy =  100  *  map_dbl(ml_score, calc_accuracy)

  )

perf_metrics

Plot results

gather(perf_metrics, metric, value, AUC, Accuracy) %>%

 ggplot(aes(reorder(model, value), value, fill = metric)) +

 geom_bar(stat =  "identity", position =  "dodge") +

 coord_flip() +

 labs(title =  "Performance metrics",

 x =  NULL,

 y =  "Percent")
image.png

总体而言,基于树的模型表现最佳 - 它们具有最高的准确率和AUC值。

特征重要性

将每个模型确定的特征作为生存的重要预测因子进行比较也很有趣。树模型实现了特征重要性度量(la randomForest::varImpPlot()。性别,票价和年龄是一些最重要的特征。

Initialize results

feature_importance <- data_frame()

Calculate feature importance

for(i in c("Decision Tree", "Random Forest", "Gradient Boosted Trees")){

  feature_importance <- ml_tree_feature_importance(ml_models[[i]]) %>%

    mutate(Model = i) %>%

    rbind(feature_importance, .)

}

Plot results

feature_importance %>%

  ggplot(aes(reorder(feature, importance), importance, fill = Model)) + 

  facet_wrap(~Model) +

  geom_bar(stat = "identity") + 

  coord_flip() +

  labs(title = "Feature importance",

       x = NULL) +

  theme(legend.position = "none") 

比较运行时间

培训模型的时间很重要。有些算法比其他算法更复杂,因此有时您需要在准确性和效率之间取得平衡。以下代码评估每个模型n时间并绘制结果。请注意,渐变增强树和神经网比其他方法花费更长的时间训练。

Number of reps per model

n <-  10

Format model formula as character

format_as_character <-  function(x){

  x <-  paste(deparse(x), collapse =  "")

  x <-  gsub("\\s+", " ", paste(x, collapse =  ""))

  x

}

Create model statements with timers

format_statements <-  function(y){

  y <-  format_as_character(y[[".call"]])

  y <-  gsub('ml_formula', ml_formula_char, y)

  y <-  paste0("system.time(", y, ")")

  y

}

Convert model formula to character

ml_formula_char <-  format_as_character(ml_formula)

Create n replicates of each model statements with timers

all_statements <-  map_chr(ml_models, format_statements) %>%

 rep(., n) %>%

 parse(text = .)

Evaluate all model statements

res <-  map(all_statements, eval)

Compile results

result <-  data_frame(model =  rep(names(ml_models), n),

 time =  map_dbl(res, function(x){as.numeric(x["elapsed"])}))

Plot

result %>%

 ggplot(aes(time, reorder(model, time))) +

 geom_boxplot() +

 geom_jitter(width =  0.4, aes(color = model)) +

 scale_color_discrete(guide =  FALSE) +

 labs(title =  "Model training times",

 x =  "Seconds",

 y =  NULL)
image.png

sparking water(H2O)和机器学习

LOOCV在哪里?k在哪里ķ - 交叉验证?好吧,sparklyr还在开发中。它不允许你做Spark可以做的每一件事。我们上面用来估计模型的函数是Spark的分布式机器学习库(MLlib)的一部分。MLlib包含交叉验证功能 -只是有没有对他们的接口sparklyr 1真正的拖累。

如果您认真考虑使用Spark并需要交叉验证和其他更强大的机器学习工具,另一个选择是H2O,一种替代的开源跨平台机器学习软件包。该rsparkling软件包提供了访问H2O的分布式机器学习功能通过sparklyr。H2O具有许多与MLlib相同的功能(如果不是更多sparklyr),但实现它有点复杂。因此,我们将大部分代码集中在MLlib算法上。

H2O和逻辑回归

作为一个快速演示,我们使用H2O估算一个10倍CV的逻辑回归模型。首先,我们需要加载一些额外的包

library(rsparkling)

library(h2o)

我们将重用之前修改的泰坦尼克号表titanic_final_tbl。但是要将它与H2O函数一起使用,我们需要将其转换为H2O数据框:

titanic_h2o <-  titanic_final_tbl %>%

 mutate(Survived =  as.numeric(Survived),

 SibSp =  as.numeric(SibSp),

 Parch =  as.numeric(Parch)) %>%

 select(Survived, Pclass, Sex, Age, SibSp, Parch, Fare, Embarked, Family_Sizes) %>%

 as_h2o_frame(sc, ., strict_version_check =  FALSE)

接下来我们可以使用估计逻辑回归模型h2o.glm()

  • 此函数不使用公式传递独立变量和因变量; 相反,它们作为字符向量参数传递给x和y

  • family = "binomial" - 确保我们运行逻辑回归,而不是连续因变量的线性回归

  • training_frame - 包含训练集的数据框(这里我们使用整个数据框,因为我们也使用交叉验证)

  • lambda_search = TRUE - 优化器函数计算参数值的参数

  • nfolds = 10 - 使用10倍交叉验证估算模型

glm_model <-  h2o.glm(x =  c("Pclass", "Sex", "Age", "SibSp", "Parch",

 "Fare", "Embarked", "Family_Sizes"),

 y =  "Survived",

 family =  "binomial",

 training_frame = titanic_h2o,

 lambda_search =  TRUE,

 nfolds =  10)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容