Единственное руководство, которое вам нужно, чтобы узнать все о GMM

Когда мы говорим о смешанной модели Гаусса (позже в этой статье она будет обозначаться как GMM), важно знать, как работает алгоритм KMeans. Поскольку GMM очень похож на KMeans, скорее всего, это вероятностная версия KMeans. Эта вероятностная функция позволяет применять GMM ко многим сложным проблемам, с которыми не может справиться KMeans.

Таким образом, KMeans имеет следующие ограничения:

  1. Предполагается, что кластеры имеют сферическую форму и одинаковый размер, что неверно в большинстве реальных сценариев.
  2. Это жесткий метод кластеризации. Это означает, что каждая точка данных назначается одному кластеру.

Из-за этих ограничений мы должны знать альтернативы KMeans при работе над нашими проектами машинного обучения. В этой статье мы рассмотрим одну из лучших альтернатив кластеризации KMeans, называемую гауссовой смешанной моделью.

На протяжении всей этой статьи мы рассмотрим следующие пункты.

  1. Как работает алгоритм Gaussian Mixture Model (GMM) — простым языком.
  2. Математика позади GMM.
  3. Внедрите GMM с помощью Python с нуля.

Как работает алгоритм Gaussian Mixture Model (GMM) — простым языком

Как я упоминал ранее, мы можем называть GMM вероятностными KMeans, потому что отправная точка и процесс обучения KMeans и GMM одинаковы. Однако KMeans использует подход, основанный на расстоянии, а GMM использует вероятностный подход. В GMM есть одно основное предположение: набор данных состоит из нескольких гауссиан, другими словами, смесь гауссовых.

Вышеупомянутый вид распределения часто называют мультимодельным распределением. Каждый пик представляет собой различное распределение Гаусса или кластер в нашем наборе данных. Но вопрос в том,

как мы оцениваем эти распределения?

Прежде чем ответить на этот вопрос, давайте сначала создадим некоторое распределение Гаусса. Обратите внимание, здесь я генерирую многомерное нормальное распределение; это более многомерное расширение одномерного нормального распределения.

Давайте определим среднее значение и ковариацию наших точек данных. Используя среднее значение и ковариацию, мы можем сгенерировать распределение следующим образом.

# Set the mean and covariance
mean1 = [0, 0]
mean2 = [2, 0]
cov1 = [[1, .7], [.7, 1]]
cov2 = [[.5, .4], [.4, .5]]

# Generate data from the mean and covariance
data1 = np.random.multivariate_normal(mean1, cov1, size=1000)
data2 = np.random.multivariate_normal(mean2, cov2, size=1000)

Давайте построим данные.

plt.figure(figsize=(10,6))

plt.scatter(data1[:,0],data1[:,1])
plt.scatter(data2[:,0],data2[:,1])

sns.kdeplot(data1[:, 0], data1[:, 1], levels=20, linewidth=10, color='k', alpha=0.2)
sns.kdeplot(data2[:, 0], data2[:, 1], levels=20, linewidth=10, color='k', alpha=0.2)

plt.grid(False)
plt.show()

Как вы можете видеть здесь, мы сгенерировали случайное распределение Гаусса, используя матрицы среднего и ковариации. Как насчет того, чтобы повернуть этот процесс вспять? Именно этим занимается GMM. Но как?

Потому что вначале у нас не было никаких сведений о кластерах и связанных с ними средних и ковариационных матрицах.

Ну, это происходит в соответствии с приведенными ниже шагами,

  1. Определите количество кластеров (чтобы решить это, мы можем использовать знание предметной области или другие методы, такие как BIC/AIC) для данного набора данных. Предположим, что у нас есть 1000 точек данных, и мы установили количество групп равным 2.
  2. Инициируйте среднее значение, ковариацию и параметр веса для каждого кластера. (мы подробнее рассмотрим это в следующем разделе)
  3. Используйте алгоритм Максимизация ожидания, чтобы сделать следующее:
  • Шаг ожидания (шаг E): вычислить вероятность каждой точки данных, принадлежащей каждому распределению, затем оценить функцию правдоподобия, используя текущую оценку параметров.
  • Шаг максимизации (шаг M): обновите предыдущие параметры среднего, ковариации и веса, чтобы максимизировать ожидаемую вероятность, найденную на шаге E.
  • Повторяйте эти шаги, пока модель не сойдется.

На этой информации я завершаю нематематическое объяснение алгоритма GMM.

Математика позади GMM

Ядро GMM лежит в алгоритме максимизации ожиданий (EM), описанном в предыдущем разделе.

Давайте продемонстрируем, как алгоритм EM применяется в GMM.

Шаг 01. Инициализация параметров среднего, ковариации и веса

  1. среднее значение (μ): инициализировать случайным образом.
  2. ковариация (Σ): инициализировать случайным образом
  3. вес (коэффициенты смешивания) (π): доля на класс относится к вероятности того, что конкретная точка данных принадлежит каждому классу. Вначале это будет одинаково для всех кластеров. Предположим, что мы подбираем GMM с тремя компонентами. В этом случае весовой параметр может быть установлен равным 1/3 для каждого компонента, что приведет к распределению вероятностей (1/3, 1/3, 1/3).

Шаг 02. Ожидание (шаг E)

  • Для каждой точки данных 𝑥𝑖:
  • Рассчитайте вероятность того, что точка данных принадлежит кластеру (𝑐), используя приведенное ниже уравнение. k — это количество распределений, которые мы должны найти.

Где 𝜋_𝑐 — коэффициент смешивания (иногда называемый весом) для гауссовского распределения c, который был инициализирован на предыдущем этапе, а 𝑁(𝒙 | 𝝁,𝚺) описывает функцию плотности вероятности (PDF) распределение Гаусса со средним значением 𝜇 и ковариацией Σ относительно точки данных x; Мы можем обозначить это, как показано ниже.

E-шаг вычисляет эти вероятности, используя текущие оценки параметров модели. Эти вероятности обычно называют «обязанностями» гауссовых распределений. Они представлены переменными r_ic,где i — это индекс точки данных, а c — индекс распределения Гаусса. Ответственность измеряет, насколько c-е распределение Гаусса отвечает за создание i-й точки данных. Здесь используется условная вероятность, а точнее теорема Байеса.

Возьмем простой пример. Предположим, у нас есть 100 точек данных, и нам нужно сгруппировать их в две группы. Мы можем написать r_ic(i=20,c=1)следующим образом. Где iпредставляет индекс точки данных, а cпредставляет индекс рассматриваемого нами кластера .

Обратите внимание, что вначале 𝜋_𝑐 инициализируется равным для каждого кластера c = 1,2,3,..,k. В нашем случае 𝜋_1 = 𝜋_2=1/2.

Результатом E-этапа является набор обязанностей для каждой точки данных и каждого распределения Гаусса в смешанной модели. Эти обязанности используются на М-этапе для обновления оценок параметров модели.

Шаг 03. Шаг максимизации (шаг M)

На этом этапе алгоритм использует функции распределений Гаусса (вычисленные на этапе E) для обновления оценок параметров модели.

М-шаг обновляет оценки параметров следующим образом:

  1. Обновите πc (коэффициенты смешивания), используя приведенное выше уравнение 4.
  2. Обновите μc, используя уравнение номер 5 выше.
  3. Затем обновите Σc, используя 6-е уравнение.

Эта обновленная оценка используется на следующем шаге E для вычисления новых обязанностей для точек данных.

И так далее, и так далее, этот процесс будет повторяться до сходимости алгоритма, обычно достигаемой, когда параметры модели существенно не меняются от одной итерации к другой.

Много уродливых и сложных уравнений, верно? :)

Давайте суммируем приведенные выше факты в одну простую диаграмму,

Не волнуйся; когда дело доходит до кодирования, это будет одна строка на каждое уравнение. Давайте начнем реализовывать GMM с нуля, используя Python.

Внедрите GMM с помощью Python с нуля.

Прежде всего, давайте создадим поддельный набор данных. В этом разделе я реализую GMM для набора одномерных данных.

import numpy as np

n_samples = 100
mu1, sigma1 = -5, 1.2 
mu2, sigma2 = 5, 1.8 
mu3, sigma3 = 0, 1.6 

x1 = np.random.normal(loc = mu1, scale = np.sqrt(sigma1), size = n_samples)
x2 = np.random.normal(loc = mu2, scale = np.sqrt(sigma2), size = n_samples)
x3 = np.random.normal(loc = mu3, scale = np.sqrt(sigma3), size = n_samples)

X = np.concatenate((x1,x2,x3))

Давайте создадим вспомогательную функцию для построения графика наших данных.

from scipy.stats import norm

def plot_pdf(mu,sigma,label,alpha=0.5,linestyle='k--',density=True):
    """
    Plot 1-D data and its PDF curve.

    """
    # Compute the mean and standard deviation of the data

    # Plot the data
    
    X = norm.rvs(mu, sigma, size=1000)
    
    plt.hist(X, bins=50, density=density, alpha=alpha,label=label)

    # Plot the PDF
    x = np.linspace(X.min(), X.max(), 1000)
    y = norm.pdf(x, mu, sigma)
    plt.plot(x, y, linestyle)

И постройте сгенерированные данные следующим образом. Обратите внимание, что вместо построения самих данных я построил плотность вероятности для каждой выборки.

plot_pdf(mu1,sigma1,label=r"$\mu={} \ ; \ \sigma={}$".format(mu1,sigma1))
plot_pdf(mu2,sigma2,label=r"$\mu={} \ ; \ \sigma={}$".format(mu2,sigma2))
plot_pdf(mu3,sigma3,label=r"$\mu={} \ ; \ \sigma={}$".format(mu3,sigma3))
plt.legend()
plt.show()

Давайте построим каждый шаг, описанный в предыдущем разделе,

Шаг 01. Инициализируйте среднее значение, ковариацию и веса

def random_init(n_compenents):
    
    """Initialize means, weights and variance randomly 
      and plot the initialization
    """
    
    pi = np.ones((n_compenents)) / n_compenents
    means = np.random.choice(X, n_compenents)
    variances = np.random.random_sample(size=n_compenents)

    plot_pdf(means[0],variances[0],'Random Init 01')
    plot_pdf(means[1],variances[1],'Random Init 02')
    plot_pdf(means[2],variances[2],'Random Init 03')
    
    plt.legend()
    plt.show()
    
    return means,variances,pi

Шаг 02. Ожидание (этап E)

def step_expectation(X,n_components,means,variances):
    """E Step
    
    Parameters
    ----------
    X : array-like, shape (n_samples,)
        The data.
    n_components : int
        The number of clusters
    means : array-like, shape (n_components,)
        The means of each mixture component.
    variances : array-like, shape (n_components,)
        The variances of each mixture component.
        
    Returns
    -------
    weights : array-like, shape (n_components,n_samples)
    """
    weights = np.zeros((n_components,len(X)))
    for j in range(n_components):
        weights[j,:] = norm(loc=means[j],scale=np.sqrt(variances[j])).pdf(X)
    return weights

После этой функции мы рассмотрели первые два уравнения, которые мы обсуждали в E Step. Здесь мы сгенерировали гауссово распределение для текущего параметра модели среднееи дисперсии. Мы достигли этого, используя модуль статистики scipy. После этого мы использовали метод PDF для расчета вероятности принадлежности к каждой точке данных для каждого кластера.

Шаг 03. Шаг максимизации (шаг M)

def step_maximization(X,weights,means,variances,n_compenents,pi):
    """M Step
    
    Parameters
    ----------
    X : array-like, shape (n_samples,)
        The data.
    weights : array-like, shape (n_components,n_samples)
        initilized weights array
    means : array-like, shape (n_components,)
        The means of each mixture component.
    variances : array-like, shape (n_components,)
        The variances of each mixture component.
    n_components : int
        The number of clusters
    pi: array-like (n_components,)
        mixture component weights
        
    Returns
    -------
    means : array-like, shape (n_components,)
        The means of each mixture component.
    variances : array-like, shape (n_components,)
        The variances of each mixture component.
    """
    r = []
    for j in range(n_compenents):  

        r.append((weights[j] * pi[j]) / (np.sum([weights[i] * pi[i] for i in range(n_compenents)], axis=0)))

        #5th equation above
        means[j] = np.sum(r[j] * X) / (np.sum(r[j]))
        
        #6th equation above
        variances[j] = np.sum(r[j] * np.square(X - means[j])) / (np.sum(r[j]))
        
        #4th equation above
        pi[j] = np.mean(r[j])

    return variances,means,pi

Давайте реализуем обучающий цикл.

def train_gmm(data,n_compenents=3,n_steps=50, plot_intermediate_steps_flag=True):
    """ Training step of the GMM model
    
    Parameters
    ----------
    data : array-like, shape (n_samples,)
        The data.
    n_components : int
        The number of clusters
    n_steps: int
        number of iterations to run
    """
    
    #intilize model parameters at the start
    means,variances,pi = random_init(n_compenents)

    for step in range(n_steps):
        #perform E step
        weights = step_expectation(data,n_compenents,means,variances)
        #perform M step
        variances,means,pi = step_maximization(X, weights, means, variances, n_compenents, pi)

    plot_pdf(means,variances)

Когда мы начнем обучение модели, мы выполним шаги E и M в соответствии с установленным нами параметром n_steps .

Но в реальных случаях использования вы будете чаще использовать версию GMM для обучения. Там вы можете найти дополнительные параметры, такие как

tol: определение критериев остановки модели. Итерации EM остановятся, когда нижняя граница среднего усиления станет ниже параметра tol.

init_params:метод, используемый для инициализации весов.

Вы можете обратиться к документации здесь.

Хорошо, давайте посмотрим, как работает наш самодельный GMM.

На приведенных выше диаграммах красные пунктирные линии представляют исходное распределение, а другие графики представляют изученные распределения. После 30-й итерации мы видим, что наша модель хорошо работает с этим игрушечным набором данных.

Вы можете найти коды в этом репозитории GitHub, если хотите следовать этой статье.

Заключение

Эта статья призвана дать исчерпывающее руководство по гауссовской модели смеси; однако читателям рекомендуется поэкспериментировать с различными алгоритмами машинного обучения, поскольку ни один лучший алгоритмне будет хорошо работать для всех проблема. Также стоит отметить сложность выбранных нами алгоритмов машинного обучения. Одна из распространенных проблем с GMM заключается в том, что он плохо масштабируется для больших наборов данных.

Спасибо за чтение! Свяжитесь со мной в LinkedIn.