
写在前面:
作为一个初入数据分析师的小白,很多时候我也处在一个迷茫期,经常会陷入到对工具的学习,缺少对业务问题的思考,甚至搞不清自己的目标任务。还有一部分小白想一口吃个大胖子(像我:)),拿到数据后,不管三七二十一,上来就想流水线生产。结果就是预处理做了,EDA做了,机器学习建模也做了,看着最后好像不错的accuracy,一抹迷之微笑的余光掠过,[omg]数据分析不过如此。但是,当疑问扑面而来的时候(为什么这样分析?分析的结果反映了用户怎样的行为?accuracy高就能说明模型效果好吗?。。。),我才深刻的得出一个结论,原来我还是一个小白。所以这里我们不打阵地战,通过游击战各个击破;同样,我们也不过于关注代码怎么实现,而是关注问题本身,因为工具和代码是一个辅助手段,而且它们多姿多态,而问题万变不离其宗。今天我们就专注数据不平衡这一问题的处理,以SMOTE和随机下采样两个策略进行不平衡数据集的采样,并通过逻辑斯蒂回归、SVM、KNN和随机森林建模,最后通过ROC曲线及对应的AUC值评估分类效果。【这篇知乎主要针对像我一样刚入门数据分析的小白们,期望能够起到抛砖引玉的作用,同时欢迎大家的批评指正!】
1.数据特点
我们要养成一个良好的习惯,拿到数据后首先得了解你的数据。
print(df.shape)
print(df.isnull().sum().reshape(1,-1))
print(df.Class.value_counts())

数据一共有284807行,31个字段,均是数值类型,且没有缺失值。这31个字段只有Amount、Time、Class三个字段已知,其他28个字段由V1~V28表示(出于数据隐私),且这28个字段都已经标准化处理。我们的目标变量Class有两类标签,分别对应正常交易和非法交易(0:No Frauds 1:Frauds),类别严重不平衡。如果直接将原始数据用于建模,它会猜想样本基本都是No Frauds,模型会出现过拟合。但是我们期望模型能够学习到少数类(Frauds)的特征,并能够根据学习到的特征准确识别出来。机器学习模型的训练一般要求不同类的样本数量要相当,所以我们需要对原始数据集进行采样。两个策略:①将多数类样本(0:No Frauds)进行随机下采样;②通过SMOTE算法将少数类样本(1:Frauds)进行过采样。这两个策略都可以得到两类标签相当的数据集。【数据来源:https://www.kaggle.com/mlg-ulb/creditcardfraud】
为方便后面机器学习模型的构建,在进行不平衡数据处理前,我们需要先对原始数据做一点预处理。由前面已经知道,V1~V28字段已经被数据整理员标准化处理了,所以我们需要对Amount、Time、Class三个字段进行标准化处理。数据标准化可以消除不同量纲和每个特征方差值带来的影响,一般通过StandardScalar(
data['scaled_amount'] = rob_scaler.fit_transform(data['Amount'].values.reshape(-1,1))
data['scaled_time'] = rob_scaler.fit_transform(data['Time'].values.reshape(-1,1))
data.drop(['Time','Amount'], axis=1, inplace=True)
print(data.loc[:,['scaled_amount','scaled_time']])