Spark CrossValidatorModel доступ к другим моделям, кроме BestModel?

Я использую Spark 1.6.1:

В настоящее время я использую CrossValidator для обучения моего ML Pipeline с различными параметрами. После обучения я могу использовать свойство bestModel CrossValidatorModel, чтобы получить модель, которая показала наилучшие результаты при перекрестной проверке. Остальные модели перекрестной проверки автоматически отбрасываются или я могу выбрать модель, которая работает хуже, чем bestModel?

Я спрашиваю, потому что я использую метрику балла F1 для перекрестной проверки, но меня также интересует weighedRecall для всех моделей, а не только для модели, которая показала наилучшие результаты во время перекрестной проверки

val folds = 6
val cv = new CrossValidator()
  .setEstimator(pipeline)
  .setEvaluator(new MulticlassClassificationEvaluator)
  .setEstimatorParamMaps(paramGrid)
  .setNumFolds(folds)

val avgF1Scores = cvModel.avgMetrics

val predictedDf = cvModel.bestModel.transform(testDf)

// Here I would like to predict as well with the other models of the cross validation

Ответы на вопрос(2)

Решение Вопроса

Искра> = 2.4.0 (> =2.3.0 в Скале)

СПАРК-21088 CrossValidator, TrainValidationSplit должны собрать все модели при установке - добавлена ​​поддержка сбора субмоделей.

cv = CrossValidator(..., collectSubModels=True)

model = cv.fit(...)
model.subModels

Искра <2,4

Если вы хотите получить доступ ко всем промежуточным моделям, вам придется создать собственный перекрестный валидатор с нуля.o.a.s.ml.tuning.CrossValidator сбрасывает другие модели, и только лучшие и метрики копируются вCrossValidatorModel.

Смотрите такжеPyspark - Получить все параметры моделей, созданных с помощью ParamGridBuilder.

 Jeremy16 июн. 2018 г., 18:48
В Scala 2.3 (возможно, раньше) есть .setCollectSubModels ()
 savinay narendra26 июл. 2019 г., 03:06
Я использовал model.subModels, но он возвращает массив. Как я могу получить оценку F1 или точность для каждой из этих подмоделей?

Если вы просто хотите сделать это для экспериментов, а не для производственной реализации чего-либо, я рекомендую использовать патчи для обезьян. Вот что я сделал, чтобы распечатать промежуточные результаты обучения. Просто используйтеCrossValidatorVerbose в качестве замены для заменыCrossValidator.

import numpy as np

from pyspark.ml.tuning import CrossValidator, CrossValidatorModel
from pyspark.sql.functions import rand


class CrossValidatorVerbose(CrossValidator):

    def _fit(self, dataset):
        est = self.getOrDefault(self.estimator)
        epm = self.getOrDefault(self.estimatorParamMaps)
        numModels = len(epm)

        eva = self.getOrDefault(self.evaluator)
        metricName = eva.getMetricName()

        nFolds = self.getOrDefault(self.numFolds)
        seed = self.getOrDefault(self.seed)
        h = 1.0 / nFolds

        randCol = self.uid + "_rand"
        df = dataset.select("*", rand(seed).alias(randCol))
        metrics = [0.0] * numModels

        for i in range(nFolds):
            foldNum = i + 1
            print("Comparing models on fold %d" % foldNum)

            validateLB = i * h
            validateUB = (i + 1) * h
            condition = (df[randCol] >= validateLB) & (df[randCol] < validateUB)
            validation = df.filter(condition)
            train = df.filter(~condition)

            for j in range(numModels):
                paramMap = epm[j]
                model = est.fit(train, paramMap)
                # TODO: duplicate evaluator to take extra params from input
                metric = eva.evaluate(model.transform(validation, paramMap))
                metrics[j] += metric

                avgSoFar = metrics[j] / foldNum
                print("params: %s\t%s: %f\tavg: %f" % (
                    {param.name: val for (param, val) in paramMap.items()},
                    metricName, metric, avgSoFar))

        if eva.isLargerBetter():
            bestIndex = np.argmax(metrics)
        else:
            bestIndex = np.argmin(metrics)

        bestParams = epm[bestIndex]
        bestModel = est.fit(dataset, bestParams)
        avgMetrics = [m / nFolds for m in metrics]
        bestAvg = avgMetrics[bestIndex]
        print("Best model:\nparams: %s\t%s: %f" % (
            {param.name: val for (param, val) in bestParams.items()},
            metricName, bestAvg))

        return self._copyValues(CrossValidatorModel(bestModel, avgMetrics))

НОТА: это решение также исправляет то, что я вижу как ошибку в v2.0.0, где CrossValidationModel.avgMetrics установлены на сумму метрик вместо среднего.

Вот пример вывода для простой 5-кратной проверкиALS:

Comparing models on fold 1
params: {'regParam': 0.1, 'rank': 5, 'maxIter': 10}     rmse: 1.122425  avg: 1.122425
params: {'regParam': 0.01, 'rank': 5, 'maxIter': 10}    rmse: 1.123537  avg: 1.123537
params: {'regParam': 0.001, 'rank': 5, 'maxIter': 10}   rmse: 1.123651  avg: 1.123651
Comparing models on fold 2
params: {'regParam': 0.1, 'rank': 5, 'maxIter': 10}     rmse: 0.992541  avg: 1.057483
params: {'regParam': 0.01, 'rank': 5, 'maxIter': 10}    rmse: 0.992541  avg: 1.058039
params: {'regParam': 0.001, 'rank': 5, 'maxIter': 10}   rmse: 0.992541  avg: 1.058096
Comparing models on fold 3
params: {'regParam': 0.1, 'rank': 5, 'maxIter': 10}     rmse: 1.141786  avg: 1.085584
params: {'regParam': 0.01, 'rank': 5, 'maxIter': 10}    rmse: 1.141786  avg: 1.085955
params: {'regParam': 0.001, 'rank': 5, 'maxIter': 10}   rmse: 1.141786  avg: 1.085993
Comparing models on fold 4
params: {'regParam': 0.1, 'rank': 5, 'maxIter': 10}     rmse: 0.954110  avg: 1.052715
params: {'regParam': 0.01, 'rank': 5, 'maxIter': 10}    rmse: 0.952955  avg: 1.052705
params: {'regParam': 0.001, 'rank': 5, 'maxIter': 10}   rmse: 0.952873  avg: 1.052713
Comparing models on fold 5
params: {'regParam': 0.1, 'rank': 5, 'maxIter': 10}     rmse: 1.140098  avg: 1.070192
params: {'regParam': 0.01, 'rank': 5, 'maxIter': 10}    rmse: 1.139589  avg: 1.070082
params: {'regParam': 0.001, 'rank': 5, 'maxIter': 10}   rmse: 1.139535  avg: 1.070077
Best model:
params: {'regParam': 0.001, 'rank': 5, 'maxIter': 10}   rmse: 1.070077
 André Machado05 дек. 2018 г., 12:25
У меня была эта проблема, но я хотел извлечь больше метрик, чем тот, который использовался для оценки. Я внес некоторые изменения в метод, который вы реализовалиссылка на сайт, Спасибо за ваш ответ, это было очень полезно.

Ваш ответ на вопрос