我是Spark和Python的新手。我使用Spark来训练一个只有两个类(0和1)的Logistic回归模型。我用我的火车数据框训练了它。
这是我的管道模型的定义方式:
# Model definition:
lr = LogisticRegression(featuresCol = "lr_features", labelCol = "targetvar")
# Pipeline definition:
lr_pipeline = Pipeline(stages = indexStages + encodeStages +[lr_assembler, lr])
# Fit the logistic regression model:
lrModel = lr_pipeline.fit(train)
然后我使用我的测试数据框运行预测:
lr_predictions = lrModel.transform(test)
现在,我的lr_predictions有一个列'概率'这对我来说就像一个嵌套列表。例如,它的第一个单元格包含:
并[1,2,[],[0.88,0.11]]
我假设,这意味着:第1类(= 0)的概率为0.88,第2类(即= 1)的概率为0.11。
默认情况下(阈值= 0.5)预测此观察结果 因为,我找到了一个最大化F-measure的值(bestThreshold)(在我的例子中它是0.21):
fMeasure = lr_summary.fMeasureByThreshold
bestThreshold = fMeasure.orderBy(fMeasure['F-Measure'].desc()).first().threshold
我想将bestThreshold应用于'概率'专栏并获得一个新的 列(' pred_new',例如)包含基于bestThreshold而非0.5的类分配(0或1)。
我无法使用下面的代码,因为'概率'列过于复杂:
from pyspark.sql.functions import when
lr_predictions = lr_predictions.withColumn("prob_best", \
when(lr_predictions["probability"] >= bestThreshold, 1).otherwise(0)
我觉得我需要映射概率'基于新阈值的新列。但我不知道该怎么做 - 鉴于这个复杂的(对我而言)概率的结构'列。
非常感谢你的建议!
答案 0 :(得分:3)
如果lrModel
为LogisticRegressionModel
:
type(lrModel)
## pyspark.ml.classification.LogisticRegressionModel
您可以使用内部Java对象来设置阈值
lrModel._java_obj.setThreshold(bestThreshold)
并转换:
lrModel.transform(data)
您也可以这样做来修改rawPredictionCol
,predictionCol
和probabilityCol
。
这将成为未来公共API的一部分(2.3):
lrModel.transform(data, {lrModel.threshold: bestThreshold})
您也可以使用UDF:
from pyspark.sql.functions import udf, lit
@udf("integer")
def predict(v, threshold):
return 0 if v[0] >= bestThreshold else 1
lr_predictions.withColumn(
"prob_best",
predict(lr_predictions["probability"], lit(bestThreshold)))
修改:
使用PipelineModel
,您可以尝试访问LogisticRegressionModel
(如your previous question中所述)并执行相同的操作。