【问题标题】:sklearn GMM classification prediction (component assignment) ordersklearn GMM分类预测(组件分配)顺序
【发布时间】:2020-07-01 18:18:10
【问题描述】:

我正在尝试将细胞分类为群体。当我使用:

gmix = mixture.GMM(n_components=3, covariance_type='full') gmix.fit(samples)

意思是输出,从下面的代码,按顺序改变,除非我设置: np.radom.seed(0).

print ("gmix.means \n", gmix.means_) colors = ['r' if i==0 else ('g' if i==1 else ('b' if i ==2 else 'm'))for i in gmix.predict(samples)]

我想要按 X 轴均值排序的类(每个类的第一项),即:

[[  3.25492404e+02   2.88403293e-02]  
[  3.73942908e+02   3.25283512e-02] 
[  5.92577646e+02   4.40595768e-02]]

所以在上面的代码中,红色总是 325,绿色 372 和蓝色 592。目前我认为没有对输出进行排序。

我试过了:

gmix.means_ = np.sort(gmix.means_, axis = 0)

但是 gmix.covars_ 和 gmix.weights_ 也需要相应地排序,这就是我卡住的地方!

非常感谢!

2016 年 4 月 5 日编辑:

感谢您的帮助并引导我朝着正确的方向前进。这是我写得不好但工作的版本:

    sort_indices = gmix.means_.argsort(axis = 0)
    order = sort_indices[:, 0]
    print('\norder:', order)
    gmix.means_ = gmix.means_[order,:]    

    gmix.covars_ = gmix.covars_[order, :]
    print ("\n sorted gmix.covars \n", gmix.covars_) 

    print ("\n\nori gmix.weights \n", gmix.weights_)
    w = np.split(gmix.weights_,3)
    w = np.asarray(w)
    w = np.ravel(w[order,:])
    gmix.weights_ = w

【问题讨论】:

    标签: python scikit-learn


    【解决方案1】:

    我一直在寻找相同的功能。这是我的解决方案,基于@ed3203 代码:

    def fit_predict_by(clf, X, order_function):
        """
        Sort `clf.fit_predict` by given attribute.
    
        It ensure that all calls to fit predict will return an array
        sorted by the given attribute. In addition, the `clf` attributes
        `means_`, `covars_`, and `weights_` are also sorted similarly.
    
        ## Usage
    
            # Sort by cluster weights
            y = fit_predict_by(clf, X, lambda clf: clf.weights_.argsort())
            # or sort by the `x` value of the mean
            y = fit_predict_by(clf, X, lambda clf: clf.means_.argsort()[:, 0])
        """
        y = clf.fit_predict(X)
        order = order_function(clf)
    
        for attr in ('means_', 'covars_', 'weights_'):
            sorted_attr = getattr(clf, attr)[order]
            setattr(clf, attr, sorted_attr)
    
        ensure_no_overlap = len(order)
        for new_val, old_val in enumerate(order):
            y[y == old_val] = new_val + ensure_no_overlap
        return y - ensure_no_overlap
    

    【讨论】:

      【解决方案2】:

      这基本上是一个矩阵/向量索引问题。我在这里可能过于冗长,但对矩阵进行排序应该只有两行。

      一般的聚类算法(在您的情况下是 GMM)不能保证每次都以相同的顺序标记聚类,也不能保证每次都给您相同的聚类,除非您修复初始条件。

      如果您希望集群按其均值的 X 坐标排序,您可能需要自己执行此操作。这涉及两个步骤,就像您在问题中提到的那样:

      a) 对均值进行排序并获取索引 b)使用索引来提取你的手段

      这可以简单地完成如下:

      a) 用你的方式发送argsort

      >>> means = np.array(np.mat('1, 2; 4, 3; 2, 6'))
      >>> sort_indices = means.argsort(axis=0)
      array([[0, 0],
             [2, 1],
             [1, 2]])
      

      您的订单将是 argsorted 数组的第一列:

      >>> order = sort_indices[:,0]
      >>> order
      array([0, 2, 1])
      

      (b) 现在,我们将使用此“命令”重新排序您的方式。

      >>> sorted_m = means[order,:]
      >>> sorted_m
      
      array([[1, 2],
             [2, 6],
             [4, 3]])
      

      还有你的协方差,让我们创建一个虚拟协方差矩阵:

      >>> c = np.array(np.mat('9, 8, 7; 6, 5, 4; 3, 2, 1'))
      >>> c
      array([[9, 8, 7],
             [6, 5, 4],
             [3, 2, 1]])
      

      现在,重新索引你的 c,一个简单的方法就是重新索引:

      >>> sorted_c = c[order,:][:, order]
      >>> sorted_c
      array([[9, 7, 8],
             [3, 1, 2],
             [6, 4, 5]])
      

      如果您看到,行和列会根据我们的新顺序重新排列。

      你有它,你的手段和协方差排序。

      您可能还需要重新标记原始标签,您可以在此处使用答案:Fast replacement of values in a numpy array

      【讨论】:

      • 感谢您的帮助并引导我朝着正确的方向前进。这是我写得不好但工作的版本:`sort_indices = gmix.means_.argsort(axis = 0) order = sort_indices[:, 0] print('\norder:', order) gmix.means_ = gmix.means_[order, :] gmix.covars_ = gmix.covars_[order, :] print ("\n sorted gmix.covars \n", gmix.covars_) print ("\n\nori gmix.weights \n", gmix.weights_) w = np.split(gmix.weights_,3) w = np.asarray(w) w = np.ravel(w[order,:]) gmix.weights_ = w
      【解决方案3】:

      由于 scikit-learn 版本是 0.23.1,正确的方法是重新排序 precisions_precisions_cholesky_。此外,covars_ 现在是 covariances_。 因此,对于 1D 版本,您应该这样做:

      order = best_gmm.means_.argsort(axis=0)[:, 0]
      best_gmm.means_ = best_gmm.means_[order]
      best_gmm.covariances_ = best_gmm.covariances_[order]
      best_gmm.weights_ = best_gmm.weights_[order]
      best_gmm.precisions_ = best_gmm.precisions_[order]
      best_gmm.precisions_cholesky_ = best_gmm.precisions_cholesky_[order]
      

      【讨论】:

        猜你喜欢
        • 2014-01-02
        • 2016-08-10
        • 2015-09-20
        • 2016-02-06
        • 2017-10-05
        • 2016-03-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多