Lineare Regression
Kurz gesagt: Die lineare Regression sagt eine Zahl mit einer Geraden y = w · x + b voraus, und der mittlere quadratische Fehler (MSE) sagt in einer Zahl, wie gut die Gerade zu den Daten passt.
Problem
Zwei Kollegen, zwei Geraden
Das Lager will Stunden versprechen, nicht Tage. Hier sind 10 frühere Bestellungen: die Entfernung und wie viele Stunden sie gedauert haben.
// frühere Bestellungen: Entfernung in km und Stunden bis zur Lieferungdouble[] km = [30, 50, 80, 100, 130, 160, 200, 240, 270, 300];double[] hours = [10, 11, 17, 17, 23, 24, 31, 33, 40, 44];Zwei Kollegen schauen sich die Punkte an und schlagen jeweils eine Regel vor:
- Gerade A: Jeder Kilometer gibt 0,08 Stunden dazu, plus 12 Stunden im Lager;
- Gerade B: Jeder Kilometer gibt 0,12 Stunden dazu, plus 6 Stunden im Lager.
Im Diagramm sehen beide ordentlich aus. Die Kollegen streiten den ganzen Nachmittag. Der Streit endet erst, wenn sie eine Zahl haben, die sagt, wie gut eine Gerade ist.
Die Idee
Die Gerade als Modell
Beide Vorschläge sind von derselben Art: Stunden = w · km + b.
- w ist die Steigung: wie viele Stunden jeder Kilometer dazugibt;
- b ist der Achsenabschnitt: die Stunden bei 0 km, also die Bearbeitung im Lager.
Ein Modell, das eine Zahl mit einer Geraden vorhersagt, heißt lineare Regression. Das Modell zu trainieren heißt, w und b zu wählen.
// die Gerade: Stunden = w · km + bstatic double Predict(double w, double b, double km) => w * km + b;Anders als die k nächsten Nachbarn merkt sich die Gerade die Bestellungen nicht. Es sind zwei Zahlen, und eine Vorhersage ist eine Multiplikation und eine Addition. Und sie setzt ihre Steigung fort: Für 500 km sagt sie 0,12 · 500 + 6 = 66 Stunden, während die Nachbarn von 500 km die Bestellungen von 300 km sind.
Die Idee
Der Fehler jeder Bestellung
Für jede Bestellung sagt die Gerade irgendeine Zahl. Der Fehler ist der Unterschied: was die Gerade sagt minus was wirklich passiert ist. Er ist positiv, wenn die Gerade mehr verspricht, und negativ, wenn sie weniger verspricht.
Gerade B, Bestellung für Bestellung:
double w = 0.12, b = 6;for (var i = 0; i < km.Length; i++){ var guess = Predict(w, b, km[i]); Console.WriteLine($"{km[i]} km: tatsächlich {hours[i]} Std., Gerade {guess:F2} Std., Fehler {guess - hours[i]:F2}");}Console.WriteLine($"MSE: {Mse(w, b):F2}");30 km: tatsächlich 10 Std., Gerade 9.60 Std., Fehler -0.4050 km: tatsächlich 11 Std., Gerade 12.00 Std., Fehler 1.0080 km: tatsächlich 17 Std., Gerade 15.60 Std., Fehler -1.40100 km: tatsächlich 17 Std., Gerade 18.00 Std., Fehler 1.00130 km: tatsächlich 23 Std., Gerade 21.60 Std., Fehler -1.40160 km: tatsächlich 24 Std., Gerade 25.20 Std., Fehler 1.20200 km: tatsächlich 31 Std., Gerade 30.00 Std., Fehler -1.00240 km: tatsächlich 33 Std., Gerade 34.80 Std., Fehler 1.80270 km: tatsächlich 40 Std., Gerade 38.40 Std., Fehler -1.60300 km: tatsächlich 44 Std., Gerade 42.00 Std., Fehler -2.00MSE: 1.83Zehn Fehler, manche plus, manche minus. Wir brauchen eine Zahl für die ganze Gerade.
Die Idee
Eine Zahl: der mittlere Quadratwert
Jeder Fehler wird quadriert, die Quadrate werden addiert und durch die Zahl der Bestellungen geteilt. Das ist der mittlere quadratische Fehler, kurz MSE. Eine Zahl, die sagt, wie schlecht ein Modell ist, heißt Verlustfunktion (Verlust). Weniger ist besser, und 0 heißt, die Gerade geht durch jeden Punkt.
// der Mittelwert der quadrierten Fehler (MSE)double Mse(double w, double b){ double sum = 0; for (var i = 0; i < km.Length; i++) { var error = Predict(w, b, km[i]) - hours[i]; sum += error * error; } return sum / km.Length;}Warum ein Quadrat? Vergleiche drei Geraden. C ist die flache Gerade durch den Mittelwert, 25 Stunden für jede Bestellung:
// der mittlere Fehler ohne Quadratdouble MeanError(double w, double b){ double sum = 0; for (var i = 0; i < km.Length; i++) { sum += Predict(w, b, km[i]) - hours[i]; } return sum / km.Length;}string[] names = ["A", "B", "C"];double[] ws = [0.08, 0.12, 0];double[] bs = [12, 6, 25];for (var i = 0; i < names.Length; i++){ Console.WriteLine($"Gerade {names[i]}: MSE {Mse(ws[i], bs[i]):F2}, mittlerer Fehler {MeanError(ws[i], bs[i]):F2}");}Gerade A: MSE 17.35, mittlerer Fehler -0.52Gerade B: MSE 1.83, mittlerer Fehler -0.28Gerade C: MSE 124.00, mittlerer Fehler 0.00Ohne das Quadrat hat Gerade C einen mittleren Fehler von 0,00: Sie liegt genauso oft über den Punkten wie darunter, und die Plusse heben die Minusse auf. Die schlechteste Gerade „gewinnt“. Mit dem Quadrat hebt sich nichts auf: C ist 124, A ist 17,35 und B ist 1,83. Der Kollege mit Gerade B gewinnt den Streit.
Das Quadrat tut noch etwas anderes: Ein großer Fehler wiegt mehr. Ein Fehler von 4 Stunden ergibt 16, zwei Fehler von je 2 Stunden ergeben zusammen 8. Eine Gerade, die überall ein bisschen falsch liegt, ist besser als eine, die bei der Hälfte der Bestellungen genau ist und bei der anderen Hälfte sehr falsch.
Sieh es dir an
Die Fehler als Quadrate
static double Predict(double w, double b, double km) => w * km + b;
double Mse(double w, double b){ double sum = 0; for (var i = 0; i < km.Length; i++) { var error = Predict(w, b, km[i]) - hours[i]; sum += error * error; } return sum / km.Length;}Schritt für Schritt, in Worten
- 10 frühere Bestellungen: wie viele km und nach wie vielen Stunden sie ankamen.
- Gerade A: 0,08 Stunden pro km plus 12 Stunden.
- Der Fehler jeder Bestellung: was die Gerade sagt minus was wirklich war. Manche Punkte liegen über der Geraden, manche darunter.
- Jeder quadrierte Fehler ist ein Quadrat, dessen Seite der Fehler ist. Die mittlere Fläche ist der MSE: 17,35.
- Gerade B: 0,12 Stunden pro km plus 6 Stunden. Die Gerade dreht sich, und die Quadrate schrumpfen.
- Der MSE von B ist 1,83, gegen 17,35 bei A.
- Die Gerade mit dem kleineren MSE liegt näher an den Punkten. Eine Zahl statt eines Streits.
Jedes Quadrat ist ein quadrierter Fehler: Seine Seite ist der Abstand vom Punkt zur Geraden. Der MSE ist ihre mittlere Fläche. Gerade B ist besser, weil ihre Quadrate kleiner sind, nicht weil jemand es so findet.
Probier es aus
Sage die Ausgabe voraus
Der Kurier berechnet 2 € pro Kilogramm. Drei Pakete von 1, 2 und 3 kg kosten 3 €, 5 € und 7 €. Was gibt das Programm aus?
double[] kg = [1, 2, 3];double[] price = [3, 5, 7];double sum = 0;for (var i = 0; i < 3; i++){ var error = 2 * kg[i] - price[i]; sum += error * error;}Console.WriteLine($"{sum / 3:F2}");Die Gerade 2 · kg ergibt 2 €, 4 € und 6 €, und die Wahrheit ist 3 €, 5 € und 7 €. Jeder Fehler ist −1, und sein Quadrat ist 1. Der Mittelwert von 1, 1 und 1 ist 1.00. Der MSE kann nicht negativ sein.
Probier es aus
Ergänze
Was wird für jede Bestellung zur Summe addiert?
var error = Predict(w, b, km[i]) - hours[i];
sum += ;Das Quadrat des Fehlers: error * error. Eine Multiplikation ist klarer und schneller als das Potenzieren, und das Ergebnis ist dasselbe.
Probier es aus
Finde den Fehler
Ein Kollege schreibt die Verlustfunktion und vergleicht die Geraden. Sein Programm sagt, die beste sei die flache Gerade C. In welcher Zeile steckt der Fehler?
Wähle die Zeile mit dem Fehler.
Der Fehler wird ohne das Quadrat addiert. Die Plusse und Minusse heben sich auf, und die Gerade durch den Mittelwert bekommt den Fehler 0. Es sollte error * error heißen.
Die Idee
Wenn die Gerade lügt
Die Gerade ist das einfachste Modell und reicht oft aus. Aber:
- Die Welt ist nicht gerade. Wenn die Bestellung nach 300 km über ein anderes Lager läuft und noch einen Tag wartet, bilden die Punkte eine Stufe. Die Gerade verläuft zwischen den beiden Teilen und liegt bei beiden falsch.
- Ein seltsamer Punkt. Eine Bestellung, die eine Woche verloren war, ist ein Fehler von Hunderten Stunden, und sein Quadrat wiegt so viel wie alle anderen zusammen. Die Gerade neigt sich zu ihm und fängt an, über die normalen Bestellungen zu lügen. Solche Punkte prüft man und entfernt sie, oder man misst mit dem mittleren absoluten Fehler.
- Weit außerhalb der Daten. Die Bestellungen reichen bis 300 km. Für 2.000 km sagt die Gerade 246 Stunden, aber niemand hat geprüft, ob es eine solche Lieferung überhaupt gibt.
- Ein Zusammenhang ist keine Ursache. Die Gerade sagt, dass weiter entfernte Bestellungen länger unterwegs sind. Sie sagt nicht, warum. Wenn die weiter entfernten Städte einfach von einem langsameren Kurier beliefert werden, zerstört ein schnellerer Kurier dort die Gerade.
Die Gerade, die die Kollegen nach Augenmaß gewählt haben, ist nur eine von unzähligen Kombinationen aus w und b. Welche die beste ist und wie man sie ohne Raten findet, steht in der Lektion über den Gradientenabstieg.
Genauer, für Neugierige
Die Formel für die beste Gerade. Für eine Gerade gibt es eine exakte Formel (die Methode der kleinsten Quadrate). w ist, wie stark sich km und Stunden gemeinsam bewegen, geteilt durch die Bewegung der km allein. b ist so gewählt, dass die Gerade durch den Mittelpunkt der Daten geht:
w = Σ (km − Mittelwert km) · (Stunden − Mittelwert Stunden) / Σ (km − Mittelwert km)², b = Mittelwert Stunden − w · Mittelwert km.
var n = km.Length;double meanKm = 0, meanHours = 0;for (var i = 0; i < n; i++){ meanKm += km[i]; meanHours += hours[i];}meanKm /= n;meanHours /= n;double top = 0, bottom = 0;for (var i = 0; i < n; i++){ top += (km[i] - meanKm) * (hours[i] - meanHours); bottom += (km[i] - meanKm) * (km[i] - meanKm);}var w = top / bottom;var b = meanHours - w * meanKm;Console.WriteLine($"die beste Gerade: {w:F4} Std./km, {b:F2} Std.");Console.WriteLine($"MSE: {Mse(w, b):F2}");die beste Gerade: 0.1241 Std./km, 5.64 Std.MSE: 1.62Die beste Gerade ist etwas besser als B (1,62 gegen 1,83). Der Kollege hat gut geurteilt.
Warum nicht immer die Formel? Sie gilt für eine Gerade mit dem quadratischen Fehler. Mit vielen Merkmalen, mit einer anderen Verlustfunktion und bei neuronalen Netzen gibt es keine exakte Formel, oder sie ist zu langsam. Deshalb nimmt man den Gradientenabstieg.
Mehr Merkmale. Die Gerade kann ein w pro Merkmal haben: Stunden = w₁ · km + w₂ · kg + w₃ · Pakete + b. Die Idee und der MSE sind dieselben.
Der mittlere absolute Fehler (MAE) addiert |Fehler| statt des Quadrats. Er bestraft einen großen Fehler nicht so stark und reagiert ruhiger auf seltsame Punkte. Der MSE ist glatter und deshalb für den Gradientenabstieg bequemer.
In den Bibliotheken: LinearRegression in scikit-learn berechnet genau diese Formel. In ML.NET ist es die Regression Sdca oder Ols.
Übung
Der Preis des Kuriers
Löse die Aufgabe in deinem Editor.
Der Kurier veröffentlicht seine Preisliste nicht, aber der Shop hat festgehalten, was er für acht Pakete gezahlt hat:
// Pakete: Gewicht in kg und der Preis des Kuriers in €double[] kg = [0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0, 6.0];double[] eur = [4.10, 4.60, 5.00, 5.60, 6.40, 7.50, 8.30, 9.40];Die Kollegen schlagen drei Geraden für den Preis vor: A ist 0,90 € pro kg plus 3,80 €, B ist 1,10 € pro kg plus 3,20 €, C ist 0,70 € pro kg plus 4,60 €. Schreibe die Verlustfunktion (MSE), gib sie für alle drei aus und sage, welche die beste ist.
Gerade A (0.90 €/kg + 3.80 €): MSE 0.0144Gerade B (1.10 €/kg + 3.20 €): MSE 0.0769Gerade C (0.70 €/kg + 4.60 €): MSE 0.2869kleinster MSE: Gerade AWeitere Aufgaben
- Der mittlere absolute Fehler. Ersetze das Quadrat durch den Betrag. Ändert sich der Gewinner?
- Die Formel. Berechne die beste Gerade mit der Formel aus „Genauer, für Neugierige“. Wie viel besser als A ist sie?
Test
Teste dich
Verwandte Lektionen
Abschnitt „Verwandte Lektionen“- Baut auf: Methoden · Parameter und return · static: was alle Objekte teilen · Was maschinelles Lernen ist
- Geht weiter in: Gradientenabstieg · Klassifikation: Betrug oder nicht · Überanpassung: Das Modell, das auswendig lernt · Das Neuron
- Aufgaben zum Thema: Wie ein Modell lernt