6

Я мастерить с некоторым кодом перекрестной проверки из документации PySpark, и пытается получить PySpark, чтобы сказать мне, что модель была выбрана:Как извлечь гипер-параметры модели из spark.ml в PySpark?

from pyspark.ml.classification import LogisticRegression 
from pyspark.ml.evaluation import BinaryClassificationEvaluator 
from pyspark.mllib.linalg import Vectors 
from pyspark.ml.tuning import ParamGridBuilder, CrossValidator 

dataset = sqlContext.createDataFrame(
    [(Vectors.dense([0.0]), 0.0), 
    (Vectors.dense([0.4]), 1.0), 
    (Vectors.dense([0.5]), 0.0), 
    (Vectors.dense([0.6]), 1.0), 
    (Vectors.dense([1.0]), 1.0)] * 10, 
    ["features", "label"]) 
lr = LogisticRegression() 
grid = ParamGridBuilder().addGrid(lr.regParam, [0.1, 0.01, 0.001, 0.0001]).build() 
evaluator = BinaryClassificationEvaluator() 
cv = CrossValidator(estimator=lr, estimatorParamMaps=grid, evaluator=evaluator) 
cvModel = cv.fit(dataset) 

Запуск этого в PySpark оболочки, я могу получить модель регрессии линейного-х коэффициенты, но я не могу найти значение lr.regParam, выбранное процедурой перекрестной проверки. Есть идеи?

In [3]: cvModel.bestModel.coefficients 
Out[3]: DenseVector([3.1573]) 

In [4]: cvModel.bestModel.explainParams() 
Out[4]: '' 

In [5]: cvModel.bestModel.extractParamMap() 
Out[5]: {} 

In [15]: cvModel.params 
Out[15]: [] 

In [36]: cvModel.bestModel.params 
Out[36]: [] 
+3

Соответствующий вопрос в Спарк Scala API: http://stackoverflow.com/questions/31749593/how-to-extract-best-parameters- from-a-crossvalidatormodel – desertnaut

+0

pyspark ответьте здесь: https://stackoverflow.com/questions/39529012/pyspark-get-all-parameters-of-models-created-with-paramgridbuilder –

+0

Обязательно отметьте ответ (wernerchao's under работал для меня). –

ответ

5

Идите в эту проблему. Я узнал, что вам нужно вызвать свойство java по какой-то причине, я не знаю почему. Так просто сделать это:

from pyspark.ml.tuning import TrainValidationSplit, ParamGridBuilder, CrossValidator 
from pyspark.ml.regression import LinearRegression 
from pyspark.ml.evaluation import RegressionEvaluator 

evaluator = RegressionEvaluator(metricName="mae") 
lr = LinearRegression() 
grid = ParamGridBuilder().addGrid(lr.maxIter, [500]) \ 
           .addGrid(lr.regParam, [0]) \ 
           .addGrid(lr.elasticNetParam, [1]) \ 
           .build() 
lr_cv = CrossValidator(estimator=lr, estimatorParamMaps=grid, \ 
         evaluator=evaluator, numFolds=3) 
lrModel = lr_cv.fit(your_training_set_here) 
bestModel = lrModel.bestModel 

печать из параметров, которые вы хотите:

>>> print 'Best Param (regParam): ', bestModel._java_obj.getRegParam() 
0 
>>> print 'Best Param (MaxIter): ', bestModel._java_obj.getMaxIter() 
500 
>>> print 'Best Param (elasticNetParam): ', bestModel._java_obj.getElasticNetParam() 
1 

Это относится и к другим методам, как extractParamMap(), а также. Они должны исправить это в ближайшее время.

+0

Nice catch. Даже лучше, чем исправить, будет функция типа 'cvModel.getAllTheBestModelsParametersPlease()' –

2

я подпрыгнул мою голову на этой стене, к сожалению, вы можете получить только конкретных параметров для конкретных моделей. К счастью для логистической регрессии вы можете получить доступ к перехвату и весам, к сожалению, вы не можете получить regParam. Это можно сделать следующим образом:

best_lr = cv.bestModel 

#get weigths 
best_lr.weights 
>>>DenseVector([3.1573]) 

#or better 
best_lr.coefficients 
>>>DenseVector([3.1573]) 

#get intercept 
best_lr.intercept 
>>>-1.0829958115287153 

Как я уже писал ранее, каждая модель имеет несколько параметров, которые могут быть извлечены. В целом получение соответствующих моделей из трубопровода (например cv.bestModel, когда крест Validator работает над Pipeline) может быть сделано с:

best_pipeline = cv.bestModel 
best_pipeline.stages 
>>>[Tokenizer_4bc8884ad68b4297fd3c,CountVectorizer_411fbdeb4100c2bfe8ef, PCA_4c538d67e7b8f29ff8d0,LogisticRegression_4db49954edc7033edc76] 

Каждая модель получается путем простого списка индексации

best_lr = best_pipeline.stages[3] 

Теперь можно применить вышеизложенное.

0

Предполагая cvModel3Day это ваши имена моделей, Титулы могут быть извлечены, как показано ниже в Спарк Scala

val params = cvModel3Day.bestModel.asInstanceOf[PipelineModel].stages(2).asInstanceOf[GBTClassificationModel].extractParamMap() 

val depth = cvModel3Day.bestModel.asInstanceOf[PipelineModel].stages(2).asInstanceOf[GBTClassificationModel].getMaxDepth 

val iter = cvModel3Day.bestModel.asInstanceOf[PipelineModel].stages(2).asInstanceOf[GBTClassificationModel].getMaxIter 

val bins = cvModel3Day.bestModel.asInstanceOf[PipelineModel].stages(2).asInstanceOf[GBTClassificationModel].getMaxBins 

val features = cvModel3Day.bestModel.asInstanceOf[PipelineModel].stages(2).asInstanceOf[GBTClassificationModel].getFeaturesCol 

val step = cvModel3Day.bestModel.asInstanceOf[PipelineModel].stages(2).asInstanceOf[GBTClassificationModel].getStepSize 

val samplingRate = cvModel3Day.bestModel.asInstanceOf[PipelineModel].stages(2).asInstanceOf[GBTClassificationModel].getSubsamplingRate 
0

Есть два вопроса, на самом деле:

  • каковы аспекты подобранной модели (например, коэффициенты и перехваты)
  • Каковы были мета-параметры, с помощью которых был установлен bestModel.

К сожалению, api встроенных оценок python (модели) не позволяет (легко) получить прямой доступ к параметрам оценки, что затрудняет ответ на последний вопрос.

Однако есть обходное решение, использующее java api.Для полноты первой полной настройки кросс проверены модели

%pyspark 
from pyspark.ml import Pipeline 
from pyspark.ml.classification import LogisticRegression 
from pyspark.ml.evaluation import BinaryClassificationEvaluator 
from pyspark.ml.tuning import CrossValidator, ParamGridBuilder 
logit = LogisticRegression(maxIter=10) 
pipeline = Pipeline(stages=[logit]) 
paramGrid = ParamGridBuilder() \ 
    .addGrid(logit.regParam, [0, 0.01, 0.05, 0.1, 0.5, 1]) \ 
    .addGrid(logit.elasticNetParam, [0.0, 0.1, 0.5, 0.8, 1]) \ 
    .build() 
evaluator = BinaryClassificationEvaluator(metricName = 'areaUnderPR') 
crossval = CrossValidator(estimator=pipeline, 
          estimatorParamMaps=paramGrid, 
          evaluator=evaluator, 
          numFolds=5) 
tuned_model = crossval.fit(train) 
model = tuned_model.bestModel 

Один затем можно использовать общие методы объекта Java, чтобы получить значения параметров, без явного обращаясь к методам, как getRegParam():

java_model = model.stages[-1]._java_obj 
{param.name: java_model.getOrDefault(java_model.getParam(param.name)) 
    for param in paramGrid[0]} 

Это выполняет следующие действия:

  1. Получить подогнанную logit model, созданный оценщиком от последней ступени лучшей модели: crossval.fit(..).bestModel.stages[-1]
  2. Получить внутренний объект Java от _java_obj
  3. Получить все сконфигурированные имена из paramGrid (который является списком словарей). Используется только первая строка, предполагая, что она является реальной сеткой, так как каждая строка содержит одни и те же ключи. В противном случае вам нужно собрать все имена, когда-либо используемые в любой строке.
  4. Получите соответствующий идентификатор параметра Param<T> из объекта java.
  5. передать экземпляр Param<T> функции getOrDefault(), чтобы получить фактическое значение
Смежные вопросы