sparkR 1.6:如何用glm(二项式族)建模时预测概率

时间:2016-06-25 19:03:12

标签: sparkr

我刚刚在CentOS上安装了sparkR 1.6.1并且没有使用hadoop。我的代码是用离散的' TARGET'来模拟数据。值如下:

# 'tr' is a R data frame with 104 numeric columns and one TARGET column
#    TARGET column is either 0 or 1
# Convert 'tr' to spark data frame

train <- createDataFrame(sqlContext, tr)

# test is an R dataframe without TARGET column
# Convert 'test' to spark Data frame
te<-createDataFrame(sqlContext,test)
# Using sparkR's glm model to model data
model <- glm(TARGET ~ . , data = train, family = "binomial")
# Make predictions
predictions <- predict(model, newData = te )

我能够如下评估成功或失败(我希望我是对的):

modelPrediction <- select(predictions, "prediction")
head(modelPrediction)

  prediction
1          0
2          0
3          0
4          0
5          0
6          0

但是当我想评估概率时,我得到的结果如下:

modelPrediction <- select(predictions, "probability")
head(modelPrediction)

                probability
1 <environment: 0x6188e1c0>
2 <environment: 0x61894b88>
3 <environment: 0x6189a620>
4 <environment: 0x618a00b8>
5 <environment: 0x618a5b50>
6 <environment: 0x618ac550>

请帮助我获取测试事件的概率值。感谢。

1 个答案:

答案 0 :(得分:1)

背景:当你的R代码从Spark后端请求一些计算结果时,Spark会进行计算并序列化结果。然后在R侧反序列化该结果,并获得R对象。

现在,它在Spark后端的工作方式是 - 如果它确定要返回的对象的类型是CharacterStringLong之一,{ {1}},Float DoubleIntegerBooleanDate或其TimeStamp等,然后序列化对象。但是如果它发现该类型与这些类型中的任何一个都不匹配,它只是为对象分配一个id,将它存储在内存中,并将该id发送给R客户端。 (RBackendHandler中的Array负责跟踪spark后端的jvm对象。)然后将其反序列化为R端的jobj类。 (您可以查看JVMObjectTracker的{​​{1}}方法,以全面了解预先序列化的内容和不预定的内容。

现在,如果您查看writeObject数据框的probability列中的对象,则在R侧,您将看到他们的班级为predictions。如上所述,此类的对象充当Spark群集上保存的实际Java对象的代理。在这种特殊情况下,后备java类是jobj。这是一个向量,因为它包含每个类的概率。并且因为此向量不是SerDe类支持的序列化类型之一,所以spark后端只返回org.apache.spark.mllib.linalg.DenseVector代理并将这些jobj对象存储在内存中,以便将来对它们进行操作。

使用该背景 - 您应该能够通过调用这些DenseVector对象上的方法获得R前端的概率值。截至目前,我认为这是唯一的方法。以下是适用于虹膜数据集的代码 -

DenseVector

有了这个我得到两个类的以下概率输出 -

irisDf <- createDataFrame(sqlContext, iris)
irisDf$target <- irisDf$Species == 'setosa'
model <- glm(target ~ . , data = irisDf, family = "binomial")
summary(model)
predictions <- predict(model, newData = irisDf)
modelPrediction <- select(predictions, "probability")
localPredictions <- SparkR:::as.data.frame(predictions)

getValFrmDenseVector <- function(x) {
    #Given it's binary classification there are just two elems in vector
    a <- SparkR:::callJMethod(x$probability, "apply", as.integer(0))
    b <- SparkR:::callJMethod(x$probability, "apply", as.integer(1))
    c(a, b)
}

t(apply(localPredictions, 1, FUN=getValFrmDenseVector))

注意: [,1] [,2] 1 3.036612e-15 1.000000e+00 2 5.919287e-12 1.000000e+00 3 7.831827e-14 1.000000e+00 4 7.712003e-13 1.000000e+00 5 4.427117e-16 1.000000e+00 6 3.816329e-16 1.000000e+00 [...] 前缀函数不会在SparkR包名称空间中导出。所以请记住,您正在编写针对包私有实现的编码。 (但我不知道如何实现这一点,除非Spark为它提供了公共API支持。)