Python中sklearn包中的Gaussianmixture有什么问题?

Python中sklearn包中的Gaussianmixture有什么问题?,python,scikit-learn,Python,Scikit Learn,我使用python中sklearn的Gaussianmixture(GM)来识别星团的成员。GM使用两个组件进行调整,其他组件为默认组件。如图所示,一颗明显不是星团成员的恒星(带红点)作为一个成员出现。在中间图中聚集的红色点是我的成员。但左上角的单个红点不应为成员。因为它离这个中间群体还不够近 我的python代码是 import numpy as np from numpy import array import pandas as pd from sklearn.mixture impor

我使用python中sklearn的Gaussianmixture(GM)来识别星团的成员。GM使用两个组件进行调整,其他组件为默认组件。如图所示,一颗明显不是星团成员的恒星(带红点)作为一个成员出现。在中间图中聚集的红色点是我的成员。但左上角的单个红点不应为成员。因为它离这个中间群体还不够近

我的python代码是

import numpy as np
from numpy import array
import pandas as pd
from sklearn.mixture import GaussianMixture

import matplotlib.pyplot as plt
from matplotlib import style
import matplotlib.colors as mtcolor

style.use("seaborn-white")
clist = ["gray", "red"]
cmap = mtcolor.ListedColormap(clist)

eX = pd.read_csv("mysatrs.csv", usecols=['col1', 'col2', 'col3']).values

col0m = (eX[:,0] >= -5) & (eX[:,0] <= 5)
col1m = (eX[:,1] >= -5) & (eX[:,1] <= 5)
col2m = (eX[:,2] > 0)

X = eX[col0m & col1m & col2m]

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

hcgmm = GaussianMixture(n_components=2)
gmmfit = hcgmm.fit(X)
gmmprd = gmmfit.predict(X)
hcprobs = gmmfit.predict_proba(X)
hcmns = hcgmm.means_

plt.scatter(X[:,0], X[:,1], c=gmmprd, s=3, cmap=cmap)
plt.show()

将numpy导入为np
从numpy导入数组
作为pd进口熊猫
从sklearn.mixed导入高斯混合
将matplotlib.pyplot作为plt导入
从matplotlib导入样式
将matplotlib.colors导入为mtcolor
样式。使用(“seaborn white”)
clist=[“灰色”、“红色”]
cmap=mtcolor.ListedColormap(clist)
eX=pd.read\u csv(“mysatrs.csv”,usecols=['col1','col2','col3'])。值
col0m=(eX[:,0]>=-5)和(eX[:,0]=-5)和(eX[:,1]0)
X=eX[col0m和col1m和col2m]
plt.图(figsize=(6,6))
hcgmm=高斯混合(n_分量=2)
gmmfit=hcgmm.fit(X)
gmmprd=gmmfit.predict(X)
hcprobs=gmmfit.预测概率(X)
hcmns=hcgmm.means_
plt.散射(X[:,0],X[:,1],c=gmmprd,s=3,cmap=cmap)
plt.show()

是否应该对GM进行另一次调整?

TLDR:每次运行它时,您得到的配合都会发生变化,请尝试几次,并保留最好的一次(最低的
hcgmm.bic()
)。你的数据似乎有三个维度,我想这另一个维度是不正确的(包括链接或绘图)

如果有人想要一个更长的例子,这里有一个MWE。首先,我们拉入包并生成一些数据:

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

background = np.random.randn(50,2) * 5
cluster = np.random.randn(50,2)

plt.scatter(background[:,0], background[:,1])
plt.scatter(cluster[:,0], cluster[:,1])
这与OP类似:

然后,通过执行以下操作,我可以像OP一样安装a:

gmm = GaussianMixture(n_components=2)
fit = gmm.fit(X)
from sklearn.metrics import adjusted_rand_score

true_labels = (np.random.random(100) < 0.5).astype(int)
ix_a, = np.nonzero(true_labels == 0)
ix_b, = np.nonzero(true_labels == 1)

gmm = GaussianMixture(n_components=2)

def test():
    X = np.empty((len(true_labels), 2), float)
    X[ix_a,:] = np.random.randn(len(ix_a), 2) * 5
    X[ix_b,:] = np.random.randn(len(ix_b), 2)

    fit = gmm.fit(X)
    ari = adjusted_rand_score(true_labels, fit.predict(X))
    return fit.bic(X), ari

fits = np.array([test() for _ in range(1000)])
并将结果绘制为:

plt.scatter(X[:,0], X[:,1], c=fit.predict(X))
但大多数情况下,我都会很不舒服。但在运行了几次之后,我发现:

这表明我们可以(至少有时)恢复一个合理的分区。这个拟合的最大值是993.5,而我经常得到大于1000的值,这在视觉上看起来很糟糕

如果我使用上述随机数据运行
fit
1000次,我可以生成一个如下所示的:

(x/y轴的方向是错误的,x是概率,y是BIC值),这意味着它将在大约10%的时间内恢复一个良好的分区。尝试其他随机抽奖的结果表明这有所不同,但我的成功率不超过40%

考虑到您只有几个点和组件,您可以尝试一种计算量更大的方法。我希望贝叶斯MCMC混合模型在这里会做得更好

我刚刚记得,分区是检查分区准确性的一种简单方法。我们可以生成大量测试数据,进行拟合,并通过以下操作获得BIC和Rand指数:

gmm = GaussianMixture(n_components=2)
fit = gmm.fit(X)
from sklearn.metrics import adjusted_rand_score

true_labels = (np.random.random(100) < 0.5).astype(int)
ix_a, = np.nonzero(true_labels == 0)
ix_b, = np.nonzero(true_labels == 1)

gmm = GaussianMixture(n_components=2)

def test():
    X = np.empty((len(true_labels), 2), float)
    X[ix_a,:] = np.random.randn(len(ix_a), 2) * 5
    X[ix_b,:] = np.random.randn(len(ix_b), 2)

    fit = gmm.fit(X)
    ari = adjusted_rand_score(true_labels, fit.predict(X))
    return fit.bic(X), ari

fits = np.array([test() for _ in range(1000)])

它再次失败得可怕(ARIThanks Sam,很抱歉丢失了数据。我不是python专家,但我会测试你的建议。我很抱歉文件名冲突。文件名已更正,现在上面的链接处于活动状态。亲爱的Sam,据我所知,你的python知识比我好,如果你用代码检查我的数据,我将非常高兴。