Как сделать кластеризацию с помощью матрицы коэффициентов корреляции?

У меня есть матрица коэффициентов корреляции (n*n). Как выполнить кластеризацию с использованием матрицы коэффициентов корреляции?

Могу ли я использовать функцию связывания и fcluster в SciPy?

Для функции связи требуется матрица n * m (согласно руководству), но я хочу использовать матрицу n*n.

Мой код

corre = mp_N.corr()    # mp_N is raw data (m*n matrix)  
Z = linkage(corre, method='average')  # 'corre' is correlation coefficient matrix
fcluster(Z,2,'distance')

Этот код подходит? Если этот код неверен, как я могу выполнить кластеризацию с матрицей коэффициентов корреляции?


person Siny    schedule 28.06.2016    source источник
comment
Без примеров данных, ожидаемых результатов и возвращенных результатов никто не может сказать, правильный ли ваш код. Создайте минимальный, полный и проверяемый пример. Кроме того, вы можете найти еще несколько библиотек кластеризации и примеры в пакете scikit-learn.   -  person tmthydvnprt    schedule 23.07.2016


Ответы (1)


Кластеризация данных с использованием корреляционной матрицы — разумная идея, но сначала необходимо предварительно обработать корреляции. Во-первых, на корреляционную матрицу, возвращаемую numpy.corrcoef, влияют ошибки машинной арифметики:

  1. Он не всегда симметричен.
  2. Диагональные члены не всегда точно равны 1

Их можно исправить, взяв среднее значение с транспонированием и заполнив диагональ 1:

import numpy as np
data = np.random.randint(0, 10, size=(20, 10))   # 20 variables with 10 observations each
corr = np.corrcoef(data)                         # 20 by 20 correlation matrix
corr = (corr + corr.T)/2                         # made symmetric
np.fill_diagonal(corr, 1)                        # put 1 on the diagonal

Во-вторых, входные данные для любого метода кластеризации, такого как linkage, должны измерять несходство объектов. Корреляция измеряет сходство. Поэтому его необходимо преобразовать таким образом, чтобы корреляция 0 сопоставлялась с большим числом, а корреляция 1 сопоставлялась с 0.

В этом сообщении блога обсуждается несколько способов получения таких данных. трансформации и рекомендует dissimilarity = 1 - abs(correlation). Идея состоит в том, что сильная отрицательная корреляция также указывает на то, что объекты связаны, как и положительная корреляция. Вот продолжение примера:

from scipy.cluster.hierarchy import linkage, fcluster
from scipy.spatial.distance import squareform

dissimilarity = 1 - np.abs(corr)
hierarchy = linkage(squareform(dissimilarity), method='average')
labels = fcluster(hierarchy, 0.5, criterion='distance')

Обратите внимание, что мы не передаем полную матрицу расстояний в linkage, ее нужно сначала сжать с помощью squareform.

Какие именно методы кластеризации использовать и какие пороги, зависит от контекста вашей проблемы, универсальных правил нет. Часто 0,5 является разумным порогом для корреляции, поэтому я так и сделал. С моими 20 наборами случайных чисел я получил 7 кластеров: закодированных в labels как

[7, 7, 7, 1, 4, 4, 2, 7, 5, 7, 2, 5, 6, 3, 6, 1, 5, 1, 4, 2] 
person Community    schedule 11.12.2017
comment
Хороший ответ! Ваше упоминание о расстоянии (несходстве) и корреляции (сходстве) для меня существенно. - person cgsdfc; 30.06.2019
comment
squareform() является ключом для преобразования между плотной матричной формой и сжатой векторной формой корреляции. И с точки зрения создания корреляции расстояния, позвольте мне добавить, что scipy использует 1 - corr, который имеет другое значение, чем 1 - abs(corr). Я не уверен, какой из них использовать, поэтому я решил пойти по пути scipy. - person cgsdfc; 30.06.2019
comment
Ваша ссылка на сообщение в блоге устарела. - person cgsdfc; 30.06.2019
comment
Я бы рекомендовал squareform(corr, checks=False, force='tovector') не проверять диагональные элементы (поскольку они отбрасываются) и задавать направление преобразования. - person cgsdfc; 30.06.2019
comment
Что нужно сделать с labels, чтобы затем упорядочить и построить корреляционную матрицу? - person Rylan Schaeffer; 27.02.2020