0

我想为一个简单的多层感知器 Keras 回归器创建一个自定义弹球损失函数。为了调整回归器的超参数,我使用了 OptunaSearchCV(其工作方式类似于 scikit-learn RandomizedSearchCV)。

我认为错误的罪魁祸首是我制作的自定义评分功能。它的功能是,对于每个实例(输入数据的行),计算长度为 3 的预测输出的弹球损失以及相应的分位数目标:0.05、0.5 和 0.95。

我有一个玩具示例来复制错误消息。

import math
import numpy as np
import pandas as pd
from severe_weather.data_prepare.config import SalesConfig, ResultsConfig
import optuna
from sklearn.metrics import make_scorer
from optuna.distributions import IntUniformDistribution, UniformDistribution
from optuna.pruners import MedianPruner
from optuna.integration import OptunaSearchCV
from optuna.samplers import RandomSampler
import tensorflow as tf
import tensorflow.keras.backend as K
from tensorflow import keras
from scikeras.wrappers import KerasRegressor
from sklearn.model_selection import train_test_split

# dummy data
df = pd.DataFrame(np.random.rand(100, 10))
train, test = train_test_split(df, test_size=0.1, random_state = 1)
x_train, y_train = train.iloc[:, :-1], train.iloc[:, -1].values.reshape(-1,1) 
x_test, y_test = test.iloc[:, :-1], test.iloc[:, -1]

# custom loss function
def pinball_loss(alpha = [0.05, 0.5, 0.95]):
    def loss(y_true, y_pred):
        err = y_true - y_pred
        par = tf.constant(np.array(alpha), dtype=tf.float32)
        return K.mean(K.maximum(par * err, (par - 1) * err), axis=-1)
    return loss

# the MLP model
def get_model(n_neurons, dropout):
    model = keras.models.Sequential()
    model.add(keras.layers.InputLayer(input_shape=[9,]))
    model.add(keras.layers.Normalization(axis=-1))
    model.add(keras.layers.Dropout(dropout))
    model.add(keras.layers.Dense(n_neurons, activation='relu'))
    model.add(keras.layers.Dense(3))
    return model

alpha = [0.05, 0.5, 0.95]

reg = KerasRegressor(get_model, n_neurons=2, dropout=0.0, loss=pinball_loss(alpha=alpha))

study = optuna.create_study(
    direction='maximize',
    sampler=RandomSampler(seed=42),
    pruner=MedianPruner())

default_trials = [study.enqueue_trial(dict(n_neurons=s, dropout=t))
                  for s in [2] for t in [0.0]]
n_trials = 1

# custom scoring function
neg_mean_pinball_loss_scorer = make_scorer(
    pinball_loss(alpha=alpha),
    greater_is_better=False)

param_distributions = {
    "n_neurons": IntUniformDistribution(2, 10),
    "dropout": UniformDistribution(0, 0.5)}

tuned_ensemble = OptunaSearchCV(
        reg, param_distributions,
        study=study, n_trials=2, n_jobs=1,
        scoring=neg_mean_pinball_loss_scorer)    

tuned_ensemble.fit(x_train, np.tile(y_train, 3), batch_size=20, epochs=5, verbose=1, validation_split=0.3)    

这是错误消息:

[W 2022-02-03 12:51:30,963] Trial 0 failed because of the following error: ValueError("scoring must return a number, got tf.Tensor(\n[-0.20005344 -0.15885974 -0.382643   -0.4041188  -0.24968709 -0.27153793\n -0.46907195 -0.09022937 -0.21099593 -0.46771994 -0.21804126 -0.35117796\n -0.24562387 -0.3742094  -0.3017985  -0.14807063 -0.2012295  -0.12404507], shape=(18,), dtype=float32) (<class 'tensorflow.python.framework.ops.EagerTensor'>) instead. (scorer=make_scorer(loss, greater_is_better=False))")
Traceback (most recent call last):
  File "/home/hdpdib/.local/lib/python3.9/site-packages/optuna/study/_optimize.py", line 213, in _run_trial
    value_or_values = func(trial)
  File "/home/hdpdib/.local/lib/python3.9/site-packages/optuna/integration/sklearn.py", line 229, in __call__
    scores = cross_validate(
  File "/home/hdpdib/.local/lib/python3.9/site-packages/sklearn/model_selection/_validation.py", line 267, in cross_validate
    results = parallel(
  File "/home/hdpdib/.local/lib/python3.9/site-packages/joblib/parallel.py", line 1043, in __call__
    if self.dispatch_one_batch(iterator):
  File "/home/hdpdib/.local/lib/python3.9/site-packages/joblib/parallel.py", line 861, in dispatch_one_batch
    self._dispatch(tasks)
  File "/home/hdpdib/.local/lib/python3.9/site-packages/joblib/parallel.py", line 779, in _dispatch
    job = self._backend.apply_async(batch, callback=cb)
  File "/home/hdpdib/.local/lib/python3.9/site-packages/joblib/_parallel_backends.py", line 208, in apply_async
    result = ImmediateResult(func)
  File "/home/hdpdib/.local/lib/python3.9/site-packages/joblib/_parallel_backends.py", line 572, in __init__
    self.results = batch()
  File "/home/hdpdib/.local/lib/python3.9/site-packages/joblib/parallel.py", line 262, in __call__
    return [func(*args, **kwargs)
  File "/home/hdpdib/.local/lib/python3.9/site-packages/joblib/parallel.py", line 262, in <listcomp>
    return [func(*args, **kwargs)
  File "/home/hdpdib/.local/lib/python3.9/site-packages/sklearn/utils/fixes.py", line 211, in __call__
    return self.function(*args, **kwargs)
  File "/home/hdpdib/.local/lib/python3.9/site-packages/sklearn/model_selection/_validation.py", line 703, in _fit_and_score
    test_scores = _score(estimator, X_test, y_test, scorer, error_score)
  File "/home/hdpdib/.local/lib/python3.9/site-packages/sklearn/model_selection/_validation.py", line 794, in _score
    raise ValueError(error_msg % (scores, type(scores), scorer))
ValueError: scoring must return a number, got tf.Tensor(
[-0.20005344 -0.15885974 -0.382643   -0.4041188  -0.24968709 -0.27153793
 -0.46907195 -0.09022937 -0.21099593 -0.46771994 -0.21804126 -0.35117796
 -0.24562387 -0.3742094  -0.3017985  -0.14807063 -0.2012295  -0.12404507], shape=(18,), dtype=float32) (<class 'tensorflow.python.framework.ops.EagerTensor'>) instead. (scorer=make_scorer(loss, greater_is_better=False))
Traceback (most recent call last):
  File "/lowes/daci/severe-weather/severe_weather/hurricanes/Phase_I/modeling/lp_test.py", line 68, in <module>
    tuned_ensemble.fit(x_train, np.tile(y_train, 3), batch_size=25, epochs=5, verbose=1, validation_split=0.3)    
  File "/home/hdpdib/.local/lib/python3.9/site-packages/optuna/integration/sklearn.py", line 875, in fit
    self.study_.optimize(
  File "/home/hdpdib/.local/lib/python3.9/site-packages/optuna/study/study.py", line 400, in optimize
    _optimize(
  File "/home/hdpdib/.local/lib/python3.9/site-packages/optuna/study/_optimize.py", line 66, in _optimize
    _optimize_sequential(
  File "/home/hdpdib/.local/lib/python3.9/site-packages/optuna/study/_optimize.py", line 163, in _optimize_sequential
    trial = _run_trial(study, func, catch)
  File "/home/hdpdib/.local/lib/python3.9/site-packages/optuna/study/_optimize.py", line 264, in _run_trial
    raise func_err
  File "/home/hdpdib/.local/lib/python3.9/site-packages/optuna/study/_optimize.py", line 213, in _run_trial
    value_or_values = func(trial)
  File "/home/hdpdib/.local/lib/python3.9/site-packages/optuna/integration/sklearn.py", line 229, in __call__
    scores = cross_validate(
  File "/home/hdpdib/.local/lib/python3.9/site-packages/sklearn/model_selection/_validation.py", line 267, in cross_validate
    results = parallel(
  File "/home/hdpdib/.local/lib/python3.9/site-packages/joblib/parallel.py", line 1043, in __call__
    if self.dispatch_one_batch(iterator):
  File "/home/hdpdib/.local/lib/python3.9/site-packages/joblib/parallel.py", line 861, in dispatch_one_batch
    self._dispatch(tasks)
  File "/home/hdpdib/.local/lib/python3.9/site-packages/joblib/parallel.py", line 779, in _dispatch
    job = self._backend.apply_async(batch, callback=cb)
  File "/home/hdpdib/.local/lib/python3.9/site-packages/joblib/_parallel_backends.py", line 208, in apply_async
    result = ImmediateResult(func)
  File "/home/hdpdib/.local/lib/python3.9/site-packages/joblib/_parallel_backends.py", line 572, in __init__
    self.results = batch()
  File "/home/hdpdib/.local/lib/python3.9/site-packages/joblib/parallel.py", line 262, in __call__
    return [func(*args, **kwargs)
  File "/home/hdpdib/.local/lib/python3.9/site-packages/joblib/parallel.py", line 262, in <listcomp>
    return [func(*args, **kwargs)
  File "/home/hdpdib/.local/lib/python3.9/site-packages/sklearn/utils/fixes.py", line 211, in __call__
    return self.function(*args, **kwargs)
  File "/home/hdpdib/.local/lib/python3.9/site-packages/sklearn/model_selection/_validation.py", line 703, in _fit_and_score
    test_scores = _score(estimator, X_test, y_test, scorer, error_score)
  File "/home/hdpdib/.local/lib/python3.9/site-packages/sklearn/model_selection/_validation.py", line 794, in _score
    raise ValueError(error_msg % (scores, type(scores), scorer))
ValueError: scoring must return a number, got tf.Tensor(
[-0.20005344 -0.15885974 -0.382643   -0.4041188  -0.24968709 -0.27153793
 -0.46907195 -0.09022937 -0.21099593 -0.46771994 -0.21804126 -0.35117796
 -0.24562387 -0.3742094  -0.3017985  -0.14807063 -0.2012295  -0.12404507], shape=(18,), dtype=float32) (<class 'tensorflow.python.framework.ops.EagerTensor'>) instead. (scorer=make_scorer(loss, greater_is_better=False))
4

0 回答 0