Agrupando uma Matriz de Correlação

20

Eu tenho uma matriz de correlação que indica como cada item é correlacionado com o outro item. Portanto, para um N itens, eu já tenho uma matriz de correlação N * N. Usando essa matriz de correlação, como agrupo os N itens nos compartimentos M para que eu possa dizer que os itens Nk no k-ésimo compartimento se comportam da mesma maneira. Por favor, me ajude. Todos os valores do item são categóricos.

Obrigado. Entre em contato se precisar de mais informações. Eu preciso de uma solução em Python, mas qualquer ajuda para me empurrar para os requisitos será uma grande ajuda.

Abhishek093
fonte
Quão grande é N normalmente?
Rodin
1
Não preciso de um cluster hierárquico para o meu problema. Só preciso dizer quais itens se comportam da mesma forma.
Abhishek093
N é tipicamente 250 - 300.
Abhishek093
3
Para sua informação, este problema é chamado de bi-clustering. Uma demonstração dele pode ser encontrada em scikit-learn.org/stable/auto_examples/bicluster/…
chanp

Respostas:

15

Parece um trabalho para modelagem de blocos. O Google para "modelagem de blocos" e os primeiros hits são úteis.

Digamos que tenhamos uma matriz de covariância em que N = 100 e na verdade existem 5 grupos: Matriz de covariância inicial

O que a modelagem de blocos está tentando fazer é encontrar uma ordem das linhas, para que os clusters se tornem aparentes como 'blocks': Ordem da matriz de covariância otimizada

Abaixo está um exemplo de código que executa uma pesquisa gananciosa básica para fazer isso. Provavelmente é muito lento para suas 250-300 variáveis, mas é um começo. Veja se você pode acompanhar os comentários:

import numpy as np
from matplotlib import pyplot as plt

# This generates 100 variables that could possibly be assigned to 5 clusters
n_variables = 100
n_clusters = 5
n_samples = 1000

# To keep this example simple, each cluster will have a fixed size
cluster_size = n_variables // n_clusters

# Assign each variable to a cluster
belongs_to_cluster = np.repeat(range(n_clusters), cluster_size)
np.random.shuffle(belongs_to_cluster)

# This latent data is used to make variables that belong
# to the same cluster correlated.
latent = np.random.randn(n_clusters, n_samples)

variables = []
for i in range(n_variables):
    variables.append(
        np.random.randn(n_samples) + latent[belongs_to_cluster[i], :]
    )

variables = np.array(variables)

C = np.cov(variables)

def score(C):
    '''
    Function to assign a score to an ordered covariance matrix.
    High correlations within a cluster improve the score.
    High correlations between clusters decease the score.
    '''
    score = 0
    for cluster in range(n_clusters):
        inside_cluster = np.arange(cluster_size) + cluster * cluster_size
        outside_cluster = np.setdiff1d(range(n_variables), inside_cluster)

        # Belonging to the same cluster
        score += np.sum(C[inside_cluster, :][:, inside_cluster])

        # Belonging to different clusters
        score -= np.sum(C[inside_cluster, :][:, outside_cluster])
        score -= np.sum(C[outside_cluster, :][:, inside_cluster])

    return score


initial_C = C
initial_score = score(C)
initial_ordering = np.arange(n_variables)

plt.figure()
plt.imshow(C, interpolation='nearest')
plt.title('Initial C')
print 'Initial ordering:', initial_ordering
print 'Initial covariance matrix score:', initial_score

# Pretty dumb greedy optimization algorithm that continuously
# swaps rows to improve the score
def swap_rows(C, var1, var2):
    '''
    Function to swap two rows in a covariance matrix,
    updating the appropriate columns as well.
    '''
    D = C.copy()
    D[var2, :] = C[var1, :]
    D[var1, :] = C[var2, :]

    E = D.copy()
    E[:, var2] = D[:, var1]
    E[:, var1] = D[:, var2]

    return E

current_C = C
current_ordering = initial_ordering
current_score = initial_score

max_iter = 1000
for i in range(max_iter):
    # Find the best row swap to make
    best_C = current_C
    best_ordering = current_ordering
    best_score = current_score
    for row1 in range(n_variables):
        for row2 in range(n_variables):
            if row1 == row2:
                continue
            option_ordering = best_ordering.copy()
            option_ordering[row1] = best_ordering[row2]
            option_ordering[row2] = best_ordering[row1]
            option_C = swap_rows(best_C, row1, row2)
            option_score = score(option_C)

            if option_score > best_score:
                best_C = option_C
                best_ordering = option_ordering
                best_score = option_score

    if best_score > current_score:
        # Perform the best row swap
        current_C = best_C
        current_ordering = best_ordering
        current_score = best_score
    else:
        # No row swap found that improves the solution, we're done
        break

# Output the result
plt.figure()
plt.imshow(current_C, interpolation='nearest')
plt.title('Best C')
print 'Best ordering:', current_ordering
print 'Best score:', current_score
print
print 'Cluster     [variables assigned to this cluster]'
print '------------------------------------------------'
for cluster in range(n_clusters):
    print 'Cluster %02d  %s' % (cluster + 1, current_ordering[cluster*cluster_size:(cluster+1)*cluster_size])
Rodin
fonte
Essa técnica não é usada para agrupar redes sociais? Isso será relevante aqui? Faz sentido usar essa matriz de correlação como matriz de distância?
Abhishek093
1) Sim, 2) Eu acho que sim, 3) Sim (valores que são altamente correlacionadas estão perto)
Rodin
OK. Vi através dos primeiros links. Ainda não sei como isso vai me ajudar a resolver meu problema.
Abhishek093
Eu editei minha resposta. Espero que seja útil para você.
Rodin
Eu vou dar uma olhada agora. Eu vou deixar você saber se isso se encaixa no meu problema. Muito obrigado.
Abhishek093
6

Você analisou o cluster hierárquico? Pode trabalhar com semelhanças, não apenas distâncias. Você pode cortar o dendrograma a uma altura em que ele se divide em k clusters, mas geralmente é melhor inspecionar visualmente o dendrograma e decidir a altura a cortar.

O agrupamento hierárquico também é frequentemente usado para produzir um reordenamento inteligente para uma vidualização de matrizes de similaridade, como visto na outra resposta: coloca entradas mais semelhantes próximas uma da outra. Isso também pode servir como uma ferramenta de validação para o usuário!

Anony-Mousse -Reinstate Monica
fonte
2

Você já olhou para agrupamentos de correlação ? Esse algoritmo de agrupamento usa as informações de correlação positiva / negativa em pares para propor automaticamente o número ideal de clusters com uma interpretação probabilística funcional bem definida e uma generativa rigorosa .

Shai
fonte
O artigo da Wikipedia promovido: Correlation clustering provides a method for clustering a set of objects into the optimum number of clusters without specifying that number in advance. Essa é uma definição do método? Se sim, é estranho, porque existem outros métodos para sugerir automaticamente o número de clusters e, também, porque é chamado "correlação".
ttnphns
@ttnphns (1) é chamado de "clustering de correlação" porque espera como entrada uma matriz de correlação em pares (veja o trabalho seminal de Bansal, N .; Blum, A .; Chawla, S. (2004). "Correlation Clustering ". Machine Learning. 56: 89).
Shai
@ttnphns sobre o "número ideal de clusters": você está certo sobre o fato de que "ideal" é ambíguo, "ideal" sob que medida? Quanto ao clustering de correlação, se você aceitar o modelo generativo proposto em "Clustering de Correlação em Grande Escala" da Bagon & Galun , o método produzirá o número ideal.
Shai
Shai, parece que você é um dos inventores do método. Eu o incentivaria a dar uma resposta mais desembrulhada, apresentando-a - se você tiver tempo e vontade. Especificamente, quer-se saber como o método é colocado entre alguns bem estabelecidos, como k-means ou hierárquicos. Observe também que a correlação é facilmente convertível em distância euclidiana (com qualquer método de agrupamento padrão aplicável posteriormente), - sabendo esse fato / truque, que coisas o seu método permite e que esse "truque" não permite? Escreva sobre isso. (Obrigado antecipadamente!)
ttnphns
1
Espero que cubra. Eu só queria dizer que é sempre uma boa idéia dar um pouco mais de detalhes em uma resposta publicada neste site, especialmente quando um método é bastante novo e quando se sabe o que dizer, ser um inventor. :-) Não, não é "muito amplo".
ttnphns
-1

Eu filtraria em algum limiar significativo (significância estatística) e depois usaria a decomposição dulmage-mendelsohn para obter os componentes conectados. Talvez antes você possa tentar remover algum problema, como correlações transitivas (A altamente correlacionada com B, B para C, C para D, para que exista um componente que contenha todos eles, mas, de fato, D para A seja baixo). você pode usar algum algoritmo baseado em intermediação. Não é um problema complexo, como alguém sugeriu, pois a matriz de correlação é simétrica e, portanto, não há algo bi.

user2843263
fonte
Esta resposta não explica bem como definir os limites sugeridos, que a IMO parece arbitrária. Além disso, como essa pergunta tem dois anos e já foi aceita uma resposta com alguns upvotes, convém elaborar as informações já existentes.
IWS