You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Scikit-learn中绘制类别权重验证曲线报错求助

解决Scikit-learn中class_weight验证曲线绘图的TypeError问题

嘿,我一眼就看出问题所在了——你用validation_curve计算分数的部分是对的,但绘图的时候直接把字典列表传给了Matplotlib,而它根本不知道怎么把字典转换成坐标轴上的数值,所以才会抛出float() argument must be a string or a number, not 'dict'这个错误。

错误根源

param_range2是一个包含class_weight字典的列表(比如[{0:1,1:6}, ...]),validation_curve能识别这种格式来给模型传参,但plt.plot()需要的是数值型的x轴数据,字典显然不符合要求。

解决方案

我们只需要把每个class_weight字典里的少数类权重值提取出来(也就是你设置的1: w里的w),用这个数值列表作为x轴的输入就行。具体修改分两步:

  1. 从字典列表中提取数值,作为绘图的x轴标签
  2. 保持validation_curve的param_range不变(因为模型需要字典格式的class_weight参数)

修改后的完整代码

from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split, StratifiedKFold, validation_curve, GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
import numpy as np
import matplotlib.pyplot as plt

def plot_validation_curve(param_range, train_scores, test_scores, title, alpha=0.1):
    train_mean = np.mean(train_scores, axis=1)
    train_std = np.std(train_scores, axis=1)
    test_mean = np.mean(test_scores, axis=1)
    test_std = np.std(test_scores, axis=1)
    
    plt.plot(param_range, train_mean, label='train score', color='blue', marker='o')
    plt.fill_between(param_range, train_mean + train_std, train_mean - train_std, color='blue', alpha=alpha)
    plt.plot(param_range, test_mean, label='test score', color='red', marker='o')
    plt.fill_between(param_range, test_mean + test_std, test_mean - test_std, color='red', alpha=alpha)
    
    plt.title(title)
    plt.grid(ls='--')
    plt.xlabel('Minority Class Weight')  # 优化x轴标签,让图表更易读
    plt.ylabel('F-measure')
    plt.legend(loc='best')
    plt.show()

if __name__ == '__main__':
    X, y = make_classification(n_classes=2, class_sep=2, weights=[0.9, 0.1],
                               n_informative=3, n_redundant=1, flip_y=0,
                               n_features=20, n_clusters_per_class=1,
                               n_samples=1000, random_state=10)
    X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
    
    st = StandardScaler()
    rg = LogisticRegression(class_weight={0: 1, 1: 6.5}, random_state=42,
                            solver='saga', max_iter=100, n_jobs=-1)
    
    param_grid = {'clf__C': [0.001, 0.01, 0.1],
                  'clf__class_weight': [{0: 1, 1: 6}, {0: 1, 1: 5.5}]}
    pipeline = Pipeline(steps=[('scaler', st), ('clf', rg)])
    cv = StratifiedKFold(n_splits=5, random_state=42, shuffle=True)  # 加上shuffle让交叉验证划分更随机
    rg_cv = GridSearchCV(pipeline, param_grid, cv=cv, scoring='f1')
    rg_cv.fit(X_train, y_train)
    
    plt.figure(figsize=(9, 6))
    param_range2 = [{0: 1, 1: 6}, {0: 1, 1: 4}, {0: 1, 1: 5.5}]
    # 从每个字典中提取少数类(类别1)的权重值,作为x轴的数值
    param_values = [weight_dict[1] for weight_dict in param_range2]
    
    train_scores, test_scores = validation_curve(
        estimator=rg_cv.best_estimator_,
        X=X_train,
        y=y_train,
        param_name="clf__class_weight",
        param_range=param_range2,  # 这里依然用字典列表,模型需要这个格式
        cv=cv,
        scoring="f1",
        n_jobs=-1
    )
    
    # 传入提取后的数值列表绘图
    plot_validation_curve(param_values, train_scores, test_scores, 
                         title="Validation Curve for Minority Class Weight", alpha=0.1)

额外优化点

  • 给StratifiedKFold加上了shuffle=True,让交叉验证的划分更随机,结果更可靠
  • 修改了x轴标签为Minority Class Weight,让图表的含义更清晰

这样修改后,代码就能正常运行,你也能直观看到少数类权重变化时模型F1分数的波动情况啦!

内容的提问来源于stack exchange,提问作者ebrahimi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 08:57:29