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.