【问题标题】:Gaussian mixture model (GMM) gives a bad fit高斯混合模型 (GMM) 拟合不佳
【发布时间】:2014-08-02 04:26:28
【问题描述】:

我一直在玩 Scikit-learn 的 GMM 函数。首先,我刚刚创建了一个沿线x=y 的分布。

from sklearn import mixture
import numpy as np 
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

line_model = mixture.GMM(n_components = 99)
#Create evenly distributed points between 0 and 1.
xs = np.linspace(0, 1, 100)
ys = np.linspace(0, 1, 100)

#Create a distribution that's centred along y=x
line_model.fit(zip(xs,ys))
plt.plot(xs, ys)
plt.show()

这会产生预期的分布:

接下来我给它拟合一个 GMM,并绘制结果:

#Create the x,y mesh that will be used to make a 3D plot
x_y_grid = []
for x in xs:
    for y in ys:
        x_y_grid.append([x,y])

#Calculate a probability for each point in the x,y grid.
x_y_z_grid = []
for x,y in x_y_grid:
    z = line_model.score([[x,y]])
    x_y_z_grid.append([x,y,z])

x_y_z_grid = np.array(x_y_z_grid)

#Plot probabilities on the Z axis.
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot(x_y_z_grid[:,0], x_y_z_grid[:,1], 2.72**x_y_z_grid[:,2])
plt.show()

生成的概率分布在x=0 和x=1 上有一些奇怪的尾部,并且在角落(x=1、y=1 和 x=0、y=0)还有额外的概率。

使用 n_components=5 也会显示这种行为:

这是 GMM 固有的问题,还是实施有问题,还是我做错了什么?

编辑:从模型中获取分数似乎摆脱了这种行为——应该这样吗?

我在同一个数据集上训练两个模型(x=y 从 x=0 到 x=1)。简单地通过 gmm 的score 方法检查概率似乎可以消除这种边界效应。为什么是这样?我附上了下面的图和代码。

# Creates a line of 'observations' between (x_small_start, x_small_end)
# and (y_small_start, y_small_end). This is the data both gmms are trained on.
x_small_start = 0
x_small_end = 1
y_small_start = 0
y_small_end = 1

# These are the range of values that will be plotted
x_big_start = -1
x_big_end = 2
y_big_start = -1
y_big_end = 2


shorter_eval_range_gmm = mixture.GMM(n_components = 5)
longer_eval_range_gmm = mixture.GMM(n_components = 5)

x_small = np.linspace(x_small_start, x_small_end, 100)
y_small = np.linspace(y_small_start, y_small_end, 100)
x_big = np.linspace(x_big_start, x_big_end, 100)
y_big = np.linspace(y_big_start, y_big_end, 100)

#Train both gmms on a distribution that's centered along y=x
shorter_eval_range_gmm.fit(zip(x_small,y_small))
longer_eval_range_gmm.fit(zip(x_small,y_small))


#Create the x,y meshes that will be used to make a 3D plot
x_y_evals_grid_big = []
for x in x_big:
    for y in y_big:
        x_y_evals_grid_big.append([x,y])
x_y_evals_grid_small = []

for x in x_small:
    for y in y_small:
        x_y_evals_grid_small.append([x,y])

#Calculate a probability for each point in the x,y grid.
x_y_z_plot_grid_big = []
for x,y in x_y_evals_grid_big:
    z = longer_eval_range_gmm.score([[x, y]])
    x_y_z_plot_grid_big.append([x, y, z])
x_y_z_plot_grid_big = np.array(x_y_z_plot_grid_big)

x_y_z_plot_grid_small = []
for x,y in x_y_evals_grid_small:
    z = shorter_eval_range_gmm.score([[x, y]])
    x_y_z_plot_grid_small.append([x, y, z])
x_y_z_plot_grid_small = np.array(x_y_z_plot_grid_small)


#Plot probabilities on the Z axis.
fig = plt.figure()
fig.suptitle("Probability of different x,y pairs")

ax1 = fig.add_subplot(1, 2, 1, projection='3d')
ax1.plot(x_y_z_plot_grid_big[:,0], x_y_z_plot_grid_big[:,1], np.exp(x_y_z_plot_grid_big[:,2]))
ax1.set_xlabel('X Label')
ax1.set_ylabel('Y Label')
ax1.set_zlabel('Probability')
ax2 = fig.add_subplot(1, 2, 2, projection='3d')
ax2.plot(x_y_z_plot_grid_small[:,0], x_y_z_plot_grid_small[:,1], np.exp(x_y_z_plot_grid_small[:,2]))
ax2.set_xlabel('X Label')
ax2.set_ylabel('Y Label')
ax2.set_zlabel('Probability')

plt.show()

【问题讨论】:

    标签: python scikit-learn


    【解决方案1】:

    编辑: 这是不正确的。与 Ronald P. 交谈,您无法获得吉布斯效应,因为高斯人无法通过“负数”来相互补偿,因为概率严格 > 0。这似乎是一个简单的绘图问题……请参阅他的答案!无论哪种方式,我都建议使用 2D 数据来测试 GMM,而不是 1D 线。

    GMM 适合您提供的数据 - 特别是:

    xs = np.linspace(0, 1, 100)
    ys = np.linspace(0, 1, 100)
    

    因为数据在 0 和 1 结束,GMM 正试图对这一事实进行建模:-.01 和 1.01 在技术上超出了训练数据范围,应该以非常低的概率进行评分。在这样做的过程中,它最终会创建一个具有较小分布(较小协方差/较高精度)的高斯,以覆盖数据的末端并模拟数据停止的事实。

    我希望添加足够多的高斯会导致pseudo-Gibbs phenomena 效果,并且您可以看到从 5 到 99 的变化。要精确建模边缘,您需要一个无限混合模型。这类似于无限频率分量 - 您也在 GMM 中表示具有一组基函数(在本例中为高斯函数)的“信号”!

    【讨论】:

      【解决方案2】:

      配合没有问题,但您使用的可视化效果。一个提示应该是连接(0,1,5)到(0,1,0)的直线,实际上只是两个点的连接的渲染(这是由于读取点的顺序所致) .尽管极值处的两个点在您的数据中,但这条 行 上的其他点实际上并不存在。

      出于上述原因,我个人认为使用 3d 图(线)来表示表面是一个相当糟糕的主意,我会推荐使用表面图或等高线图。

      试试这个:

      from sklearn import mixture
      import numpy as np 
      import matplotlib.pyplot as plt
      from mpl_toolkits.mplot3d import Axes3D
      
      line_model = mixture.GMM(n_components = 99)
      #Create evenly distributed points between 0 and 1.
      xs = np.atleast_2d(np.linspace(0, 1, 100)).T
      ys = np.atleast_2d(np.linspace(0, 1, 100)).T
      
      #Create a distribution that's centred along y=x
      line_model.fit(np.concatenate([xs, ys], axis=1))
      plt.scatter(xs, ys)
      plt.show()
      
      #Create the x,y mesh that will be used to make a 3D plot
      X, Y = np.meshgrid(xs, ys)
      x_y_grid = np.c_[X.ravel(), Y.ravel()]
      
      #Calculate a probability for each point in the x,y grid.
      z = line_model.score(x_y_grid)
      z = z.reshape(X.shape)
      
      #Plot probabilities on the Z axis.
      fig = plt.figure()
      ax = fig.add_subplot(111, projection='3d')
      ax.plot_surface(X, Y, z)
      plt.show()
      

      从学术角度来看,我对通过 2D 混合模型在 2D 空间中拟合 1D 线的目标感到非常不舒服。使用 GMM 进行流形学习至少需要法线方向的方差为零,从而减少到狄拉克分布。在数值和分析上这是不稳定的,应该避免(在 gmm 拟合中似乎有一些稳定技巧,因为模型的方差在直线法线方向上相当大)。

      还建议在绘制数据时使用plt.scatter 而不是plt.plot,因为在拟合它们的联合分布时没有理由将这些点连接起来。

      希望这有助于阐明您的问题。

      【讨论】:

      • 现实中的数据不会像狄拉克那样。 GMM 将用于预测在给定时间投掷球在给定位置的可能性。使用您的解决方案,分布仍然在角落有额外的概率颠簸。知道为什么吗?
      猜你喜欢
      • 2015-02-20
      • 2011-09-07
      • 2012-05-21
      • 2017-04-15
      • 2017-02-26
      • 2018-07-19
      • 2016-07-25
      • 2019-02-12
      • 2015-03-30
      相关资源
      最近更新 更多