分类问题之多标签相关知识

多标签的向量表示

from sklearn.preprocessing import MultiLabelBinarizer
  • 只有数据,未知全部标签,需要统计
mlb = MultiLabelBinarizer()
labellist = [('红'),('绿色'),('红色','绿色')]
mlb.fit(labellist) # 直接用fit函数,统计label种类
mlb.fit_transform([label])
mlb.classes_
  • 已知全部标签,不需要统计
mlb = MultiLabelBinarizer(classes = ["红", "黄", "绿"]) # 注意这里加了classes参数
mlb.fit_transform([("红", "绿"), ("黄"),("红", "黄")])
mlb.classes_
  • 将预测的tensor转成标签
mlb.inverse_transform(predict_tensor)

样本不均衡

过采样(Oversampling)

对某个样本比较少的标签进行过采样,这是一种用于处理不平衡数据集的数据处理方法。在机器学习和数据分析中,不平衡数据集是指其中一个类别的样本数量明显少于其他类别的样本数量。这种不平衡会对模型的训练和性能产生不利影响,导致模型倾向于测数量更多的类别。过采样的目的是通过增加少数类样本的复制或合成新样本,使其数量增加到与多数类相似,从而达到数据平衡的效果。这样可以更好地训练模型以正确识别少数类别,提高模型的性能和稳定性。

赋权重

  • label weight
    在各种分类任务中,我们常常会遇到样本不均衡问题,这时需要对各个类别设置不同的权重,在pytorch中可以在初始化loss函数时传入权重
weight = torch.empty(nb_classes).uniform_(0, 1)
criterion = nn.CrossEntropyLoss(weight=weight)   // 初始化CrossEntropy函数时传入各个class的权重
loss = criterion(inputs,outputs)
  • sample weight
    但有时候,不仅每个类别有权重,而且每个样本的权重也不相同。这就需要更精细的控制了,可通过两步来达到此目的:
    (1) 在初始化函数时设置 reduction='none', 此时loss函数返回的是一个array,表示各个sample的loss;reduction默认设置为mean,表示loss函数会默认对所有样本的loss取平均,返回一个标量;
    (2) 手动加权,得到各个样本的loss array后,我们可以对每个loss赋予(乘以)相应的权重,这时即达到了对不同样本赋予不同权重的目的。
weight = torch.empty(nb_classes).uniform_(0, 1)
criterion = nn.CrossEntropyLoss(weight=weight, reduction='none')

sample_weight = torch.empty(batch_size).uniform_(0, 1)
loss = criterion(output, target)
loss = loss * sample_weight
loss.mean().backward()

此外,还可以对每个样本的loss进行归一化,使得所有batch的loss大小范围较为相近:

loss =(loss * sample_weight / sample_weight.sum()).sum()

一点实践感受:感觉过采样的效果比赋权重效果明显,也可能是我权重向量没有初始化契合

多标签的评估

使用sklearn里的方法

from sklearn.metrics import classification_report
result = classification_report(y_true, y_pred, label_names, output_dict=True)
posted @ 2023-08-14 17:49  嘎吱嘎吱脆  阅读(32)  评论(0编辑  收藏  举报