训练集从几张业务表合并而来,缺失值在源表里写成字符串 null 和 None 两种形式,清洗脚本只按 isna 判断,约百分之八的样本被当成有效文本送进训练,模型开始学会在输出里带 null 这个词。

一开始怀疑是「清洗只做类型转换,没有把占位值映射成空」,查了一圈,方向不对。

真正麻烦的地方在于,几个原因的现象几乎一样。源表用字符串 null 表示缺失,isna 识别不到。另一种情况是不同表的缺失标记不统一,有 None 也有大写 NULL。

还有一种情况,统计缺失率用了另一套规则,两边口径对不上。

先统计各列的缺失标记分布

python -c "import pandas as pd;d=pd.read_csv('train.csv');print(d.apply(lambda s: s.astype(str).isin(['null','None','NULL','nan']).sum()))"

接着统一把占位值映射成真正的空值

python -c "import pandas as pd;d=pd.read_csv('train.csv',keep_default_na=False);d=d.replace({'null':None,'NULL':None,'None':None});print(d.isna().sum())"

然后按缺失比例决定丢弃还是保留

python drop_missing.py --max-ratio 0.05 --report

末了重跑清洗并核对样本数与缺失率

python pipeline.py --stage label --report rows,missing

改完先别撤,确认这几项。字符串形式的缺失值全部被识别,缺失率与源库统计一致,训练样本里不再出现 null 这个字面量。

补一句。缺失值不是一种写法而是一组写法,读入时关掉默认推断再显式映射,比事后补规则省事。这类问题最好一次改到位,反复小改反而容易把原因搅混。

作者 9823189