Inleiding tot Scikit-learn: classificatie van giftige paddenstoelen en glas soorten

Gepubliceerd op:
Leer hoe je giftige paddenstoelen en soorten glas kunt classificeren met Scikit-learn in Python. Deze tutorial behandelt **data-preprocessing**, **modeltraining** en **evaluatie**.

Inleiding

We gebruiken twee bekende datasets uit de machine learning wereld in deze handleiding, namelijk de champignon dataset en de glas dataset. Deze datasets zijn ook populair in oefeningen voor studenten die met deep learning bezig zijn. De glas dataset bevat zes soorten glas, die worden geïdentificeerd door het type mineralen in hun samenstelling, zoals Fe, K, en Na. De data is numeriek, wat betekent dat het alleen getallen bevat. Dit maakt het makkelijker om mee te werken, vooral met pakketten zoals numpy die alleen getallen verwerken. De champignon dataset bevat informatie over eetbare en giftige paddenstoelen. Het bevat ook niet-numerieke waarden. Daarom zullen we de informatie eerst coderen voordat we met de data aan de slag gaan. Je kunt de data downloaden via de onderstaande links. Bewaar de datasets door met de rechtermuisknop te klikken en 'Opslaan als' te selecteren: - glass.csv - mushrooms.csv Deze data komt oorspronkelijk van de Machine Learning Repository van de University of California Irvine (hier en hier).

Classificeren van de glasgegevens

Voordat we naar de paddenstoelendata gaan, laten we eerst de eenvoudiger glasdataset onderzoeken. We laden deze dataset in Python met behulp van de pandas package, die het meest gebruikt wordt voor data-analyse in Python. Voordat we de data gaan classificeren, gebruiken we pandas om de data in de juiste vorm te krijgen.

Zorg ervoor dat je de benodigde Python-pakketten hebt geïnstalleerd. Doe dat in je terminal met:

pip install pandas
pip install numpy
pip install matplotlib
pip install seaborn
pip install sklearn

Importeer dan deze en de scikit-learn bibliotheken (geïmporteerd als 'sklearn') in een Python-bestand met de volgende code:

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import time
 
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler, LabelEncoder
 
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.neighbors import KNeighborsClassifier
from sklearn import tree
from sklearn.neural_network import MLPClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.gaussian_process.kernels import RBF
from sklearn.ensemble import RandomForestClassifier
from sklearn.naive_bayes import GaussianNB

Enkele dingen om op te merken over de imports:

  • De StandardScaler van sklearn is ontworpen voor het normaliseren en standaardiseren van datasets.
  • De LabelEncoder wordt gebruikt om categorische eigenschappen in de paddenstoelendataset om te zetten naar numerieke waarden.
  • Voor visualisatie, om grafieken te tekenen, gebruiken we de Seaborn bibliotheek, die is gebaseerd op matplotlib.
  • De andere bibliotheken worden gebruikt om de dataset te classificeren.

Tijdens het werken met datasets is het belangrijk om stil te staan bij vragen over de datakwaliteit en inhoud, zoals:

  • Bevat onze dataset numerieke, categorische, geografische of andere soorten data?
  • Is onze dataset compleet, of mist er data?
  • Is er dubbele data in onze dataset?
  • Zijn er grote verschillen tussen de waarden van de eigenschappen? Zo ja, dan moeten we mogelijk de dataset normaliseren.

Laten we de dataset laden.

filename_glass = './data/glass.csv'
df_glass = pd.read_csv(filename_glass)
 
print(df_glass.shape)
display(df_glass.head())
display(df_glass.describe())

Zoals je ziet, bestaat de data uit 10 kolommen en 214 rijen. Ze bevatten allemaal numerieke data. Er is ook geen ontbrekende informatie om ons zorgen over te maken, en de waarden van de eigenschappen zijn van dezelfde orde van grootte.

We hoeven voorlopig dus geen tijd te besteden aan het voorbewerken van de dataset.

De describe() methode van de pandas bibliotheek geeft ons een snel overzicht van de dataset, met name de volgende informatie:

  • Het aantal rijen in de dataset
  • Beschrijvende statistieken zoals het gemiddelde, standaarddeviatie, maximale en minimale waarden

Classificeren en valideren van de data

Laten we beginnen met het bouwen en trainen van de daadwerkelijke classifier, die ons in staat stelt om te classificeren en het type glas van elke invoer in de dataset te achterhalen.

De eerste stap is om de dataset te verdelen in twee afzonderlijke sets: de trainingsets en testsets. De trainingset wordt gebruikt om de classifier te trainen, terwijl de testset wordt gebruikt om te controleren hoe nauwkeurig de classifier is. Conventioneel wordt een verhouding van 70% - 30% gebruikt bij het splitsen van de dataset.

Het is belangrijk om de verdeling van verschillende klassen in zowel de trainings- als de testdatasets te controleren. De twee sets moeten dezelfde klasseverdeling bevatten, anders worden de resultaten vervormd. Om ervoor te zorgen dat dit het geval is, wordt de originele dataset willekeurig gesplitst:

def get_train_test(df, y_col, x_cols, ratio):
    mask = np.random.rand(len(df))  ratio
    df_train = df[mask]
    df_test = df[~mask]
       
    Y_train = df_train[y_col].values
    X_train = df_train[x_cols].values
    Y_test = df_test[y_col].values
    X_test = df_test[x_cols].values
    return df_train, df_test, X_train, Y_train, X_test, Y_test
 
y_col_glass = 'typeglass'
x_cols_glass = list(df_glass.columns.values)
x_cols_glass.remove(y_col_glass)
 
train_test_ratio = 0.7
df_train, df_test, X_train, Y_train, X_test, Y_test = get_train_test(df_glass, y_col_glass, x_cols_glass, train_test_ratio)

Nu de dataset is gesplitst in trainings- en testsets, kunnen we het classificatiemodel maken. We hebben geen logica van tevoren om te bepalen welk type classifier het best presteert op deze specifieke dataset. We weten bijvoorbeeld niet of een 'functionele aanpak' als Logistic Regression het beste is, of dat we beter Gradient Boosting of een Random Forest kunnen gebruiken.

Een van de voordelen van sklearn is dat je al deze classifiers tegelijkertijd kunt testen. We voegen elk van hen in en optimaliseren ze om te zien welke best presteert. Dit doen we door een woordenboek te maken dat alle gewenste classifiers bevat, waarbij hun namen als sleutels en instanties van de classifiers als waarden worden gebruikt.

dict_classifiers = {
    "Logistic Regression": LogisticRegression(),
    "Nearest Neighbors": KNeighborsClassifier(),
    "Linear SVM": SVC(),
    "Gradient Boosting Classifier": GradientBoostingClassifier(n_estimators=1000),
    "Decision Tree": tree.DecisionTreeClassifier(),
    "Random Forest": RandomForestClassifier(n_estimators=1000),
    "Neural Net": MLPClassifier(alpha = 1),
    "Naive Bayes": GaussianNB(),
    #"AdaBoost": AdaBoostClassifier(),
    #"QDA": QuadraticDiscriminantAnalysis(),
    #"Gaussian Process": GaussianProcessClassifier()
}

Nu itereren we over elk item in het woordenboek en doen we het volgende:

  • Gebruik .fit(X_train, Y_train) om de classifier te trainen.
  • Bekijk hoe een bepaalde classifier het doet op de trainingset met .score(X_train, Y_train).
  • Doe hetzelfde voor de testset met .score(X_test, Y_test).
  • Sla onze getrainde modellen op, samen met bijbehorende trainings- en testscores en de traintijden, in een nieuw woordenboek. Je kunt de pickle module gebruiken om het woordenboek op te slaan als een speciaal Python-object op de schijf.

Laten we de functie definiëren die dit doet, waarbij hij de train- en testsets neemt als X- en Y-matrices. Hij past ze toe op alle classifiers die gespecificeerd zijn in het dict_classifier hierboven. De getrainde modellen en bijbehorende nauwkeurigheden worden opgeslagen in een woordenboek.

  • Opmerking: de SVM, Random Forest en Gradient Boosting classifiers nemen meestal wat meer tijd in beslag bij het trainen. Daarom is het bij grote datasets het beste om ze eerst op een kleinere steekproef te trainen en vervolgens te beslissen of je ze opneemt, gebaseerd op de nauwkeurigheid die ze leveren.
def batch_classify(X_train, Y_train, X_test, Y_test, n_classifiers = 5, verbose = True):
    
    dict_models = {}
    for classifier_name, classifier in list(dict_classifiers.items())[:n_classifiers]:
        classifier.fit(X_train, Y_train)
        
        train_score = classifier.score(X_train, Y_train)
        test_score = classifier.score(X_test, Y_test)
        
        dict_models[classifier_name] = {'model': classifier, 'train_score': train_score, 'test_score': test_score}
        print("trained {c} in {f:.2f} s".format(c=classifier_name, f=t_diff))
    return dict_models
 
 
 
def display_dict_models(dict_models, sort_by='test_score'):
    clskeys = [key for key in dict_models.keys()]
    test_score = [dict_models[key]['test_score'] for key in clskeys]
    training_score = [dict_models[key]['train_score'] for key in clskeys]
    
    df2 = pd.DataFrame(data=np.zeros(shape=(len(clskeys),4)), columns = ['classifier', 'train_score', 'test_score', 'train_time'])
    for ii in range(0,len(clskeys)):
        df2.loc[ii, 'classifier'] = clskeys[ii]
        df2.loc[ii, 'train_score'] = training_score[ii]
        df2.loc[ii, 'test_score'] = test_score[ii]
    
   df2.sort_values(by=sort_by, ascending=False)

De score() methode in de code hierboven geeft de nauwkeurigheid terug. Deze nauwkeurigheid wordt gemeten met de accuracy_score() functie die deel is van de metrics module. Deze module bevat veel handige functies om classificatie- en regressiemodellen te evalueren.

Om precisie - de f1-score en de recall van de klassen in de dataset - te berekenen, wordt de classification_report functie gebruikt. Deze informatie is erg belangrijk als je de nauwkeurigheid van een classifier wilt verbeteren, of als je wilt nagaan of je de verwachte resultaten in termen van nauwkeurigheid krijgt.

De nauwkeurigheid op de trainingset en testset wordt ook opgeslagen: de display_dict_models() methode kan gebruikt worden om de resultaten te inspecteren en ze te ordenen op score/nauwkeurigheid.

dict_models = batch_classify(X_train, Y_train, X_test, Y_test, n_classifiers = 8)
display_dict_models(dict_models)

Het ziet er misschien niet zo mooi uit van een Python-perspectief, maar dit is een handige manier om met meer dan één classifier tegelijk om te gaan en te zien welke de beste resultaten oplevert voor de betreffende dataset. Na de initiële testfase kun je dit verder verfijnen, bijvoorbeeld door te herhalen met de top drie classifiers en hun parameters aan te passen om hun nauwkeurigheid te verbeteren.

Het meest nauwkeurige model in dit geval is de Gradient Boosting classifier. Deze classifier, en vergelijkbare zoals Random Forest, in combinatie met xgboost of een andere vorm van boosting, presteren meestal vrij goed (bijv. op Kaggle-problemen). Scikit-learn heeft uitgebreide documentatie over de theorie achter deze classifiers en waarom sommige in bepaalde gevallen beter kunnen presteren dan andere.

Hyperparameteroptimalisatie op de gekozen classifier

We hebben verschillende strategieën geprobeerd om een classifier te kiezen en bepaald welke het beste werkt. Nu kunnen we het verder verbeteren door de hyperparameters te optimaliseren als volgt:

GDB_params = {
    'n_estimators': [250, 500, 2000],
    'learning_rate': [0.5, 0.1, 0.01, 0.001],
    'criterion': ['friedman_mse', 'mse', 'mae']
}

df_train, df_test, X_train, Y_train, X_test, Y_test = get_train_test(df_glass, y_col_glass, x_cols_glass, 0.6)

for n_est in GDB_params['n_estimators']:
    for lr in GDB_params['learning_rate']:
        for crit in GDB_params['criterion']:
            clf = GradientBoostingClassifier(n_estimators=n_est,
                                             learning_rate=lr,
                                             criterion=crit)
            clf.fit(X_train, Y_train)
            train_score = clf.score(X_train, Y_train)
            test_score = clf.score(X_test, Y_test)
            print("Voor ({}, {}, {}) - train, test score: \t {:.5f} \t-\t {:.5f}".format(n_est, lr, crit[:4], train_score, test_score))

Hierboven optimaliseren we een GradientBoostingClassifier door te spelen met het aantal bomen, de leersnelheid, en het type criterium. We passen het model aan op de trainingsdata en kijken hoe goed het werkt op de testdata. Hierdoor kunnen we de beste instellingen vinden die voor dit specifieke probleem het beste resultaat geven.

Classificatie van giftige versus eetbare paddenstoelen

We gaan nu aan de slag met de paddestoel dataset, die data bevat over welke paddestoelen eetbaar zijn en welke giftig. In de dataset staan 8124 paddestoelen, waarvan 4208 eetbaar zijn en 3915 giftig. Elke paddestoel heeft 22 kenmerken.

In tegenstelling tot de glas dataset hebben we hier geen numerieke waarden. De paddestoel dataset bevat categorische waarden. Daarom moeten we een extra stap zetten: het coderen van de waarden, als volgt:

filename_mushrooms = './data/mushrooms.csv'
df_mushrooms = pd.read_csv(filename_mushrooms)
display(df_mushrooms.head())

Om de categorieën te achterhalen, printen we de unieke waarden van elke kolom. We controleren ook op ontbrekende waarden en kijken of er onnodige kolommen zijn die kunnen worden verwijderd.

for col in df_mushrooms.columns.values:
    print(col, df_mushrooms[col].unique())

Er zijn 22 categorische kenmerken in de dataset. Een van de kenmerken, genaamd “veil-type”, heeft slechts één waarde “p”. Dat is niet nuttig en voegt geen waarde toe aan de classifier. We kunnen deze kolom dus verwijderen:

for col in df_mushrooms.columns.values:
    if len(df_mushrooms[col].unique())  1:
        print("Removing column {}, which only contains the value: {}".format(col, df_mushrooms[col].unique()[0]))

Ontbrekende waarden

Datasets kunnen ontbrekende waarden bevatten, weergegeven als '', NaN of Null. Afhankelijk van de omstandigheden, moet je beslissen wat je doet met ontbrekende data:

  • Als er niet veel rijen met ontbrekende waarden zijn, kun je die rijen verwijderen. Maar pas op: je kunt informatie verliezen.
  • Een ontbrekende waarde kan ook op zichzelf waardevolle informatie zijn en je kunt die classificeren als een aparte entiteit.
  • Je kunt ook ontbrekende waarden aanvullen (bijvoorbeeld met het gemiddelde of de mediaan).

Rijen verwijderen bij ontbrekende waarden:

df_mushrooms.dropna(inplace=True)

Kolommen verwijderen wanneer een bepaald percentage ontbreekt:

drop_percentage = 0.8
df_mushrooms_dropped_cols = df_mushrooms.copy(deep=True)
df_mushrooms_dropped_cols.loc[df_mushrooms_dropped_cols['stalk-root'] == '?', 'stalk-root'] = np.nan
 
for col in df_mushrooms_dropped_cols.columns.values:
    no_rows = df_mushrooms_dropped_cols[col].isnull().sum()
    percentage = no_rows / df_mushrooms_dropped_cols.shape[0]
    if percentage  drop_percentage:
        del df_mushrooms_dropped_cols[col]
        print("Kolom {} bevat {} ontbrekende waarden. Dit is {} procent. We laten deze kolom weg.".format(col, no_rows, percentage))

Ontbrekende waarden vullen met nullen:

df_mushrooms_zerofill = df_mushrooms.copy(deep=True)
df_mushrooms_zerofill.loc[df_mushrooms_zerofill['stalk-root'] == '?', 'stalk-root'] = np.nan
df_mushrooms_zerofill.fillna(0, inplace=True)

Ontbrekende waarden aanvullen met backward fill:

df_mushrooms_bfill = df_mushrooms.copy(deep=True)
df_mushrooms_bfill.loc[df_mushrooms_bfill['stalk-root'] == '?', 'stalk-root'] = np.nan
df_mushrooms_bfill.fillna(method='bfill', inplace=True)

Ontbrekende waarden aanvullen met forward fill:

df_mushrooms_ffill = df_mushrooms.copy(deep=True)
df_mushrooms_ffill.loc[df_mushrooms_ffill['stalk-root'] == '?', 'stalk-root'] = np.nan
df_mushrooms_ffill.fillna(method='ffill', inplace=True)

Codering van categorische variabelen

Aangezien sommige classifiers niet goed werken met niet-numerieke data, moet je categorische waarden in numerieke waarden omzetten. Dit kan met One-Hot Encoding in scikit-learn. Er zijn twee opties:

    1. Converteer de categorische waarden naar numerieke waarden met One-Hot Encoding.
    1. Splits de kolom in meerdere kolommen met binaire waarden.

Bijvoorbeeld, een kolom genaamd “FRUIT” met de waarden ['ORANGE', 'APPLE', 'PEAR'] kan op twee manieren worden gecodeerd:

  • Met de eerste methode worden de unieke waarden omgezet in [0,1,2].
  • Met de tweede methode wordt de kolom omgezet in drie kolommen genaamd ['FRUIT_IS_ORANGE', 'FRUIT_IS_APPLE', 'FRUIT_IS_PEAR'] met binaire waarden.

Je moet voorzichtig zijn met hoe je deze data gebruikt, want numerieke waarden kunnen in sommige classifiers verkeerd geïnterpreteerd worden.

Hieronder coderen we de kolommen:

def label_encode(df, columns):
    for col in columns:
        le = LabelEncoder()
        col_values_unique = list(df[col].unique())
        le_fitted = le.fit(col_values_unique)
 
        col_values = list(df[col].values)
        le.classes_
        col_values_transformed = le.transform(col_values)
        df[col] = col_values_transformed
 
df_mushrooms_ohe = df_mushrooms.copy(deep=True)
to_be_encoded_cols = df_mushrooms_ohe.columns.values
label_encode(df_mushrooms_ohe, to_be_encoded_cols)
display(df_mushrooms_ohe.head())

Nu doen we hetzelfde voor de andere dataframes

df_mushrooms_dropped_rows_ohe = df_mushrooms_dropped_rows.copy(deep=True) df_mushrooms_zerofill_ohe = df_mushrooms_zerofill.copy(deep=True) df_mushrooms_bfill_ohe = df_mushrooms_bfill.copy(deep=True) df_mushrooms_ffill_ohe = df_mushrooms_ffill.copy(deep=True)

label_encode(df_mushrooms_dropped_rows_ohe, to_be_encoded_cols) label_encode(df_mushrooms_zerofill_ohe, to_be_encoded_cols) label_encode(df_mushrooms_bfill_ohe, to_be_encoded_cols) label_encode(df_mushrooms_ffill_ohe, to_be_encoded_cols)

We maken kopieën van onze dataframes: df_mushrooms_dropped_rows_ohe, df_mushrooms_zerofill_ohe, df_mushrooms_bfill_ohe, en df_mushrooms_ffill_ohe. Elk van deze kopieën wordt dieper gekopieerd zodat de originele dataframes veilig zijn voor wijzigingen.

Vervolgens worden ze gecodeerd met label_encode voor de kolommen die we willen coderen.

def expand_cols(df, list_columns):
    for column in list_columns:
        colvalues = df[column].unique()
        for colvalue in colvalues:
            newcol_name = "{}_is_{}".format(column, colvalue)
            df.loc[df[column] == colvalue, newcol_name] = 1
            df.loc[df[column] != colvalue, newcol_name] = 0
    df.drop(list_columns, inplace=True, axis=1)

y_col = 'class'
cols_to_expand = list(df_mushrooms.columns.values)
cols_to_expand.remove(y_col)

df_mushrooms_expanded = df_mushrooms.copy(deep=True)
label_encode(df_mushrooms_expanded, [y_col])
expand_cols(df_mushrooms_expanded, cols_to_expand)

We breiden de kolommen uit met de functie expand_cols. Deze functie gaat al onze specifieke kolommen bekijken en maakt nieuwe kolommen voor elke unieke waarde.

We maken een kopie van df_mushrooms, de kopie heet df_mushrooms_expanded. De kolom 'klasse' wordt gecodeerd en vervolgens worden alle andere kolommen uitgeklapt.

Met de functie expand_cols worden alle waarde-categorieën omgezet in aparte kolommen, waarna de originele kolommen verwijderd worden.

Nu doen we hetzelfde voor alle andere dataframes.

df_mushrooms_dropped_rows_expanded is een kopie van df_mushrooms_dropped_rows, gebruikmakend van deep copy om alles mee te nemen.

df_mushrooms_zerofill_expanded is een kopie van df_mushrooms_zerofill.

df_mushrooms_bfill_expanded is ook een kopie, net als df_mushrooms_ffill_expanded van hun respectieve dataframes.

Gebruik de label_encode functie op df_mushrooms_dropped_rows_expanded met y_col.

Doe hetzelfde voor df_mushrooms_zerofill_expanded, df_mushrooms_bfill_expanded, en df_mushrooms_ffill_expanded met y_col.

Breid de kolommen uit in df_mushrooms_dropped_rows_expanded met behulp van expand_cols functie in cols_to_expand.

Pas dezelfde uitbreiding toe op df_mushrooms_zerofill_expanded, df_mushrooms_bfill_expanded, en df_mushrooms_ffill_expanded.

Classificeren en valideren van de gegevens

Net als eerder gaan we proberen om erachter te komen welke classifier het beste werkt op de paddenstoelendataset door ze allemaal tegelijk te testen.

Het doel is om de classifier met de hoogste nauwkeurigheid te vinden. We gebruiken weer dezelfde verdeling van 70% / 30% voor het splitsen van de data in train en test sets.

dict_dataframes = {
    "df_mushrooms_ohe": df_mushrooms_ohe,
    "df_mushrooms_dropped_rows_ohe": df_mushrooms_dropped_rows_ohe,
    "df_mushrooms_zerofill_ohe": df_mushrooms_zerofill_ohe,
    "df_mushrooms_bfill_ohe": df_mushrooms_bfill_ohe,
    "df_mushrooms_ffill_ohe": df_mushrooms_ffill_ohe,
    "df_mushrooms_expanded": df_mushrooms_expanded,
    "df_mushrooms_dropped_rows_expanded": df_mushrooms_dropped_rows_expanded,
    "df_mushrooms_zerofill_expanded": df_mushrooms_zerofill_expanded,
    "df_mushrooms_bfill_expanded": df_mushrooms_bfill_expanded,
    "df_mushrooms_ffill_expanded": df_mushrooms_ffill_expanded
}

y_col = 'class'
train_test_ratio = 0.7

for df_key, df in dict_dataframes.items():
    x_cols = list(df.columns.values)
    x_cols.remove(y_col)
    df_train, df_test, X_train, Y_train, X_test, Y_test = get_train_test(df, y_col, x_cols, train_test_ratio)
    dict_models = batch_classify(X_train, Y_train, X_test, Y_test, n_classifiers = 8, verbose=False)
    
    print()
    print(df_key)
    display_dict_models(dict_models)

De nauwkeurigheid van de classifiers is hierbij behoorlijk hoog.

Werken met complexe datasets en deze begrijpen

Niet alle datasets zijn makkelijk om mee te werken. Soms is het lastig te bepalen welke kenmerken helpen bij classificatie of regressie, en welke juist onnodige ruis toevoegen aan de resultaten.

Om een beter begrip van zulke datasets te krijgen, kun je een paar methodes gebruiken om te zien hoe een dataset wordt gekarakteriseerd door zijn kenmerken.

De correlatiematrix

Voor een beter inzicht in hoe sterk elk individueel kenmerk gerelateerd is aan het type glas in onze eerste dataset, is het handig om een correlatiematrix te berekenen en te plotten met de volgende code:

correlation_matrix = df_glass.corr()
plt.figure(figsize=(10,8))
ax = sns.heatmap(correlation_matrix, vmax=1, square=True, annot=True,fmt='.2f', cmap ='GnBu', cbar_kws={"shrink": .5}, robust=True)
plt.title('Correlation matrix between the features', fontsize=20)
plt.show()

Uit de resultaten kunnen we zien dat oxiden zoals aluminium en magnesium veel sterker gecorreleerd zijn met het type glas, terwijl het gehalte aan calcium niet zo'n belangrijke rol speelt. Als je dataset kenmerken bevat die helemaal geen correlatie hebben met de variabele van interesse, kan het helpen om deze volledig te verwijderen, omdat ze alleen maar ruis toevoegen aan je resultaten.

Correlatie van één kenmerk met meerdere andere kenmerken

In een dataset met veel kenmerken kan de correlatiematrix erg groot worden als de kenmerken op complexe manieren met elkaar gecorreleerd zijn. Gelukkig is er een manier om de correlaties van één kenmerk te bekijken, en je kunt de resultaten visualiseren in de vorm van een grafiek:

def display_corr_with_col(df, col):
    correlation_matrix = df.corr()
    correlation_type = correlation_matrix[col].copy()
    abs_correlation_type = correlation_type.apply(lambda x: abs(x))
    desc_corr_values = abs_correlation_type.sort_values(ascending=False)
    y_values = list(desc_corr_values.values)[1:]
    x_values = range(0,len(y_values))
    xlabels = list(desc_corr_values.keys())[1:]
    fig, ax = plt.subplots(figsize=(8,8))
    ax.bar(x_values, y_values)
    ax.set_title('Correlation of all features with {}'.format(col), fontsize=20)
    ax.set_ylabel('Pearson correlation coefficient', fontsize=16)
    plt.xticks(x_values, xlabels, rotation='vertical')
    plt.show()
 
display_corr_with_col(df_glass, 'typeglass')

Cumulatieve Verklaarde Variantie

Deze methode laat je zien hoeveel van de variantie wordt vastgelegd door de eerste N kenmerken. Bijvoorbeeld, de volgende plot laat zien hoe de eerste vier kenmerken met de grootste correlatie 90% van de variantie in de dataset vastleggen.

X = df_glass[x_cols_glass].values
X_std = StandardScaler().fit_transform(X)
 
pca = PCA().fit(X_std)
var_ratio = pca.explained_variance_ratio_
components = pca.components_
#print(pca.explained_variance_)
plt.plot(np.cumsum(var_ratio))
plt.xlim(0,9,1)
plt.xlabel('Number of Features', fontsize=16)
plt.ylabel('Cumulative explained variance', fontsize=16)
plt.show()

Je kunt overwegen om de kenmerken met de laagste correlatie te verwijderen als je classificatie/regressie model een lage nauwkeurigheid heeft. Je kunt ook de kenmerken met de hoogste correlatie stapsgewijs toevoegen en kijken of de resultaten verbeteren.

Pairwijze relaties tussen verschillende kenmerken

Naast de correlatiematrix is het mogelijk om naar de pairwijze relaties tussen bepaalde kenmerken te kijken en deze te plotten om te zien hoe ze gecorreleerd zijn.

ax = sns.pairplot(df_glass, hue='typeglass')
plt.title('Pairwise relationships between the features')
plt.show()

Conclusie

De Scikit-learn bibliotheek is een erg nuttige en gemakkelijk te gebruiken bibliotheek voor machinaal leren. Het heeft veel functies en kan werken met verschillende datasets, ongeacht hun type.


Delen

Opmerkingen (0)

Een reactie plaatsen

© 2023 - 2024 — TensorScience. Alle rechten voorbehouden.