Betrachten wir ein Beispiel. Zunächst generieren wir einige nichtlineare Daten anhand einer einfachen quadratischen Gleichung7 (zuzüglich von etwas Rauschen; siehe Abbildung 4-12):
m = 100
X = 6 * np.random.rand(m, 1) - 3
y = 0.5 *X**2 + X + 2 + np.random.randn(m, 1)
Abbildung 4-12: Generierte nichtlineare verrauschte Daten
Offensichtlich lassen sich diese Daten nicht angemessen mit einer Geraden fitten. Daher verwenden wir die Scikit-Learn-Klasse PolynomialFeatures, um unsere Trainingsdaten zu transformieren und zu jedem Merkmal in den Trainingsdaten dessen Quadrat (das Polynom 2. Grades) als neues Merkmal hinzuzufügen (in diesem Fall gibt es nur ein Merkmal):
>>> from sklearn.preprocessing import PolynomialFeatures
>>> poly_features = PolynomialFeatures(degree=2, include_bias=False)
>>> X_poly = poly_features.fit_transform(X)
>>> X[0]
array([-0.75275929])
>>> X_poly[0]
array([-0.75275929, 0.56664654])
X_poly enthält jetzt das ursprüngliche Merkmal aus X sowie das Quadrat dieses Merkmals. Nun können Sie ein mit LinearRegression erstelltes Modell auf diese erweiterten Trainingsdaten anwenden (Abbildung 4-13):
>>> lin_reg = LinearRegression()
>>> lin_reg.fit(X_poly, y)
>>> lin_reg.intercept_, lin_reg.coef_
(array([ 1.78134581]), array([[ 0.93366893, 0.56456263]]))
Nicht schlecht: Das Modell schätzt ŷ = 0,5621 + 0,93x1 + 1,78, während die ursprüngliche Funktion y = 0,5x12 + 1,0x1 + 2,0 normalverteiltes Rauschen lautete.
Wenn es mehrere Merkmale gibt, ist die polynomielle Regression in der Lage, Wechselbeziehungen zwischen Merkmalen zu finden (was ein einfaches lineares Regressionsmodell nicht kann). Dies ist dadurch möglich, dass PolynomialFeatures bis zu einem bestimmten Grad sämtliche Kombinationen von Merkmalen hinzufügt. Wenn es beispielsweise zwei Merkmale a und b gibt, erzeugt PolynomialFeatures mit degree=3 nicht nur die Merkmale a2, a3, b2 und b3, sondern auch die Kombinationen ab, a2b und ab2.
Abbildung 4-13: Vorhersagen eines polynomiellen Regressionsmodells
|
PolynomialFeatures(degree=d) transformiert ein Array mit n Merkmalen in ein Array mit |
Lernkurven
Wenn Sie höhergradige polynomielle Regressionen durchführen, werden Sie die Trainingsdaten deutlich genauer fitten als mit einer gewöhnlichen linearen Regression. Beispielsweise wird in Abbildung 4-14 ein polynomielles Modell 300. Grades auf die obigen Trainingsdaten angewandt und das Ergebnis mit einem gewöhnlichen linearen Modell und einem quadratischen Modell (einem Polynom 2. Grades) verglichen. Achten Sie darauf, wie das Polynom 3. Grades hin und her schwankt, um so nah wie möglich an die Trainingsdatenpunkte zu gelangen.
Abbildung 4-14: Regression mit einem höhergradigen Polynom
Natürlich ist beim Modell mit der höhergradigen Regression sehr starkes Overfitting zu finden, während beim linearen Modell Underfitting vorliegt. In diesem Fall verallgemeinert das quadratische Modell am besten. Das ist sinnvoll, weil ja auch den Daten ein quadratisches Modell zugrunde liegt, aber im Allgemeinen wissen Sie nicht, mit welcher Funktion die Daten generiert wurden. Wie also sollen Sie entscheiden, wie komplex Ihr Modell sein muss? Woher wissen Sie, ob Overfitting oder Underfitting der Daten vorliegt?
In Kapitel 2 haben Sie eine Kreuzvalidierung durchgeführt, um die Verallgemeinerungsleistung des Modells abzuschätzen. Wenn ein Modell auf den Trainingsdaten gut, aber bei der Kreuzvalidierung schlecht abschneidet, liegt in Ihrem Modell Overfitting vor. Erbringt es bei beiden eine schlechte Leistung, ist es Underfitting. Auf diese Weise können Sie herausfinden, ob Ihr Modell zu einfach oder zu komplex ist.
Eine Alternative dazu ist, sich die Lernkurven anzusehen: Diese Diagramme zeigen die Leistung des Modells auf den Trainings- und den Validierungsdaten über der Größe des Trainingsdatensatzes (oder die Trainingsiterationen). Um diese Plots zu erzeugen, trainieren Sie einfach das Modell mehrmals auf unterschiedlich großen Teilmengen des Trainingsdatensatzes. Der folgende Code definiert eine Funktion, die die Lernkurve eines Modells anhand der Trainingsdaten plottet:
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
def plot_learning_curves(model, X, y):
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2)
train_errors, val_errors = [], []
for m in range(1, len(X_train)):
model.fit(X_train[:m], y_train[:m])
y_train_predict = model.predict(X_train[:m])
y_val_predict = model.predict(X_val)
train_errors.append(mean_squared_error(y_train[:m], y_train_predict))
val_errors.append(mean_squared_error(y_val, y_val_predict))
plt.plot(np.sqrt(train_errors), "r-+", linewidth=2, label="train")
plt.plot(np.sqrt(val_errors), "b-", linewidth=3, label="val")
Schauen wir uns die Lernkurven des einfachen linearen Regressionsmodells an (einer Geraden, Abbildung 4-15):
lin_reg = LinearRegression()
plot_learning_curves(lin_reg, X, y)
An dieser Stelle sind einige Erklärungen zum Underfitting-Modell angebracht. Zuerst betrachten wir die Vorhersageleistung auf den Trainingsdaten: Wenn der Trainingsdatensatz nur aus ein oder zwei Datenpunkten besteht, kann das Modell diese perfekt fitten. Deshalb beginnt die Kurve bei null. Aber sobald neue Datenpunkte hinzukommen, wird die perfekte Anpassung unmöglich, weil die Daten Rauschen enthalten und weil sie überhaupt nichtlinear sind. Daher steigt der Fehler auf den Trainingsdaten, bis er ein Plateau erreicht, bei dem zusätzliche Daten die durchschnittliche Abweichung weder verbessern noch verschlechtern.