#!/usr/bin/env python # coding: utf-8 # In[1]: from datetime import datetime print(f'Päivitetty {datetime.now()}') # # Luottokorttipetokset # # Data löytyy lähteestä: https://www.kaggle.com/mlg-ulb/creditcardfraud # # Datassa ei ole alkuperäisiä selittäviä muuttujia, vaan niistä pääkomponenttianalyysilla muodostetut uudet muuttujat (sekä tietosuojan että tilastotieteellisten syiden takia). **Class**-muuttuja on kohdemuuttuja (0 = 'ei petos', 1 = 'petos'). # # Petoksia on vähän suhteessa kaikkiin luottokorttitapahtumiin. Tämän vuoksi data on syytä tasapainottaa. Käytän tasapainottamiseen imbalanced-learn-kirjastoa, joka ei ole Anacondassa valmiiksi asennettuna. Sen voi asentaa komentoriviltä (Anaconda prompt) komennolla: # # `conda install -c conda-forge imbalanced-learn` # In[2]: import pandas as pd import matplotlib.pyplot as plt import seaborn as sns # train_test_split osaa jakaa datan opetusdataan ja testidataan from sklearn.model_selection import train_test_split # Datan tasapainottamiseen from imblearn.over_sampling import RandomOverSampler from imblearn.under_sampling import RandomUnderSampler # Kokeiltavat mallit from sklearn.linear_model import LogisticRegression from sklearn.tree import DecisionTreeClassifier, plot_tree from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier # Sekaannusmatriisin näyttämiseen from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay # ## Datan tarkastelua # In[3]: # Data on sen verran iso, että suosittelen sen lataamista # omalle koneelle ennen avaamista! df = pd.read_csv('https://taanila.fi/creditcard.csv') df.info() # In[4]: # Kohdemuuttujan jakauma df['Class'].value_counts() # Kohdemuuttujan jakauma on epätasapainoinen. # ## Tasapainotus ja mallien sovittaminen # In[5]: # Selittävät muuttujat X = df.drop('Class', axis=1) # Kohdemuuttuja y = df['Class'] # Jako opetus- ja testidataan X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=2) # Data on iso, jos tasapainotetaan kasvattamalla pienempää ryhmää isomman kokoiseksi (**RandomOverSampler**). Tämän seurauksena mallin sovittaminen kestää niin kauan että välillä ehtii kahville. # # Nopeampi ratkaisu on tasapainottaa pienentämällä isompaa ryhmää (**RandomUnderSampler**), mutta tällä ei päästä yhtä hyviin malleihin. # In[6]: # Tasapainotus ja mallien sovitus # RandomOverSampler kasvattaa satunnaisotoksilla pienempää ryhmää # Voit myös kokeilla RandomUnderSampler, joka toimii nopeammin rs = RandomOverSampler(random_state=2) X_train, y_train = rs.fit_resample(X_train, y_train) lrc = LogisticRegression() lrc.fit(X_train, y_train) dtc = DecisionTreeClassifier(max_depth=3, random_state=2) dtc.fit(X_train, y_train) rfc = RandomForestClassifier(max_depth=4, random_state=2) rfc.fit(X_train, y_train) gbc = GradientBoostingClassifier(max_depth=2, random_state=2) gbc.fit(X_train, y_train) # ## Mallien arviointia # In[7]: # Oikeaan osuneiden ennusteiden osuus opetusdatassa print('Ennusteiden tarkkuus opetusdatassa:') print(f'Logistinen regressio {lrc.score(X_train, y_train):.3f}') print(f'Päätöspuu {dtc.score(X_train, y_train):.3f}') print(f'Satunnaismetsä {rfc.score(X_train, y_train):.3f}') print(f'Gradienttitehostus {gbc.score(X_train, y_train):.3f}') # In[8]: # Oikeaan osuneiden ennusteiden osuus testidatassa print(f'Logistinen regressio {lrc.score(X_test, y_test):.3f}') print(f'Päätöspuu {dtc.score(X_test, y_test):.3f}') print(f'Satunnaismetsä {rfc.score(X_test, y_test):.3f}') print(f'Gradienttitehostus {gbc.score(X_test, y_test):.3f}') # In[9]: # Mallien antamat ennusteet testidatalle y_test_lrc = lrc.predict(X_test) y_test_dtc = dtc.predict(X_test) y_test_rfc = rfc.predict(X_test) y_test_gbc = gbc.predict(X_test) # In[10]: cm = confusion_matrix(y_test, y_test_lrc) ConfusionMatrixDisplay(confusion_matrix=cm).plot() # Logistinen regressio tunnistaa parhaiten petoksia, mutta ennustaa paljon ok-tapahtumia petoksiksi. # In[11]: cm = confusion_matrix(y_test, y_test_dtc) ConfusionMatrixDisplay(confusion_matrix=cm).plot() # In[12]: cm = confusion_matrix(y_test, y_test_rfc) ConfusionMatrixDisplay(confusion_matrix=cm).plot() # Satunnaismetsä erehtyy vähiten ok-tapahtumissa, mutta tunnistaa huonoiten petoksia. # In[13]: cm = confusion_matrix(y_test, y_test_gbc) ConfusionMatrixDisplay(confusion_matrix=cm).plot() # Gradienttitehostus on hyvä kompromissi väärien negatiivisten ja väärien positiivisten väliltä. # In[14]: # Päätöspuumallin voin havainnollistaa kaaviona plt.figure(figsize=(10, 6)) plot_tree(decision_tree=dtc, feature_names=X.columns)