Walkthrough: Categorizing Fraudulent Credit Card Transactions
By: Joe Cowell
Tags: Supervised Learning, Streamlit, Classification, Xgboost, Postgresql

Walkthrough: Categorizing Fraudulent Credit Card Transactions

Photo by Karolina Grabowska of Pexels.com

Intro:

As a student of the Metis Data Science Bootcamp, I chose to explore fraudulent card transactions for my second individual project. This project had three requirements: query data from a postgreSQL database with SQL, develop a classification model, and create an interactive visualization. I found the postgreSQL and interactive visualization components fairly straight forward, so the bulk of this post discusses the development of a usable model, however, I included some insights and tips for the other two components. Also, check out the Github Repository for all of the code behind the project.

Background:

After looking for some interesting data to analyze, I came across this competition on Kaggle. An e-commerce payment solutions company, Vesta Corporation, put together a few .csv files containing card transaction information, including the transaction amount, card type, browser of purchase, some other various basic information, and over 300 features that were engineered by the company but were left undefined in the data description. The target was contained in a column named “isFraud” and defined fraudulent transactions with a 1 and valid transactions with a 0. With the .csv files in hand, it was time to throw them into a postgreSQL database and turn this information into insights.

Before I dig in, I would like to lay out the project:

SQL Skills (postgreSQL, SQLAlchemy, Psycopg2)

Classification Modeling (Logistic Regression, XG Boost, Random Forest, and much more)

Interactive Visualization (Streamlit)

Step 1: Using postgreSQL 🗄

As I stated earlier, a requirement of this project was the use of SQL to query the data. Having the data in .csv files, I was able to turn them into DataFrames to throw into an SQL database.

The code is below and I’ll discuss what it all means. First, I read the .csv files into DataFrames and then created an engine to connect to the local postgreSQL database that I named ‘project3’. This SQLAlchemy engine is the key to this whole block of code. It allows the jupyter notebook to interact with postgreSQL and create tables in a given database. Also, these .csv files contain a variety of types (objects, ints, floats, etc.), and it’s amazing how SQLAlchemy can interpret the DataFrame and create columns with corresponding datatypes. Also, it makes this process a lot faster than using command line (the bigger .csv file has over 300 columns).

# First, turn those csv files into DataFrames. train_identity = pd.read_csv('../Project-3/train_identity.csv') train_transaction = pd.read_csv('../Project-3/train_transaction.csv') # Create a connection to the project3 postgreSQL database. engine = create_engine(‘postgresql://[USERNAME]:[PASSWORD]@localhost:5432/project3’) # Turn the DataFrames into tables in the postgreSQL database table_name = 'train_ident' train_identity.to_sql(table_name,

engine,

if_exists='replace',

index=False,

chunksize=500) table_name = 'train_trans' train_transaction.to_sql(table_name,

engine,

if_exists='replace',

index=False,

chunksize=500)

That’s the bulk of the SQL component of the project. I won’t touch any more on this, but I’ll just post the more complicated SQL query joining both tables to investigate the data further.

mastercard_full = pd.read_sql(

"""SELECT * FROM train_trans LEFT JOIN train_ident ON train_trans.”TransactionID” = train_ident.”TransactionID” WHERE train_trans.card4=’mastercard’""", con=engine)

Step 2: Classification Modeling 🎯

With the data successfully stored in a postgreSQL database and then queried into a DataFrame, I started with some basic EDA and quickly understood my main challenge: class imbalance.

Image by Author

The issue with class imbalance comes down to how one determines the success of the model. If I only cared about accuracy, I could predict all transactions as valid and have 97% accuracy. To the untrained eye, 97% accuracy looks very desirable, but this means the model predicts 0% of fraudulent transactions. This 0% metric is referred to as recall. Recall answers the question: of all the fraudulent transactions, what percentage were correctly predicted by the model? On the other hand, the recall for valid transactions would be 100%, since all of the valid transactions were correctly predicted as valid. Since it is understood that class imbalance is the issue, and the goal is to predict fraudulent transactions, the metric for success became recall for fraudulent transactions combined with overall accuracy.

So, how did I address the issue of class imbalance? There are a few ways to tackle class imbalance, but I chose to focus on oversampling. The three methods I explored were RandomOverSampler, SMOTE, and ADASYN. Each of these methods take the minority class and over-samples it until it is balanced with the majority class. RandomOverSampler randomly duplicates data points in the minority class. Synthetic Minority Oversampling Technique (SMOTE) creates new points in the minority class, but with linear interpolations and the use of K-nearest neighbors, so it is a more advanced oversampling technique. Lastly, Adaptive Synthetic Sampling (ADASYN) creates new points in the minority class according to their density distributions.

In regards to the code, it is very simple to implement these oversampling techniques as shown below. It is important to note that the training data is oversampled, which is then used to fit a model, resulting in a better model overall.

# RandomOverSampler

ros = RandomOverSampler(random_state=0)

X_tr_sam, y_tr_sam = ros.fit_sample(X_train,y_train) # SMOTE

X_smoted, y_smoted = SMOTE(random_state=42).fit_sample(X_train,y_train) # ADASYN

X_adasyn, y_adasyn = ADASYN(random_state=42).fit_sample(X_train,y_train)

Another common metric for evaluating binary classification problems is the ROC curve and the area under that curve (AUC). Below are three ROC curves corresponding to the different methods of overfitting and a few classifier models I wanted to test. It’s fairly obvious that Random Forest and XG Boost are the best models, also, they are ensemble models, which speaks to the superior quality of ensembling models together to create a better model as a whole.