二进制多标签分类:如何按频率筛选标签以优化模型?
解决多标签分类中高频标签筛选的实现方案
嘿,刚好之前处理过类似的大规模多标签分类任务,针对你要筛选出现频率≥10%标签的需求,我给你拆解成具体可落地的步骤,结合你用scikit-learn的场景来实现:
第一步:明确频率统计的正确方式
首先要注意:多标签场景下的「标签频率」,我们通常指的是包含该标签的样本数占总样本数的比例,而不是标签出现的总次数(因为一个样本可能同时有多个标签,次数统计会重复)。另外,你替换的UNKNOWN是缺失值占位符,不算有效标签,统计时要排除它。
先看你提供的示例数据:
处理后部分数据如下:
148 UNKNOWN
149 RM106 |RM159
150 UNKNOWN
151 MI291
152 TM187
153 UNKNOWN
第二步:统计标签频率并筛选
假设你用pandas存储数据(如果不是,也可以转成DataFrame方便处理),先把每个样本的标签拆分并过滤掉UNKNOWN:
import pandas as pd from collections import Counter # 假设你的数据存储在df中,标签列名为'labels' df = pd.DataFrame({ 'id': [148, 149, 150, 151, 152, 153], 'labels': ['UNKNOWN', 'RM106 |RM159', 'UNKNOWN', 'MI291', 'TM187', 'UNKNOWN'] }) # 拆分标签,去掉空格和UNKNOWN df['valid_labels'] = df['labels'].str.split('|').apply( lambda x: [lbl.strip() for lbl in x if lbl.strip() != 'UNKNOWN'] ) # 统计每个标签出现在多少个样本中 label_sample_counts = Counter() for labels in df['valid_labels']: for lbl in labels: label_sample_counts[lbl] += 1 # 计算阈值(总样本数的10%) total_samples = len(df) threshold = 0.1 * total_samples # 筛选出符合频率要求的标签 selected_labels = [lbl for lbl, cnt in label_sample_counts.items() if cnt >= threshold]
第三步:适配scikit-learn的MultiLabelBinarizer
筛选完标签后,你需要调整MultiLabelBinarizer的初始化,只保留选中的标签,这样生成的二值化矩阵就只会包含高频标签:
from sklearn.preprocessing import MultiLabelBinarizer # 初始化时指定classes为选中的标签,确保输出矩阵的列对应这些标签 mlb = MultiLabelBinarizer(classes=selected_labels) # 对过滤后的标签进行二值化 binary_labels = mlb.fit_transform(df['valid_labels']) # 可以查看二值化后的列名(就是选中的标签) print(mlb.classes_)
额外注意事项
- 如果某个样本过滤后没有有效标签(比如原标签是
UNKNOWN的样本),你可以选择保留它(二值化后全0)或者过滤掉:df = df[df['valid_labels'].str.len() > 0] - 如果10%的阈值筛选后标签还是过多,可以根据实际任务效果调整阈值(比如5%或15%)
- 如果你的标签存储格式不是字符串分隔(比如已经是列表形式),可以跳过拆分步骤直接统计
内容的提问来源于stack exchange,提问作者Joey LU
相关产品推荐
相关产品推荐

