<jupyter_start><jupyter_text>Downloading Data<jupyter_code>%%shell
wget https://bitbucket.org/!api/2.0/snippets/singhsidhukuldeep/rXXG7o/7e66099bfc00fdb8141b9b31d32989fbfa2a74c9/files/transactions.csv.zip
unzip -o transactions.csv.zip
mv transactions.csv.zip transactions.csv
head -3 transactions.csv<jupyter_output>--2021-09-26 14:14:17--  https://bitbucket.org/!api/2.0/snippets/singhsidhukuldeep/rXXG7o/7e66099bfc00fdb8141b9b31d32989fbfa2a74c9/files/transactions.csv.zip
Resolving bitbucket.org (bitbucket.org)... 172.16.58.3, fd00:c2b6:b24b:be67:2827:688d:e6a1:6a3b:513, fd00:a516:7c1b:17cd:6d81:2137:bd2a:2c5b:ea4a, ...
Connecting to bitbucket.org (bitbucket.org)|172.16.58.3|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 183597220 (175M) [application/zip]
Saving to: ‘transactions.csv.zip’

transactions.csv.zi 100%[===================>] 175.09M  55.5MB/s    in 3.6s    

2021-09-26 14:14:27 (48.9 MB/s) - ‘transactions.csv.zip’ saved [183597220/183597220]

Archive:  transactions.csv.zip
  inflating: transactions.csv.zip    
step,type,amount,nameOrig,oldbalanceOrig,newbalanceOrig,nameDest,oldbalanceDest,newbalanceDest,isFraud
1,PAYMENT,9839.64,C1231006815,170136.0,160296.36,M1979787155,0.0,0.0,0
1,PAYMENT,1864.28,C1666544295,21249.0,19384.72,M2044282225,0.0,0.0,0<jupyter_text>Importing modules<jupyter_code>import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from xgboost.sklearn import XGBClassifier
import seaborn as sb

from tqdm.auto import tqdm
tqdm.pandas()

!pip install -q pandarallel
from pandarallel import pandarallel
pandarallel.initialize(progress_bar=True)

data_file_loc = 'transactions.csv'
debug = False
debug_size=0.1
test_train_size=0.3<jupyter_output>Building wheel for pandarallel (setup.py) ... [?25l[?25hdone
INFO: Pandarallel will run on 2 workers.
INFO: Pandarallel will use Memory file system to transfer data between the main process and workers.<jupyter_text>Opening dataset<jupyter_code>df = pd.read_csv(data_file_loc)
if debug:
    print(f'>> Before debug {df.shape}')
    df,_ = train_test_split(df, stratify=df.isFraud, train_size=debug_size)
    df.reset_index(drop=True, inplace=True)
    print(f'>> After debug {df.shape}')
df.head()<jupyter_output><empty_output><jupyter_text>Exploratory Data Analysis<jupyter_code># Null values and Duplicates check
df.isnull().values.any(), df.duplicated(df.columns[:-1]).values.any()
# Im-balance check
df.isFraud.value_counts(), df.isFraud.value_counts()*100/len(df), (df.isFraud.value_counts()*100/len(df)).plot.bar()
# value ditribution for fraud
fig, axes = plt.subplots(nrows=4,ncols=2,figsize=(12,6))
for i,label in enumerate([0,1]):
    temp=df[df.isFraud==label]
    temp ['diffrence'] = temp.amount-temp.oldbalanceOrig
    for j,col in enumerate(['amount','newbalanceOrig','oldbalanceOrig','diffrence']):
        temp[col].plot.hist(ax = axes[j,i],subplots=True)
        plt.setp(axes[j,i], ylabel=f'{label}>{col}')
# type distribution
df[['isFraud','type']].value_counts(), df[['isFraud','type']].value_counts().plot.bar()
# are the frauds doing more transactions
print(df[df['isFraud']==1].duplicated('nameOrig').values.any(), df[df['isFraud']==1].duplicated('nameDest').values.any())
# are not frauds doing more transactions
print(df[df['isFraud']==0].duplicated('nameOrig').values.any(), df[df['isFraud']==0].duplicated('nameDest').values.any())
# checking if sequence occurs enough number of times to create a feature out of it
print(df.duplicated(['step','nameOrig', 'nameDest']).values.any(), df.duplicated(['amount','nameOrig', 'nameDest']).values.any(),)
print(df.duplicated(['nameOrig', 'nameDest']).values.any())
print(df.duplicated(['step','nameOrig']).values.any(), df.duplicated(['step','nameDest']).values.any())
print(df.duplicated(['amount','nameOrig']).values.any(), df.duplicated(['amount','nameDest']).values.any(), df.duplicated(['step','amount','nameDest']).values.any())
print(df.duplicated(['isFraud','step','nameOrig']).values.any(), df.duplicated(['isFraud','step','nameDest']).values.any(),df.duplicated(['isFraud','amount','nameDest']).values.any())
# checking flow of money
df['debit']=df.oldbalanceOrig - df.newbalanceOrig
df['credit']=df.newbalanceDest - df.oldbalanceDest
df['bal0Orig']=df.parallel_apply(lambda x: x.oldbalanceOrig==0 and x.newbalanceOrig==0, axis=1)
df['bal0Dest']=df.parallel_apply(lambda x: x.oldbalanceDest==0 and x.newbalanceDest==0, axis=1)
df['credit_error']=df.credit-df.amount
df['debit_error']=df.debit-df.amount
df=df.round(2)
df
grouped_temp = df[['step','amount','nameDest']].value_counts().to_dict()
df['step_amnt_nDst_cnt']=df.progress_apply(lambda x: grouped_temp[(x.step,x.amount,x.nameDest)], axis=1)
corr = df.corr()
sb.heatmap(corr, cmap="Blues", annot=True).set_title('Heat Map')
corr = df[df['isFraud']==1].corr()
sb.heatmap(corr, cmap="Blues", annot=True).set_title('Fraud')
corr = df[df['isFraud']==0].corr()
sb.heatmap(corr, cmap="Blues", annot=True).set_title('Not Fraud')<jupyter_output><empty_output><jupyter_text>Processing<jupyter_code>df = df[df['type'].isin(['CASH_OUT', 'TRANSFER'])]
df['type_encoded']=df.progress_apply(lambda x: 1 if x.type=='CASH_OUT' else 0, axis=1)
X = df[[_ for _ in list(df.columns) if _ not in ['isFraud','nameOrig','nameDest','type']]]
Y = df['isFraud']
trainX, testX, trainY, testY = train_test_split(X, Y, stratify=Y, train_size=test_train_size)<jupyter_output><empty_output><jupyter_text>Training<jupyter_code>%%time
clf = XGBClassifier(
    max_depth = 3, 
    scale_pos_weight = trainY.count()/trainY.sum(), 
    n_jobs = 4)
model = clf.fit(trainX, trainY)<jupyter_output>CPU times: user 2min 19s, sys: 360 ms, total: 2min 19s
Wall time: 1min 13s<jupyter_text>Testing<jupyter_code>testX.columns
print(classification_report(testY, model.predict(testX)))<jupyter_output>precision    recall  f1-score   support

           0       1.00      1.00      1.00   1930229
           1       1.00      0.99      1.00      5402

    accuracy                           1.00   1935631
   macro avg       1.00      1.00      1.00   1935631
weighted avg       1.00      1.00      1.00   1935631<jupyter_text>Predictions<jupyter_code>def transform(step, 
              type, 
              amount, 
              nameOrig, 
              oldbalanceOrig, 
              newbalanceOrig, 
              nameDest, 
              oldbalanceDest, 
              newbalanceDest):
    return [
            {
                'step':step,
                'amount':amount,
                'oldbalanceOrig':oldbalanceOrig,
                'newbalanceOrig':newbalanceOrig,
                'oldbalanceDest':oldbalanceDest,
                'newbalanceDest':newbalanceDest,
                'debit':oldbalanceOrig - newbalanceOrig,
                'credit':newbalanceDest - oldbalanceDest,
                'bal0Orig':oldbalanceOrig==newbalanceOrig==0,
                'bal0Dest':oldbalanceDest==newbalanceDest==0,
                'credit_error':newbalanceDest - oldbalanceDest-amount,
                'debit_error':oldbalanceOrig - newbalanceOrig-amount,
                'step_amnt_nDst_cnt':0, # ['step','amount','nameDest'] count
                'type_encoded':1 if type=='CASH_OUT' else 0, #only ['CASH_OUT', 'TRANSFER']
            }
            ]
inp=transform(step=1, 
              type="PAYMENT", 
              amount=9839.64, 
              nameOrig="C1231006815", 
              oldbalanceOrig=170136.0, 
              newbalanceOrig=160296.36, 
              nameDest="M1979787155", 
              oldbalanceDest=0, 
              newbalanceDest=0)
model.predict(pd.DataFrame(inp)),model.predict_proba(pd.DataFrame(inp))<jupyter_output><empty_output><jupyter_text>Model Visulisation<jupyter_code>from xgboost import plot_importance
plot_importance(model)
from xgboost import to_graphviz
to_graphviz(model)
import pickle
file_name = "xgb_v1.pkl"

# save
pickle.dump(model, open(file_name, "wb"))

# load
model_loaded = pickle.load(open(file_name, "rb"))
model_loaded.predict(pd.DataFrame(inp)),model.predict_proba(pd.DataFrame(inp))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.15404317599707282, 'fraction_numerical': 0.05695816562995487, 'mean_word_length': 4.514458641560188, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 39, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '315828', 'license': 'MIT', 'n_tokens_mistral': 3295, 'n_tokens_neox': 2975, 'n_words': 441, 'path': 'Financial_Payment_Services_Fraud_Prediction.ipynb', 'repo_name': 'singhsidhukuldeep/Fraud-Prediction', 'size': '8165'}