UserWarning:一个或多个测试分数是非有限的 - GridSearchCV for MultiOutputClassifier(MLPClassifier)

UserWarning: One or more of the test scores are non-finite – GridSearchCV for MultiOutputClassifier(MLPClassifier)

我第一次尝试 scikit-learn,解决 Multi-Output Multi-Class text classification 问题。为此,我正在尝试使用 GridSearchCV 来优化 MLPClassifier 的参数。

下面是我目前的代码:

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.multioutput import MultiOutputClassifier
from sklearn.neural_network import MLPClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import accuracy_score

df = pd.read_csv('data.csv')

df.fillna('', inplace=True) #Replaces NaNs with "" in the DataFrame (which would be considered a viable choice in this multi-classification model)

x_features = df['input_text']
y_labels = df[['output_text_label_1', 'output_text_label_2']]

x_train, x_test, y_train, y_test = train_test_split(x_features, y_labels, test_size=0.3, random_state=7)

当我尝试在没有任何参数优化的情况下为 MultiOutputClassifier(MLPClassifier()) 设置 Pipeline 时,pipe.score 给出了 ~0.837 的分数,这似乎表明上面的代码正在做某物。 运行 pipe.predict() 在某些测试字符串上似乎产生了相对足够的输出结果。

pipe = Pipeline(steps=[('cv', CountVectorizer()),
                       ('mlpc', MultiOutputClassifier(MLPClassifier()))])

pipe.fit(x_train, y_train)

pipe.score(x_test, y_test)

但是,当尝试使用下面的另一个 的起始代码单独使用 GridSearchCV 时,我 运行 遇到了问题:

mlpc = MLPClassifier(solver='adam',
                     learning_rate_init=0.01,
                     max_iter=300,
                     activation='relu',
                     early_stopping=True)
pipe = Pipeline(steps=[('cv', CountVectorizer(ngram_range=(1, 1))),
                       ('scale', StandardScaler(with_mean=False)),
                       ('mlpc', MultiOutputClassifier(mlpc))])
search_space = {
    'cv__max_df': (0.9, 0.95, 0.99),
    'cv__min_df': (0.01, 0.05, 0.1),
    'mlpc__estimator__alpha': 10.0 ** -np.arange(1, 5),
    'mlpc__estimator__hidden_layer_sizes': ((64, 32), (128, 64),
                                            (64, 32, 16), (128, 64, 32)),
    'mlpc__estimator__tol': (1e-3, 5e-3, 1e-4),
}

grid_search = GridSearchCV(pipe, search_space, scoring='accuracy', error_score='raise', n_jobs=-1)

grid_search.fit(x_train, y_train)

这个警告似乎与评分问题有关,UserWarning: One or more of the test scores are non-finite:

UserWarning: One or more of the test scores are non-finite: [nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan]
  warnings.warn(

x_trainx_testy_trainy_test.shape(3036,)(1302,)(3036, 2) (1302, 2)分别。内容都是字符串,在上面的代码中可以看到,我已经将多次出现的NaN替换为空字符串"",这对于模型来说应该是一个可行的选择(基本上有它select None 作为 class):

df.fillna('', inplace=True) #Replaces NaNs with "" in the DataFrame (which would be considered a viable choice in this multi-classification model)

我在 GridSearchCV 中尝试了其他 scoring= 方法:roc_auc_ovrf1_macro,但问题基本相同。

如果我在 GridSearchCV 中包含以下选项:error_score='raise',我会收到错误消息:ValueError: multiclass-multioutput is not supported.

ValueError                                Traceback (most recent call last)
<ipython-input-10-14bccd802d09> in <module>
     21 #
     22 
---> 23 grid_search.fit(x_train, y_train)

~/condaenv/lib/python3.9/site-packages/sklearn/model_selection/_search.py in fit(self, X, y, groups, **fit_params)
    889                 return results
    890 
--> 891             self._run_search(evaluate_candidates)
    892 
    893             # multimetric is determined here because in the case of a callable

~/condaenv/lib/python3.9/site-packages/sklearn/model_selection/_search.py in _run_search(self, evaluate_candidates)
   1390     def _run_search(self, evaluate_candidates):
   1391         """Search all candidates in param_grid"""
-> 1392         evaluate_candidates(ParameterGrid(self.param_grid))
   1393 
   1394 

~/condaenv/lib/python3.9/site-packages/sklearn/model_selection/_search.py in evaluate_candidates(candidate_params, cv, more_results)
    836                     )
    837 
--> 838                 out = parallel(
    839                     delayed(_fit_and_score)(
    840                         clone(base_estimator),

~/condaenv/lib/python3.9/site-packages/joblib/parallel.py in __call__(self, iterable)
   1059 
   1060             with self._backend.retrieval_context():
-> 1061                 self.retrieve()
   1062             # Make sure that we get a last message telling us we are done
   1063             elapsed_time = time.time() - self._start_time

~/condaenv/lib/python3.9/site-packages/joblib/parallel.py in retrieve(self)
    938             try:
    939                 if getattr(self._backend, 'supports_timeout', False):
--> 940                     self._output.extend(job.get(timeout=self.timeout))
    941                 else:
    942                     self._output.extend(job.get())

~/condaenv/lib/python3.9/site-packages/joblib/_parallel_backends.py in wrap_future_result(future, timeout)
    540         AsyncResults.get from multiprocessing."""
    541         try:
--> 542             return future.result(timeout=timeout)
    543         except CfTimeoutError as e:
    544             raise TimeoutError from e

~/condaenv/lib/python3.9/concurrent/futures/_base.py in result(self, timeout)
    444                     raise CancelledError()
    445                 elif self._state == FINISHED:
--> 446                     return self.__get_result()
    447                 else:
    448                     raise TimeoutError()

~/condaenv/lib/python3.9/concurrent/futures/_base.py in __get_result(self)
    389         if self._exception:
    390             try:
--> 391                 raise self._exception
    392             finally:
    393                 # Break a reference cycle with the exception in self._exception

ValueError: multiclass-multioutput is not supported

在四处寻找解决方案时,我发现了 ,这表明 CountVectorizer 需要一维输入。我的 .shape 中有两个功能用于多输出。我不知道这个答案是否正确,因为我是第一次评估 scikit-learn。答案建议使用 ColumnTransformer 来解决这个问题,但我需要一个代码示例来理解如果这确实是问题。

您的 y 有多个列,而不是您的 X,因此 CountVectorizer 不是问题所在。相反,问题在于您有两个目标,每个目标都有两种以上的可能结果。来自同一页面的the User Guide, MLPClassifier supports multilabel, but not multi-output multiclass. Later,关于评分的额外警告:

Warning: At present, no metric in sklearn.metrics supports the multiclass-multioutput classification task.

所以即使您将分类器包装在例如MultiOutputClassifier 网格搜索的评分将失败。我认为您应该能够定义一个自定义记分器来完成这项工作?您可能还会考虑您的标签是否真正正确排序为 label_1 和 label_2,或者这是否可以转换为多标签问题,将目标二值化?