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

如何让LightGBM交叉验证支持自定义macroF1评估指标?

解决LightGBM交叉验证不显示自定义macroF1指标的问题

你的代码存在两个核心问题,导致自定义指标未生效:

1. 自定义评估函数适配错误

原函数是针对多分类场景编写的,但你使用的是二分类任务(objective: binary)。二分类下LightGBM返回的predictions是每个样本的正类概率值(一维数组),而非多分类的类别概率矩阵,原代码中reshape(len(np.unique(truth)),-1).argmax(axis=0)的逻辑完全不适用,会导致计算错误,最终被LightGBM忽略。

修正后的二分类自定义macroF1函数:

def evaluate_macroF1_lgb(truth, predictions):  
    # 二分类场景下,将概率转为0/1标签(默认阈值0.5)
    pred_labels = np.where(predictions >= 0.5, 1, 0)
    f1 = f1_score(truth, pred_labels, average='macro')
    # 返回格式:(指标名称, 指标值, 是否需要最大化该指标)
    return ('macroF1', f1, True) 

2. 自定义指标的参数传递错误

LightGBM中,内置指标通过metric参数指定,而自定义评估函数必须通过feval参数单独传入,不能混放到metric列表中。你之前注释了feval参数,这是导致自定义指标不生效的关键原因。

调整后的参数网格配置:

param_grid = {
    'objective': ['binary'],
    'metric': [['auc', 'binary_error']],  # 仅保留内置指标
    'min_data_in_leaf': [20, 50],
    'verbose': [-1],
    'is_unbalance': [True],
    'feval': [evaluate_macroF1_lgb]  # 单独传入自定义评估函数
}

修正后的完整代码

import lightgbm as lgb
import numpy as np
from itertools import product
import warnings
from sklearn.metrics import f1_score
import pandas as pd
from tqdm import tqdm  # 补充原代码遗漏的tqdm导入

# 屏蔽警告
warnings.filterwarnings("ignore")

# 生成模拟训练数据
train = pd.DataFrame({
    'id': np.arange(100),
    'feature1': np.random.rand(100),
    'feature2': np.random.rand(100),
    'label': np.random.randint(2, size=100)
})

# 准备训练数据集
X = train.drop(["id", "label"], axis=1)
y = train["label"]
train_data = lgb.Dataset(X, label=y)

# 修正后的自定义macroF1评估函数
def evaluate_macroF1_lgb(truth, predictions):  
    pred_labels = np.where(predictions >= 0.5, 1, 0)
    f1 = f1_score(truth, pred_labels, average='macro')
    return ('macroF1', f1, True) 

# 调整后的参数网格
param_grid = {
    'objective': ['binary'],
    'metric': [['auc', 'binary_error']],
    'min_data_in_leaf': [20, 50],
    'verbose': [-1],
    'is_unbalance': [True],
    'feval': [evaluate_macroF1_lgb]
}

# 遍历参数组合进行交叉验证
best_error = float('inf')
best_params = {}
max_length_param_grid = len(list(product(*param_grid.values())))
for params_combination in tqdm(product(*param_grid.values()), total=max_length_param_grid):
    params = dict(zip(param_grid.keys(), params_combination))
    cv_results = lgb.cv(params, train_data, num_boost_round=100, nfold=5, stratified=True, verbose_eval=False)
    mean_auc = np.mean(cv_results['auc-mean'])
    if mean_auc < best_error:
        best_error = mean_auc
        best_params = params
        
print(cv_results.keys())

执行后,cv_results.keys()会输出包含macroF1-mean和macroF1-stdv的结果,示例如下:
dict_keys(['auc-mean', 'auc-stdv', 'binary_error-mean', 'binary_error-stdv', 'macroF1-mean', 'macroF1-stdv'])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 10:53:17