欺詐檢測

背景介紹

數(shù)據(jù)集包含歐洲持卡人于2013年9月通過信用卡進行的交易痪寻。這個數(shù)據(jù)集顯示了兩天內(nèi)發(fā)生的交易击困,在284,807筆交易中我們有492筆詐騙做盅。
數(shù)據(jù)集非常不平衡最冰,正面類(欺詐)占所有交易的0.172%。
數(shù)據(jù)集只包含數(shù)值輸入變量猖闪,這是PCA變換的結(jié)果鲜棠。不幸的是,由于保密問題培慌,我們無法提供有關(guān)數(shù)據(jù)的原始特征和更多背景信息豁陆。特征V1,V2吵护,... V28是使用PCA獲得的主要組件盒音,沒有用PCA轉(zhuǎn)換的特征是“時間”和“金額”表鳍。“時間”包含數(shù)據(jù)集中每個事務和第一個事務之間經(jīng)過的秒數(shù)祥诽∑┦ィ“金額”是交易額,此特征可用于基于樣本的成本靈敏度學習原押。特征'類'是響應變量胁镐,如果發(fā)生欺詐偎血,則取值1诸衔,否則為0。

初步分析

我們的目的是通過訓練得到一個模型颇玷,這個模型通過特征變量能識別出該筆交易是否發(fā)生欺詐笨农。
由背景介紹可知:

  1. 正反樣本分布極度不平衡,可能對預測存在影響帖渠,需要衡量采用過采樣還是下采樣來解決這個問題谒亦。
  2. 數(shù)據(jù)集已經(jīng)過PCA變換,相對干凈空郊,可以將重點放在建模分析上份招。
  3. 一般評價模型我們用的準確度,但是結(jié)合實際業(yè)務狞甚,在準確度很高的情況下可能FN很高但是TP很低锁摔,翻譯一下就是欺詐識別能力不怎么樣,這不符合我們的預期哼审。我們希望考察模型的欺詐識別能力谐腰,同時也兼顧模型的準確度,所以我們考慮用Recall指標:TP/(TP+FN)

數(shù)據(jù)預處理

由于數(shù)據(jù)已相對干凈涩盾,這里我們著重考慮樣本平衡問題十气。
首先還是處理一下“amount”變量,做一個變換讓變量值落在[-1,1]的區(qū)間內(nèi)春霍。

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from sklearn.preprocessing import StandardScaler

data = pd.read_csv("creditcard.csv")

data['normAmount'] = StandardScaler().fit_transform(data['Amount'].reshape(-1, 1))
data = data.drop(['Time','Amount'],axis=1)

現(xiàn)在我們考慮樣本平衡問題砸西,要讓樣本平衡很容易想到的一個方法就是反面樣本集中抽取和正面樣本集數(shù)量一致的樣本形成新的反面樣本集,也就是所謂的下采樣方法址儒。

number_records_fraud = len(data[data.Class == 1])#欺詐樣本數(shù)量
fraud_indices = np.array(data[data.Class == 1].index)#欺詐樣本索引
normal_indices = data[data.Class == 0].index#正常樣本索引
random_normal_indices = np.random.choice(normal_indices, number_records_fraud, replace = False)#從正常樣本中采樣芹枷,第二個參數(shù)表示采樣數(shù)量
random_normal_indices = np.array(random_normal_indices)

under_sample_indices = np.concatenate([fraud_indices,random_normal_indices])#合并正常樣本和欺詐樣本形成新的數(shù)據(jù)集索引

# 根據(jù)索引形成下采樣數(shù)據(jù)集
under_sample_data = data.iloc[under_sample_indices,:]
print(u"正常樣本比例: ", len(under_sample_data[under_sample_data.Class == 0])/len(under_sample_data))
print(u"欺詐樣本比例: ", len(under_sample_data[under_sample_data.Class == 1])/len(under_sample_data))
print(u"下采樣總樣本數(shù): ", len(under_sample_data))

#正常樣本比例:  0.5
#欺詐樣本比例:  0.5
#總樣本數(shù):  984

下采樣已經(jīng)完成,可以切分數(shù)據(jù)集準備建模了离福。

X_undersample = under_sample_data.loc[:, under_sample_data.columns != 'Class']
y_undersample = under_sample_data.loc[:, under_sample_data.columns == 'Class']
X_train_undersample, X_test_undersample, y_train_undersample, y_test_undersample = train_test_split(X_undersample,y_undersample ,test_size = 0.3 ,random_state = 0)

建模分析

分類算法我們先考慮業(yè)界的流行算法——邏輯回歸杖狼。
確定特征、確定模型之后妖爷,我們還需要考慮的就是模型的參數(shù)蝶涩。利用交叉驗證法我們來選一下邏輯回歸的正則化懲罰力度參數(shù)理朋。

#邏輯回歸的參數(shù)選擇
def printing_Kfold_scores(x_train_data,y_train_data):
    fold = KFold(5,shuffle=False) 

    # 待選參數(shù)數(shù)組
    c_param_range = [0.01,0.1,1,10,100]

    results = pd.DataFrame(index = range(len(c_param_range),1), columns = ['C_parameter','Mean recall score'])
    results['C_parameter'] = c_param_range

    # k-fold 后, indices[0]作為訓練集, indices[1]作為測試集
    j = 0
    for c_param in c_param_range:
        print('-------------------------------------------')
        print('C parameter: ', c_param)
        print('-------------------------------------------')
        print('')

        recall_accs = []
        for iteration, indices in enumerate(fold.split(x_train_data,y_train_data),start=1):

            lr = LogisticRegression(C = c_param, penalty = 'l1')
            lr.fit(x_train_data.iloc[indices[0],:],y_train_data.iloc[indices[0],:].values.ravel())
            y_pred_undersample = lr.predict(x_train_data.iloc[indices[1],:].values)

            #計算recall值
            recall_acc = recall_score(y_train_data.iloc[indices[1],:].values,y_pred_undersample)
            recall_accs.append(recall_acc)
            print('Iteration ', iteration,': recall score = ', recall_acc)

        # The mean value of those recall scores is the metric we want to save and get hold of.
        results_table.ix[j,'Mean recall score'] = np.mean(recall_accs)
        j += 1
        print('')
        print('Mean recall score ', np.mean(recall_accs))
        print('')

    #選出分數(shù)最高的參數(shù)C
    best_c = results_table.loc[results_table['Mean recall score'].idxmax()]['C_parameter']
    
    # Finally, we can check which C parameter is the best amongst the chosen.
    print('*********************************************************************************')
    print('Best model to choose from cross validation is with C parameter = ', best_c)
    print('*********************************************************************************')
    
    return best_c

這組參數(shù)中c=0.01時表現(xiàn)最好绿聘,下采樣測試集上的recall為 0.938775510204嗽上,暫取c=0.01。(PS:0.01不是最佳參數(shù)熄攘,只是這一組中表現(xiàn)最好的)
看看模型在整個測試集上的表現(xiàn)兽愤。

import itertools
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size = 0.3, random_state = 0)
#建模預測
lr = LogisticRegression(C = best_c, penalty = 'l1')
lr.fit(X_train,y_train.values.ravel())
y_pred= lr.predict(X_test.values)

#混肴矩陣
cnf_matrix = confusion_matrix(y_test,y_pred)
np.set_printoptions(precision=2)

print("基于測試集的Recall: ", cnf_matrix[1,1]/(cnf_matrix[1,0]+cnf_matrix[1,1]))

# 圖形化
class_names = [0,1]
plt.figure()
plot_confusion_matrix(cnf_matrix
                      , classes=class_names
                      , title='Confusion matrix')
plt.show()

recall為0.925170068027,表現(xiàn)良好挪圾。
所謂沒有對比就沒有傷害浅萧,我們來看看沒有經(jīng)過下采樣處理的情況。
將輸入改成整個數(shù)據(jù)集哲思,再做一次參數(shù)選擇洼畅。

best_c = printing_Kfold_scores(X_train,y_train)

這回選的是10,且recall為0.61847902217棚赔。
結(jié)果說明下采樣處理能夠顯著提高欺詐識別能力帝簇。

過采樣

上文提到除了下采樣我們還可以采用過采樣,也就是我們構(gòu)造數(shù)據(jù)使欺詐樣本和正常樣本保持平衡靠益。
這里我們采用過采樣中的經(jīng)典算法SMOTE丧肴。

oversampler=SMOTE(random_state=0)
X_oversample,y_oversample=oversampler.fit_sample(X_train,y_train)
X_oversample = pd.DataFrame(X_oversample)
y_oversample = pd.DataFrame(y_oversample)
best_c = printing_Kfold_scores(X_oversample,y_oversample)
lr = LogisticRegression(C = best_c, penalty = 'l1')
lr.fit(X_oversample,y_oversample.values.ravel())
y_pred = lr.predict(X_test.values)

cnf_matrix = confusion_matrix(y_test,y_pred)
np.set_printoptions(precision=2)

print("基于測試集的Recall: ", cnf_matrix[1,1]/(cnf_matrix[1,0]+cnf_matrix[1,1]))

class_names = [0,1]
plt.figure()
plot_confusion_matrix(cnf_matrix
                      , classes=class_names
                      , title='Confusion matrix')
plt.show()

c選擇100,recall為0.918367346939胧后。

小結(jié)

對比下采樣和過采樣芋浮,兩者的recall指標相差不遠,但是下采樣的誤殺率明顯高于過采樣绩卤,因此在處理樣本不平衡問題時途样,SMOTE是被廣泛采用用的手段之一。


下采樣

過采樣

綜上濒憋,在解決欺詐檢測類問題時何暇,樣本不平衡問題可能是我們無法避免的問題,一方面欺詐本就屬于不常見樣本凛驮,缺乏歷史數(shù)據(jù)裆站,和安全類軟件的病毒檢測處于類似的境地;另一方面黔夭,參考安全問題宏胯,我們目前解決的還是根據(jù)歷史經(jīng)驗解決欺詐問題,面對越來越復雜的環(huán)境本姥,我們可能需要更多的預防手段肩袍,僅僅依賴歷史數(shù)據(jù)可能還不夠。



最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末婚惫,一起剝皮案震驚了整個濱河市氛赐,隨后出現(xiàn)的幾起案子魂爪,更是在濱河造成了極大的恐慌,老刑警劉巖艰管,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件滓侍,死亡現(xiàn)場離奇詭異,居然都是意外死亡牲芋,警方通過查閱死者的電腦和手機撩笆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缸浦,“玉大人夕冲,你說我怎么就攤上這事〔图茫” “怎么了耘擂?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長絮姆。 經(jīng)常有香客問我,道長秩霍,這世上最難降的妖魔是什么篙悯? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮铃绒,結(jié)果婚禮上鸽照,老公的妹妹穿的比我還像新娘。我一直安慰自己颠悬,他們只是感情好矮燎,可當我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著赔癌,像睡著了一般诞外。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上灾票,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天峡谊,我揣著相機與錄音,去河邊找鬼刊苍。 笑死既们,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的正什。 我是一名探鬼主播啥纸,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼婴氮!你這毒婦竟也來了斯棒?” 一聲冷哼從身側(cè)響起馒索,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎名船,沒想到半個月后绰上,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡渠驼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年蜈块,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片迷扇。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡百揭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蜓席,到底是詐尸還是另有隱情器一,我是刑警寧澤,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布厨内,位于F島的核電站祈秕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏雏胃。R本人自食惡果不足惜请毛,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瞭亮。 院中可真熱鬧方仿,春花似錦、人聲如沸统翩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽厂汗。三九已至委粉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間面徽,已是汗流浹背艳丛。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留趟紊,地道東北人氮双。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像霎匈,于是被迫代替她去往敵國和親戴差。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內(nèi)容