簡體   English   中英

使用 matplotlib 和 seaborn 生成和繪制高斯混合圖

[英]Generating and plotting a mixture of gaussians with matplotlib and seaborn

我試圖在下面生成這個圖。 具體來說,混合標簽非常適合顯示這是高斯混合。

在此處輸入圖片說明

如果有人可以幫助我知道如何標准化兩個組成法線(因此它們低於混合物),那么我使用以下代碼獲得了第二張圖像:

import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns

n = 10000
mu = [0, 10]
sigma = [1, 1]
samples = []
samples0 = []
samples1 = []
for i in range(n):  # iteratively draw samples
    Z = np.random.choice([0, 1])  # latent variable
    if Z == 0:
        samples0.append(np.random.normal(mu[Z], sigma[Z], 1))
    else:
        samples1.append(np.random.normal(mu[Z], sigma[Z], 1))

    samples.append(np.random.normal(mu[Z], sigma[Z], 1))
sns.distplot(samples, hist=False, kde_kws={"shade": False})
sns.distplot(samples0, hist=False, kde_kws={"shade": True})
sns.distplot(samples1, hist=False, kde_kws={"shade": True})
plt.show()

噸

據我所知,如果您想使用seaborn.distplot您只能通過添加圖像范圍之外的點作為 hack 來實現。 但是,您可以使用 scipy 和 matplotlib 輕松復制 seaborn 行為。 請注意,分布並不完全填充相同的空間,這可能是內核密度估計的產物。 您可以手動調整帶寬來解決此問題。

或者,如果您已經知道分布的參數,您可以只繪制函數值而不是核密度估計,這似乎是在頂部圖片中所做的。

import numpy as np
import scipy.stats
import matplotlib.pyplot as plt

n = 10000
mu = [0, 10]
sigma = [1, 1]
samples = []
samples0 = []
samples1 = []
for i in range(n):  # iteratively draw samples
    Z = np.random.choice([0, 1])  # latent variable
    if Z == 0:
        samples0.append(np.random.normal(mu[Z], sigma[Z]))
        samples.append(samples0[-1])
    else:
        samples1.append(np.random.normal(mu[Z], sigma[Z]))
        samples.append(samples1[-1])

grid = np.linspace(min(samples)-0.5, max(samples)+0.5,1000)
y = scipy.stats.gaussian_kde(samples).evaluate(grid)
# Double the number of points to make sure the bandwidth in the KDE will be the same
y0 = scipy.stats.gaussian_kde(samples0*2).evaluate(grid)
y1 = scipy.stats.gaussian_kde(samples1*2).evaluate(grid)
# Multiply by maximum height to scale
y /= max(y)
y0 /= max(y0)
y1 /= max(y1)
plt.plot(grid, y0, label='Component 1')
plt.fill_between(grid, 0, y0, alpha=0.5)
plt.plot(grid, y1, label='Component 2')
plt.fill_between(grid, 0, y1, alpha=0.5)
plt.plot(grid, y, '--', label='Mixture')
plt.legend()
plt.show()

當您使用高斯分布時,您可以很容易地憑經驗完成所有事情:

import numpy as np
from scipy import stats
import matplotlib.pyplot as plt

# define your distributions
d1 = stats.norm(2, 1.1)
d2 = stats.norm(5, 0.9)

# set mixture component weights
mc = [0.5, 0.5]
mc = mc / np.sum(mc) # ensuring they sum to 1

# where to evaluate the densities
x = np.linspace(0, 10, 501)
# calculate density and apply mixture weights
c1 = d1.pdf(x) * mc[0]
c2 = d2.pdf(x) * mc[1]

# plot everything
plt.plot(x, c1, label='Component 1')
plt.plot(x, c2, label='Component 2')
plt.plot(x, c1 + c2, '--', label='Mixture')

給我:

通用汽車

這與你的第一個情節非常接近

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM