Hier ist ein Beispiel für die Expectation Maximization (EM), mit der der Mittelwert und die Standardabweichung geschätzt werden. Der Code ist in Python, aber es sollte leicht zu befolgen sein, auch wenn Sie nicht mit der Sprache vertraut sind.
Die Motivation für EM
Die unten gezeigten roten und blauen Punkte stammen aus zwei verschiedenen Normalverteilungen mit jeweils einem bestimmten Mittelwert und einer bestimmten Standardabweichung:
Um vernünftige Annäherungen der "wahren" Mittel- und Standardabweichungsparameter für die Rotverteilung zu berechnen, könnten wir sehr einfach die roten Punkte betrachten und die Position von jedem aufzeichnen und dann die bekannten Formeln verwenden (und ähnlich für die blaue Gruppe) .
Betrachten Sie nun den Fall, in dem wir wissen, dass es zwei Gruppen von Punkten gibt, wir jedoch nicht sehen können, welcher Punkt zu welcher Gruppe gehört. Mit anderen Worten, die Farben sind versteckt:
Es ist überhaupt nicht klar, wie man die Punkte in zwei Gruppen aufteilt. Wir können jetzt nicht nur die Positionen betrachten und Schätzungen für die Parameter der Rotverteilung oder der Blauverteilung berechnen.
Hier kann EM zur Lösung des Problems eingesetzt werden.
Verwenden von EM zum Schätzen von Parametern
Hier ist der Code, der zum Generieren der oben gezeigten Punkte verwendet wird. Sie können die tatsächlichen Mittelwerte und Standardabweichungen der Normalverteilungen sehen, aus denen die Punkte gezogen wurden. Die Variablen red
und blue
halten die Positionen der einzelnen Punkte in der roten bzw. der blauen Gruppe:
import numpy as np
from scipy import stats
np.random.seed(110) # for reproducible random results
# set parameters
red_mean = 3
red_std = 0.8
blue_mean = 7
blue_std = 2
# draw 20 samples from normal distributions with red/blue parameters
red = np.random.normal(red_mean, red_std, size=20)
blue = np.random.normal(blue_mean, blue_std, size=20)
both_colours = np.sort(np.concatenate((red, blue)))
Wenn wir die Farbe jedes Punktes sehen könnten , würden wir versuchen, Mittelwerte und Standardabweichungen mithilfe von Bibliotheksfunktionen wiederherzustellen:
>>> np.mean(red)
2.802
>>> np.std(red)
0.871
>>> np.mean(blue)
6.932
>>> np.std(blue)
2.195
Aber da die Farben uns verborgen sind, werden wir den EM-Prozess starten ...
Zuerst raten wir nur die Werte für die Parameter jeder Gruppe ( Schritt 1 ). Diese Vermutungen müssen nicht gut sein:
# estimates for the mean
red_mean_guess = 1.1
blue_mean_guess = 9
# estimates for the standard deviation
red_std_guess = 2
blue_std_guess = 1.7
Ziemlich schlechte Vermutungen - die Mittelwerte sehen so aus, als wären sie weit von einer "Mitte" einer Gruppe von Punkten entfernt.
Um mit EM fortzufahren und diese Vermutungen zu verbessern, berechnen wir die Wahrscheinlichkeit, dass jeder Datenpunkt (unabhängig von seiner geheimen Farbe) unter diesen Vermutungen für den Mittelwert und die Standardabweichung erscheint ( Schritt 2 ).
Die Variable both_colours
enthält jeden Datenpunkt. Die Funktion stats.norm
berechnet die Wahrscheinlichkeit des Punktes unter Normalverteilung mit den angegebenen Parametern:
likelihood_of_red = stats.norm(red_mean_guess, red_std_guess).pdf(both_colours)
likelihood_of_blue = stats.norm(blue_mean_guess, blue_std_guess).pdf(both_colours)
Dies zeigt uns zum Beispiel, dass der Datenpunkt bei 1,761 nach unseren derzeitigen Schätzungen viel wahrscheinlicher rot (0,189) als blau (0,00003) ist.
Wir können diese beiden Wahrscheinlichkeitswerte in Gewichtungen umwandeln ( Schritt 3 ), sodass sie wie folgt zu 1 summieren:
likelihood_total = likelihood_of_red + likelihood_of_blue
red_weight = likelihood_of_red / likelihood_total
blue_weight = likelihood_of_blue / likelihood_total
Mit unseren aktuellen Schätzungen und unseren neu berechneten Gewichten können wir jetzt neue, wahrscheinlich bessere Schätzungen für die Parameter berechnen ( Schritt 4 ). Wir brauchen eine Funktion für den Mittelwert und eine Funktion für die Standardabweichung:
def estimate_mean(data, weight):
return np.sum(data * weight) / np.sum(weight)
def estimate_std(data, weight, mean):
variance = np.sum(weight * (data - mean)**2) / np.sum(weight)
return np.sqrt(variance)
Diese sehen hinsichtlich Mittelwert und Standardabweichung der Daten den üblichen Funktionen sehr ähnlich. Der Unterschied besteht in der Verwendung eines weight
Parameters, der jedem Datenpunkt eine Gewichtung zuweist.
Diese Gewichtung ist der Schlüssel zu EM. Je größer das Gewicht einer Farbe auf einem Datenpunkt ist, desto stärker beeinflusst der Datenpunkt die nächsten Schätzungen für die Parameter dieser Farbe. Letztendlich hat dies den Effekt, dass jeder Parameter in die richtige Richtung gezogen wird.
Die neuen Vermutungen werden mit diesen Funktionen berechnet:
# new estimates for standard deviation
blue_std_guess = estimate_std(both_colours, blue_weight, blue_mean_guess)
red_std_guess = estimate_std(both_colours, red_weight, red_mean_guess)
# new estimates for mean
red_mean_guess = estimate_mean(both_colours, red_weight)
blue_mean_guess = estimate_mean(both_colours, blue_weight)
Der EM-Prozess wird dann mit diesen neuen Annahmen ab Schritt 2 wiederholt. Wir können die Schritte für eine bestimmte Anzahl von Iterationen (z. B. 20) wiederholen oder bis die Parameter konvergieren.
Nach fünf Iterationen sehen wir, dass sich unsere anfänglichen Fehleinschätzungen verbessern:
Nach 20 Iterationen ist der EM-Prozess mehr oder weniger konvergiert:
Zum Vergleich werden hier die Ergebnisse des EM-Prozesses mit den berechneten Werten verglichen, bei denen die Farbinformationen nicht verborgen sind:
| EM guess | Actual
----------+----------+--------
Red mean | 2.910 | 2.802
Red std | 0.854 | 0.871
Blue mean | 6.838 | 6.932
Blue std | 2.227 | 2.195
Hinweis: Diese Antwort wurde von meiner Antwort auf Stack Overflow hier angepasst .