2017-01-13 2 views
6

Я пытаюсь понять результаты реализации модели гауссовой модели scikit-learn. Взгляните на следующий пример:Понимание моделей гауссовой смеси

#!/opt/local/bin/python 
import numpy as np 
import matplotlib.pyplot as plt 
from sklearn.mixture import GaussianMixture 

# Define simple gaussian 
def gauss_function(x, amp, x0, sigma): 
    return amp * np.exp(-(x - x0) ** 2./(2. * sigma ** 2.)) 

# Generate sample from three gaussian distributions 
samples = np.random.normal(-0.5, 0.2, 2000) 
samples = np.append(samples, np.random.normal(-0.1, 0.07, 5000)) 
samples = np.append(samples, np.random.normal(0.2, 0.13, 10000)) 

# Fit GMM 
gmm = GaussianMixture(n_components=3, covariance_type="full", tol=0.001) 
gmm = gmm.fit(X=np.expand_dims(samples, 1)) 

# Evaluate GMM 
gmm_x = np.linspace(-2, 1.5, 5000) 
gmm_y = np.exp(gmm.score_samples(gmm_x.reshape(-1, 1))) 

# Construct function manually as sum of gaussians 
gmm_y_sum = np.full_like(gmm_x, fill_value=0, dtype=np.float32) 
for m, c, w in zip(gmm.means_.ravel(), gmm.covariances_.ravel(), 
       gmm.weights_.ravel()): 
    gmm_y_sum += gauss_function(x=gmm_x, amp=w, x0=m, sigma=np.sqrt(c)) 

# Normalize so that integral is 1  
gmm_y_sum /= np.trapz(gmm_y_sum, gmm_x) 

# Make regular histogram 
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=[8, 5]) 
ax.hist(samples, bins=50, normed=True, alpha=0.5, color="#0070FF") 
ax.plot(gmm_x, gmm_y, color="crimson", lw=4, label="GMM") 
ax.plot(gmm_x, gmm_y_sum, color="black", lw=4, label="Gauss_sum") 

# Annotate diagram 
ax.set_ylabel("Probability density") 
ax.set_xlabel("Arbitrary units") 

# Draw legend 
plt.legend() 
plt.show() 

Resulting plot from the code above

Здесь я первый генерировать распределение выборки, построенный из гауссовых, затем установите гауссова модель смеси к этим данным. Затем я хочу рассчитать вероятность для некоторого заданного ввода. Удобно, что реализация scikit предлагает метод score_samples, чтобы сделать именно это. Теперь я пытаюсь понять эти результаты. Я всегда думал, что я могу просто взять параметры гауссианцев из подгонки GMM и построить такое же распределение, суммируя их, а затем нормализуя интеграл к 1. Однако, как вы можете видеть на сюжете, образцы, взятые из метод score_samples идеально подходит (красная линия) к исходным данным (синяя гистограмма), вручную построенное распределение (черная линия) - нет. Я хотел бы понять, где мое мышление пошло не так, и почему я не могу сам построить дистрибуцию, суммируя гауссиан, как это дается GMM!!! Большое спасибо за любой вклад!

ответ

10

Только в случае, если кто-нибудь в будущем задаваться вопросом о том же: Нужно нормализовать отдельные компоненты, а не сумма:

import numpy as np 
import matplotlib.pyplot as plt 
from sklearn.mixture import GaussianMixture 

# Define simple gaussian 
def gauss_function(x, amp, x0, sigma): 
    return amp * np.exp(-(x - x0) ** 2./(2. * sigma ** 2.)) 

# Generate sample from three gaussian distributions 
samples = np.random.normal(-0.5, 0.2, 2000) 
samples = np.append(samples, np.random.normal(-0.1, 0.07, 5000)) 
samples = np.append(samples, np.random.normal(0.2, 0.13, 10000)) 

# Fit GMM 
gmm = GaussianMixture(n_components=3, covariance_type="full", tol=0.001) 
gmm = gmm.fit(X=np.expand_dims(samples, 1)) 

# Evaluate GMM 
gmm_x = np.linspace(-2, 1.5, 5000) 
gmm_y = np.exp(gmm.score_samples(gmm_x.reshape(-1, 1))) 

# Construct function manually as sum of gaussians 
gmm_y_sum = np.full_like(gmm_x, fill_value=0, dtype=np.float32) 
for m, c, w in zip(gmm.means_.ravel(), gmm.covariances_.ravel(), gmm.weights_.ravel()): 
    gauss = gauss_function(x=gmm_x, amp=1, x0=m, sigma=np.sqrt(c)) 
    gmm_y_sum += gauss/np.trapz(gauss, gmm_x) * w 

# Make regular histogram 
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=[8, 5]) 
ax.hist(samples, bins=50, normed=True, alpha=0.5, color="#0070FF") 
ax.plot(gmm_x, gmm_y, color="crimson", lw=4, label="GMM") 
ax.plot(gmm_x, gmm_y_sum, color="black", lw=4, label="Gauss_sum", linestyle="dashed") 

# Annotate diagram 
ax.set_ylabel("Probability density") 
ax.set_xlabel("Arbitrary units") 

# Make legend 
plt.legend() 

plt.show() 

enter image description here

+0

Спасибо за размещение ответ –

+0

Это действительно лаконично, спасибо. У меня было много проблем с передачей данных в «GaussianMixture.fit», поскольку я не понимал, что форма должна быть 'np.expand_dims (samples, 1) .shape' вместо' samples.shape' – FriskyGrub

+0

Теперь как бы вы приступить к вычислению вероятности нового тестового образца X (так что вы можете оценить, является ли вероятность того, что точка данных является новинкой)? Из того, что я понял, np.exp (gmm.score_samples (X)) дает значение PDF в X, а не вероятность X. – felipeduque