网格搜索 scala实现

导包

import org.apache.spark.ml.{Model, Pipeline, PipelineModel, PipelineStage}
import org.apache.spark.ml.evaluation.{BinaryClassificationEvaluator, Evaluator}
import org.apache.spark.ml.tuning.ParamGridBuilder
import org.apache.spark.ml.param.ParamMap
import org.apache.spark.ml.tuning.{CrossValidator}
import org.apache.spark.ml.classification.LogisticRegression
import org.apache.spark.sql.functions._
import org.apache.spark.ml.feature.VectorAssembler
import org.apache.spark.ml.linalg.{Vector, Vectors}
import org.apache.spark.sql.{DataFrame, Row, SparkSession}

数据构造

var dfTrain = Seq(
    (1, 5.1, 3.5, 1.4, 0.2, 0),
    (2, 4.9, 3.0, 1.4, 0.2, 1),
    (3, 4.7, 3.2, 1.3, 0.2, 0),
    (4, 4.6, 3.1, 1.5, 0.2, 1),
    (5, 5.0, 3.6, 1.4, 0.2, 0),
    (56, 5.7, 2.8, 4.5, 1.3,1),
    (57, 5.3, 3.3, 4.7, 1.6,0),
    (58, 4.9, 2.4, 3.3, 1.0,1),
    (59, 6.6, 3.9, 4.6, 1.3,1),
    (60, 5.2, 2.7, 3.9, 1.4,0)
  ).toDF("id","x1","x2", "x3","x4","label")
val dfTest = dfTrain
dfTrain.show()

pipeline

省略复杂的数据预处理过程

// 向量化
val assemble = new VectorAssembler()
      .setInputCols(Array("x1","x2","x3","x4"))
      .setOutputCol("features")
// 逻辑回归 
val lr = new LogisticRegression().
            setMaxIter(10).
            setRegParam(0.01)
// 模型
val pipeline = new Pipeline().setStages(Array(assemble, lr))

网格搜索

网格参数设置

val elasticNetParamArray =Array(0.2,0.3,0.5)
val regParamArray =Array(0.01, 0.1)
val paramGrid = new ParamGridBuilder().
      addGrid(lr.elasticNetParam,elasticNetParamArray ).
      addGrid(lr.regParam,regParamArray ).
      build()

这里需要关注下paramGrid是一个Array,里面的元素是ParamMap

cv设置

CV设置主要参数为:

  • K折交叉验证的K
  • 评估指标
val evaluator = new BinaryClassificationEvaluator()
val evaluator1 =
  new BinaryClassificationEvaluator()
    .setLabelCol("label") 
    .setRawPredictionCol("rawPrediction")
    .setMetricName("areaUnderROC") // (supports "areaUnderROC" (default), "areaUnderPR")
// 准确率,二分类多分类通用
// val evaluator1 = new MulticlassClassificationEvaluator().
//       setLabelCol("label").
//       setPredictionCol("prediction").
//       setMetricName("accuracy")
// 多分类f1、precision、recall
// val evaluator1 = new MulticlassClassificationEvaluator().
//          setLabelCol("label").
//          setPredictionCol("prediction").
//          setMetricName("f1")//(supports "f1" (default), "weightedPrecision", "weightedRecall", "accuracy")
//需要注意的是BinaryClassificationEvaluator只有AUC、AUPR,而MulticlassClassificationEvaluator的精确率、召回率、f1都是加了权重的,并不适用二分类问题。准确率多分类和二分类一样。
val cv = new CrossValidator().
  setEstimator(pipeline).
  setEvaluator(evaluator1). //评估指标
  setEstimatorParamMaps(paramGrid). //网格搜索参数
  setNumFolds(3) // 3折交叉验证  
// 执行cv
val moedel = cv.fit(dfTrain)

cv结果

做完交叉验证,我们一般想知道:

  • 每个参数组合的avgMetric是多少
  • 最优参数组合是什么//某种意义上和前面一致
  • 最优模型,及其参数

其中avgMetric是可以从cv中直接获取的,它的顺序和paramGrid是一样的。最优模型可以通过bestModel属性获得。

// zip之后生成Array,每个元素都是Tuple2
// Tuple2._1是网格搜索的维度组合,ParamMap类型;Tuple2._2是该参数组合cv之后avgMetric
// 按照avgMetric升序排序
val combined = paramGrid.zip(moedel.avgMetrics).sortBy(_._2)
// 输出交叉验证的结果
println(s"validation result:${combined.toList}")
// 输出metric的max和min值,不同的场景最优的avgMetric可能是最大值也可能是最小值
println("*=*=*=*=*=*=*=*=*=*=*=*CV:Max Min avgMetric=*=*=*=*=*=*=*=*=*=*=*=*=*")
println(combined.maxBy(_._2))
println(combined.minBy(_._2))
println("*=*=*=*=*=*=*=*=*=*=*=*CV:Max Min avgMetric=*=*=*=*=*=*=*=*=*=*=*=*=*")

最优模型

val bestModel = moedel.bestModel

输出模型参数

bestModel.asInstanceOf[PipelineModel].stages.last.extractParamMap

预测

bestModel.transform(dfTest).show()

疑问:
lr模型设定threshold备选参数并通过cv找到最优参数后在预测时为何依然选中默认的0.5?

参考:
模型调参

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值