Читать книгу Praxiseinstieg Machine Learning mit Scikit-Learn, Keras und TensorFlow - Aurélien Géron - Страница 114
Formel 4-4: Normalengleichung
Оглавление= (XTX)–1 XT y
ist der Wert von θ, für den die Kostenfunktion minimal wird.
y ist ein Vektor der Zielwerte von y(1) bis y(m).
Erstellen wir einige annähernd lineare Daten, um diese Gleichung auszuprobieren (Abbildung 4-1):
import numpy as np
X = 2 * np.random.rand(100, 1)
y = 4 + 3* X + np.random.randn(100, 1)
Abbildung 4-1: Zufällig generierter linearer Datensatz
Berechnen wir nun mithilfe der Normalengleichung. Wir verwenden die Funktion inv() aus dem in NumPy enthaltenen Modul für lineare Algebra (np.linalg), um die Inversion der Matrix und die Methode dot() zur Matrizenmultiplikation zu berechnen:
X_b = np.c_[np.ones((100, 1)), X] # füge x0 = 1 zu jedem Datenpunkt hinzu
theta_best = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y)
Die eigentliche Funktion zum Generieren der Daten ist y = 4 + 3x1 + normalverteiltes Rauschen. Sehen wir einmal, was die Gleichung herausgefunden hat:
>>> theta_best
array([[4.21509616],
[2.77011339]])
Wir hatten gehofft, θ0 = 4 und θ1 = 3 anstelle von θ0 = 4,215 und θ1 = 2,770 zu erhalten. Das ist nah dran, aber durch das Rauschen wurde es unmöglich, die Parameter der ursprünglichen Funktion exakt zu reproduzieren.
Nun können Sie mithilfe von Vorhersagen treffen:
>>> X_new = np.array([[0], [2]])
>>> X_new_b = np.c_[np.ones((2, 1)), X_
new] # füge x0 = 1 zu jedem Datenpunkt hinzu
>>> y_predict = X_new_b.dot(theta_best)
>>> y_predict
array([[4.21509616],
[9.75532293]])
Anschließend plotten wir die Vorhersagen dieses Modells (Abbildung 4-2):
plt.plot(X_new, y_predict, "r-")
plt.plot(X, y, "b.")
plt.axis([0, 2, 0, 15])
plt.show()
Abbildung 4-2: Vorhersagen des linearen Regressionsmodells
Das Durchführen der linearen Regression mit Scikit-Learn ist einfach:2
>>> from sklearn.linear_model import LinearRegression
>>> lin_reg = LinearRegression()
>>> lin_reg.fit(X, y)
>>> lin_reg.intercept_, lin_reg.coef_
(array([4.21509616]), array([[2.77011339]]))
>>> lin_reg.predict(X_new)
array([[4.21509616],
[9.75532293]])
Die Klasse LinearRegression basiert auf der Funktion scipy.linalg.lstsq() (der Name steht für »Least Squares«), die Sie auch direkt aufrufen können:
>>> theta_best_svd, residuals, rank,s = np.linalg.lstsq(X_b, y, rcond=1e-6)
>>> theta_best_svd
array([[4.21509616],
[2.77011339]])
Diese Funktion berechnet = X+y, wobei es sich bei X+ um die Pseudoinverse von X handelt (genauer gesagt die Moore-Penrose-Inverse). Sie können np.linalg.pinv() verwenden, um sie direkt zu berechnen:
>>> np.linalg.pinv(X_b).dot(y)
array([[4.21509616],
[2.77011339]])
Die Pseudoinverse selbst wird mit einer Standard-Matrixfaktorisierungstechnik namens Singulärwertzerlegung (SWZ; Singular Value Decomposition, SVD) berechnet, die die Matrix X mit dem Trainingsdatensatz in die Matrixmultiplikation der drei Matrizen UΣVT zerlegt (siehe numpy.linalg.svd()). Die Pseudoinverse wird so berechnet: X+ = VΣ+UT. Um die Matrix Σ+ zu berechnen, nimmt der Algorithmus Σ und setzt alle Werte auf null, die kleiner als ein kleiner Schwellenwert sind, dann ersetzt er alle Nicht-null-Werte durch ihr Inverses und transponiert schließlich die so entstandene Matrix. Dieses Vorgehen ist effizienter als das Berechnen der Normalengleichung, zudem kommt sie mit Randfällen besser zurecht: Die Normalengleichung funktioniert eventuell nicht, wenn die Matrix XTX nicht invertierbar (also singulär) ist, wenn beispielsweise m < n oder wenn Features redundant sind. Aber die Pseudoinverse ist immer definiert.