我刚刚在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>
请帮助我获取测试事件的概率值。感谢。
答案 0 :(得分:1)
背景:当你的R代码从Spark后端请求一些计算结果时,Spark会进行计算并序列化结果。然后在R侧反序列化该结果,并获得R对象。
现在,它在Spark后端的工作方式是 - 如果它确定要返回的对象的类型是Character
,String
,Long
之一,{ {1}},Float
Double
,Integer
,Boolean
,Date
或其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支持。)