Ich werde zu viel über die Modellvalidierung vergessen, daher hier ein Minimum an Dingen, an die man sich erinnern sollte. In diesem Artikel werde ich auf die wichtigsten Validierungsmethoden wie Hold-out-Methode und Kreuzvalidierung sowie den Umgang mit Zeitreihendaten eingehen. Referenzen: [Kaggle-Buch](https://www.amazon.co.jp/Kaggle%E3%81%A7%E5%8B%9D%E3%81%A4%E3%83%87%E3%83% BC% E3% 82% BF% E5% 88% 86% E6% 9E% 90% E3% 81% AE% E6% 8A% 80% E8% A1% 93-% E9% 96% 80% E8% 84% 87 -% E5% A4% A7% E8% BC% 94 / dp / 4297108437 / ref = sr_1_1_sspa? __Mk_ja_JP =% E3% 82% AB% E3% 82% BF% E3% 82% AB% E3% 83% 8A & Schlüsselwörter = Kaggle % E3% 81% A7% E5% 8B% 9D% E3% 81% A4% E3% 83% 87% E3% 83% BC% E3% 82% BF% E5% 88% 86% E6% 9E% 90% E3 81%% AE% E6% 8A% 80% E8% A1% 93 & qid = 1583042364 & sr = 8-1-spons & PSC = 1 & sPLA = ZW5jcnlwdGVkUXVhbGlmaWVyPUExTkhDNkExUTRFMzQ2JmVuY3J5cHRlZElkPUEwMzc3MjMyMzFUQ0g5SERIQ1BDSiZlbmNyeXB0ZWRBZElkPUFMT0hMWThLWFhJNDUmd2lkZ2V0TmFtZT1zcF9hdGYmYWN0aW9uPWNsaWNrUmVkaXJlY3QmZG9Ob3RMb2dDbGljaz10cnVl)
Es wurde bestätigt, dass der Code im Artikel unter Windows-10, Python 3.7.3 funktioniert.
import platform
print(platform.platform())
print(platform.python_version())
Lesen Sie Regressions- und binäre Klassifizierungsdatensätze aus sklearn.datasets.
from sklearn import datasets
import numpy as np
import pandas as pd
#Datensatz für die Regression
boston = datasets.load_boston()
boston_X = pd.DataFrame(boston.data, columns=boston.feature_names)
boston_y = pd.Series(boston.target)
#Binar-Klassifizierungsdatensatz
cancer = datasets.load_breast_cancer()
cancer_X = pd.DataFrame(cancer.data, columns=cancer.feature_names)
cancer_y = pd.Series(cancer.target)
Dies ist die einfachste und einfachste Methode. Speichern Sie einige zur Validierung und trainieren Sie das Modell mit dem Rest. Ich höre oft "Teilen wir es in 7: 3", aber wenn Sie darüber nachdenken, hängt es von der Datenmenge ab, sodass es kein festes Verhältnis gibt. Validierungsdaten können nicht zum Lernen verwendet werden. Wenn also die Datenmenge gering ist, sollte eine Kreuzvalidierung usw. in Betracht gezogen werden, die später beschrieben wird. Umgekehrt sollte die Hold-out-Methode verwendet werden, wenn sie sehr groß ist. Grundsätzlich mischen und teilen Sie die Daten. Zeitreihendaten werden jedoch nicht gemischt. Dies liegt daran, dass das Risiko besteht, zukünftige Informationen zu lernen (zu verlieren), wenn diese gemischt werden, während versucht wird, die Zukunft anhand vergangener Informationen vorherzusagen. Ich hatte einmal einen Fehler damit. Unten finden Sie den Code, der die Daten in 3: 1 unterteilt und mit einem Entscheidungsfaktor bewertet. Übrigens sind die Bewertungsindizes wie der Bestimmungskoeffizient zuvor in hier zusammengefasst.
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score
from sklearn.model_selection import train_test_split
tr_x, va_x, tr_y, va_y = train_test_split(boston_X, boston_y, test_size=0.25, random_state=2020, shuffle=True)
slr = LinearRegression()
slr.fit(tr_x, tr_y)
va_pred = slr.predict(va_x)
score = r2_score(va_y, va_pred)
print(score)
0.732147337324218
Eine Methode zum mehrmaligen Wiederholen der vorherigen Hold-out-Methode. Das Bild ist Rocket Empitsu. Nach der Auswertung des Modells in einem Block besteht der nächste Schritt darin, diesen Block zu den Trainingsdaten hinzuzufügen, in einem anderen Block auszuwerten usw. und die Anzahl der Blöcke zu wiederholen. Da Validierungsdaten nicht für das Training in der Hold-out-Methode verwendet werden können, wird die Kreuzvalidierung häufig ausgewählt, wenn die Datenmenge gering ist. Wenn die Anzahl der Blöcke = die Anzahl der Falten zunimmt, nehmen die Trainingsdaten zu, aber auch die Berechnungszeit. Dies hängt auch von der Datenmenge ab, aber ungefähr 4 oder 5 sind üblich. Betrachten Sie bei der Bewertung der Genauigkeit (Generalisierungsleistung) des Modells entweder die durchschnittliche Punktzahl jeder Falte oder berechnen Sie die Punktzahl erneut mit den vorhergesagten Werten aller Falten. Unten finden Sie den Kreuzvalidierungscode. Es ist nicht so einfach wie die Hold-Out-Methode, also vergiss es.
from sklearn.metrics import mean_absolute_error
from sklearn.model_selection import KFold
i = 0
scores = []
kf = KFold(n_splits=4, shuffle=True, random_state=2020)
for tr_idx, va_idx in kf.split(boston_X):
i += 1
tr_x, va_x = boston_X.iloc[tr_idx], boston_X.iloc[va_idx]
tr_y, va_y = boston_y.iloc[tr_idx], boston_y.iloc[va_idx]
slr = LinearRegression()
slr.fit(tr_x, tr_y)
va_pred = slr.predict(va_x)
score = mean_absolute_error(va_y, va_pred)
print('fold{}: {:.2f}'.format(i, score))
scores.append(score)
print(np.mean(scores))
fold1: 3.34 fold2: 3.39 fold3: 3.89 fold4: 3.02 3.4098095699116184
Die Validierung ist jetzt abgeschlossen, es gibt jedoch so viele Modelle wie Falten. Es muss irgendwie zusammengesetzt werden.
--Machen Sie den Durchschnitt jedes Falzmodells.
Es spielt keine Rolle, welches Sie verwenden, aber in der Praxis sollten Sie das in letzterem erstellte Modell speichern und betreiben. 4. stratified k-fold Dies ist die Methode für Klassifizierungsaufgaben. Zum Beispiel kann es bei der Aufgabe, als negativ oder positiv zu klassifizieren, bei extrem wenigen positiven Ergebnissen vorkommen, dass die Validierungsdaten nach zufälliger Aufteilung der Daten keine positiven enthalten. Daher besteht eine Motivation, eine geschichtete Stichprobe durchzuführen, damit der Anteil der in jeder Falte enthaltenen Klassen gleich ist. Im Gegenteil, wenn das Verhältnis ausgeglichen ist, gibt es nicht viel zu befürchten.
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import log_loss
from sklearn.model_selection import StratifiedKFold
# hold-Auch mit der out-Methode möglich
# tr_x, va_x, tr_y, va_y = train_test_split(cancer_X, cancer_y, test_size=0.25, random_state=2020, shuffle=True, stratify=cancer_y)
i = 0
scores = []
kf = StratifiedKFold(n_splits=4, shuffle=True, random_state=2020)
for tr_idx, va_idx in kf.split(cancer_X, cancer_y):
i += 1
tr_x, va_x = cancer_X.iloc[tr_idx], cancer_X.iloc[va_idx]
tr_y, va_y = cancer_y.iloc[tr_idx], cancer_y.iloc[va_idx]
lr = LogisticRegression(solver='liblinear')
lr.fit(tr_x, tr_y)
va_pred = lr.predict_proba(va_x)[:, 1]
score = log_loss(va_y, va_pred)
print('fold{}: {:.2f}'.format(i, score))
scores.append(score)
print(np.mean(scores))
fold1: 0.11 fold2: 0.17 fold3: 0.09 fold4: 0.07 0.11030074372001544
Davon abgesehen habe ich es nicht benutzt, aber es gibt so etwas, also werde ich nur die Methode aufschreiben. 5-1. group k-fold Eine Methode zum Teilen von Daten durch Variablen, die Gruppen darstellen. Zum Beispiel möchten wir bei einer Aufgabe wie dem Lernen der Kaufhistorie jedes Kunden und dem Bewerten neuer Kunden nicht, dass derselbe Kunde in den Trainingsdaten und Validierungsdaten koexistiert. Dies liegt daran, dass davon ausgegangen wird, dass die Antwort teilweise mit den Trainingsdaten gemischt ist (Leck). Wenn Sie die Daten anhand der Kunden-ID teilen möchten, führen Sie daher die Gruppe k-fach aus. Sie können eine Klasse namens "GroupKFold" verwenden. Es gibt jedoch keine Shuffle- und Random-Seeding-Funktion. 5-2. leave-one-out (LOO) Ich habe das auch nie benutzt. Es gibt extrem wenig Daten, und ich möchte die Anzahl von N so weit wie möglich erhöhen. → Es scheint eine radikale Methode zu sein, die Anzahl der Falten um die Anzahl der Datensätze zu erhöhen. Sie müssen lediglich die Anzahl der Datensätze in n_splits mit KFold angeben. Es gibt jedoch auch eine dedizierte Klasse namens "LeaveOneOut".
Das vielleicht Wichtigste in diesem Artikel ist, dass die Techniken, mit denen wir uns bisher befasst haben, nicht direkt für Zeitreihendaten verwendet werden sollten. Da Alt / Neu Information für sich ist, müssen Sie beim Lernen und Bewerten die Zeitreihen kennen.
Da sklearn.datasets nicht über die richtigen Zeitreihendaten verfügt, werden wir die Daten von SIGNATE ([Übungsfrage] Lunch Demand Forecast](https://signate.jp/competitions/24) verwenden.
import matplotlib.pyplot as plt
%matplotlib inline
#Daten gelesen
train = pd.read_csv('./train.csv')
#Schließen Sie alte Daten mit unterschiedlichen Trends aus
train.index = pd.to_datetime(train['datetime'])
train = train['2014-05-01':].copy()
#Handlung
train['y'].plot(figsize=(15, 3))
plt.show()
#Feature-Erstellung
train = train.reset_index(drop=True)
train['days'] = train.index
train['fun'] = train['remarks'].apply(lambda x: 1 if x == 'Spaßmenü' else 0)
train['curry'] = train['name'].apply(lambda x: 1 if x.find('Curry') >= 0 else 0)
train_X = train[['days', 'fun', 'curry']].copy()
train_y = train['y'].copy()
Grundsätzlich ist die Anzahl der Verkäufe rückläufig (negative Korrelation mit der Anzahl der Tage), sie wird jedoch bei beliebten Menüs (unterhaltsames Menü, Curry) erhöht. Wie weit können wir mit einer einfachen linearen Regression vorhersagen?
from sklearn.metrics import mean_squared_error
slr = LinearRegression()
slr.fit(train_X, train_y)
train['pred'] = slr.predict(train_X)
rmse = np.sqrt(mean_squared_error(train['y'], train['pred']))
print(rmse)
train.plot(y=['y', 'pred'], figsize=(15, 3))
plt.show()
10.548692191381326
Es ist ziemlich falsch, aber ich habe eine ungefähre Vorstellung. Ich werde auf das Thema Validierung zurückkommen, mit dem starken Wunsch, die Beziehung zwischen den Residuen und anderen Merkmalsgrößen zu sehen.
Am einfachsten ist wahrscheinlich die Nicht-Shuffle-Hold-Out-Methode. False sollte im Argument shuffle der Funktion train_test_split angegeben werden. Durch Lernen mit alten Daten und Auswerten mit neuen Daten können auch Zeitreihendaten problemlos validiert werden. Es ist jedoch immer noch eine Verschwendung, die Daten, die die neuesten oder neuesten Trends am besten widerspiegeln, nicht für Schulungen zu verwenden. Wenn die Generalisierungsleistung bestätigt werden kann, wird sie daher häufig mit allen Daten neu gelernt. Trotzdem wird es immer noch Beschwerden darüber geben, ob die Genauigkeit für andere Zeiträume verbessert wird oder einfach die Datenmenge nicht ausreicht, dh der Wunsch, die Daten effizienter zu nutzen. Daher wird eine Methode namens TimeSeries Split angezeigt. Die Idee selbst ist einfach, kurz gesagt, es handelt sich um eine Methode zur Kreuzvalidierung in chronologischer Reihenfolge. Trotzdem bin ich immer noch unzufrieden mit der Tatsache, dass die neuesten Daten nicht verwendet werden können und dass die Länge der Trainingsdaten für jede Falte unterschiedlich ist. Aber es ist besser, es zu benutzen.
from sklearn.model_selection import TimeSeriesSplit
i = 0
scores = []
tss = TimeSeriesSplit(n_splits=4)
for tr_idx, va_idx in tss.split(train_X):
i += 1
tr_x, va_x = train_X.iloc[tr_idx], train_X.iloc[va_idx]
tr_y, va_y = train_y.iloc[tr_idx], train_y.iloc[va_idx]
slr = LinearRegression()
slr.fit(tr_x, tr_y)
va_pred = slr.predict(va_x)
score = np.sqrt(mean_squared_error(va_y, va_pred))
print('fold{}: {:.2f}'.format(i, score))
scores.append(score)
print(np.mean(scores))
fold1: 20.29 fold2: 9.21 fold3: 15.05 fold4: 9.68 13.557202833084698
Es ist ein Ergebnis, das schwer zu beurteilen ist. Es ist interessant, dass sich die Genauigkeit mit zunehmender Menge an Trainingsdaten nicht verbessert. Es gibt noch Raum zum Experimentieren, aber es geht über den Rahmen dieses Artikels hinaus und endet hier.
Die Validierung von Zeitreihendaten ist daher schwierig, eindeutige Schlussfolgerungen zu ziehen. Insbesondere wenn sich der Trend in letzter Zeit ändert, ist es richtig, dass die Trainingsdaten die Validierungsdaten nicht erklären können, sondern dass das Modell unter Verwendung der Validierungsdaten trainiert werden sollte. Im Steuerungssystem ist es möglich, die Genauigkeit mit RMSE oder etwas anderem zu überwachen, zur vorhandenen Steuerung zurückzukehren, wenn der Schwellenwert überschritten wird, neu zu lernen, wenn die erforderliche Anzahl von Daten akkumuliert ist, und die Steuerung neu zu starten. Alternativ könnte die Idee sein, das Modell mit Online-Lernen ständig zu aktualisieren. Was ist mit dem Bedarfsprognosesystem? Da es nicht immer notwendig ist, einen bestimmten Zeitraum wie einen Wettbewerb vorherzusagen, kann ein ARIMA-Modell, das eine kurzfristige Autokorrelation berücksichtigt, effektiv sein. Ich möchte das nächste Mal das Nachfrageprognoseteam fragen.
Recommended Posts