python數據分析之金融欺詐行為檢測


python數據分析之金融欺詐行為檢測

  1. 項目的思維導圖
    思維導圖
  2. 數據分析與處理
  • 聲明所使用的庫
    `import numpy as np   
    import pandas as pd   #panda主要用於處理結構化的數據列表,具有數據挖掘和數據分析,對數據進行清洗
    import matplotlib.pyplot as plt    #繪圖工具
    import matplotlib.cm as cm     #色彩映射函數
    import seaborn as sns    #基於Matplotlib圖形可視化的python包,便於做出統計圖表
    
    from sklearn import preprocessing    #數據建模用的一個庫
    from scipy.stats import skew,boxcox
    import os`
  • 處理數據的結構
    注意:代碼中處理的是csv文件,這里為了簡單明了,使用excel呈現出
    ![在這里插入圖片描述](https://img-blog.csdnimg.cn/20201018195727579.png?x-oss-
    process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDg3MTkwMw==,size_16,color_FFFFFF,t_70#pic_center)

關於數據列的解釋如下
(1)step:對應現實中的時間單位(小時)
(2)type:轉賬類型
(3)amout:金額
(4)nameOrig: 轉賬發起人
(5)oldbalanceOrg: 轉帳前發起人賬戶余額
(6)newbalanceOrig: 轉賬后發起人賬戶余額
(7)nameDest: 轉賬收款人
(8)oldbalanceDest: 轉賬前收款人賬戶余額,收款人是商戶(M開頭)時沒有該項信息
(9)newbalanceDest: 轉賬后收款人余額,收款人是商戶(M開頭)時沒有該項信息
(10)isFraud:該轉賬行為是欺詐行為
(11)isFlaggedFraud: 商業模型為了控制大額轉賬並且標記為非法操作,在這兒,非法操作是指轉賬金額超過20萬。

  • 讀取文件
    在代碼所在的文件夾中創建一個新的文件夾,用於存放數據集
    dataset_path='./pythonjinrong'
    csvfile_path=os.path.join(dataset_path,'PS.csv')
    
    #解壓數據集
    raw_data=pd.read_csv(csvfile_path)
  • 統計數據集中的各轉賬類型的數量
    print('轉賬類型記錄統計:')
    print(raw_data['type'].value_counts())
    fig,ax=plt.subplots(1,1,figsize=(8,4))
    raw_data['type'].value_counts().plot(kind='bar',title='Transaction Type',ax=ax,figsize=(8,4))
    plt.show()

結果會輸出統計數量結果,以及繪制柱形圖,從下圖中可以看出數量最多的類型是支付類型(PAYMENT),共1391例,最少的是借款(DEBIT),共152例
![在這里插入圖片描述](https://img-blog.csdnimg.cn/20201018200623687.png?x-oss-
process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDg3MTkwMw==,size_16,color_FFFFFF,t_70#pic_center)

  • 查看各類型中欺詐行為的數量
    (1)首先,用“0”表示沒有欺詐行為,用“1”表示存在欺詐行為
    (2)統計存在欺詐行為的類型的數量
    #查看轉賬類型和欺詐標記的記錄
    ax=raw_data.groupby(['type','isFraud']).size().plot(kind='bar')
    ax.set_title('#of transactions vs (type+isFraud)')
    ax.set_xlabel('(type,isFraud)')
    ax.set_ylabel('#of transaction')
    #添加標注
    for p in ax.patches:
        ax.annotate(str(format(int(p.get_height()),',d')),(p.get_x(),p.get_height()*1.01))

(3)運行結果如下
![在這里插入圖片描述](https://img-blog.csdnimg.cn/20201018201453234.png?x-oss-
process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDg3MTkwMw==,size_16,color_FFFFFF,t_70#pic_center)
從結果分析,存在欺詐行為的類型有現金提取(CASH_OUT)和轉賬(DEBIT)

  • 使用箱線圖比較欺詐行為和正常行為
    #對數據進行分析
    fig,axs=plt.subplots(2,2,figsize=(10,10))
    transfer_data=raw_data[raw_data['type']=='TRANSFER']
    
    a=sns.boxplot(x='isFlaggedFraud',y='amount',data=transfer_data,ax=axs[0][0])
    axs[0][0].set_yscale('log')   #比較金額
    
    b=sns.boxplot(x='isFlaggedFraud',y='oldbalanceDest',data=transfer_data,ax=axs[0][1])
    axs[0][1].set(ylim=(0,0.5e8)) #比較轉賬前收款人賬戶余額
    
    c=sns.boxplot(x='isFlaggedFraud',y='oldbalanceOrg',data=transfer_data,ax=axs[1][0])
    axs[1][0].set(ylim=(0,3e7))    #比較轉賬前付款人的賬戶余額
    
    d=sns.regplot(x='oldbalanceOrg',y='amount',data=transfer_data[transfer_data['isFlaggedFraud']==1])   
    plt.show()   

由於小編的電腦內存僅剩幾個G,所以跑不動高達481968k的數據集,所以自己提取了204K的數據運行,但結果不佳,圖1是204k數據跑的結果,圖2、3是換了設備后大數據集的結果
![在這里插入圖片描述](https://img-blog.csdnimg.cn/20201018202607243.png?x-oss-
process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDg3MTkwMw,size_16,color_FFFFFF,t_70#pic_center)
![在這里插入圖片描述](https://img-blog.csdnimg.cn/20201018202757561.png?x-oss-
process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDg3MTkwMw
,size_16,color_FFFFFF,t_70#pic_center)
![在這里插入圖片描述](https://img-blog.csdnimg.cn/20201018202807249.png?x-oss-
process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDg3MTkwMw==,size_16,color_FFFFFF,t_70#pic_center)
結果差別還是挺大的,所以還是要有一台配置好的電腦。
從大數據集跑出來的結果可以分析出以下幾個特點
圖(1)欺詐行為涉及的金額大——重要特點
圖(4)之前賬戶的余額與轉賬金額的關系——可能呈線性關系

  • 數據處理(數據清洗和數據合並)

(1)首先將數據集中不存在欺詐行為的類型去掉,保留存在欺詐的取款和轉賬兩種類型,然后重新設置索引

     #數據處理:包括數據清洗和樣本數據合並
    used_data=raw_data[(raw_data['type']=='TRANSFER') | (raw_data['type']=='CASH_OUT')]
    #去掉不用的數據
    used_data.drop(['step','nameOrig','nameDest','isFlaggedFraud'],axis=1,inplace=True)
    #重新設置索引
    used_data=used_data.reset_index(drop=True)

(2)將取款(CASH_OUT)和轉賬(DEBIT)兩種類型分別表示為“0”和“1”

    #將type轉換成類別數據,即0,1
    type_label_encoder=preprocessing.LabelEncoder()
    type_category=type_label_encoder.fit_transform(used_data['type'].values)
    used_data['typeCategory']=type_category
    
    #print(used_data.head())
    
    sns.heatmap(used_data.corr()) #使用PRT相關技術分析變量間的相關性

預覽前五行數據可以看到處理后的表格
在這里插入圖片描述
在輸出結果中,通過typeCategory這一列,我們可以看到兩種類型都已被編碼
相關程度圖如下,顏色越淺,相關度越高
![在這里插入圖片描述](https://img-blog.csdnimg.cn/20201018205504188.png?x-oss-
process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDg3MTkwMw==,size_16,color_FFFFFF,t_70#pic_center)
從圖中可以看出,轉帳前和轉賬后付款人和收款人的余額有很大的相關性,余額也跟轉賬金額有關系。

  • 查看轉賬和取款類型數量
    #查看轉賬類型記錄個數
    ax=used_data['type'].value_counts().plot(kind='bar',title="Transaction Type",figsize=(6,6))
    for p in ax.patches:
        ax.annotate(str(format(int(p.get_height()),',d')),(p.get_x(),p.get_height()*1.01))
    plt.show()

結果如下:
![在這里插入圖片描述](https://img-blog.csdnimg.cn/20201018210128533.png?x-oss-
process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDg3MTkwMw==,size_16,color_FFFFFF,t_70#pic_center)
從這個圖中可以看出取款類型多於轉賬類型
注意:繪制此圖時,建議把繪制相關性圖的那行代碼注釋掉,不然畫出來的兩個圖就混到一起了。

  • 查看正常行為與欺詐行為數量
    #查看轉賬類型中欺詐記錄個數
    ax1=pd.value_counts(used_data['isFraud'],sort=True).sort_index().plot(kind='bar',title="Fraud Transaction Count")
    for p in ax1.patches:
        ax1.annotate(str(format(int(p.get_height()),',d')),(p.get_x(),p.get_height()*1.01))
    plt.show()

結果如下
![在這里插入圖片描述](https://img-blog.csdnimg.cn/20201018210437348.png?x-oss-
process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDg3MTkwMw==,size_16,color_FFFFFF,t_70#pic_center)
從這張圖可以看出,正常行為遠遠多於欺詐行為。

  1. 數學模型的構建

(1)准備模型
由上面的分析可知,金融欺詐行為數量遠遠小於正常行為,為了構建模型,采用下采樣法取出與欺詐行為數量相等的正常行為,然后輸出比例驗證下采樣法。

    #准備模型
    feature_names=['amount','oldbalanceOrg','newbalanceOrig','oldbalanceDest','newbalanceDest','typeCategory']
    X=used_data[feature_names]
    y=used_data['isFraud']
    #print(X.head())      
    #print(y.head()) 
            
    
    #用下采樣法處理不平衡數據
    #欺詐記錄的條數
    number_records_fraud=len(used_data[used_data['isFraud']==1])
    #欺詐記錄的索引
    fraud_indices=used_data[used_data['isFraud']==1].index.values
    
    #得到非欺詐記錄的索引
    nonfraud_indices=used_data[used_data['isFraud']==0].index
    
    #隨即選取相同數量的非欺詐記錄
    random_nonfraud_indices=np.random.choice(nonfraud_indices,number_records_fraud,replace=False)
    random_nonfraud_indices=np.array(random_nonfraud_indices)
    
    #整合兩樣本的索引
    under_sample_indices=np.concatenate([fraud_indices,random_nonfraud_indices])
    under_sample_data=used_data.iloc[under_sample_indices,:]
    
    X_undersample=under_sample_data[feature_names].values
    y_undersample=under_sample_data['isFraud'].values
    
    print("非欺詐記錄比例:",len(under_sample_data[under_sample_data['isFraud']==0])/len(under_sample_data))
    print("欺詐記錄比例:",len(under_sample_data[under_sample_data['isFraud']==1])/len(under_sample_data))
    print("欠采樣記錄數:",len(under_sample_data))

比例輸出結果如下:
在這里插入圖片描述
從之前的統計中可以知道金融欺詐行為的數量為16,取出相同數量的正常行為16例,所以欠采樣記錄數為32

(2)模型構建
采用邏輯回歸模型,該模型主要用於分類問題,特別是分為0和1兩類的問題

    #數據建模
    from sklearn.model_selection import train_test_split
    from sklearn.linear_model import LogisticRegression
    from sklearn.metrics import roc_curve,auc
    
    #分割訓練集和測試集
    X_train,X_test,y_train,y_test=train_test_split(X_undersample,y_undersample,test_size=0.3,random_state=0)
    
    lr_model=LogisticRegression()
    lr_model.fit(X_train,y_train)
    
    y_pred_score=lr_model.predict_proba(X_test)
    
    fpr,tpr,thresholds=roc_curve(y_test,y_pred_score[:,1])
    roc_auc=auc(fpr,tpr)
    
    #繪制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])
    plt.ylabel('True Positive Rate')
    plt.xlabel('False Positive Rate')
    plt.show()

![在這里插入圖片描述](https://img-blog.csdnimg.cn/20201018212529981.png?x-oss-
process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDg3MTkwMw==,size_16,color_FFFFFF,t_70#pic_center)
ROC曲線的AUC越接近1,說明模型越好,在這兒AUC=0.78,說明模型還可以。

然后,項目就做完了。

備注:數據在kaggle里,鏈接:https://www.kaggle.com/ntnu-testimon/paysim1

在這里插入圖片描述


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM