#34883·scikit-learn

[BUG] `compute_class_weight` 在 1.9 中强制将类标签转换为整数,从而破坏字符串标签的字典查找

作者: TonyBagnall创建于 2026年9月4日更新于 2026年9月17日
标签Bug

在 1.9 中,使用 class_weight="balanced" 进行森林集成时,如果类标签是字符串(例如 "1", "2" 等),就会引发 ValueError。在 1.8 和之前的版本中,相同代码可以正常运行。真正的整数类标签,或者不可以解析为整数的字符串("a", "b")则不受影响。 这个问题来自于 #32644 中添加的用户定义字典分支的 compute_class_weight(提交 9ca766b, "FEA Add array API support for LogisticRegression with LBFGS"):

           for i, c in enumerate(classes):
              try:
                  c = int(c)
              except ValueError:  # `classes` contains strings
                  c = str(c)
              if c in class_weight:
``` 目的是将数组标量归一化为 Python 标量,以便在非 numpy 命名空间中通过键进行字典查找。但是 int("1") 成功,因此它永远不会触发 except 子句,该子句将保留字符串。 即使用户要求 "balanced",该分支也会被触发,因为 `BaseForest._validate_y_class_weight` 不会直接通过 "balanced"。它进行了回调(sklearn/ensemble/_forest.py:861): 
```Python
  # Computing class_weight (dict or list) for the "balanced" option.
  class_weight_k_vect = compute_class_weight("balanced", classes=self.classes_[k], ...)
  class_weight_k = {key: val for (key, val) in zip(self.classes_[k], class_weight_k_vect)}
  ...
  expanded_class_weight = compute_sample_weight(class_weight, y_original)
``` 它首先将 "balanced" 扩展为以原始标签为键的明确字典 - {"1": 1.0, "2": 1.0}, 字符串键 - 然后将该字典反馈给它。第二次调用通过字典分支进行,键被强制转换为整数,每次查找都失败,所有类都被报告为未加权。 直接将 "balanced" 传递给 compute_class_weight(DecisionTreeClassifier, RidgeClassifierCV, SVC 等)的估计器采用专用的 `elif  class_weight == "balanced"` 分支,该分支使用 LabelEncoder 并从未进行强制转换,因此它们不受影响。

内容来源: scikit-learn/scikit-learn