模型评估与改进(四)// 样本不均衡

一、什么是样本不均衡?
回答:在有监督分类算法中,标签的类别比重差异大。

二、如何从采样角度纠正样本不均衡?
回答:
1、上采样(over-sampling):通过增加分类中少数类样本的数量来实现样本均衡。比较好的方法有SMOTE算法,通过插值的方式加入近邻的数据点。
2、下采样(under-sampling):通过减少分类中多数类样本的数量来实现样本均衡。这个方法可能导致信息缺失,为克服这一缺点,RandomUnderSampler丢掉更多类别边界部分的数据。

from imblearn.over_sampling import SMOTE #类,上采样
from imblearn.under_sampling import RandomUnderSampler #类,下采样

三、分类算法中哪些超参数可以调和样本不均衡?
回答:机器学习算法中以下4个算法有超参数class_weight用来调和样本不均衡问题。
模型评估与改进(四)// 样本不均衡_第1张图片
四、样本不均衡情况下的评估指标?
回答:此时用accuracy不合适,可以改用recall、f1指标,辅以ROC曲线、P-R曲线。
(详见上一篇:模型评估与改进(三)// 评估指标)

五、如何通过阈值调优来提高少数类的预测?
回答:一般正例样本的决策阈值是0.5,可以通过手写函数来实现阈值调优。以下代码参考李御玺教授的论文思想,我自己手写的阈值调优函数,该函数的目标是寻找最高f1的决策阈值。

def Find_BestMetrics(y_true,y_predp):
    '''
    函数功能:生成不同决策阈值下的presicion、recall、f1的df表,以及最优的正例决策阈值
    参数说明:
        y_true:series格式,真实y值
        y_predp:array格式,算法模型给出的样本预测为1的概率
    返回:
        resultdf:不同决策阈值下的presicion、recall、f1的表格
        best_p:最佳f1下的决策阈值p
    '''
    #第一步:构造以真实标签、预测为1概率的DF数据集
    columns=['y_true','proba1']
    data=np.concatenate((y_true.values,y_predp[:,1].reshape(y_true.shape[0],1)),axis=1)
    df=pd.DataFrame(data,columns=columns)
    df=df.sort_values(by='proba1',ascending=False)
    df.index=range(df.shape[0]) #索引重置
    df['cum_count']=pd.Series(range(1,df.shape[0]+1)) #辅助列
    y_0_count=df['y_true'].value_counts()[0] #负例样本数量
    y_1_count=df['y_true'].value_counts()[1] #正例样本数量

    #第二步:重新计算在不同决策阈值下的presicion、recall、f1
    df['cum_count_1']=df['y_true'].cumsum()
    df['presicion']=df['cum_count_1']/df['cum_count']
    df['recall']=df['cum_count_1']/y_1_count
    df['f1']=(2*df['presicion']*df['recall'])/(df['recall']+df['presicion'])
    
    #第三步:最佳f1下的决策阈值p
    best_p=df.iloc[np.argmax(df['f1']),1]
    
    resultdf=df.drop(['cum_count','cum_count_1'],axis=1)
    return resultdf,best_p
def Metrics_Report(p,y_true,y_predp):
    '''
    函数功能:返回正例决策阈值p下的presicion、recall、f1
    参数说明:
        p:决策阈值
        y_true:真实y标签
        y_predp:算法模型给出的样本预测为1的概率
    '''
    metrics_df,ptt=Find_BestMetrics(y_true,y_predp) #只有ytt_df有用
    
    presicion=metrics_df[metrics_df['proba1']>=p]['presicion'].iloc[-1]
    recall=metrics_df[metrics_df['proba1']>=p]['recall'].iloc[-1]
    f1=metrics_df[metrics_df['proba1']>=p]['f1'].iloc[-1]
    print('presicion is:\t%0.2f'%presicion)
    print('recall is:\t%0.2f'%recall)
    print('f1 is:\t\t%0.2f'%f1)
    return presicion,recall,f1
def Label_Predict(p,y_predp):
    '''
    函数功能:返回标签预测
    参数说明:
        p:决策阈值
        y_predp:算法模型给出的样本预测为1的概率
    '''
    label_pred=y_predp[:,1].copy()
    label_pred[y_predp[:,1]>=p]=1
    label_pred[y_predp[:,1]<p]=0
    return label_pred

你可能感兴趣的:(Python)