LGBMRanker样本数不一致报错求助(样本数44980/3)
问题分析与解决
核心错误原因
- groups参数传值错误:你用
X.groupby('Item')作为groups,这返回的是Pandas分组对象,不是模型需要的长度等于样本数的一维数组。直接导致样本数(44980)和groups长度(3个分组)不匹配,触发报错。 - 分组逻辑错误:排序任务中,
groups的作用是定义需要排序的样本集合——同一组内的样本是要互相比较排序的。你的场景是每天对3个项目排名,正确的分组维度应该是日期(Date),而非项目(Item)。按Item分组会把单个项目的所有日期数据归为一组,完全不符合排序需求。
修正步骤
1. 生成正确的groups数组
给每个样本标记所属的日期组,生成长度和X、y一致的数组:
# 利用Date索引分组,生成每个日期对应的组ID groups = df.groupby(level='Date').ngroup()
这样groups的每个元素对应样本所在的日期组,长度正好是44980,和X、y匹配。
2. 适配ndcg_score的评分器
默认ndcg_score需要适配排序任务的输入格式,需指定needs_proba=False(LGBMRanker输出排序得分而非概率),并可指定评估的top-k值(比如k=3,对应每天3个项目):
from sklearn.metrics import make_scorer, ndcg_score # 定义适配的NDCG评分器 ndcg_scorer = make_scorer(ndcg_score, needs_proba=False, k=3)
3. 完整修正后的代码
paths_dict = {'1':'../../1.csv', '2':'../../2.csv', '3':'../../3.csv',} def load_paths(paths_dict): df = pd.DataFrame() for key, value in paths_dict.items(): df[key] = pd.read_csv(value, index_col=0, parse_dates=True)['Close'] df = df.iloc[::-1] return df df = load_paths(paths_dict) df = df.stack().reset_index() df.columns = ['Date', 'Item', 'Target'] df['Item'] = df['Item'].astype('int') df['Target'] = df.groupby('Date')['Target'].rank('dense', ascending=False).astype(int) df.set_index('Date', inplace=True) y = df['Target'] X = df.drop(['Target'], axis=1) # 生成正确的groups数组 groups = df.groupby(level='Date').ngroup() model = LGBMRanker(n_jobs=-1) # 修正评分器配置 ndcg_scorer = make_scorer(ndcg_score, needs_proba=False, k=3) score = cross_val_score(model, X=X, y=y, groups=groups, cv=TimeSeriesSplit(n_splits=24), scoring=ndcg_scorer)
额外注意点
- LGBMRanker的
y标签:你用rank('dense', ascending=False)得到1(最高)、2、3的排名,LGBMRanker默认逻辑是y值越高排序越靠前,这个逻辑是正确的,若后续调整rank方向需同步适配模型参数。 - 时间序列交叉验证:
TimeSeriesSplit按时间顺序拆分数据,符合你的时间序列场景,这部分无需修改。
内容的提问来源于stack exchange,提问作者Tomward Matthias
相关产品推荐
相关产品推荐

