基础知识_样本不均衡处理

目录

0、安装 imblearn 库 

 一、两种类别的样本不均衡【首先阅读文章:一文详解数据不平衡问题】

  1.1、样本不平衡问题

  1.2、两种常见的样本不均衡

  1.3、数据不平衡经典场景

二、样本不均衡的处理思想

三、采样处理样本不平衡

  3.1、欠采样处理样本不均衡

    3.1.1、随机放回、不放回采样 RandomUnderSampler

    3.1.2、K-means 原型生成 prototype generation

  3.2、过采样处理样本不均衡

    3.2.1、复制少数量样本数据

    3.2.2、SMOTE基本算法 ------ SMOTE-Regular

    3.2.3、SMOTE改进算法 ------ 强调类边界 Borderline1-Smote、Borderline2-Smote、Svm-Smote

    3.2.4、SMOTE改进算法 ------ 强调类区域 Kmeans-Smote

    3.2.5、几种SMOTE过采样效果总结

四、模型算法处理样本不均衡

  4.1、Meta-Cost【cost sensitive】

  4.2、Focal-loss

    4.2.1、Focal-loss 与  CE交叉熵损失的关系

    4.2.2、Focal-loss 的两个参数 α 于 γ 的作用

    4.2.3、Focal-loss 多分类代码

五、评价指标【一文详解数据不平衡问题、评估指标2】

  5.1、acc、precision、recall、F1_score 以及对应的宏平均macro 、微平均micro

  5.2、ROC曲线、PR曲线 、AUC 值 以及对应的宏平均macro 、微平均micro

    5.2.1、二分类 ROC 曲线与AUC值

    5.2.2、多分类的ROC曲线与AUC值

    5.2.3、ROC曲线、PR曲线的区别 以及使用场景?

  5.3、样本不均衡的评估指标 G-mean

六、NLP场景中数据增强

  6.1、EDA简单的样本增强

  6.2、UDA半监督一致性数据增强

    6.2.1、UDA 一致性训练的图解

    6.2.2、UDA训练损失函数的定义

    6.2.3、UDA训练过程中‘ 退火训练 ’ TSA

七、NLP实际项目中数据不均衡的解决步骤

八、课程文献资料


0、安装 imblearn 库 

安装python imblearn 库:

pip install -i https://mirrors.aliyun.com/pypi/simple/ imblearn

 一、两种类别的样本不均衡【首先阅读文章:一文详解数据不平衡问题

  1.1、样本不平衡问题

1、什么是样本不平衡
    样本不平衡指的是不同类别样本分布比例相差较大。

2、样本不平衡会造成什么问题
    基于统计过程的机器学习、深度学习模型在每一个类别Loss代价等权重时,训练好的模型的参数往往会偏向样本数目多的类
    别,样本数目多的类别评估指标性能很好,但样本数目少的类别效果很差,而工程中往往样本数目小的类别是我们重点关注
    的对象,这显然是不符需求的。

  1.2、两种常见的样本不均衡

1、大数据分布不均衡
    整体数据规模很大,而某个类别所占的比例很小。例如:总数量有1000w个样本,2个类别,某个类别只有200w的数据。

2、小数据分布不均衡
    正题数据规模较小,某个类别的数目也很少。例如:总数量有100个样本,2个类别,某个类别只有20个数据。


以经验来看:样本比例差距在10倍左右时,应当引起样本不均衡的警觉;当样本比例差距在20倍以上时,必须解决样本不均衡问题。

  1.3、数据不平衡经典场景

场景一:
    CTR广告预估:广告的点击率,通常只是百分之几,点击的样本占比非常的少,大量的数据是未点击的样本数据。

场景二:
    异常检测:比如恶意刷单、黄牛订单、信用卡欺诈、电力窃电、设备故障等,这些数据样本所占的比例通常是整体样本中很少
    的一部分。以反欺诈为例,是实体信用卡的欺诈比例一般都在0.1%以内。

二、样本不均衡的处理思想

数据不平衡的问题解决思想:
    1. 数据上解决不均衡问题:
        ① 欠采样:当少数量样本的数量满足模型的训练时,可以对多数样本类别进行欠采样。
        ② 过采样:当少数量样本的数量不满足模型的训练时,可以对少数样本类型进行过采样。
    2. 模型上解决不均衡问题:
        ③ 类别代价敏感模型:如果模型训练不做处理,那么模型对于每一类别“代价敏感”是等价的,通过带有倚重权重的模型算法,针对
      少量样本着重拟合,加强模型对少量样本特征的学习。
        ④ focal loss 损失函数
    3. 评估指标上解决不均衡问题:
        3.1 G-mean ( sqrt(正召回率 * 负召回率)
        3.2 ROC (横:FPR[1 - 负例的召回率] 纵:TPR[正例召回率])
        3.3 PR (横:TPR[正例召回率] 纵:正例精确率)
    4. NLP解决不均衡问题
        4.1 EDA 简单解决不均衡的问题
        4.2 半监督学习解决不均衡的问题
            4.2.1 UDA 解决不均衡问题
            4.2.2 mix text 解决不均衡问题

三、采样处理样本不平衡

  3.1、欠采样处理样本不均衡

当少数量类型的样本满足模型训练的需求时,我们可以对多数量类型样本欠采样。
tip:我们一般不会使用欠采样,数据不均衡通常处理的都是少数量类型的样本数据
# 原始数据准备
from collections import Counter
from sklearn.datasets import make_classification
from imblearn.over_sampling import SMOTE,ADASYN,KMeansSMOTE

X, y = make_classification(n_samples=5000, n_features=2, n_informative=2,
                           n_redundant=0, n_repeated=0, n_classes=3,
                           n_clusters_per_class=1,
                           weights=[0.01, 0.05, 0.94],  # 生成样本的比例权重
                           class_sep=0.8, random_state=0)

print(Counter(y))

out:
Counter({2: 4674, 1: 262, 0: 64})

print(sorted(Counter(y).items()))

out:
[(0, 64), (1, 262), (2, 4674)]

    3.1.1、随机放回、不放回采样 RandomUnderSampler

        注意:RandomUnderSampler 获取的样本存在于源数据集种,原型生成(prototype generation)获取的数据是新的样本,可能不存在源数据集中

随机抽样 欠采样的缺点:
    随机采样的过程充满着随机性,抽样出现的新数据集不能代表原始数据集样本的分布情况
# imblearn 库
from imblearn.under_sampling import RandomUnderSampler
rus = RandomUnderSampler(random_state=42)
X_res, y_res = rus.fit_resample(X, y)

# numpy API
import numpy as np
import random

seed_idx = np.arange(0,100,1)
sample_idx = random.sample(seed_idx,40)  # 从 seed_idx 中随机抽取 40 个样本

    3.1.2、K-means 原型生成 prototype generation

        注意:原型生成(prototype generation)获取的数据是新的样本,可能不存在源数据集中

1、PG【原型生成的执行步骤】:
    1)以少数类样本总数出发,确定多数类样本集均衡后的样本数为N 【即从该多数类样本集中生成 N个样本】
    2)从一个多数类样本集出发,利用 K-means 算法随机的计算该多数类样本 k 个的中心【这里面的k == N,相当于生成N个簇】
    3)使用这N个簇均值而得到N个簇中心点,那么这N个簇中心点将代表源数据集。【簇中心点可以有效代表源数据集样本的分布】
    4)重复 2、3两个步骤,均衡其他的多数类样本集
2、PG 欠采样算法相对于 随机抽样 的好处:
    ① K-means的簇中心相比于随机抽样更能代表 这一个多数量样本集的样本分布情况
    ② PG算法不会捕捉离群的噪声点,因为这些离群点会被kmeans的簇内均值拉回中心处。
ClusterCentroids 算法是 imblearn 中提供的原型生成算法的一个示例。 该算法通过 KMeans 算法,使得一个多数类样本生
    成 N 个簇样本,并使用 N 个簇样本的中心点的坐标替换多数样本的簇。从而达到保留 N 个多数类
    样本的目的。

from sklearn.datasets import make_classification
from imblearn.under_sampling import ClusterCentroids # 使用 kmeans 进行过采样
from collections import Counter
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

def plot_scatter(X,y):
    data = {}
    for idx,label in enumerate(y):
        if not label in data:
            data[label] = []
        else:
            data[label].append(X[idx])
    for key in data:
        tmp1 = np.array(data[key])
        plt.scatter(tmp1[:,0],tmp1[:,1])
    plt.show()

# 生成分类的数据
X, y = make_classification(n_samples=5000, n_features=2, n_informative=2,
                           n_redundant=0, n_repeated=0, n_classes=3,
                           n_clusters_per_class=1,
                           weights=[0.01, 0.05, 0.94],  # 生成样本的比例权重
                           class_sep=0.8, random_state=0)
print(Counter(y))

out:
Counter({2: 4674, 1: 262, 0: 64})

plot_scatter(X,y)

cc = ClusterCentroids(random_state=0)
X_resampled, y_resampled = cc.fit_sample(X, y)

plot_scatter(X_resampled,y_resampled)
print(sorted(Counter(y_resampled).items()))

out:
[(0, 64), (1, 64), (2, 64)]

      

  3.2、过采样处理样本不均衡

当少数量类型的样本不满足模型训练的需求时,我们可以对少数量类型样本过采样。
tip:数据不均衡通常处理的都是少数量类型的样本数据

    3.2.1、复制少数量样本数据

        注意:这是最简单的过采样,缺点是容易过拟合

    3.2.2、SMOTE基本算法 ------ SMOTE-Regular

1、smote 算法过采样的过程:
    tip:首先先说明第一点,smote会生成新的样本,这与简单复制样本是有本质的区别的
    
    算法过程如下:
    smote针对少数量样本,随机选择少数量样本集a中的一个样本Xi,使用KNN计算该样本在a样本集中最近的k个样本,随机选
    择k个样本中m个样本【m < k,m由少数样本与多数样本的差异而定,k值则人为定义】,生成样本:
        X_new = Xi + λ*(Xj - Xi) # 其中 λ 为 0-1 的随机数

       图解如下: 

2、smote 基本算法的优点:
    smote 线性随机注入噪声生成的新样本来代替 简单的样本复制,可以有效减少过拟合的风险。
2、smote 基本算法的缺点:
    主要有的缺点:
    ① 传统的smote算法对少数样本的噪声点不敏感【传统的smote算法选中少量样本时没有考虑到该样本周围多数量样本
      的分布,有可能会放大噪声样本的作用】
    ② 在特征维度较高的时候,样本分布的空间较为稀疏,我们不能保证生成的新样本具有少数量样本的特征
    ③ m值可以根据少数量样本与多数量样本的差异比例来定,当时k的大小比较难定

tip:NLP词汇表的维度一般比较高,所以NLP中很少用SMOTE算法
3、SMOTE-Regular 代码:

from sklearn.datasets import make_classification
from imblearn.over_sampling import SMOTE,ADASYN,KMeansSMOTE,BorderlineSMOTE
from collections import Counter

def plot_scatter(X,y):
    data = {}
    for idx,label in enumerate(y):
        if not label in data:
            data[label] = []
        else:
            data[label].append(X[idx])
    for key in data:
        tmp1 = np.array(data[key])
        plt.scatter(tmp1[:,0],tmp1[:,1])
    plt.show()

# 生成分类的数据
X, y = make_classification(n_samples=5000, n_features=2, n_informative=2,
                           n_redundant=0, n_repeated=0, n_classes=3,
                           n_clusters_per_class=1,
                           weights=[0.01, 0.05, 0.94],  # 生成样本的比例权重
                           class_sep=0.8, random_state=0)

print('不均衡的数据量:%s' %Counter(y))
plot_scatter(X,y)

out:
不均衡的数据量:Counter({2: 4674, 1: 262, 0: 64})

sm = SMOTE(random_state=42,n_jobs=-1)
X_res,y_res = sm.fit_resample(X,y)

print('过采样后数据量:%s' %Counter(y_res))
plot_scatter(X_res,y_res)

out:
过采样后数据量:Counter({2: 4674, 1: 4674, 0: 4674})

   

    3.2.3、SMOTE改进算法 ------ 强调类边界 Borderline1-Smote、Borderline2-Smote、Svm-Smote

一、简述Borderline1-smote 执行过程:
    1、说到borderline-smote算法的执行过程,首先了解什么是 ‘噪声集’、‘危险集’、‘安全集’的概念?
        borderline-smote 是针对少数量样本的smote方法,它根据少数量样本周围多数量样本的分布将样本分为3类:
            1.1、安全集safe:样本 KNN 近邻样本中超过一半的样本为该少数量样本
            1.2、危险集danger【边界集】:样本 KNN 近邻样本中超过一半的样本为多数量样本
            1.3、噪声集noise:样本 KNN 近邻样本中全部为多数量样本
        borderline-smote 仅仅对 ‘danger集【边界集】’ 的样本进行 smote。
borderline-smote 的优点:
    由上述borderline-smote执行过程可知:
    ① 该方法不会对‘noise集’的样本进行smote,不会放大噪声数据的影响
    ② 该方法仅仅对‘边界集’的样本进行smote,充分加强了 [类边界] 的识别能力
Boderline-Smoote 有2种处理方式:
    1、Bodeline1-Smote:使用‘danger集’ 与 KNN少数量样本 进行smote
    2、Bodeline2-Smote:使用‘danger集’ 与 KNN少数量样本和多数量样本 进行smote【注意:与多数量样本smote生
       成的新样本标签仍然是少数量样本的label】

SVM-smote:
    SVM-smote 首先用 SVM 分类器找到 支持向量,然后在支持向量的基础上生成新的样本,与Boderline-smote一样,SVM-smote也将少量样本分为 ‘safe’、‘danger’、‘noise’

         Boderline-1-smote代码:

from sklearn.datasets import make_classification
from imblearn.over_sampling import SMOTE,ADASYN,KMeansSMOTE,BorderlineSMOTE
from collections import Counter
import numpy as np
import matplotlib.pyplot as plt

def plot_scatter(X,y):
    data = {}
    for idx,label in enumerate(y):
        if not label in data:
            data[label] = []
        else:
            data[label].append(X[idx])
    for key in data:
        tmp1 = np.array(data[key])
        plt.scatter(tmp1[:,0],tmp1[:,1])
    plt.show()


# 生成分类的数据
X, y = make_classification(n_samples=5000, n_features=2, n_informative=2,
                           n_redundant=0, n_repeated=0, n_classes=3,
                           n_clusters_per_class=1,
                           weights=[0.01, 0.05, 0.94],  # 生成样本的比例权重
                           class_sep=0.8, random_state=0)

print('不均衡的数据量:%s' %Counter(y))
plot_scatter(X,y)

sm = BorderlineSMOTE(kind="borderline-1",random_state=42,n_jobs=-1)
X_res,y_res = sm.fit_resample(X,y)
plot_scatter(X_res,y_res)

print('过采样后数据量:%s' %Counter(y_res))

   

         Boderline-2-smote代码:

from sklearn.datasets import make_classification
from imblearn.over_sampling import SMOTE,ADASYN,KMeansSMOTE,BorderlineSMOTE,SVMSMOTE
from collections import Counter
import numpy as np
import matplotlib.pyplot as plt

def plot_scatter(X,y):
    data = {}
    for idx,label in enumerate(y):
        if not label in data:
            data[label] = []
        else:
            data[label].append(X[idx])
    for key in data:
        tmp1 = np.array(data[key])
        plt.scatter(tmp1[:,0],tmp1[:,1])
    plt.show()


# 生成分类的数据
X, y = make_classification(n_samples=5000, n_features=2, n_informative=2,
                           n_redundant=0, n_repeated=0, n_classes=3,
                           n_clusters_per_class=1,
                           weights=[0.01, 0.05, 0.94],  # 生成样本的比例权重
                           class_sep=0.8, random_state=0)

print('不均衡的数据量:%s' %Counter(y))
plot_scatter(X,y)

sm = BorderlineSMOTE(kind="borderline-2",random_state=42,n_jobs=-1)
X_res,y_res = sm.fit_resample(X,y)
plot_scatter(X_res,y_res)

print('过采样后数据量:%s' %Counter(y_res))

   

         svm-smote代码:

from sklearn.datasets import make_classification
from imblearn.over_sampling import SMOTE,ADASYN,KMeansSMOTE,BorderlineSMOTE,SVMSMOTE
from collections import Counter
import numpy as np
import matplotlib.pyplot as plt

def plot_scatter(X,y):
    data = {}
    for idx,label in enumerate(y):
        if not label in data:
            data[label] = []
        else:
            data[label].append(X[idx])
    for key in data:
        tmp1 = np.array(data[key])
        plt.scatter(tmp1[:,0],tmp1[:,1])
    plt.show()


# 生成分类的数据
X, y = make_classification(n_samples=5000, n_features=2, n_informative=2,
                           n_redundant=0, n_repeated=0, n_classes=3,
                           n_clusters_per_class=1,
                           weights=[0.01, 0.05, 0.94],  # 生成样本的比例权重
                           class_sep=0.8, random_state=0)

print('不均衡的数据量:%s' %Counter(y))
plot_scatter(X,y)

sm = SVMSMOTE(random_state=42,n_jobs=-1)
X_res,y_res = sm.fit_resample(X,y)
plot_scatter(X_res,y_res)

print('过采样后数据量:%s' %Counter(y_res))

  

    3.2.4、SMOTE改进算法 ------ 强调类区域 Kmeans-Smote

         Kmeans-Smote算法执行步骤:

总体来说分为三个步骤:kmeans --- 簇过滤 ---- smote 

    1、kmeans 步骤:输入所有的数据集进行Kmeans,该过程不考虑类别
    2、簇过滤 步骤:获得每个簇的簇标签,过滤掉标签为多数类别label的簇【其实就是选择那些少数量样本比例较高的簇】
    3、smote 步骤:对剩下的簇中的样本进行 smote

K-means smote 的特点:
    簇过滤的阶段其实是选择少数量样本集密度较高的区域,对该区域进行smote 其实是强调 [类区域] 的做法,这一点
    不同于borderline-smote

         Kmeans-Smote代码:

from sklearn.datasets import make_classification
from imblearn.over_sampling import SMOTE,ADASYN,KMeansSMOTE,BorderlineSMOTE,SVMSMOTE
from collections import Counter
import numpy as np
import matplotlib.pyplot as plt

def plot_scatter(X,y):
    data = {}
    for idx,label in enumerate(y):
        if not label in data:
            data[label] = []
        else:
            data[label].append(X[idx])
    for key in data:
        tmp1 = np.array(data[key])
        plt.scatter(tmp1[:,0],tmp1[:,1])
    plt.show()


# 生成分类的数据
X, y = make_classification(n_samples=5000, n_features=2, n_informative=2,
                           n_redundant=0, n_repeated=0, n_classes=3,
                           n_clusters_per_class=1,
                           weights=[0.01, 0.05, 0.94],  # 生成样本的比例权重
                           class_sep=0.8, random_state=0)

print('不均衡的数据量:%s' %Counter(y))
plot_scatter(X,y)

sm = KMeansSMOTE(random_state=42,n_jobs=-1,k_neighbors=5,kmeans_estimator=50)  # kmeans_estimator 簇的个数
X_res,y_res = sm.fit_resample(X,y)
plot_scatter(X_res,y_res)

print('过采样后数据量:%s' %Counter(y_res))

 

    3.2.5、几种SMOTE过采样效果总结

1、传统的smote
    1.1、优点【相对于随机复制样本】:引入了随机噪声生成了新的样本,缓解了过拟合的风险
    1.2、缺点:
            ① 没有考虑到少数量样本周围多数量样本的分布,容易加大噪声点的影响
            ② 特征维度高时,特征空间稀疏,不能保证生成的新样本可以代表少数量样本的特征
            ③ KNN的K值难以确定
2、强调类边界的smote
    优点:考虑了少数量样本周围多数量样本的分布,不增强噪声点,只增强边界‘danger集’
        2.1、borderline1-smote
        2.2、borderline2-smote
        2.3、SVM-smote
3、强调类区域的smote
    优点:考虑了少数量样本周围多数量样本的分布,不增强噪声点,增强少数类样本类区域
        3.1、k-means smote

四、模型算法处理样本不均衡

1、模型算法解决数据不平衡的问题的思想:
    通过在模型算法引入 权重倚重,用来调节数据不均衡的各种类别样本对模型的作用效果。

2、最常见的几种方式:
    cost-sensitive:
        代表:meta-cost
    focal-loss:

  4.1、Meta-Cost【cost sensitive】

        github代码:meta-cost 代码 python

        cost sensitive 代价敏感矩阵的定义:Cost Sensitive 算法通过增加少数量样本代价损失来加强模型对少量样本特征的学习

        cost sensitive论文:代价铭感 Cost Sensitive 论文

代价敏感引入模型的方法:
    1、通过修改模型预测阈值的方式增加模型对少数类别样本重视。
    2、利用集成学习的思想更改模型的参数权重,代表 meta cost

        Meta Cost 的步骤:

(1)利用集成学习的思想,在原始数据中m次采样,训练m个模型
(2)根据m个模型,计算预测样本属于 各个类别概率 p(y= 0,1,2,... j|x) 【采用m个模型求均值的方式】
(3)根据上述类别概率分布 与 类别代价分布矩阵 使得该样本的代价损失最小,更改样本的类标签
(4)训练修改过的数据集,得到新的模型

     

  4.2、Focal-loss

        阅读文章:【二分问题focal-loss解释】【多分类问题focal-loss代码

        github代码:focal-loss for NER多分类Focal-loss 多分类代码

    4.2.1、Focal-loss 与  CE交叉熵损失的关系

          以二分类为例【多分类的softmax是一样的,因为不管是二分类或多分类,- log p 只计算 真实label所对应位置的交叉熵,而其他位置值为0

            1、  CE交叉熵表示方式

                  

            2、将 p 与 1-p 用函数 p(t) 表示,p(t) 表示样本在每一个类别对应位置预测概率,多分类时是样本预测softmax的概率值

                  

            3、CE 交叉熵最终表示为

                 

            4、Focal Loss 在 CE 的基础上添加 alpha 与 γ 参数

               

            5、最后得出 Focal Loss 与 CE 交叉熵函数的关系

         focal_loss = (alpha * (1-p(t))**gamma * ce_loss).mean()   # 多分类的时候,p(t)是样本softmax的概率值

    4.2.2、Focal-loss 的两个参数 α 于 γ 的作用

1、数据不均衡的数据有两个主要的问题:
    ① 每一个类别样本数量差异性太大
    ② 样本中存在容易分类样本与困难分类样本【容易分类样本对模型更新往往没有作用,γ参数可以减低容易样本对loss的贡献权重】

2、focal loss 中 alpha 与 γ参数
    alpha参数:可以平衡样本类别比例不均衡的问题。以二分类为例,y = 1是,使用alpha 平衡,y = 0时,使用 1- alpha 平衡;但
               实际上作用不大,因此 代码中不管是二分类还是softmax多分类,alpha 统统使用一个值即可
    γ参数:为了解决 容易样本与困难样本 的问题。

                    

  •       用一个例子说明 Focal-loss 中 alpha 与 γ 使用方法与意义
1、假设:alpha = 0.25,γ = 2,容易样本预测概率为 p1 = 0.95,困难样本预测概率为 p2 = 0.1
    
    计算 CE 与 focal loss:
        
        CE:
            容易样本:  -log 0.95
            困难样本:  -log 0.1

        focal:
            容易样本:  (1 - alpha) * (1 - 0.95)**γ * -log 0.95 = 0.75 * 0.0025 * -log 0.95
            困难样本:  alpha * (1 - 0.1)**γ * -log 0.95 = 0.25 * 0.81 * -log 0.1
            
    tip:
        容易样本使用较大的 1 - alpha 可以理解为不让 容易样本loss权重过于小,而困难样本使用 alpha

    4.2.3、Focal-loss 多分类代码

大致步骤如下:
def focacl_loss(output,target,reduction="none",alpha=1.0 , gamma=2.0):
    """
        ********** 给定模型前向传播的输出 log output:[batch,num_class]与真实值target:[batch,],计算loss误差 ************
        1. 仅仅在训练的时候使用 focal_loss ,验证时不使用 focal_loss
        2. 由于focal_loss乘以一个小于1的数,整体比 传统的CE要小很多,所以再加入focal_loss时可以适当增加学习率

    """
    ce_loss = F.nll_loss(input = output,target = target, reduction=reduction)  # ce_loss dim: [B,]
    pt = torch.exp(-ce_loss)                                                   # pt      dim: [B,]
    # 构建 focal_loss
    focalloss = (alpha * (1.0 - pt)**gamma * ce_loss).mean()
    return focalloss

五、评价指标【一文详解数据不平衡问题评估指标2

  5.1、acc、precision、recall、F1_score 以及对应的宏平均macro 、微平均micro

      宏平均macro F1特点:不受样本分布不平衡的影响,但会受到 高 recall 与 高 precision 值得影响

      微平均micro F1 特点:容易受到样本不平衡的印象,当预测类别均属于训练类别时,micro 的4个指标的值恒相等。

from sklearn import metrics
 
y_test    = [1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4]
y_predict = [1, 1, 1, 3, 3, 2, 2, 3, 3, 3, 4, 3, 4, 3]
 
print('准确率:', metrics.accuracy_score(y_test, y_predict)) #预测准确率输出
 
print('宏平均精确率:',metrics.precision_score(y_test,y_predict,average='macro')) #预测宏平均精确率输出
print('微平均精确率:', metrics.precision_score(y_test, y_predict, average='micro')) #预测微平均精确率输出
print('加权平均精确率:', metrics.precision_score(y_test, y_predict, average='weighted')) #预测加权平均精确率输出
 
print('宏平均召回率:',metrics.recall_score(y_test,y_predict,average='macro'))#预测宏平均召回率输出
print('微平均召回率:',metrics.recall_score(y_test,y_predict,average='micro'))#预测微平均召回率输出
print('加权平均召回率:',metrics.recall_score(y_test,y_predict,average='micro'))#预测加权平均召回率输出
 
print('宏平均F1-score:',metrics.f1_score(y_test,y_predict,labels=[1,2,3,4],average='macro'))#预测宏平均f1-score输出
print('微平均F1-score:',metrics.f1_score(y_test,y_predict,labels=[1,2,3,4],average='micro'))#预测微平均f1-score输出
print('加权平均F1-score:',metrics.f1_score(y_test,y_predict,labels=[1,2,3,4],average='weighted'))#预测加权平均f1-score输出
 
print('混淆矩阵输出:\n',metrics.confusion_matrix(y_test,y_predict,labels=[1,2,3,4]))#混淆矩阵输出
print('分类报告:\n', metrics.classification_report(y_test, y_predict,labels=[1,2,3,4]))#分类报告输出
 
 
输出:
准确率: 0.571428571429
宏平均精确率: 0.696428571429
微平均精确率: 0.571428571429
加权平均精确率: 0.775510204082
宏平均召回率: 0.566666666667
微平均召回率: 0.571428571429
加权平均召回率: 0.571428571429
宏平均F1-score: 0.579166666667
微平均F1-score: 0.571428571429
加权平均F1-score: 0.615476190476
混淆矩阵输出:
 [[3 0 2 0]
 [0 2 2 0]
 [0 0 2 1]
 [0 0 1 1]]
分类报告:
              precision    recall  f1-score   support
 
          1       1.00      0.60      0.75         5
          2       1.00      0.50      0.67         4
          3       0.29      0.67      0.40         3
          4       0.50      0.50      0.50         2

  5.2、ROC曲线、PR曲线 、AUC 值 以及对应的宏平均macro 、微平均micro

    5.2.1、二分类 ROC 曲线与AUC值

               评估指标【二分类ROC曲线与AUC值】

    5.2.2、多分类的ROC曲线与AUC值

               评估指标【多分类ROC曲线与macro_roc与micro_roc曲线与AUC值】

    5.2.3、ROC曲线、PR曲线的区别 以及使用场景?

1、ROC曲线与PR曲线的区别:
    ① ROC曲线基于 TPR 与 FPR,即共同参考了正例与负例,相对比较均衡,而PR曲线完全使用正例的precision与recall
      PR曲线更加关注于正例
    ② 当正负例数据比较均衡时,ROC曲线与PR评估效果相差不多,若突然加入大量的负例数据时,ROC曲线的波动变化比较平稳,而
      PR变化及其不稳定;
      但是需要注意的是,大量负例增加会导致FPR值不会大幅度变化,从而导致ROC会给定一个过于乐观的值。

2、ROC曲线与PR曲线的使用场景:
    ① 不考虑不同类别样本分布,综合评估正负例分类器的整体性能可以用ROC曲线;考虑不同类别样本分布对分类器性能影响使用PR曲线
    ② 模型评估指标聚焦于正例时使用PR曲线
    ② 样本分布不均衡的情况下,ROC曲线通常会给定一个过于‘乐观’的值,所以这时大多数情况使用 PR 曲线。


最后,根据一个具体的业务场景,在曲线中选取一个合适的 recal precision F1_socre 的指标,去调整模型的阈值,可以得到该
    业务场景合适的模型
  •           ROC曲线场景举例

  •           PR曲线场景举例

场景:假设对用户的UGC数据进行分类,假设现在有涉政、涉黄、违禁买卖、暴恐、广告五个标签,场景为多
      标签多分类问题,使用sigmiod进行多标签多分类

场景特点:
    1. 多标签多分类,使用sigmiod进行多次二分类任务
    2. 数据存在不均衡问题,且少数量样本为正例样本,我们的注意力主要在正例样本上

观察上图:
    涉政标签的3个算法模型的PR曲线如上图所示,那么怎么选择合适的模型呢?怎么选择合适的模型阈值呢?

模型与模型阈值的选择方法:
    模型选择:涉政业务场景要求高recall,可以牺牲一定的precision,因此C模型是比较合适的模型
    阈值的选择:根据涉政的业务场景,根据制定的recall与precision在PR曲线上找到合适的模型阈值

  5.3、样本不均衡的评估指标 G-mean

      略

六、NLP场景中数据增强

  6.1、EDA简单的样本增强

1、EDA样本数据增强的操作:随机 替换、插入、交换、删除 四个操作
    ① 从句子中随机选取 n 个不属于停用词集的单词,并随机选择同义词替换。
    ② 随机的找出句子中某个不属于停用词集的词,并求出其随机的同义词,将该同义词插入句子的一个随机位置,重复 n 次。
    ③ 随机的选择句中两个单词并交换他们的位置,重复 n 次
    ④ 以 p 的概率,随机的移除句子中的单词 
  •        EDA for english?   EDA for chinese ? github 代码:

              EDA_NLP_for_Chinese

  6.2、UDA半监督一致性数据增强

            UDA论文:Unsupervised Data Augmentation for Consistency Training

            UDA github 代码:

                1、Unsupervised Data Augmentation 【github code】

                2、UDA pytorch with Bert 【文章地址:Google无监督数据增强方法UDA在文本分类上的实验

            论文解析:

                 1、论文阅读笔记:UDA

                 2、半监督学习:Unsupervised Data Augmentation

                 3、谷歌惊艳的无监督数据增强方法 UDA

                 4、Google无监督数据增强方法UDA在文本分类上的实验

    6.2.1、UDA 一致性训练的图解

 

    6.2.2、UDA训练损失函数的定义

       

    6.2.3、UDA训练过程中‘ 退火训练 ’ TSA

          参考上面的文章

七、NLP实际项目中数据不均衡的解决步骤

        第一步:寻找更多的标注数据,这是最终极的解决方案

        第二步:通常情况下我们的数据都是不足的,这个时候可以先做一个baseline模型得出结果,并且可以分析数据类别的分布情况,如下图: 

         第三步:如果我们使用的模型是bert家族,那么我们就可以使用UDA进行半监督的数据增强,而且可以魔改loss损失函数。如果模型不是bert家族,那可能会使用EDA这种数据增强的方法,需要注意的是EDA效果并非都是正向的。NLP中一般不会使用SMOTE采样,这是因为NLP项目特征维度较高,SMOTE未必有较好的效果。

        第四步:模型训练完后,如果是sigmoid多分类问题,对于数据不均衡的场景,我们通常使用PR曲线关注正例,通过业务需求的recall与precision使用PR曲线来选取合适的模型,再通过业务需求的recall与precision使用PR曲线选取合适的模型阈值。

八、课程文献资料

  1. GitHub 中文 EDA_NLP_for_Chinese
  2. UDA Google 源代码 
  3. 机器学习评估指标详细介绍
  4. 一文详解数据不平衡问题

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值