机器学习笔记(2)-预测信用卡欺诈

一、项目简介

Credit Card Fraud Detection是一个典型的分类问题,欺诈分类的比例比较小,直接使用分类模型容易忽略。在实际应用场景下往往是保证一定准确率的情况下尽量提高召回率。一个典型案例是汽车制造行业,一旦发生一例汽车安全故障,同批次的车辆需要全部召回,造成了巨大的经济损失。

二、数据印象

详细分析过程见在线脚本

2.1. 简单数据分析

数据规模:中度规模(对于mac而言)。数据共284807条,后期算法选择需要注意复杂度。
数据特征:V1~V28是PCA的结果,而且进行了规范化,可以做一些统计上的特征学习;Amount字段和Time字段可以进行额外的统计学和bucket统计。
数据质量:无缺失值,数据规整,享受啊。
经验时间字段最好可以处理为月份、小时和日期,直接的秒数字段往往无意义。

2.2. 探索性数据分析

三、数据预处理

数据已经十分规整了,所以先直接使用基础模型来预测下数据。

from sklearn.linear_model import LogisticRegression
from sklearn.cross_validation import cross_val_score
from sklearn.model_selection import StratifiedShuffleSplit
from sklearn import metrics

def train_lr(X, y, plot_roc=False):
    sss = StratifiedShuffleSplit(n_splits=10, test_size=0.2, random_state=10)
    lr = None
    for train_index, test_index in sss.split(X, y):
        X_train, X_test = X.iloc[train_index], X.iloc[test_index]
        y_train, y_test = y.iloc[train_index], y.iloc[test_index]
        lr = LogisticRegression(C=0.01, penalty='l1')
        lr.fit(X_train, y_train)
        y_predict = lr.predict(X_test)
        print "roc_auc:", metrics.roc_auc_score(y_test, y_predict)
        print "f1score:", metrics.f1_score(y_test, y_predict)
        print "precision:", metrics.precision_score(y_test, y_predict)
        print "recall:", metrics.precision_score(y_test, y_predict)
        print ""
    
        if plot_roc:
            fpr, tpr, thresholds = metrics.roc_curve(y_test, y_predict)
            roc_auc = metrics.auc(fpr,tpr)

            # Plot ROC
            plt.title('Receiver Operating Characteristic')
            plt.plot(fpr, tpr, 'b',label='AUC = %0.2f'% roc_auc)
            plt.legend(loc='lower right')
            plt.plot([0,1],[0,1],'r--')
            plt.xlim([-0.1,1.0])
            plt.ylim([-0.1,1.01])
    return lr
        
lr = train_lr(X, y, plot_roc=False)

L1规划化


L1规范化的模型

L2规范化


L2规范化的模型

Baseline基础模型:采用线性模型,利用L1的稀疏性,precisionrecall均可以达到0.85左右,roc_auc可以达到0.79左右。

基础模型结果

由上图可见:

  • precision较大时波动波动比较大。recall大于0.8后,准确率下滑严重。
  • AUC面积是0.97,后来根据参考文献3知,AUC大于0.92时之后比较难修正。

Baseline模型的评价metric

  1. 收集更多的数据,不适合这个场景。
  2. 改变评价标准:
    • 使用混淆矩阵计算准确度和回收度。
    • F1score
    • Kappa
    • ROC curves - sensitivity/specificity ratio

数据采样处理
- 收集等多数据:不适合这个场景。
- 过采样Over-sampling:当数据集较少时,主动添加少类别的数据;SMOT算法通过插值来实现。不适合本数据集。容易过拟合,运算时间长。
- 欠采样Under-sampling:当数据集足够大时,删除大类别的数据;集成方法EasyEnsemble/BalanceCascade通过将反例放在不同学习器中使用,从全局看不会丢失重要信息。

本案例数据量中等:选用欠采样+EasyEnsemble的方式进行数据处理。

使用im-balanced生成测试数据。

from imblearn.ensemble import EasyEnsemble

n_subsets = X.size * 2 / (us_X.size) - 1
ee = EasyEnsemble(n_subsets=n_subsets)
sample_X, sample_y = ee.fit_sample(X, y)

四、模型印象

模型:
选用easy_ensemble模型来优化。

具体实现代码见在线脚本

核心adboost代码如下:

def boost_data(X, y, weight):
    size = y.shape[0]
    index_list = np.linspace(0, size-1, size).astype(int)
    train_index = np.random.choice(index_list, size, p=weight)
    train_X = X[train_index, :]
    train_y = y[train_index]
    return train_X, train_y
        
def adboost(X, y, rounds):
    ensemble = EnsembleModel(rounds)
    
    # 初始化weight
    size = y.shape[0]
    weight = np.zeros(size)
    weight[y == 1] = float(1) / sum(y == 1)
    weight[y == 0] = float(1) / sum(y == 0)
    weight /= sum(weight)
    
    result = np.zeros(size)
    
    for i in xrange(rounds):
        train_X, train_y = boost_data(X, y, weight)
        dt = DecisionTreeClassifier()
        ensemble.trees[i] = dt
        
        dt.fit(train_X, train_y)
        y_predict = dt.predict(X)
#         print "sum:", sum(y_predict != y)
        train_error = sum(weight * (y_predict != y))
#         print "train:", train_error
        beta = (1 - train_error) / float(train_error)
        ensemble.alpha[i] = 0.5 * np.log(beta)
        weight *= np.exp(-ensemble.alpha[i] * (y -0.5) * (y - 0.5) * 4)
        weight /= sum(weight)
    
    ensemble.thresh = sum(ensemble.alpha) / 2
    return ensemble

结果如下:


easy_ensembel

对比普通的adboost数据


对比图

由上图可知,easy_ensemble提升了平滑度,但是AUC未有提升。

五、特征选择和特征学习

  • L1模型进行了嵌入式的特征选择,效果优于L2模型。在寻找解释性时会有帮助。

根据数据的统计特征,可以学习一些统计变量。


统计学习

增加如下的特征。

new_X = X_train.copy()
new_X['V1_'] = new_X.V1.map(lambda x: 1 if x < -3 else 0)
new_X['V2_'] = new_X.V2.map(lambda x: 1 if x > 2.5 else 0)
new_X['V3_'] = new_X.V3.map(lambda x: 1 if x < -4 else 0)
new_X['V4_'] = new_X.V4.map(lambda x: 1 if x > 2.5 else 0)

六、分析结果
使用SNE分析(常用于非线性可视化分析)来观看一次under_sample的结果。如下图所示

SNE图

由上图可知两种类别的数据是可以区分的,但是部分数据融合在一起,当追求recall较大时,将会误判大量数据。

七、迭代问题

可以优化的方向:

  • 可以通过学习新的特征,将数据在新维度上拉开距离
  • 在计算机能力允许的情况下,设置合适的round轮次来调参。

八、表述模型

  • 根据模型的SNE图和数据性可知,数据质量是比较好的。
  • easy_ensemble模型本身使用了adboost和bagging,每棵tree的复杂度不高,降低了bias;通过bagging,降低了variance。最终得到了较好的P-R图和AUC值。
  • 通过LR模型的稀疏性特征值,可以制作出一个解释性报告。

参考

  1. GBM vs xgboost vs lightGBM
  2. imbalanced-learn
  3. Exploratory Undersampling for Class-Imbalance Learning
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容