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.
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
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).
Das Folgende ist eine detaillierte Erklärung der Formel. Wenn Sie also nicht interessiert sind, überspringen Sie sie bitte.
Satz von Bayes und
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_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.
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.
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
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
Es wurde bestätigt, dass die Verzerrung aufgrund von Unterabtastung entfernt und die Wahrscheinlichkeit korrigiert werden kann. Das ist alles zur Überprüfung.
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.
Recommended Posts