[PYTHON] Wahrscheinlichkeitsvorhersage von unausgeglichenen Daten

Einführung

Wenn Sie mit maschinellem Lernen klassifizieren, möchten Sie möglicherweise die Wahrscheinlichkeit der Zugehörigkeit zu diesen Klassen sowie die Klassifizierungsergebnisse ermitteln. Wenn die Anzahl der positiven Daten im Vergleich zur Anzahl der negativen Daten extrem gering ist (solche Daten werden als unausgeglichene Daten bezeichnet), wenn Sie ein Vorhersagemodell mit all diesen Daten erstellen, ist das Vorhersageergebnis ebenfalls negativ. In vielen Fällen ist es schwierig, positive Daten genau zu klassifizieren. Daher wird in vielen Fällen ein Modell unter Verwendung von unterabgetasteten Daten konstruiert, so dass die Anzahl der negativen Beispieldaten gleich der Anzahl der positiven Beispieldaten ist. Dies ermöglicht es, positive Beispieldaten genau zu klassifizieren. Da sich das Gleichgewicht zwischen der Anzahl positiver und negativer Daten von den Originaldaten unterscheidet, ist das Ergebnis der Wahrscheinlichkeitsvorhersage aufgrund von Unterabtastung verzerrt. Ich werde am Ende.

Einige Leute haben bereits im folgenden Blog usw. zusammengefasst, wie mit diesem Problem umgegangen werden soll, aber ich werde als Memorandum zusammenfassen, wie die Verzerrung der Wahrscheinlichkeitsausgabe durch das mit unterabgetasteten Daten erstellte Modell beseitigt und korrigiert werden kann. .. In diesem Artikel verwenden wir einfach das logistische Regressionsmodell als Modell für die probabilistische Vorhersage.

So korrigieren Sie die Vorspannung aufgrund von Unterabtastung

Die Methode zur Korrektur der Verzerrung durch Unterabtastung ist in der Veröffentlichung [Kalibrieren der Wahrscheinlichkeit mit Unterabtastung für eine unausgeglichene Klassifizierung] beschrieben. Vorgeschlagen unter (https://www3.nd.edu/~dial/publications/dalpozzolo2015calibrating.pdf).

Betrachten Sie nun eine binäre Klassifizierungsaufgabe, die die Zielvariable $ Y $ ($ Y $ nimmt entweder 0 oder 1) aus der erklärenden Variablen $ X $ vorhersagt. Der ursprüngliche Datensatz $ (X, Y) $ ist ein unausgeglichener Datensatz mit einer extrem kleinen Anzahl positiver Beispiele, und der Datensatz, in dem die Anzahl negativer Beispiele gleich der Anzahl positiver Beispiele durch Unterabtastung ist, ist $ (X_s). , Y_s) $. Wenn einige in $ (X, Y) $ enthaltene Daten (Beispiel) auch in $ (X_s, Y_s) $ enthalten sind, wird 1 benötigt, und wenn sie nicht in $ (X_s, Y_s) $ enthalten sind, ist sie 0. Führt eine Stichprobenvariable $ s $ ein, die benötigt wird.

Originaldatensatz(X, Y)Wenn einem unter Verwendung eines Modells konstruierten Modell eine erklärende Variable gegeben wird, ist die Wahrscheinlichkeit, es als positives Beispiel vorherzusagen, gleichp(y=1|x)Es wird ausgedrückt als. Auch unterabgetastete Datensätze(X_s, Y_s)Wenn einem unter Verwendung eines Modells konstruierten Modell eine erklärende Variable gegeben wird, ist die Wahrscheinlichkeit, es als positives Beispiel vorherzusagen, gleichp(y=1|x,s=1)Es wird ausgedrückt als.p=p(y=1|x), p_s=p(y|x,s=1)DannpWannp_sDie Beziehung von ist wie folgt.

p=\frac{\beta p_s}{\beta p_s-p_s+1}

Hier ist $ \ beta = N ^ + / N ^ - $ ($ N ^ + $ ist die Anzahl der positiven Daten, $ N ^ - $ ist die Anzahl der negativen Daten).

Ableitung

Das Folgende ist eine detaillierte Erklärung der Formel. Wenn Sie also nicht interessiert sind, überspringen Sie sie bitte.

Satz von Bayes undp(s|y,x)=p(s|y)Aus dem unterabgetasteten Datensatz(X_s, Y_s)Die Wahrscheinlichkeit, die von dem unter Verwendung des Modells erstellten Modell vorhergesagt wird, wird wie folgt geschrieben.

p(y=1|x,s=1)=\frac{p(s=1|y=1)p(y=1|x)}{p(s=1|y=1)p(y=1|x)+p(s=1|y=0)p(y=0|x)}

Jetzt ist die Anzahl der regulären Daten extrem gering, und alle Daten, für die $ y = 1 $ abgetastet wird, sind also, wenn $ p (s = 1 | y = 1) = 1 $,

p(y=1|x,s=1)=\frac{p(y=1|x)}{p(y=1|x)+p(s=1|y=0)p(y=0|x)}

Kann geschrieben werden. des Weiteren,p=p(y=1|x), p_s=p(y|x,s=1), \beta=p(s=1|y=0)Dann

p_s=\frac{p}{p+\beta(1-p)}

Es wird sein. Wenn schließlich $ p $ so transformiert wird, dass es sich auf der linken Seite befindet,

p=\frac{\beta p_s}{\beta p_s-p_s+1}

Es wird sein. Die letzte Gleichung bedeutet, dass das mit den unterabgetasteten Daten erstellte Modell die Wahrscheinlichkeit $ p_s $ durch Korrigieren der Verzerrung vorhersagt und das mit den Originaldaten erstellte Modell die Wahrscheinlichkeit $ vorhersagt Dies bedeutet, dass Sie p $ berechnen können.

Wobei $ \ beta = p (s = 1 | y = 0) $ die Wahrscheinlichkeit darstellt, dass negative Beispieldaten abgetastet werden. Da nun negative Beispieldaten in derselben Anzahl wie positive Beispieldaten abgetastet werden, ist $ \ beta = N ^ + / N ^ - $ ($ N ^ + $ ist die Anzahl der positiven Beispieldaten, $ N ^ - $ ist Sie kann an die Anzahl der Daten im negativen Beispiel angenähert werden.

Codebeispiel

Im Folgenden führen wir ein Experiment durch, um die Vorhersagewahrscheinlichkeit zu korrigieren und gleichzeitig ein tatsächliches Codebeispiel zu zeigen. (Die Betriebsumgebung des folgenden Codes ist Python 3.7.3, Pandas 0.24.2, Scikit-Learn 0.20.3.)

Das Experiment wird gemäß dem folgenden Ablauf durchgeführt.

  1. Erstellen Sie ein Modell unter Verwendung der unausgeglichenen Daten und überprüfen Sie die Klassifizierungsgenauigkeit.
  2. Erstellen Sie ein Modell mit unterabgetasteten Daten und stellen Sie sicher, dass die Klassifizierungsgenauigkeit verbessert ist, die Genauigkeit der Wahrscheinlichkeitsvorhersage jedoch gering ist.
  3. Überprüfen Sie, ob die Wahrscheinlichkeit der Wahrscheinlichkeitsvorhersage verbessert werden kann, indem Sie eine Korrektur anwenden, die die Vorspannung aufgrund von Unterabtastung beseitigt.

Hier der [Adult Dataset](http: //archive.ics.uci.), Der im UCI Machine Learning Repository veröffentlicht wurde. Verwenden Sie edu / ml / maschinelles Lernen / erwachsene /). Dieser Datensatz ist ein Datensatz zur Klassifizierung, ob das jährliche Einkommen einer Person 50.000 USD oder mehr beträgt, basierend auf Daten wie Geschlecht und Alter.

Laden Sie zunächst die zu verwendenden Daten. Hier in Adult Dataset Speichern Sie adult.data und adult.test lokal als CSV-Dateien und verwenden Sie erstere als Trainingsdaten und letztere als Verifizierungsdaten.

import numpy as np
import pandas as pd

#Daten lesen
train_data = pd.read_csv('./adult_data.csv', names=['age', 'workclass', 'fnlwgt', 'education', 'education-num', 
                                         'marital-status', 'occupation', 'relationship', 'race', 'sex', 
                                         'capital-gain', 'capital-loss', 'hours-per-week', 'native-country', 'obj'])
test_data = pd.read_csv('./adult_test.csv', names=['age', 'workclass', 'fnlwgt', 'education', 'education-num', 
                                         'marital-status', 'occupation', 'relationship', 'race', 'sex', 
                                         'capital-gain', 'capital-loss', 'hours-per-week', 'native-country', 'obj'],
                       skiprows=1)
data = pd.concat([train_data, test_data])

#Erklärende Variable X.,Verarbeitung der Zielvariablen Y.
X = pd.get_dummies(data.drop('obj', axis=1))
Y = data['obj'].map(lambda x: 1 if x==' >50K' or x==' >50K.' else 0) #Die Zielvariable ist 1 oder 0

#Unterteilt in Trainingsdaten und Verifizierungsdaten
train_size = len(train_data)
X_train, X_test = X.iloc[:train_size], X.iloc[train_size:] 
Y_train, Y_test = Y.iloc[:train_size], Y.iloc[train_size:]

Betrachtet man den Prozentsatz der positiven Fälle in den Trainingsdaten, so sind es ungefähr 24%, was weniger als die negativen Fälle ist und als unausgewogene Daten bezeichnet werden kann.

print('positive ratio = {:.2f}%'.format((len(Y_train[Y_train==1])/len(Y_train))*100))
#Ausgabe=> positive ratio = 24.08%

Wenn Sie ein Modell mit diesen Trainingsdaten erstellen, können Sie feststellen, dass die Klassifizierungsgenauigkeit nur AUC = 0,57 und die Rückrufrate (Recall) nur 0,26 beträgt. Es wird angenommen, dass die Anzahl der negativen Beispiele in den Trainingsdaten groß ist, das Vorhersageergebnis häufig negativ ist und die Rückrufrate (die Rate, mit der positive Daten korrekt als positiv klassifiziert werden können) niedrig ist.

from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score, recall_score

#Modellbau
lr = LogisticRegression(random_state=0)
lr.fit(X_train, Y_train)

#Überprüfen Sie die Klassifizierungsgenauigkeit
prob = lr.predict_proba(X_test)[:, 1] #Sagen Sie die Wahrscheinlichkeit voraus, dass die Zielvariable 1 ist
pred = lr.predict(X_test) #Klassifiziert als 1 oder 0
auc = roc_auc_score(y_true=Y_test, y_score=prob)
print('AUC = {:.2f}'.format(auc))
recall = recall_score(y_true=Y_test, y_pred=pred)
print('recall = {:.2f}'.format(recall))

#Ausgabe=> AUC = 0.57
#Ausgabe=> recall = 0.26

Als nächstes wird eine Unterabtastung durchgeführt, so dass die Anzahl der negativen Beispiele in den Trainingsdaten gleich der Anzahl der positiven Beispiele ist, und wenn ein Modell unter Verwendung dieser Daten konstruiert wird, wird die Klassifizierungsgenauigkeit stark auf AUC = 0,90 und Rückruf = 0,86 verbessert. Sie können sehen, dass

#Unterabtastung
pos_idx = Y_train[Y_train==1].index
neg_idx = Y_train[Y_train==0].sample(n=len(Y_train[Y_train==1]), replace=False, random_state=0).index
idx = np.concatenate([pos_idx, neg_idx])
X_train_sampled = X_train.iloc[idx]
Y_train_sampled = Y_train.iloc[idx]

#Modellbau
lr = LogisticRegression(random_state=0)
lr.fit(X_train_sampled, Y_train_sampled)

#Überprüfen Sie die Klassifizierungsgenauigkeit
prob = lr.predict_proba(X_test)[:, 1]
pred = lr.predict(X_test)
auc = roc_auc_score(y_true=Y_test, y_score=prob)
print('AUC = {:.2f}'.format(auc))
recall = recall_score(y_true=Y_test, y_pred=pred)
print('recall = {:.2f}'.format(recall))

#Ausgabe=> AUC = 0.90
#Ausgabe=> recall = 0.86

Schauen wir uns zu diesem Zeitpunkt die Vorhersagegenauigkeit der Wahrscheinlichkeit an. Sie können sehen, dass der Protokollverlust 0,41 beträgt und das Kalibrierungsdiagramm unterhalb der 45-Grad-Linie verläuft. Die Tatsache, dass das Kalibrierungsdiagramm unterhalb der 45-Grad-Linie verläuft, bedeutet, dass die vorhergesagte Wahrscheinlichkeit größer als die tatsächliche Wahrscheinlichkeit ist. Da das Modell unter Verwendung von unterabgetasteten Daten so konstruiert ist, dass die Anzahl der negativen Beispieldaten gleich der Anzahl der positiven Beispieldaten ist, wird das Lernen mit dem Verhältnis der Anzahl der positiven Beispieldaten durchgeführt, das größer als die tatsächliche Anzahl ist. Es wird angenommen, dass die Wahrscheinlichkeit ziemlich hoch ist.

import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.calibration import calibration_curve
from sklearn.metrics import  log_loss

def calibration_plot(y_true, y_prob):
    prob_true, prob_pred = calibration_curve(y_true=y_true, y_prob=y_prob, n_bins=20)

    fig, ax1 = plt.subplots()
    ax1.plot(prob_pred, prob_true, marker='s', label='calibration plot', color='skyblue') #Erstellen Sie ein Kalibrierungsdiagramm
    ax1.plot([0, 1], [0, 1], linestyle='--', label='ideal', color='limegreen') #Zeichnen Sie die 45-Grad-Linie
    ax1.legend(bbox_to_anchor=(1.12, 1), loc='upper left')
    plt.xlabel('predicted probability')
    plt.ylabel('actual probability')
    
    ax2 = ax1.twinx() #2 Achsen hinzugefügt
    ax2.hist(prob, bins=20, histtype='step', color='orangered') #Plot mit Score-Histogramm
    plt.ylabel('frequency')
    plt.show()

prob = lr.predict_proba(X_test)[:, 1]
loss = log_loss(y_true=Y_test, y_pred=prob)
print('log loss = {:.2f}'.format(loss))
calibration_plot(y_true=Y_test, y_prob=prob)

#Ausgabe=> log loss = 0.41

image.png

Entfernen wir nun die Verzerrung aufgrund von Unterabtastung und korrigieren die Wahrscheinlichkeit. Berechnen Sie $ \ beta $ und $ Wenn Sie die Wahrscheinlichkeit gemäß p = \ beta p_s / (\ beta p_s-p_s + 1 $) korrigieren, können Sie sehen, dass sich der Protokollverlust auf 0,32 verbessert hat und das Kalibrierungsdiagramm fast auf der 45-Grad-Linie lag. Beachten Sie, dass $ \ beta $ die Anzahl der positiven / negativen Beispiele für Trainingsdaten verwendet (die Anzahl der positiven / negativen Beispiele für Verifizierungsdaten ist unbekannt).

beta = len(Y_train[Y_train==1]) / len(Y_train[Y_train==0])
prob_corrected = beta*prob / (beta*prob - prob + 1)

loss = log_loss(y_true=Y_test, y_pred=prob_corrected)
print('log loss = {:.2f}'.format(loss))
calibration_plot(y_true=Y_test, y_prob=prob_corrected)

#Ausgabe=> log loss = 0.32

image.png

Es wurde bestätigt, dass die Verzerrung aufgrund von Unterabtastung entfernt und die Wahrscheinlichkeit korrigiert werden kann. Das ist alles zur Überprüfung.

abschließend

In diesem Artikel habe ich kurz zusammengefasst, wie die Wahrscheinlichkeit korrigiert werden kann, die von einem Modell vorhergesagt wird, das unter Verwendung von unterabgetasteten Daten erstellt wurde. Ich würde mich freuen, wenn Sie auf Fehler hinweisen könnten.

Referenz

Recommended Posts

Wahrscheinlichkeitsvorhersage von unausgeglichenen Daten
Abtastung in unausgeglichenen Daten
Vorverarbeitung von Präfekturdaten
Auswahl der Messdaten
Experiment zur Optimierung der Tensorflow-Daten
Visualisierung von Daten nach Präfektur
Vorhersage des Nikkei-Durchschnitts mit Pytorch 2
Fourier-Transformation von Rohdaten
Durchschnittliche Schätzung der begrenzten Daten
Vorhersage des Nikkei-Durchschnitts mit Pytorch
Ist die Niederschlagswahrscheinlichkeit korrekt?
Umgang mit unausgeglichenen Daten
Datenvorhersagewettbewerb in 3 Schritten (titanisch)
Speichersparende Matrixkonvertierung von Protokolldaten
Vorhersage der Sinuswelle mit Keras
Differenzierung von Zeitreihendaten (diskret)
10 Auswahlen der Datenextraktion durch pandas.DataFrame.query
Animation von Geodaten durch Geopandas
Empfehlung zur Datenanalyse mit MessagePack
Zeitreihenanalyse 3 Vorverarbeitung von Zeitreihendaten
Datenverarbeitung 2 Analyse verschiedener Datenformate
4/22 Vorhersage der Sinuswelle mit Keras
Zusammenfassung der Wahrscheinlichkeitsverteilungen, die häufig in Statistiken und Datenanalysen vorkommen
Python: Vorverarbeitung beim maschinellen Lernen: Umgang mit fehlenden / Ausreißern / unausgeglichenen Daten