Korrekter Umgang mit Ausreißern zur Verbesserung von Überanpassungsszenarien
Einführung
Der Hauptansatz des maschinellen Lernens besteht darin, die Daten in Trainings- und Testsätze aufzuteilen. Algorithmen für maschinelles Lernen werden dann auf dem Trainingssatz (Datensatz) trainiert, um von einer Verzerrung auf die unsichtbaren Daten, d. h. auf einen Testsatz, zu verallgemeinern. Wenn es einem Algorithmus nicht gelingt, das, was er aus dem Trainingssatz gelernt hat, auf den Testsatz zu übertragen, liegt eine Überanpassung des Algorithmus vor.
Überanpassung ist ein häufiges Drawback beim überwachten Lernen. Tatsächlich besteht eine der großen Aufgaben bei der Klassifizierung darin, sie zu berücksichtigen und zu überpassen. Die Unterstützung kann die Qualität unseres Modells und sogar unsere Meinung als Datenwissenschaftsexperten beeinträchtigen.
Wenn alle Testsatzdaten der gleichen Verteilung wie der Trainingssatz folgen, warum kommt es dann zu einer Überanpassung?
Es stellt sich heraus, dass die Verteilung von Trainings- oder Testdaten Unregelmäßigkeiten aufweisen kann, die verhindern, dass das Modell an alle Daten angepasst wird. Dies geschieht im Wesentlichen in Fällen, in denen das Lernen über einen längeren Zeitraum durchgeführt wird oder in Fällen, in denen Trainingsbeispiele selten sind, was dazu führt, dass ein Modell an bestimmte zufällige Merkmale des Trainingssatzes angepasst wird. Diese Modelle verletzen oft Occams Rasiermesser.
Die getreue Übersetzung dieser Wörter lautet „Entitäten dürfen nicht über das notwendige Maß hinaus multipliziert werden“. Basierend auf diesen Wörtern kann dies in einem Überanpassungsszenario wie folgt interpretiert werden:
Wenn es zwei Modelle mit ähnlicher Leistung gibt, wählen Sie immer das einfachste.
Als praktisches Beispiel für die in diesem Beitrag beschriebenen statistischen Ansätze verwenden wir Irisdaten.
Der in diesem Artikel verwendete Datensatz kann direkt von heruntergeladen werden UCI-Repositoryobwohl es auch möglich ist, die Scikit-learn-Bibliothek aufzurufen.
Wenn Sie den Datensatz bereits auf Ihrem Laptop haben, können Sie die Daten mit Pandas laden:
import pandas as pd
filename = "iris.csv"
names = ["SepalLength","SepalWidth","PetalLength","PetalWidth","Species"]
df = pd.read_csv(filename,names=names)
df.head(5)
Der Iris-Pflanzendatensatz wurde dank des Statistikers und Biologen RA Fisher populär, als er ihn in seinem Artikel mit dem Titel vorstellte Die Verwendung mehrerer Messungen ent wickelt Probleme als Beispiel für die lineare Diskriminanzanalyse im Jahr 1936. Es wird heute häufig in der Literatur zur Mustererkennung verwendet. Dieser Datensatz enthält fünf Variablen, nämlich:
- Kelchblattlänge in cm
- Kelchblattbreite in cm
- Blütenblattlänge in cm
- Blütenblattbreite in cm
- Klasse:
— Iris Setosa
— Iris Versicolor
— Iris Virginica
Wie im UCI-Repository angegeben, gibt es tatsächlich einige Unregelmäßigkeiten in den Irisdaten:
Das 35. Beispiel sollte sein: 4.9,3.1,1.5,0.2, „Iris-setosa“, wobei der Fehler im vierten Merkmal liegt. Beispiel 38: 4.9,3.6,1.4,0.1 „Iris-setosa“, wobei die Fehler im zweiten und dritten Merkmal liegen.
Kann dies die Leistung unseres Modells beeinträchtigen? Dies ist möglich, auch wenn der Unterschied angesichts der beträchtlichen Datenmenge, die korrekt erfasst wurde, unbedeutend erscheint. Wir sollten uns jedoch immer dafür entscheiden, etwaige Unregelmäßigkeiten in unserem Trainingssatz zu korrigieren.
Wir erhalten weiterhin eine statistische Beschreibung unserer Daten und rufen außerdem eine Pandas-Funktion auf, um die Anzahl unserer Ausgabeklassen (Arten) zu zählen:
df.describe()
class_count = df.groupby('Species').dimension()
class_count
Wir haben 3 Klassen mit jeweils 50 Mitgliedern. Wir können auch den Mittelwert, die Standardabweichung und die Quartile jeder Klasse überprüfen.
Wir können eine visuelle Beschreibung unserer Daten erhalten.
import matplotlib.pyplot as plt# Set species and colours
species = ['Iris-setosa', 'Iris-versicolor', 'Iris-virginica']
colours = ['blue', 'orange', 'red']
plt.determine(figsize=(8, 6))
for i, sp in enumerate(species):
subset = df[df['Species'] == sp]
plt.scatter(subset['SepalLength'], subset['SepalWidth'], colour=colours[i], label=sp)
plt.xlabel('Sepal Size')
plt.ylabel('Sepal Width')
plt.title('Scatter Plot of Iris Species')
plt.present()
Tatsächlich ist es möglich, basierend auf der Größe des Kelch- und Blütenblatts die folgenden Regeln festzulegen:
Wenn die Blütenblattlänge < 2,45 ist, dann Iris-setosa
Wenn Kelchblattbreite < 2,10, dann Iris-versicolor
Wenn Kelchblattbreite < 2,45 und Blütenblattlänge < 4,55, dann Iris-versicolor
Wenn Kelchblattbreite < 2,95 und Blütenblattbreite < 1,35, dann Iris-versicolor
Wenn Blütenblattlänge < 2,45 und Blütenblattlänge < 4,45, dann Iris-versicolor
Wenn Kelchblattlänge >= 5,85 und Blütenblattlänge < 4,75, dann Iris-versicolor
Wenn Kelchblattbreite < 2,55 und Blütenblattlänge < 4,95 und Blütenblattbreite < 1,55, dann
Iris versicolor
Wenn Blütenblattlänge >= 2,45 und Blütenblattlänge < 4,95 und Blütenblattbreite < 1,55, dann
Iris versicolor
Wenn Kelchblattlänge >= 6,55 und Blütenblattlänge < 5,05, dann Iris-versicolor
Wenn Kelchblattbreite < 2,75 und Blütenblattbreite < 1,65 und Kelchblattlänge < 6,05
dann Iris-versicolor
Wenn Kelchblattlänge >= 5,85 und Kelchblattlänge < 5,95 und Blütenblattlänge < 4,85
dann Iris-versicolor
Wenn die Blütenblattlänge >= 5,15 ist, dann Iris-virginica
Wenn die Blütenblattbreite >= 1,85 ist, dann Iris-virginica
Wenn Blütenblattbreite >= 1,75 und Kelchblattbreite < 3,05, dann Iris-virginica
Wenn Blütenblattlänge >= 4,95 und Blütenblattbreite < 1,55, dann Iris-virginicaWenn die Blütenblattlänge >= 5,15 ist, dann Iris-virginica
Wenn die Blütenblattbreite >= 1,85 ist, dann Iris-virginica
Wenn Blütenblattbreite >= 1,75 und Kelchblattbreite < 3,05, dann Iris-virginica
Wenn Blütenblattlänge >= 4,95 und Blütenblattbreite < 1,55, dann Iris-virginica
Der nächste Schritt besteht darin, unsere Daten zu standardisieren. Einige Algorithmen schneiden besser ab, wenn sie einer Normalverteilung ausgesetzt werden. Wir können versuchen, dies durch die Z-Rating-Transformation zu erreichen.
Dabei ist n die Anzahl der Elemente im Datensatz und std die Standardabweichung.
Seien Sie vorsichtig bei der Verwendung dieser Formel. Wenn die Daten mehrdimensional sind, müssen Sie diese Formel wie folgt ändern:
Bevor wir jedoch zum nächsten Schritt übergehen, werfen wir einen Blick auf einige Konzepte zur Gaußschen Verteilung und zum Z-Rating selbst.
In einer Gaußschen Verteilung, auch Normalverteilung genannt, liegen etwa 68,3 % der Datensätze zwischen:
Etwa 95,4 % der Datensätze liegen zwischen:
Etwa 99,7 % der Datensätze liegen zwischen:
In Summe:
Tatsächlich ist es nach dem zentralen Grenzwertsatz nur dann möglich, mit der Z-Rating-Transformation eine Standardnormalverteilung zu erreichen, wenn die Anzahl der Stichproben groß genug ist. Wenn die Anzahl der Stichproben nicht groß genug ist, stehen wir vor einem T- Verteilung Pupil. Die T-Pupil-Verteilung ähnelt einer Normalverteilung, wobei die Glockenform abhängig von den Freiheitsgraden flacher ist. Im Allgemeinen gilt: Je größer die Freiheitsgrade, desto näher kommt sie einer Normalverteilung.
Es wird oft gesagt, dass wir nach der Z-Rating-Transformation einen Mittelwert von 0 und eine Standardabweichung von 1 haben, aber tatsächlich ist der Z-Rating selbst eine Zufallsvariable, der Wert der Varianz ist nicht sicher bekannt, sondern nur ein Schätzungen, bei denen es sich um Annäherungen an diese Werte handelt.
Es entsteht eine Überanpassung
Wir werden ein häufiges Überanpassungsszenario evaluieren, wir werden ein logistisches Regressionsmodell trainieren, um unsere Iris-Daten zu klassifizieren, und um ein Überanpassungsszenario zu simulieren, werden wir die Daten in Trainingssätze (90 %) und Testsätze (10) aufteilen, ohne die Daten zu randomisieren Wenn die Daten geordnet sind, können wir nur alle Datensätze der Klassen Iris Setosa und Iris Versicolor und nur 70 % der Klasse Iris Virginica erfassen. Da der Algorithmus nur sehr wenige Daten aus dieser Klasse trainiert hat, wird er bei der Datenauswertung keine gute Leistung erbringen In dieser Klasse ist es mit anderen Worten möglich, deduktiv zu schließen, dass eine Überanpassung vorliegt. Unser Ziel ist es, einen Ansatz zu entwickeln, um die Leistung des Modells auf 100 % zu verbessern, ohne die Daten zu randomisieren oder das Modell für das Coaching weiteren Daten auszusetzen . Wäre das möglich? Wir werden es als nächstes sehen.
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_reportarray = df.values
X = array[:,0:4] # knowledge
Y = array[:,4] # label
# Standardize the information
X = (X - np.imply(X))/2*np.std(X)
# Reserve 10% to check.
break up = int(X.form[0]*0.9)
X_train = X[0:split]
Y_train = Y[0:split]
X_test = X[split:]
Y_test = Y[split:]
mannequin = LogisticRegression(max_iter=1000)
mannequin.match(X_train, Y_train)
outcome = mannequin.rating(X_test, Y_test)
Unser Modell ist zu 93 % genau. Das sieht fantastisch aus, aber es gibt tatsächlich ein Drawback zu lösen: Unser Modell battle nicht in der Lage, die Datensätze der letzten Klasse wie erwartet korrekt zu klassifizieren, und da wir uns an die Lösung machten, müssen wir nach einer Möglichkeit suchen, die Leistung von zu verbessern unser Modell für diese Klasse.
Der Ansatz zur Lösung dieses Issues liegt in der statistischen Behandlung von Ausreißern. Ausreißer sind Werte außerhalb der Verteilung unserer Daten. Der Diagrammtyp, der sie am besten beschreibt, sind Boxplots. Hier finden Sie eine kurze Beschreibung, wie sie zu interpretieren sind.
df.plot(variety='field')
Wie es im Bild zu sehen ist, sind diese Punkte außerhalb der Schnurrhaare unsere Ausreißer. Das beobachten wir Kelchblattbreite Ausreißer haben, zum Glück haben wir eine Möglichkeit, sie zu lokalisieren, additionally analysieren wir unser Drawback statistischer:
Da X eine Variable der Setosa-, Verginica- oder Versicolor-Klasse ist, ist X ein Ausreißer, wenn:
Oder alternativ:
Da wir nun wissen, wie man einen Ausreißer aufspürt, müssen wir ihn nur noch in unsere Lieblingsprogrammiersprache übersetzen. Ah! Wir müssen die Ausreißerpunkte durch die Standardabweichung ersetzen.
def outlier_search(column):
quantile1 = df[column].quantile(0.25)
quantile3 = df[column].quantile(0.75)
inter_quantile = quantile3 - quantile1
out_found = df.loc[(df[column] < (quantile1 - (1.5*inter_quantile))) | (df[column] > (quantile3 + (1.5*inter_quantile))), column] = df[column].std()
return columnoutlier_search('SepalWidth')
Lassen Sie uns die Boxplots noch einmal visualisieren.
Wir scheinen eine sehr deutliche Verbesserung unserer Daten erreicht zu haben.
Leider gibt es kein klares Muster für den Umgang mit Ausreißern, daher müssen wir einige Anpassungen an der Formel vornehmen, um die Bewertung des Modells zu verbessern. Lassen Sie uns das ändern Quantil3 Variable, indem wir sie durch 2 dividieren. Unsere endgültige Formel sollte so aussehen:
Nachdem wir nun alle Variablen gesammelt haben, müssen wir nur noch alles zusammenfügen und sehen, welches Ergebnis wir daraus erzielen können:
...
...def outlier_search(column):
quantile1 = df[column].quantile(0.25)
quantile3_optimized = (df[column].quantile(0.75))/2
inter_quantile = df[column].quantile(0.75) - df[column].quantile(0.25)
out_found = df.loc[(df[column] < (quantile1 - (1.5*inter_quantile))) | (df[column] > (quantile3_optimized + (1.5*inter_quantile))), column] = df[column].std()
return column
outlier_search('SepalWidth')
array = df.values
X = array[:,0:4] # knowledge
Y = array[:,4] # take a look at
# Standardize the information
X = (X - np.imply(X))/2*np.std(X)
# Reserve 10% to check
break up = int(X.form[0]*0.9)
X_train = X[0:split]
Y_train = Y[0:split]
X_test = X[split:]
Y_test = Y[split:]
mannequin = LogisticRegression(max_iter=1000)
mannequin.match(X_train, Y_train)
outcome = mannequin.rating(X_test, Y_test)
Unser! Unser Modell-Rating ist jetzt 100%! Wir erreichen unser Ziel einfach dadurch, dass wir einen Ansatz zum Umgang mit Ausreißern anbieten.
Abschluss
In diesem Artikel versuchen wir, das Drawback der Überanpassung und ihre Auswirkungen auf unser Modell zu diskutieren. Wir haben herausgefunden, dass das Löschen der Ausreißer unser Modell erheblich verbessern könnte. Am Ende stellen wir eine statistische Methode vor, wie wir die Ausreißer in unseren Daten lokalisieren können.
Wir haben auch die Genauigkeit mit und ohne Ausreißer verglichen. Dies ist nur ein Ansatz zur Lösung des Überanpassungsproblems, das auf ein Szenario mit unausgeglichenen Trainingsdaten zurückzuführen ist.
Haftungsausschluss: Der Hauptzweck dieses Artikels besteht darin, zu beweisen, dass der Umgang mit Ausreißern den Zugdaten-Rating wirklich erheblich verbessern kann. Daher wurde das Überanpassungsszenario absichtlich erstellt. Sie sollten einen Ansatz wie eine Kreuzvalidierung verwenden, um eine Überanpassung zu vermeiden.
Ich hoffe, dieser Beitrag hat klargestellt, was es ist und wie man mit diesem Drawback umgeht.
Danke fürs Lesen des Beitrags!
Folgen Sie mir für weitere Inhalte wie diesen, es hilft sehr!