Spacy v3训练textcat_multilabel模型时DocBin数据格式报错如何解决
问题根因
从spacy debug data的输出可以直接定位核心问题:你的doc.cats的键被错误填充成了单个字符,而非预期的分类标签,具体有两个常见诱因:
- 你传入转换函数的
cats_empty参数格式错误:如果你传的不是预构造好的「全分类标签为键、默认值为0」的字典,而是直接传了分类标签字符串/列表,用dict(cats_empty)转换时会自动把字符串拆分为单个字符作为键,就会出现debug输出里的'v' 'F' 'm'这类无效标签。 - 未处理
GROUP_CONCAT(j.name)的异常值:当数据库中某条数据没有关联分类时,GROUP_CONCAT返回的结果为空,split(',')会得到空字符串/无意义字符,也会污染cats的键列表。
textcat_multilabel组件初始化时会从训练数据的doc.cats中提取所有键作为分类体系,因此组件实际存储的标签都是上述无效单个字符,评估阶段碰到真实的分类标签(如Politique fédérale)时找不到对应项,就会触发KeyError。
解决方案
1. 预构造全量分类标签字典
提前整理所有待分类的标签列表,构造初始的全0字典,不要在转换函数中动态生成:
# 提前定义所有分类标签 ALL_CATEGORIES = [ 'Santé', 'Économie', 'Infrastructure', 'Politique fédérale', 'Politique provinciale', 'Politique municipale', 'Éducation', 'Faits divers', 'Culture' ] # 构造初始全0字典,作为参数传入转换函数 cats_empty = {cat: 0.0 for cat in ALL_CATEGORIES}
2. 修正转换代码中的分类赋值逻辑
增加空值过滤和合法性校验,避免无效标签污染cats:
def convert_cat_annontation_from_sentinelle_db(output_path, nlp, input_path, cats_empty): db = DocBin() annotated_data = pd.read_csv(input_path) for idx, row in annotated_data.iterrows(): cats = dict(cats_empty) try: article = newspaper.Article(row['link']) article.download() article.parse() doc = nlp.make_doc(article.text) # 处理分类标签,过滤空值和空白符 cats_str = row["GROUP_CONCAT(j.name)"] if pd.notna(cats_str): cats_list = cats_str.split(',') # 过滤空标签、去前后空格 cats_list = [cat.strip() for cat in cats_list if cat.strip()] for cat in cats_list: # 只给存在于预设分类体系的标签赋值 if cat in cats: cats[cat] = 1.0 doc.cats = cats db.add(doc) except Exception as e: # 可自行添加错误日志打印,方便排查抓取失败的问题 continue db.to_disk(output_path)
3. 校验数据后再训练
重新生成训练集和验证集的DocBin文件后,先跑spacy debug data确认「Text Classification (Multilabel)」板块的标签是你预设的9个分类,没有单个字符的无效标签后,再启动训练即可。
内容的提问来源于stack exchange,提问作者Alex Dube
相关产品推荐
相关产品推荐

