Agrupando una matriz de correlación

20

Tengo una matriz de correlación que establece cómo cada elemento se correlaciona con el otro elemento. Por lo tanto, para N elementos, ya tengo una matriz de correlación N * N. Usando esta matriz de correlación, ¿cómo agrupo los N elementos en M bins para poder decir que los Nk Items en el kth bin se comportan de la misma manera? Amablemente ayúdame. Todos los valores de los artículos son categóricos.

Gracias. Avíseme si necesita más información. Necesito una solución en Python, pero cualquier ayuda para impulsarme hacia los requisitos será de gran ayuda.

Abhishek093
fuente
¿Qué tan grande es normalmente N?
Rodin
1
No necesito una agrupación jerárquica para mi problema. Solo necesito decir qué elementos se comportan de la misma manera.
Abhishek093
N es típicamente 250 - 300.
Abhishek093
3
FYI, este problema se llama bi-clustering. Se puede encontrar una demostración en scikit-learn.org/stable/auto_examples/bicluster/…
chanp

Respuestas:

15

Parece un trabajo para el modelado de bloques. Google para "modelado de bloques" y los primeros resultados son útiles.

Digamos que tenemos una matriz de covarianza donde N = 100 y en realidad hay 5 grupos: Matriz de covarianza inicial

Lo que intenta hacer el modelado de bloques es encontrar un orden de las filas, de modo que los grupos se vuelvan aparentes como 'bloques': Orden de matriz de covarianza optimizado

A continuación se muestra un ejemplo de código que realiza una búsqueda codiciosa básica para lograr esto. Probablemente sea demasiado lento para sus variables 250-300, pero es un comienzo. Vea si puede seguir los comentarios:

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
fuente
¿No se utiliza esa técnica para la agrupación de redes sociales? ¿Será eso relevante aquí? ¿Tiene sentido usar esa matriz de correlación como una matriz de distancia?
Abhishek093
1) Sí, 2) Creo que sí, 3) Sí (los valores que están altamente correlacionados están cerca)
Rodin
Bueno. Vi a través de los primeros enlaces. Todavía no sé cómo esto me ayudará a resolver mi problema.
Abhishek093
He editado mi respuesta. Espero que te sea útil.
Rodin
Lo voy a comprobar ahora. Te haré saber si se ajusta a mi problema. Muchas gracias.
Abhishek093
6

¿Has mirado el agrupamiento jerárquico? Puede funcionar con similitudes, no solo distancias. Puede cortar el dendrograma a una altura donde se divide en k grupos, pero generalmente es mejor inspeccionar visualmente el dendrograma y decidir la altura de corte.

La agrupación jerárquica también se usa a menudo para producir una reordenación inteligente para una visualización de matriz de similitud como se ve en la otra respuesta: coloca entradas más similares una al lado de la otra. ¡Esto también puede servir como una herramienta de validación para el usuario!

Anony-Mousse -Reinstate a Monica
fuente
2

¿Has estudiado el agrupamiento de correlaciones ? Este algoritmo de agrupamiento utiliza la información de correlación positiva / negativa por pares para proponer automáticamente el número óptimo de grupos con una interpretación probabilística generativa funcional y rigurosa bien definida .

Shai
fuente
El artículo de 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. ¿Es esa una definición del método? En caso afirmativo, es extraño porque existen otros métodos para sugerir automáticamente el número de grupos, y también, ¿por qué entonces se llama "correlación".
ttnphns
@ttnphns (1) se llama "agrupación de correlación" porque espera como entrada una matriz de correlación por pares (ver el trabajo seminal de Bansal, N .; Blum, A .; Chawla, S. (2004). "Correlation Clustering ". Machine Learning. 56: 89).
Shai
@ttnphns con respecto al "número óptimo de clústeres": ¿tiene razón sobre el hecho de que "óptimo" es ambiguo, "óptimo" bajo qué medida? En cuanto a la agrupación de correlación, si acepta el modelo generativo propuesto en "Agrupación de correlación a gran escala" de Bagon & Galun , entonces el método genera el número óptimo.
Shai
Shai, parece que eres uno de los inventores del método. Le animo a que dé una respuesta más desenvuelta presentándola, si tiene tiempo y ganas. Específicamente, uno quiere saber cómo se coloca el método entre algunos bien establecidos, como k-means o jerárquico. Tenga en cuenta también que la correlación es fácilmente convertible a distancia euclidiana (con cualquier método de agrupamiento estándar aplicable después), - sabiendo ese hecho / truco, ¿qué cosas permite su método que ese "truco" no permite? Escribe sobre eso. (¡Gracias de antemano!)
ttnphns
1
Espero que lo cubra. Solo quería decir que siempre es una buena idea dar un poco más de detalles en una respuesta publicada en este sitio, especialmente cuando un método es bastante nuevo y cuando uno sabe qué decir, ser inventor. :-) No, no es "demasiado amplio".
ttnphns
-1

Filtraría en algún umbral significativo (significación estadística) y luego usaría la descomposición dulmage-mendelsohn para obtener los componentes conectados. Tal vez antes de que pueda intentar eliminar algún problema, como las correlaciones transitivas (A altamente correlacionado con B, B a C, C a D, por lo que hay un componente que los contiene a todos, pero de hecho D a A es bajo). puedes usar un algoritmo basado en la intermediación. Como alguien sugirió, no es un problema de biclustering, ya que la matriz de correlación es simétrica y, por lo tanto, no hay bi-algo.

usuario2843263
fuente
Esta respuesta no explica del todo cómo establecer los umbrales sugeridos, lo que la OMI parece arbitrario. Además, como esta pregunta tiene dos años y ya se ha aceptado una respuesta con un par de votos a favor, es posible que desee dar más detalles sobre la información ya existente.
IWS