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

sparkR 1.6: How to predict probability when modeling with glm (binomial family)

我刚刚在 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>

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

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

现在,它在 Spark 后端上的工作方式是——如果它认为要返回的对象类型是 CharacterStringLong 之一, Float, Double Integer, Boolean, Date, TimeStamp 或它们的 Array 等,然后它序列化对象。但是如果它发现类型不匹配这些中的任何一个,它会简单地为对象分配一个 id,将它存储在内存中与该 id 相对应,并将该 id 发送给 R 客户端。 (RBackendHandler is responsible for keeping track of jvm object on spark backend.) This is then deserialized into jobj class on the R side. (You can look at writeObject method of SerDe.scala 中的 JVMObjectTracker 以全面了解什么是预先序列化的,什么不是。)

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

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

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))

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

        [,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::: 前缀函数不会在 SparkR 包命名空间中导出。所以请记住,您正在针对包私有实现进行编码。 (但我真的不知道如何才能实现这一目标,除非 Spark 提供 public API 支持。)