MLPClassifier 字符串标签开启 early_stopping 后报 isnan 类型错误
MLPClassifier 早停评分对字符串预测执行数值有限性检查时会失败,应更新修复版本或保留完整的类别编码映射。
MLPClassifier 可以接受字符串类别,打开 early_stopping=True 后,训练却报 ufunc 'isnan' not supported for the input types。如果堆栈落在 _score_with_function,先检查早停评分收到的预测 dtype,而不是把全部输入都强制转成浮点数。
scikit-learn 1.7.2 的一个具体案例中,模型预测已经还原成原来的字符串标签,早停评分却对这些标签无条件调用 np.isnan、np.isinf。这两项数值检查不适用于字符串类别;特征矩阵合法,也可能在这一步失败。
把早停与类别类型一起复验
下面生成一个小分类数据集,并把整数类别映射为明确的字符串:
import numpy as np
import sklearn
from sklearn.datasets import make_classification
from sklearn.neural_network import MLPClassifier
X, numeric_y = make_classification(
n_samples=200, n_features=10, n_classes=3,
n_informative=5, random_state=42,
)
labels = np.array(["class_a", "class_b", "class_c"], dtype=object)
y = labels[numeric_y]
model = MLPClassifier(early_stopping=True, max_iter=50, random_state=42)
model.fit(X, y)
print(sklearn.__version__, model.classes_)
assert model.validation_scores_ is not None
assert len(model.validation_scores_) == model.n_iter_
assert np.isfinite(model.validation_scores_).all()
assert set(model.predict(X[:5])).issubset(set(labels))
scikit-learn 1.9.0 包含修复:只有预测 dtype 为浮点型时,才通过 isfinite 检查数值有限性。字符串标签继续进入正常的分类评分,而不是作为浮点数处理。升级后应保留 early_stopping=True 运行原任务;仅关闭早停后训练成功,没有覆盖修复路径。
这个例子可能产生收敛警告,警告与上述类型异常不同。不能因为不再抛 TypeError,就宣称五十轮已经得到合格的分类器;模型质量、迭代次数和早停阈值仍需单独评估。
临时编码类别,要保留还原关系
受版本约束时,可将类别编码为整数,避开字符串预测上的数值检查:
from sklearn.preprocessing import LabelEncoder
encoder = LabelEncoder().fit(y)
encoded_y = encoder.transform(y)
model = MLPClassifier(early_stopping=True, max_iter=50, random_state=42)
model.fit(X, encoded_y)
predicted_labels = encoder.inverse_transform(model.predict(X[:5]))
print(predicted_labels)
编码器与模型应一起保存。预测概率的列顺序对应 model.classes_ 中的编码,也应通过编码器映射回业务类别。不要只在训练中临时编号,部署时又按另一种类别排序解释输出。
关闭早停虽然可能避开异常,但改变了训练终止条件,不适合作为无说明的长期修法。将标签随意改成浮点数也会掩盖类别语义。若相同异常出现在别的评分回调、预处理器或自定义 estimator 中,检查其实际 dtype 路径;这项版本修复只覆盖 MLP 早停评分的有限性检查。


