различные результаты, полученные с помощью GMM

Я хотел бы кластеризовать с помощью GMM классический набор данных радужной оболочки. Я получил набор данных от:

https://gist.github.com/netj/8836201

и моя программа пока следующая:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.mixture import GaussianMixture as mix
from sklearn.cross_validation import StratifiedKFold

def main():
    data=pd.read_csv("iris.csv",header=None)

    data=data.iloc[1:]

    data[4]=data[4].astype("category")

    data[4]=data[4].cat.codes

    target=np.array(data.pop(4))
    X=np.array(data).astype(float)


    kf=StratifiedKFold(target,n_folds=10,shuffle=True,random_state=1234)

    train_ind,test_ind=next(iter(kf))
    X_train=X[train_ind]
    y_train=target[train_ind]

    gmm_calc(X_train,"full",y_train)

def gmm_calc(X_train,cov,y_train):
    print X_train
    print y_train
    n_classes = len(np.unique(y_train))
    model=mix(n_components=n_classes,covariance_type="full")
    model.means_ = np.array([X_train[y_train == i].mean(axis=0) for i in 
 xrange(n_classes)])
    model.fit(X_train)
    y_predict=model.predict(X_train)
    print cov," ",y_train
    print cov," ",y_predict
    print (np.mean(y_predict==y_train))*100

У меня возникла проблема, когда я пытаюсь получить количество совпадений y_predict=y_train, потому что каждый раз, когда я запускаю программу, я получаю разные результаты. Например:

Первый забег:

full   [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]
full   [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 2 2 2 2 2 2 2 2 2
 2 2 2 0 2 2 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
0.0

Второй запуск:

full   [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]
full   [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0
 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]
33.33333333333333

Третий запуск:

full   [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]
full   [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1
 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]
98.51851851851852

Итак, как вы можете видеть, результаты различаются при каждом запуске. Я нашел код в Интернете, который находится в:

https://scikit-learn.org/0.16/auto_examples/mixture/plot_gmm_classifier.html

Но они получили с полной ковариацией точность примерно 82% для набора поездов. Что я делаю не так в этом случае?

Спасибо

Обновление: я обнаружил, что в примере из Интернета используется GMM вместо нового GaussianMixture. Я также обнаружил, что в примере параметры GMM были инициализированы контролируемым способом: classifier.means_ = np.array([X_train[y_train == i].mean(axis=0) for i in xrange(n_classes)])

Я поставил модифицированный код выше, но он все равно меняет результаты каждый раз, когда я его запускаю, а с библиотекой GMM этого не происходит.


person Little    schedule 11.11.2018    source источник


Ответы (2)


1) Классификатор GMM использует алгоритм максимизации ожидания-максимизации, чтобы соответствовать сочетанию гауссовские модели: гауссовские компоненты случайным образом центрируются на точках данных, затем алгоритм перемещает их, пока не сойдется к локальному оптимуму. Из-за случайной инициализации результаты могут быть разными при каждом запуске. Поэтому вы также должны использовать параметр random_state для GMM (или попытаться установить большее количество инициализаций n_init и ожидать более похожих результатов).

2) Проблема с точностью возникает из-за того, что GMM (то же, что и kmeans) просто соответствует n гауссианам и сообщает "число" гауссовского компонента, которому принадлежит каждая точка; это число отличается в каждом прогоне. В ваших прогнозах видно, что кластеры одинаковые, но их метки поменялись местами: (1,2,0) -> (1,0,2) -> (0,1,2), последняя комбинация совпадает с правильные классы, так что вы получите 98% баллов. Если вы нарисуете их, вы увидите, что сами гауссовы, как правило, остаются неизменными в этом случае, например, введите здесь описание изображения Вы можете использовать несколько метрики кластеризации, учитывающие это:

>>> [round(i,5) for i in  (metrics.homogeneity_score(y_predict, y_train),
 metrics.completeness_score(y_predict, y_train),
 metrics.v_measure_score(y_predict,y_train),
 metrics.adjusted_rand_score(y_predict, y_train),
 metrics.adjusted_mutual_info_score(y_predict,  y_train))]
[0.86443, 0.8575, 0.86095, 0.84893, 0.85506]

Код для построения графиков из https://scikit-learn.org/stable/auto_examples/mixture/plot_gmm_covariances.html, обратите внимание, что код различается между версиями, если вы используете старый, вам нужно заменить функцию make_ellipses:

model = mix(n_components=len(np.unique(y_train)), covariance_type="full", verbose=0, n_init=100)
X_train = X_train.astype(float)
model.fit(X_train)
y_predict = model.predict(X_train)

import matplotlib as mpl
import matplotlib.pyplot as plt

def make_ellipses(gmm, ax):
    for n, color in enumerate(['navy', 'turquoise', 'darkorange']):
        if gmm.covariance_type == 'full':
            covariances = gmm.covariances_[n][:2, :2]
        elif gmm.covariance_type == 'tied':
            covariances = gmm.covariances_[:2, :2]
        elif gmm.covariance_type == 'diag':
            covariances = np.diag(gmm.covariances_[n][:2])
        elif gmm.covariance_type == 'spherical':
            covariances = np.eye(gmm.means_.shape[1]) * gmm.covariances_[n]
        v, w = np.linalg.eigh(covariances)
        u = w[0] / np.linalg.norm(w[0])
        angle = np.arctan2(u[1], u[0])
        angle = 180 * angle / np.pi  # convert to degrees
        v = 2. * np.sqrt(2.) * np.sqrt(v)
        ell = mpl.patches.Ellipse(gmm.means_[n, :2], v[0], v[1],
                                  180 + angle, color=color)
        ell.set_clip_box(ax.bbox)
        ell.set_alpha(0.5)
        ax.add_artist(ell)


def plot(model, X, y, y_predict):

    h = plt.subplot(1, 1, 1)
    plt.subplots_adjust(bottom=.01, top=0.95, hspace=.15, wspace=.05,
                    left=.01, right=.99)
    make_ellipses(model, h)
    for n, color in enumerate( ['navy', 'turquoise', 'darkorange']):
        plt.scatter(X[y == n][:,0], X[y == n][:,1],  color=color,marker='x')
        plt.text(0.05, 0.9, 'Accuracy: %.1f' % ((np.mean(y_predict == y)) * 100),
                 transform=h.transAxes)

    plt.show()
plot(model, X_train, y_train, y_predict)
person hellpanderr    schedule 11.11.2018
comment
спасибо @hellpanderr извините за вопрос, но не могли бы вы добавить код для графики, которую вы показали? - person Little; 12.11.2018

Очень поздно для вашего запроса. Может быть полезно для других. Как сообщил @hellpanderr, используйте в GMM random_state=1

person user3883642    schedule 09.06.2021