# This Python 3 environment comes with many helpful analytics libraries installed
# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python
# For example, here's several helpful packages to load

import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)

# Input data files are available in the read-only "../input/" directory
# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory

import os
for dirname, _, filenames in os.walk('/kaggle/input'):
    for filename in filenames:
        print(os.path.join(dirname, filename))

# You can write up to 5GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using "Save & Run All" 
# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session
"""
## Importing the Required Libraries
"""
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from scipy.stats import zscore
from collections import Counter
"""
## Reading the Data
"""
df = pd.read_csv('../input/creditcardfraud/creditcard.csv')

"""
## First 3 Rows of the Dataset
"""
df.head(3)
"""
## The Total Distribution of the classes 
"""
sns.countplot(df['Class'])

"""
## Dividing the data into X and Y
"""
x = df.drop(columns = ['Class'])
y = df.Class
# Shape of the x and y
print(x.shape,y.shape)

"""
## Checking for the Null values
"""
x.info()

"""
## Normalizing the two column
"""
x['Amount'] = zscore(x['Amount'])
x['Time']= zscore(x['Time'])
"""
## Scatter plot for the data classes
"""
plt.figure(figsize=(12,6))
sns.lmplot(x = 'Time',y='Amount',hue = 'Class',data = df,fit_reg=False)
"""
### Imbalanced classification involves developing predictive models on classification datasets that have a severe class imbalance. 
### For This Problem we will use imblearn library for handling the imbalance in the dataset. 
### There are 3 Techniques that we can use 
     1. Under sampling
     2. Over Sampling
     3. SMOTE
     
 
"""
from imblearn.under_sampling import NearMiss
"""
### In the random under-sampling, the majority class instances are removed at random until a  balanced data is reached.
"""
nm = NearMiss()
x_bal,y_bal = nm.fit_sample(x,y)

print("x :-",x_bal.shape,"y :-",y_bal.shape)
"""
### Data Distributon after performing Under Sampling
"""
frame = [x_bal,y_bal]
df_under = pd.concat(frame,axis=1)
sns.lmplot(x = 'Time', y = 'Amount',hue = 'Class',fit_reg=False,data = df_under)
"""
### Using Logestic Regression To perform classification task
"""
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score,classification_report,confusion_matrix
"""
### Dividing the Data into test and train
"""
xtrain,xtest,ytrain,ytest =train_test_split(x_bal,y_bal,test_size = 0.2,random_state = 42)
lr = LogisticRegression()
lr.fit(xtrain,ytrain)
yp = lr.predict(xtest)
"""
### Testing Our accuracy 
"""
accuracy_score(ytest,yp)
"""
### Heatmap of confusion matrix
"""
sns.heatmap(confusion_matrix(ytest,yp,labels=[0,1]),annot=True)
"""
### the random oversampling is making the copies of the minority class but this may result in overfitting
"""
from imblearn.over_sampling import RandomOverSampler
os = RandomOverSampler(random_state=42)
x_bal,y_bal = os.fit_sample(x,y)
"""
### Data Distributon after performing OverSampling
"""
frame = [x_bal,y_bal]
df_under = pd.concat(frame,axis=1)
sns.lmplot(x = 'Time', y = 'Amount',hue = 'Class',fit_reg=False,data = df_under)
x_bal.shape,y_bal.shape

"""
### Using Logestic Regression To perform classification task
"""
xttrain,xtest,ytrain,ytest = train_test_split(x_bal,y_bal,test_size = 0.2,random_state = 42)
lr.fit(xttrain,ytrain)
y_pred = lr.predict(xtest)
accuracy_score(ytest,y_pred)

sns.heatmap(confusion_matrix(ytest,y_pred,labels=[0,1]),annot=True)
"""
### classification report after performing the classification task
"""
print(classification_report(ytest,y_pred))
from imblearn.combine import SMOTETomek
"""
### Synthetic Minority Oversampling Technique(SMOTE) it works by selecting a minority class instance "a" at random and finds its k nearest minority class neighbors
"""
smk = SMOTETomek(random_state=42)
x_smk,y_smk = smk.fit_sample(x,y)
"""
### Data distrubution after performing the SMOTE technque
"""
frame = [x_smk,y_smk]
df_under = pd.concat(frame,axis=1)
sns.lmplot(x = 'Time', y = 'Amount',hue = 'Class',fit_reg=False,data = df_under)
x_smk.shape,y_smk.shape
"""
### Using Logestic Regression To perform classification task
"""
xttrain,xtest,ytrain,ytest = train_test_split(x_smk,y_smk,test_size = 0.2,random_state = 42)
lr.fit(xttrain,ytrain)
ypred = lr.predict(xtest)
accuracy_score(ytest,ypred)
sns.heatmap(confusion_matrix(ytest,ypred,labels=[0,1]),annot=True)
"""
### classification report after performing the classification
"""
print(classification_report(ytest,ypred))