使用Fastai构建表格模型时遇TypeError:Categorical不支持mean归约
问题排查与解决
错误原因
报错TypeError: 'Categorical' with dtype category does not support reduction 'mean'的核心原因是连续特征列(cont_names)中混入了分类类型的列。Fastai的Normalize处理器会对连续列计算均值(mean)做标准化,但分类列(Categorical dtype)不支持mean操作,因此触发错误。
结合你的代码和CSV结构来看:
- 你仅将
databrand、KP_STA、tag1、tag2标记为分类列,但CSV中还有dataprod、databatch、datatime这些object类型的列,它们被错误地纳入了constant_names(即连续列列表)。 - 通过
set(col_list) - set(category_names)- set(y_names)生成连续列的方式不够严谨,会把所有未明确标记为分类/目标列的字段都归为连续列,包括非数值型的object列。
解决方案
1. 明确分类列与连续列的划分规则
- 分类列:所有非数值型(
object)的列,以及虽为int类型但实际是枚举值的列(如tag1、tag2)。 - 连续列:仅保留数值型(
int64/float64)且具备连续数值意义的列,排除无预测价值的唯一标识(如dataid)和目标列。
2. 修正后的代码
from pathlib import Path import pandas as pd from fastai.tabular.all import * path = Path("D:\\workdir\\req4_IndustryControl_0\\IndustryControl\\data") df = pd.read_csv(path/"tech_datas_his.csv") def is_empty(value): return pd.isnull(value) or value == '' print(df.shape) df = df[df.map(is_empty).any(axis=1) == False] print(df.shape) y_names=['KP_D74'] # 明确所有分类列:object类型列 + 枚举型int列 category_names = ['databrand','KP_STA','tag1','tag2', 'dataprod', 'databatch', 'datatime'] # 排除无意义列:目标列、分类列、唯一标识dataid exclude_cols = y_names + category_names + ['dataid'] # 筛选连续列:仅保留数值型且不在排除列表中的列 constant_names = [col for col in df.columns if df[col].dtype in ['int64', 'float64'] and col not in exclude_cols] procs = [Categorify, FillMissing, Normalize] df.info() dls = TabularDataLoaders.from_df(df, path, procs=procs, cat_names=category_names, cont_names=constant_names, y_names=y_names, valid_idx=list(range(1,10000)), bs=64) dls.show_batch(10) learn = tabular_learner(dls, y_range=(0.0,4.0)) learn.fit_one_cycle(5) learn.save("proportion_predict") test_pf = pd.read_csv(path/"test.csv") row, clas, probs = learn.predict(test_pf.iloc[0]) print(row) print(clas,probs)
3. 额外注意事项
dataid作为样本唯一标识,务必从特征中排除,避免引入无效噪声。- 如果
datatime是时间序列数据,建议单独处理(如提取年/月/日、时间差等特征),而非直接作为分类列,这样能更好地利用时间维度信息。 - 可通过
print(df[constant_names].dtypes)验证连续列,确保所有列都是数值型,避免再次混入非数值列。
内容的提问来源于stack exchange,提问作者hahahahahaha
相关产品推荐
相关产品推荐

