Ось приклад максимізації очікування (EM), який використовується для оцінки середнього та стандартного відхилень. Код є в Python, але його слід легко дотримуватися, навіть якщо ви не знайомі з мовою.
Мотивація ЕМ
Червоні та сині точки, показані нижче, намальовані з двох різних нормальних розподілів, кожен з певним середнім та стандартним відхиленням:
Для обчислення розумних наближень до "справжнього" середнього та стандартного параметрів відхилення для розподілу червоного кольору ми могли б дуже легко подивитися на червоні точки та записати положення кожного з них, а потім використати знайомі формули (і аналогічно для синьої групи) .
Тепер розглянемо випадок, коли ми знаємо, що існує дві групи точок, але ми не можемо побачити, яка точка належить до якої групи. Іншими словами, кольори приховані:
Зовсім не очевидно, як розділити бали на дві групи. Зараз ми не можемо просто подивитися на позиції та обчислити параметри параметрів червоного чи синього розподілу.
Саме тут ЕМ можна використовувати для вирішення проблеми.
Використання ЕМ для оцінки параметрів
Ось код, який використовується для створення точок, показаних вище. Ви можете бачити фактичні середні та стандартні відхилення нормальних розподілів, з яких були проведені точки. Змінні red
та blue
утримують позиції кожної точки у червоній та синій групах відповідно:
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)))
Якби ми могли бачити колір кожної точки, ми б спробували відновити засоби та стандартні відхилення за допомогою функцій бібліотеки:
>>> np.mean(red)
2.802
>>> np.std(red)
0.871
>>> np.mean(blue)
6.932
>>> np.std(blue)
2.195
Але оскільки кольори приховані від нас, ми розпочнемо процес ЕМ ...
Спочатку ми просто вгадуємо значення для параметрів кожної групи ( крок 1 ). Ці здогадки не повинні бути хорошими:
# 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
Досить погані здогадки - засоби виглядають так, що вони далекі від будь-якої "середини" групи очок.
Для продовження ЕМ та вдосконалення цих здогадок, ми обчислюємо ймовірність появи кожної точки даних (незалежно від її секретного кольору) серед цих здогадок для середнього та стандартного відхилень ( крок 2 ).
Змінна both_colours
містить кожну точку даних. Функція stats.norm
обчислює ймовірність точки при нормальному розподілі із заданими параметрами:
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)
Це говорить нам, наприклад, що, за нашими теперішніми здогадами, точка даних у 1.761 набагато частіше буде червоною (0,189), ніж синьою (0,00003).
Ми можемо перетворити ці два значення ймовірності у ваги ( крок 3 ), щоб вони дорівнювали 1 наступним чином:
likelihood_total = likelihood_of_red + likelihood_of_blue
red_weight = likelihood_of_red / likelihood_total
blue_weight = likelihood_of_blue / likelihood_total
За нашими поточними оцінками та нашими щойно розрахованими вагами ми тепер можемо обчислити нові, ймовірно, кращі оцінки параметрів ( крок 4 ). Нам потрібна функція для середнього і функція для стандартного відхилення:
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)
Вони дуже схожі на звичайні функції на середнє та стандартне відхилення даних. Різниця полягає у використанні weight
параметра, який присвоює вагу кожній точці даних.
Це зважування є ключем до ЕМ. Чим більша вага кольору в точці даних, тим більше точка даних впливає на наступні оцінки параметрів цього кольору. Зрештою, це призводить до того, що кожен параметр потягне в правильному напрямку.
Нові здогадки обчислюються цими функціями:
# 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)
Потім процес ЕМ повторюється з цими новими здогадами з кроку 2. Ми можемо повторити кроки для заданої кількості ітерацій (скажімо, 20) або поки не побачимо, що параметри збігаються.
Після п'яти повторень ми бачимо, що наші початкові погані здогадки починають покращуватися:
Після 20 ітерацій процес ЕМ більш-менш сходився:
Для порівняння, ось результати EM процесу порівняно зі значеннями, обчисленими там, де інформація про кольори не прихована:
| 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
Примітка: ця відповідь була адаптована з моєї відповіді на тут .