样本不均衡---过采样

过采样

  • 代价敏感加权对不均衡问题有一定帮助,但如果想达到更好的效果,仍需为模型引入更多的负样本。
  • 过采样是常见的一种样本不均衡的解决方案,常用的过采样方法
    • 随机过采样:将现有样本复制,但训练得到的模型泛化能力通常较差
    • SMOTE-少数类别过采样技术(Synthetic Minority Oversampling Technique)
SMOTE算法
  • SMOTE算法是一种用于合成少数类样本的过采样技术
    • 其基本思想是对少数类样本进行分析,然后在现有少数类样本之间进行插值,人工合成新样本,并将新样本添加到数据集中进行训练
    • 该技术是目前处理非平衡数据的常用手段,并受到学术界和工业界的一致认同
  • SMOTE算法基本步骤如下
    • 采样最邻近算法,计算出每个少数类样本的K个近邻
    • 从K个近邻中随机挑选N个样本进行随机线性插值
    • 构造新的少数类样本
    • 将新样本与原数据合成,产生新的训练集

在这里插入图片描述

SMOTE核心:就是通过人工合成的方式把少数类样本数量增加,直到和多数类样本数量一致。

SMOTE案例
  • 接下来通过引入SMOTE算法使该模型得到更好的模型效果。由于SMOTE算法是基于样本空间进行插值的,会放大数据集中的噪声和异常,因此要对训练样本进行清洗。这里使用LightGBM算法对数据进行拟合,将预测结果较差的样本权重降低不参与SMOTE算法的插值过程。
    • 导包
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score,roc_curve,auc
import lightgbm as lgb
  • 获取数据
data = pd.read_csv('data/Bcard.txt')
data.head()
feature_lst = ['person_info','finance_info','credit_info','act_info']
train = data[data.obs_mth != '2018-11-30'].reset_index().copy()
val = data[data.obs_mth == '2018-11-30'].reset_index().copy()
x = train[feature_lst]
y = train['bad_ind']

val_x =  val[feature_lst]
val_y = val['bad_ind']
  • 创建lightGBM方法,返回AUC
def lgb_test(train_x,train_y,test_x,test_y): 
    clf =lgb.LGBMClassifier(boosting_type = 'gbdt',  
                            objective = 'binary',  
                            metric = 'auc',  
                            learning_rate = 0.1,  
                            n_estimators = 24,  
                            max_depth = 4,  
                            num_leaves = 25, 
                            max_bin = 40, 
                            min_data_in_leaf = 5,  
                            bagging_fraction = 0.6,  
                            bagging_freq = 0,  
                            feature_fraction = 0.8,  
                            ) 
    clf.fit(train_x,train_y,eval_set=[(train_x,train_y),(test_x,test_y)],eval_metric = 'auc')
    return clf,clf.best_score_['valid_1']['auc']
  • 选择四个比较重要的特征
feature_lst = ['person_info','finance_info','credit_info','act_info']

#准备数据
train_x = train[feature_lst]
train_y = train['bad_ind']
test_x = val[feature_lst]
test_y = val['bad_ind']

#调用函数,进行训练
lgb_model,lgb_auc  = lgb_test(train_x,train_y,test_x,test_y)  

#模型预测
sample = train_x.copy()
sample['bad_ind'] = train_y 
sample['pred'] = lgb_model.predict_proba(train_x)[:,1]

#对预测结果进行降序排序,这样,排序后的结果中,预测为正样本(坏人)概率越大的越靠前
sample = sample.sort_values(by=['pred'],ascending=False).reset_index()  
sample['rank'] = sample.index.values/len(sample)  
sample

在这里插入图片描述

  • 定义函数去掉预测值与实际值不符的部分
#x:真实的结果
#y:预测的结果
#过滤预测和真实的情况严重不相符的样本
#由于上述表格中,我们是按照pred降序排序,因此越往前,是正样本(坏人)的概率越大,但是实际上是负样本(好人),所以这部分的数据要排除,同理,越往后,是负样本(好人)的概率越大,但是实际上是正样本(坏人),这部分的数据也要排除。
def weight(x, y):
    # 真实标签为0,违约概率为所有样本中最高的10%
    if x == 0 and y < 0.1:
        return 0.1
    # 真实标签为1  违约概率为所有样本中最低的30%
    elif x == 1 and y > 0.7:
        return 0.1
    else:
        return 1

sample['weight'] = sample.apply(lambda row:weight(row['bad_ind'],row['rank']),axis = 1)
#把预测相对比较准的取出来进行过采样
smote_sample = sample[sample.weight == 1]
train_x_smote = smote_sample[feature_lst]
train_y_smote = smote_sample['bad_ind']
smote_sample.shape

在这里插入图片描述

  • 创建smote过采样函数,进行过采样
def smote(train_x_smote,train_y_smote,K=15,random_state=0):
    from imblearn.over_sampling import SMOTE
    smote = SMOTE(k_neighbors=K, n_jobs=1,random_state=random_state)
    #fit_resample,找K个邻居,然后进行过采样
    rex,rey = smote.fit_resample(train_x_smote,train_y_smote)
    return rex,rey
rex,rey =smote(train_x_smote,train_y_smote)

#查看数据
train_y_smote.value_counts()
rey.value_counts()

在这里插入图片描述

  • 使用过采样数据建模,使用训练集数据和测试集数据验证
# 使用过采样数据建模, 使用训练集数据和测试集数据验证
lr_model = LogisticRegression(C=0.1)
lr_model.fit(rex[feature_lst],rey)
x = train[feature_lst]
y = train['bad_ind']
val_x =  val[feature_lst]
val_y = val['bad_ind']

y_pred = lr_model.predict_proba(x)[:,1] #取出训练集预测值
fpr_lr_train,tpr_lr_train,_ = roc_curve(y,y_pred) #计算TPR和FPR
train_ks = abs(fpr_lr_train - tpr_lr_train).max() #计算训练集KS
print('train_ks : ',train_ks)

y_pred = lr_model.predict_proba(val_x)[:,1] #计算验证集预测值
fpr_lr,tpr_lr,_ = roc_curve(val_y,y_pred)   #计算验证集预测值
val_ks = abs(fpr_lr - tpr_lr).max()         #计算验证集KS值
print('val_ks : ',val_ks)

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值