Получение «недостающих 2 требуемых позиционных аргументов» из-за пользовательского счетчика, который я передаю cross_val_score

#python #pandas #scikit-learn

#python #панды #scikit-learn

Вопрос:

Итак, основная идея состоит в том, чтобы создать пользовательский счетчик для измерения специфичности, потому что он не является частью предопределенных методов подсчета очков scikit learn.

Метод, похоже, работает нормально, однако, когда я пытаюсь передать результаты из cross_val_score во фрейм данных, который я позже построю с помощью seaborn boxplot, я получаю следующую ошибку.

TypeError: __call__() missing 2 required positional arguments: 'X' and 'y_true'

Процесс, который вызывает cross_val_score

         mbox = pd.DataFrame()
        for metric in metrics:
            if metric == 'specificity':
                metric = make_scorer(custom_specificity)
            results = cross_val_score(model, x_test_m, y_test_m, cv=cv_num, scoring=metric)
            print('results', type(results))
            if show_raw_data:
                raw = np.array2string(results, threshold=np.inf, max_line_width=np.inf, separator=',')
                raw.replace('n', '').replace(' ', '')
                print(metric, ": %.3f%% Std.: %.3f%%" % (results.mean() * 100.0, results.std() * 100.0))
                print("Metric raw data: ", raw)
            mbox[metric] = results
 

Для остальных предопределенных показателей я получаю следующие результаты.

 results <class 'numpy.ndarray'>
accuracy : 87.361% Std.: 4.934%
Metric raw data:  [0.8125    ,0.875     ,0.93333333]
 

Для пользовательского счетчика я получаю следующие результаты.

 results <class 'numpy.ndarray'>
make_scorer(custom_specificity) : 83.333% Std.: 11.785%
Metric raw data:  [0.75,0.75,1.  ]
 

Пользовательская функция счетчика

 def custom_specificity(y_true, y_pred, **kwargs):
    tp, fp, tn, fn = custom_measure(y_true, y_pred)
    if tn   fp == 0:
        return 1
    else:
        return tn / (tn   fp)
 

Функция custom_measure

 def custom_measure(y_actual, y_hat):
    tp, fp, tn, fn = 0, 0, 0, 0
    cm = confusion_matrix(y_actual, y_hat)
    tn = cm[0][0]
    fn = cm[1][0]
    tp = cm[1][1]
    fp = cm[0][1]
    return tp, fp, tn, fn
 

Трассировка стека

 ---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-7-0ebc81311532> in <module>
      2 trained_models_using_pca_comp = train.train_models(pca_train_x, pca_train_y, pca_test_x, pca_test_y)
      3 evaluate.generate_metrics(trained_models_using_pca_comp, pca_test_x, pca_test_y, 
----> 4                           ['accuracy', 'precision', 'recall', 'f1', 'specificity'], cv_num=cross_val_num, show_raw_data=True)

~thesisProjectthesismoduleMetrics.py in generate_metrics(models, x_test, y_test, metrics, cv_num, show_raw_data)
     74                     print(metric, ": %.3f%% Std.: %.3f%%" % (results.mean() * 100.0, results.std() * 100.0))
     75                     print("Metric raw data: ", raw)
---> 76                 mbox[metric] = results
     77 
     78             # plot confusion matrix

~anaconda3libsite-packagespandascoreframe.py in __setitem__(self, key, value)
   3023 
   3024     def __setitem__(self, key, value):
-> 3025         key = com.apply_if_callable(key, self)
   3026 
   3027         # see if we can slice the rows

~anaconda3libsite-packagespandascorecommon.py in apply_if_callable(maybe_callable, obj, **kwargs)
    339     """
    340     if callable(maybe_callable):
--> 341         return maybe_callable(obj, **kwargs)
    342 
    343     return maybe_callable

TypeError: __call__() missing 2 required positional arguments: 'X' and 'y_true'
 

Комментарии:

1. Для меня это нормально, поэтому это должно зависеть от вашего набора данных. Кстати, когда вы устанавливаете mbox[metric] = results и метрика есть scorer_specificity , вы передаете в качестве ключа mbox словарю вывод make_scorer(custom_specificity, greater_is_better=False) , а не строку 'scorer_specificity' (что, я думаю, не то, что вы хотите).

2. Я думаю, вы правы, я только что видел нечто подобное и в другой части моего кода. Спасибо, что упомянули об этом.

3. Дэвид М. решил вашу проблему?

4. @gtomer Да, он это сделал, я действительно допустил ошибку в интерпретации его комментария.

Ответ №1:

Итак, спасибо @David M. Я понял, что я просто передавал
<class 'sklearn.metrics._scorer._PredictScorer'> в качестве ключа к фрейму данных Pandas.

Итак, я решил это, сначала проверив тип метрики в этот момент, используя
isinstance(type(metric), str) и в случае, если это _PredictScorer, я просто передаю имя для пользовательского счетчика в качестве ключа к фрейму данных.