Scikit-learn, GMM: проблема с возвратом из атрибута.means_

Так, видимо.. means_ Атрибут возвращает разные результаты из средних значений, рассчитанных для каждого кластера. (или я неправильно понимаю, что это возвращает!)

Ниже приведен код, который я написал, чтобы проверить, как GMM соответствует данным временного ряда, которые у меня есть.

import numpy as np
import pandas as pd
import seaborn as sns
import time
import matplotlib as mpl
import matplotlib.pyplot as plt

from sklearn.mixture import BayesianGaussianMixture
from sklearn.mixture import GaussianMixture


toc = time.time()

input содержит (количество метров / образцов) х (количество функций)

read = pd.read_csv('input', sep='\t', index_col= 0, header =0, \
               names =['meter', '6:30', '9:00', '15:30', '22:30', 'std_year', 'week_score', 'season_score'], \
               encoding= 'utf-8')
read.drop('meter', 1, inplace=True)
read['std_year'] = read['std_year'].divide(4).round(2)

input = read.as_matrix(columns=['6:30', '9:00', '15:30', '22:30',])

поместите его в GMM с 10 кластерами. (Используя график BIC, 5 было оптимальным числом с наименьшей оценкой... но при -7000. Это не невозможно после обсуждения с моим советником, но все же это странно.)

gmm = GaussianMixture(n_components=10, covariance_type ='full', \
                  init_params = 'random', max_iter = 100, random_state=0)
gmm.fit(input)
print(gmm.means_.round(2))
cluster = gmm.predict(input)

Далее я должен вручную вычислить центр тяжести / центр - если правильно использовать эти термины для обозначения средних векторов - каждого кластера, используя метки, возвращаемые из .predict,

Чтобы быть конкретным, кластер содержит значение от 0 до 9, каждое из которых указывает кластер. Я переставляю это и соединяю с входной матрицей (# образцов) x (# атрибутов) в виде массива. Я хочу использовать простоту библиотеки панд в обработке таких больших данных, поэтому превратите ее в фрейм данных.

cluster = np.array(cluster).reshape(-1,1) #(3488, 1)
ret = np.concatenate((cluster, input), axis=1) #(3488, 5)
ret_pd = pd.DataFrame(ret, columns=['label','6:30', '9:00', '15:30', '22:30'])
ret_pd['label'] = ret_pd['label'].astype(int)

Для характеристик каждого счетчика его кластер классифицируется под столбцом "метка". Таким образом, следующие кластеры кода для каждой метки, а затем я беру среднее значение по столбцу.

cluster_mean = []
for label in range(10):
#take mean by columns per each cluster
    segment= ret_pd[ret_pd['label']== label]
    print(segment)
    turn = np.array(segment)[:, 1:]
    print(turn.shape)
    mean_ = np.mean(turn, axis =0).round(2) #series
    print(mean_)
    plt.plot(np.array(mean_), label='cluster %s' %label) 

    cluster_mean.append(list(mean_))

print(cluster_mean)

xvalue = ['6:30', '9:00', '15:30', '22:30']
plt.ylabel('Energy Use [kWh]')
plt.xlabel('time of day')
plt.xticks(range(4), xvalue)
plt.legend(loc = 'upper center', bbox_to_anchor = (0.5, 1.05),\
       ncol =2, fancybox =True, shadow= True)
plt.savefig('cluster_gmm_100.png')

tic = time.time()
print('time ', tic-toc)

Что интересно, так это то, что .means_ из внутренней библиотеки возвращает разные значения из того, что я вычисляю в этом коде.

Scikit учиться-х .means_:

[[ 0.46  1.42  1.12  1.35]
 [ 0.49  0.78  1.19  1.49]
 [ 0.49  0.82  1.01  1.63]
 [ 0.6   0.77  0.99  1.55]
 [ 0.78  0.75  0.92  1.42]
 [ 0.58  0.68  1.03  1.57]
 [ 0.4   0.96  1.25  1.47]
 [ 0.69  0.83  0.98  1.43]
 [ 0.55  0.96  1.03  1.5 ]
 [ 0.58  1.01  1.01  1.47]]

Мои результаты:

[[0.45000000000000001, 1.6599999999999999, 1.1100000000000001, 1.29],    
 [0.46000000000000002, 0.73999999999999999, 1.26, 1.48], 
[0.45000000000000001, 0.80000000000000004, 0.92000000000000004, 1.78], 
[0.68000000000000005, 0.72999999999999998, 0.85999999999999999, 1.5900000000000001], 
[0.91000000000000003, 0.68000000000000005, 0.84999999999999998, 1.3600000000000001], 
[0.58999999999999997, 0.65000000000000002, 1.02, 1.5900000000000001], 
[0.35999999999999999, 1.03, 1.28, 1.46], 
[0.77000000000000002, 0.88, 0.94999999999999996, 1.3500000000000001], 
[0.53000000000000003, 1.0700000000000001, 0.97999999999999998, 1.53], 
[0.66000000000000003, 1.21, 0.95999999999999996, 1.3600000000000001]]

Как сторона, я не уверен, почему результаты, которые я возвращаю, не округлены до 2 десятичных цифр должным образом..

1 ответ

Решение

Хотя я не совсем уверен в том, что делает ваш код, я вполне уверен, что проблема здесь.

Параметры, возвращаемые means_ являются средствами параметрических (гауссовых) распределений, составляющих модель. Где, например, когда вы вычисляете средства, которые вы делаете, беря среднее значение всех данных, кластеризованных в каждом компоненте, это почти всегда дает разные (хотя и схожие результаты). Чтобы лучше понять, почему они могут отличаться, я бы посоветовал прочитать немного больше об алгоритме максимизации ожидания, который scikit-learn использует для соответствия GMM.

Другие вопросы по тегам