Scikit-learn: поиск функций, которые вносят вклад в каждый кластер KMeans

Скажем, у вас есть 10 функций, которые вы используете для создания 3 кластеров. Есть ли способ увидеть уровень вклада, который каждая из функций имеет для каждого из кластеров?

То, что я хочу сказать, - это то, что для кластера k1 функции 1,4,6 были основными функциями, где в качестве основных характеристик кластера k2 было 2,5,7.

Это базовая настройка того, что я использую:

k_means = KMeans(init='k-means++', n_clusters=3, n_init=10)
k_means.fit(data_features)
k_means_labels = k_means.labels_

Ответ 1

Вы можете использовать

Принципиальный анализ компонентов (PCA)

PCA может быть выполнено путем разложения по собственным значениям ковариационной (или корреляционной) матрицы данных или сингулярной декомпозиции матрицы данных, обычно после среднего центрирования (и нормализации или использования Z-баллов) матрицы данных для каждого атрибута. Результаты PCA обычно обсуждаются в терминах показателей компонентов, иногда называемых коэффициентами (преобразованные значения переменных, соответствующие конкретной точке данных), и загрузки (вес, по которому каждая стандартизованная исходная переменная должна быть умножена, чтобы получить оценку компонента).

Некоторые существенные моменты:

  • собственные значения отражают часть дисперсии, объясняемую соответствующим компонентом. Скажем, у нас есть 4 функции с собственными значениями 1, 4, 1, 2. Это отклонения, объясняемые соответствием. векторы. Второе значение относится к первому основному компоненту, так как оно объясняет 50% от общей дисперсии, а последнее значение относится ко второму основному компоненту, объясняющему 25% общей дисперсии.
  • собственные векторы представляют собой линейные комбинации компонентов. Дайте весы для функций, чтобы вы могли знать, которые характеризуются высоким/низким воздействием.
  • использовать PCA на основе матрицы корреляции вместо эмпирической ковариационной матрицы, , если собственные значения сильно отличаются (величины).

Примерный подход

  • сделать PCA на весь набор данных (что то, что делает функция ниже)
    • взять матрицу с наблюдениями и функциями
    • центрируйте его до среднего (среднее значение значений функции среди всех наблюдений)
    • вычислить эмпирическую ковариационную матрицу (например, np.cov) или корреляцию (см. выше).
    • выполнить разложение
    • сортировать собственные значения и собственные векторы по собственным значениям для получения компонентов с наибольшим воздействием
    • использовать компоненты по исходным данным
  • исследуем кластеры в преобразованном наборе данных. Проверяя их местоположение на каждом компоненте, вы можете получить функции с высоким и низким воздействием на распределение/дисперсию.

Пример функции

Вам нужно import numpy as np и scipy as sp. Он использует sp.linalg.eigh для разложения. Возможно, вы захотите также проверить модуль разметки scikit.

PCA выполняется на матрице данных с наблюдениями (объектами) по строкам и функциям в столбцах.

def dim_red_pca(X, d=0, corr=False):
    r"""
    Performs principal component analysis.

    Parameters
    ----------
    X : array, (n, d)
        Original observations (n observations, d features)

    d : int
        Number of principal components (default is ``0`` => all components).

    corr : bool
        If true, the PCA is performed based on the correlation matrix.

    Notes
    -----
    Always all eigenvalues and eigenvectors are returned,
    independently of the desired number of components ``d``.

    Returns
    -------
    Xred : array, (n, m or d)
        Reduced data matrix

    e_values : array, (m)
        The eigenvalues, sorted in descending manner.

    e_vectors : array, (n, m)
        The eigenvectors, sorted corresponding to eigenvalues.

    """
    # Center to average
    X_ = X-X.mean(0)
    # Compute correlation / covarianz matrix
    if corr:
        CO = np.corrcoef(X_.T)
    else:
        CO = np.cov(X_.T)
    # Compute eigenvalues and eigenvectors
    e_values, e_vectors = sp.linalg.eigh(CO)

    # Sort the eigenvalues and the eigenvectors descending
    idx = np.argsort(e_values)[::-1]
    e_vectors = e_vectors[:, idx]
    e_values = e_values[idx]
    # Get the number of desired dimensions
    d_e_vecs = e_vectors
    if d > 0:
        d_e_vecs = e_vectors[:, :d]
    else:
        d = None
    # Map principal components to original data
    LIN = np.dot(d_e_vecs, np.dot(d_e_vecs.T, X_.T)).T
    return LIN[:, :d], e_values, e_vectors

Использование образца

Здесь пример script, который использует данную функцию и использует scipy.cluster.vq.kmeans2 для кластеризации. Обратите внимание, что результаты варьируются в зависимости от каждого прогона. Это связано с тем, что исходные кластеры были инициализированы случайным образом.

import numpy as np
import scipy as sp
from scipy.cluster.vq import kmeans2
import matplotlib.pyplot as plt

SN = np.array([ [1.325, 1.000, 1.825, 1.750],
                [2.000, 1.250, 2.675, 1.750],
                [3.000, 3.250, 3.000, 2.750],
                [1.075, 2.000, 1.675, 1.000],
                [3.425, 2.000, 3.250, 2.750],
                [1.900, 2.000, 2.400, 2.750],
                [3.325, 2.500, 3.000, 2.000],
                [3.000, 2.750, 3.075, 2.250],
                [2.075, 1.250, 2.000, 2.250],
                [2.500, 3.250, 3.075, 2.250],
                [1.675, 2.500, 2.675, 1.250],
                [2.075, 1.750, 1.900, 1.500],
                [1.750, 2.000, 1.150, 1.250],
                [2.500, 2.250, 2.425, 2.500],
                [1.675, 2.750, 2.000, 1.250],
                [3.675, 3.000, 3.325, 2.500],
                [1.250, 1.500, 1.150, 1.000]], dtype=float)

clust,labels_ = kmeans2(SN,3)    # cluster with 3 random initial clusters
# PCA on orig. dataset 
# Xred will have only 2 columns, the first two princ. comps.
# evals has shape (4,) and evecs (4,4). We need all eigenvalues 
# to determine the portion of variance
Xred, evals, evecs = dim_red_pca(SN,2)   

xlab = '1. PC - ExpVar = {:.2f} %'.format(evals[0]/sum(evals)*100) # determine variance portion
ylab = '2. PC - ExpVar = {:.2f} %'.format(evals[1]/sum(evals)*100)
# plot the clusters, each set separately
plt.figure()    
ax = plt.gca()
scatterHs = []
clr = ['r', 'b', 'k']
for cluster in set(labels_):
    scatterHs.append(ax.scatter(Xred[labels_ == cluster, 0], Xred[labels_ == cluster, 1], 
                   color=clr[cluster], label='Cluster {}'.format(cluster)))
plt.legend(handles=scatterHs,loc=4)
plt.setp(ax, title='First and Second Principle Components', xlabel=xlab, ylabel=ylab)
# plot also the eigenvectors for deriving the influence of each feature
fig, ax = plt.subplots(2,1)
ax[0].bar([1, 2, 3, 4],evecs[0])
plt.setp(ax[0], title="First and Second Component Eigenvectors ", ylabel='Weight')
ax[1].bar([1, 2, 3, 4],evecs[1])
plt.setp(ax[1], xlabel='Features', ylabel='Weight')

Выход

Собственные векторы показывают весовое значение каждого признака для компонента

enter image description here

enter image description here

Короткая интерпретация

Давайте просто взглянем на кластер ноль, красный. Мы будем в основном заинтересованы в первом компоненте, так как он объясняет около 3/4 дистрибутива. Красный кластер находится в верхней части первого компонента. Все наблюдения дают довольно высокие значения. Что это значит? Теперь, глядя на линейную комбинацию первого компонента, мы видим на первый взгляд, что вторая особенность довольно несущественна (для этого компонента). Первая и четвертая функции - самые высокие, а третий - отрицательный. Это означает, что, поскольку все красные вершины имеют довольно высокий балл на первом ПК, эти вершины будут иметь высокие значения в первой и последней характеристиках, и в то же время, у них низкие оценки относительно третья особенность.

Что касается второй функции, мы можем взглянуть на второй компьютер. Однако обратите внимание, что общий эффект намного меньше, поскольку этот компонент объясняет только примерно 16% дисперсии по сравнению с ~ 74% первого ПК.

Ответ 2

Вы можете сделать это следующим образом:

>>> import numpy as np
>>> import sklearn.cluster as cl
>>> data = np.array([99,1,2,103,44,63,56,110,89,7,12,37])
>>> k_means = cl.KMeans(init='k-means++', n_clusters=3, n_init=10)
>>> k_means.fit(data[:,np.newaxis]) # [:,np.newaxis] converts data from 1D to 2D
>>> k_means_labels = k_means.labels_
>>> k1,k2,k3 = [data[np.where(k_means_labels==i)] for i in range(3)] # range(3) because 3 clusters
>>> k1
array([44, 63, 56, 37])
>>> k2
array([ 99, 103, 110,  89])
>>> k3
array([ 1,  2,  7, 12])

Ответ 3

Я предполагаю, что, говоря "основная особенность", которую вы имеете в виду, оказал наибольшее влияние на класс. Хорошее исследование, которое вы можете сделать, это посмотреть на координаты центров кластеров. Например, график для каждой функции, которую он координирует в каждом из K-центров.

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

Ответ 4

Попробуй это,

estimator=KMeans()
estimator.fit(X)
res=estimator.__dict__
print res['cluster_centers_']

Вы получите матрицу cluster и feature_weights, из чего вы можете заключить, что функция, имеющая больший вес, играет главную роль в создании кластера.