Je veux trouver les paramètres de ParamGridBuilder
qui font le meilleur modèle dans CrossValidator dans Spark 1.4.x,
Dans Exemple de pipeline dans la documentation Spark, ils ajoutent différents paramètres (numFeatures
, regParam
) en utilisant ParamGridBuilder
dans le pipeline. Ensuite, à la ligne de code suivante, ils créent le meilleur modèle:
val cvModel = crossval.fit(training.toDF)
Maintenant, je veux savoir quels sont les paramètres (numFeatures
, regParam
) de ParamGridBuilder
qui produisent le meilleur modèle.
J'ai déjà utilisé les commandes suivantes sans succès:
cvModel.bestModel.extractParamMap().toString()
cvModel.params.toList.mkString("(", ",", ")")
cvModel.estimatorParamMaps.toString()
cvModel.explainParams()
cvModel.getEstimatorParamMaps.mkString("(", ",", ")")
cvModel.toString()
De l'aide?
Merci d'avance,
Une méthode pour obtenir un objet ParamMap
correct consiste à utiliser CrossValidatorModel.avgMetrics: Array[Double]
pour rechercher le paramètre argmax ParamMap
:
implicit class BestParamMapCrossValidatorModel(cvModel: CrossValidatorModel) {
def bestEstimatorParamMap: ParamMap = {
cvModel.getEstimatorParamMaps
.Zip(cvModel.avgMetrics)
.maxBy(_._2)
._1
}
}
Lorsque vous utilisez la CrossValidatorModel
formée dans le pipeline, vous avez cité l'exemple suivant:
scala> println(cvModel.bestEstimatorParamMap)
{
hashingTF_2b0b8ccaeeec-numFeatures: 100,
logreg_950a13184247-regParam: 0.1
}
val bestPipelineModel = cvModel.bestModel.asInstanceOf[PipelineModel]
val stages = bestPipelineModel.stages
val hashingStage = stages(1).asInstanceOf[HashingTF]
println("numFeatures = " + hashingStage.getNumFeatures)
val lrStage = stages(2).asInstanceOf[LogisticRegressionModel]
println("regParam = " + lrStage.getRegParam)
Voici comment vous obtenez les paramètres choisis
println(cvModel.bestModel.getMaxIter)
println(cvModel.bestModel.getRegParam)
ce code Java devrait fonctionner: cvModel.bestModel().parent().extractParamMap()
.vous pouvez le traduire en code scala parent()
method renverra un estimateur, vous pourrez alors obtenir les meilleurs paramètres.
C'est la ParamGridBuilder ()
paraGrid = ParamGridBuilder().addGrid(
hashingTF.numFeatures, [10, 100, 1000]
).addGrid(
lr.regParam, [0.1, 0.01, 0.001]
).build()
Il y a 3 étapes dans le pipeline. Il semble que nous puissions évaluer les paramètres comme suit:
for stage in cv_model.bestModel.stages:
print 'stages: {}'.format(stage)
print stage.params
print '\n'
stage: Tokenizer_46ffb9fac5968c6c152b
[Param(parent='Tokenizer_46ffb9fac5968c6c152b', name='inputCol', doc='input column name'), Param(parent='Tokenizer_46ffb9fac5968c6c152b', name='outputCol', doc='output column name')]
stage: HashingTF_40e1af3ba73764848d43
[Param(parent='HashingTF_40e1af3ba73764848d43', name='inputCol', doc='input column name'), Param(parent='HashingTF_40e1af3ba73764848d43', name='numFeatures', doc='number of features'), Param(parent='HashingTF_40e1af3ba73764848d43', name='outputCol', doc='output column name')]
stage: LogisticRegression_451b8c8dbef84ecab7a9
[]
Cependant, il n'y a pas de paramètre dans la dernière étape, logiscRegression.
Nous pouvons également obtenir les paramètres poids et interception de la régression logistique comme suit:
cv_model.bestModel.stages[1].getNumFeatures()
10
cv_model.bestModel.stages[2].intercept
1.5791827733883774
cv_model.bestModel.stages[2].weights
DenseVector([-2.5361, -0.9541, 0.4124, 4.2108, 4.4707, 4.9451, -0.3045, 5.4348, -0.1977, -1.8361])
Exploration complète: http://kuanliang.github.io/2016-06-07-SparkML-pipeline/
Je travaille avec Spark Scala 1.6.x et voici un exemple complet de la façon dont je peux définir et adapter une CrossValidator
, puis renvoyer la valeur du paramètre utilisé pour obtenir le meilleur modèle (en supposant que training.toDF
donne un cadre de données prêt à être utilisé) :
import org.Apache.spark.ml.classification.LogisticRegression
import org.Apache.spark.ml.tuning.{CrossValidator, ParamGridBuilder}
import org.Apache.spark.ml.evaluation.MulticlassClassificationEvaluator
// Instantiate a LogisticRegression object
val lr = new LogisticRegression()
// Instantiate a ParamGrid with different values for the 'RegParam' parameter of the logistic regression
val paramGrid = new ParamGridBuilder().addGrid(lr.regParam, Array(0.0001, 0.001, 0.01, 0.1, 0.25, 0.5, 0.75, 1)).build()
// Setting and fitting the CrossValidator on the training set, using 'MultiClassClassificationEvaluator' as evaluator
val crossVal = new CrossValidator().setEstimator(lr).setEvaluator(new MulticlassClassificationEvaluator).setEstimatorParamMaps(paramGrid)
val cvModel = crossVal.fit(training.toDF)
// Getting the value of the 'RegParam' used to get the best model
val bestModel = cvModel.bestModel // Getting the best model
val paramReference = bestModel.getParam("regParam") // Getting the reference of the parameter you want (only the reference, not the value)
val paramValue = bestModel.get(paramReference) // Getting the value of this parameter
print(paramValue) // In my case : 0.001
Vous pouvez faire la même chose pour n’importe quel paramètre ou tout autre type de modèle.
Pour tout imprimer dans paramMap
, vous n'avez pas besoin d'appeler le parent:
cvModel.bestModel().extractParamMap()
Pour répondre à la question de OP, pour obtenir un seul meilleur paramètre, par exemple regParam
:
cvModel.bestModel().extractParamMap().apply(cvModel.bestModel.getParam("regParam"))