It is common for data to come without being labeled with examples of fraud. In such situations, the analyst will identify potential instances of fraud. In this post, we will learn how to overcome this problem using unsupervised learning.
The main strategy for addressing unlabeled data is to cluster the data using kmeans or another clustering algorithm. Once the clusters are developed, you will then find outliers that do not fit inside any of the clusters. Even at this point, you have suspected instances of fraud, and it is now necessary to have an expert examine the individual cases
Load Libraries
We begin by loading the needed libraries and looking at them
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# Import the scaler
from sklearn.preprocessing import MinMaxScaler
df = pd.read_csv("C:/Users/dthom/Documents/python/fraud/chapter_3/chapter_3/banksim_adj.csv")
Pandas and numpy are needed to manipulate the data. We will use matplotlib to make visuals. The MinMaxScaler will be for scaling the data before creating our clusters. Below is some of the columns from the data.
print(df.head())
Unnamed: 0 age amount fraud M es_barsandrestaurants es_contents \
0 0 3 49.71 0 0 0 0
1 1 4 39.29 0 0 0 0
2 2 3 18.76 0 0 0 0
3 3 4 13.95 0 1 0 0
4 4 2 49.87 0 1 0 0
There are many more columns than this, as this is just a peak.
Scale the Data
As you examine the data, you can see that the scaling differs for each variable. The kmeans algorithm is sensitive to scaling, so we must ensure that the scaling is the same for all variables. In the code below, we convert the data to float values and then scale the data
# Take the float values of df for X
X = df.values.astype(float)
# Define the scaler and apply to the data
scaler = MinMaxScaler()
X_scaled = scaler.fit_transform(X)
Below is what the data looks like now.
X_scaled
array([[0.00000000e+00, 5.00000000e-01, 2.06810025e-01, ...,
0.00000000e+00, 1.00000000e+00, 0.00000000e+00],
[1.38908182e-04, 6.66666667e-01, 1.62478579e-01, ...,
0.00000000e+00, 0.00000000e+00, 0.00000000e+00],
[2.77816363e-04, 5.00000000e-01, 7.51345685e-02, ...,
0.00000000e+00, 1.00000000e+00, 0.00000000e+00],
...,
[9.99722184e-01, 1.66666667e-01, 1.00000000e+00, ...,
0.00000000e+00, 0.00000000e+00, 1.00000000e+00],
[9.99861092e-01, 1.66666667e-01, 1.00000000e+00, ...,
0.00000000e+00, 0.00000000e+00, 0.00000000e+00],
[1.00000000e+00, 6.66666667e-01, 1.00000000e+00, ...,
0.00000000e+00, 0.00000000e+00, 0.00000000e+00]])
The data looks much different, but the columns are still present. The main differences are that the values are scaled appropriately so that no variable has too much influence compared to the others.
Determine Number of Clusters
The next step is to determine the number of clusters. We will need the KMeans algorithm and the cdist() function to obtain the values for the elbow plot. Since we don’t know how many clusters we will set K for, anywhere from 1 to 10 clusters
# Import MiniBatchKmeans
from sklearn.cluster import KMeans
from scipy.spatial.distance import cdist
# Define the model
distortions = []
K = range(1,10)
for k in K:
kmeanModel = KMeans(n_clusters=k).fit(df)
distortions.append(sum(np.min(cdist(df, kmeanModel.cluster_centers_, 'euclidean'), axis=1)) / df.shape[0])
plt.plot(K, distortions, 'bx-')
plt.xlabel('k')
plt.ylabel('Distortion')
plt.title('The Elbow Method showing the optimal k')
plt.show()
in the code above, we create a for loop to calculate the number of clusters from 1 to 10. For each of these clustering combinations, we calculate the Euclidean distance for each centroid. We then plot this in the plot below. We are looking for the elbow in the plot at which the reduction in distortion drops significantly, which indicates that adding more clusters is no longer beneficial.

In the plot above, the elbow appears at k = 3. This indicates that we need 3 clusters for a fraud analysis.
KMeans and Groups
We can now explore our data by first fitting our 3 clusters to our data and creating a column called ‘predict’. With this new column, we can calculate group means and understand the characteristics of each group.
km=KMeans(3,init='k-means++',random_state=3425)
km.fit(df.values)
df['predict']=km.predict(df.values)
print(df.groupby('predict').amount.mean())
print(df.groupby('predict').age.mean())
print(df.groupby('predict').es_travel.mean())
predict
0 45.853826
1 32.604894
2 32.477959
Name: amount, dtype: float64
predict
0 2.982471
1 3.007503
2 2.979114
Name: age, dtype: float64
predict
0 0.007513
1 0.000000
2 0.000000
Name: es_travel, dtype: float64
The values for the amount spent are higher for group 0 compared to groups 1 and 2. The ages of each group are about the same as are the values for es_travel. This is a cursory analysis, and many more values and even visualizations could be developed.
Plot of Groups
In the example below, we examine the age, amount, and cluster simultaneously. The goal here is to see if any patterns emerge.
clust_map={0:'group 1',1:'group 2',2:'group 3'}
df['perf']=df.predict.map(clust_map)
d_color={'group 1':'y','group 2':'r','group 3':'g'}
fig, ax=plt.subplots()
for clust in clust_map.values():
colored=d_color[clust]
df[df.perf==clust].plot(kind='scatter',x='amount',y='age',label=clust, ax=ax, color=colored)
plt.show()
In the code, we assign each cluster a name (i.e., “group 1”) and a color (i.e., “yellow”). We then create a for loop that plots all the values on a scatterplot as shown below.

It appears that group 3 has the bulk of the lower valued amounts. Group 2 has a lot of mid-level amounts with some extreme values, while group 1 has a large number of extreme values.
Conclusion
The next step in this process is to determine which examples do not fit within any of these three clusters. The outliers could be examples of fraud.




























































