No sé cómo es posible extraer palabras clave con aprendizaje supervisado, pero sí sé cómo hacerlo con aprendizaje no supervisado.
Existen varios métodos para hacerlo, así que aquí están:
Jerárquico
Puede aplicar cualquier método de agrupamiento jerárquico en el término matriz de similitud directamente (con cualquier función de similitud, no solo coseno)
En scikit-learn harías algo como esto:
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.cluster import AgglomerativeClustering
vectorizer = TfidfVectorizer(stop_words='english')
X = vectorizer.fit_transform(data)
C = 1 - cosine_similarity(X.T)
ward = AgglomerativeClustering(n_clusters=k, linkage='ward').fit(C)
label = ward.labels_
Fuente: [1]
Pero dado que es un clúster aglomerativo, es computacionalmente costoso y tomará un tiempo calcularlo.
K-medias
Otra posibilidad es hacer k-medias habituales en las filas de la matriz de términos y documentos, y luego encontrar los términos más comunes para cada centroide
Por ejemplo, en scikit aprender, esta es la forma de hacerlo:
from sklearn.cluster import KMeans
km = KMeans(n_clusters=k, init='k-means++', max_iter=100, n_init=1)
km.fit(X)
order_centroids = km.cluster_centers_.argsort()[:, ::-1]
terms = vectorizer.get_feature_names()
for i in range(k):
print("Cluster %d:" % i, end='')
for ind in order_centroids[i, :10]:
print(' %s' % terms[ind], end='')
Fuente: [2]
Pero k-means se basa en la distancia euclidiana, lo cual es malo para datos dispersos de alta dimensión. Existen otras técnicas que funcionan mejor para textos y utilizan la similitud de coseno
Coseno K-medias y dispersión / recolección
Es posible usar Coseno con medias K (ver, por ejemplo, [3] ): calcule los centroides como una media sobre todos los documentos en cada grupo, y luego use el coseno para calcular la distancia al centroide más cercano.
Al final, puede extraer palabras clave de la misma manera que para k-means habituales.
Calcular el centroide promedio como una media de todos los documentos en el clúster no siempre es bueno. Se sugiere otro enfoque en el algoritmo Scatter / Gather [4] : el centroide de un grupo es la concatenación de todos los documentos en este grupo.
Para este enfoque, solo tendrá que tomar los términos más frecuentes para cada grupo centroide.
No hay implementación de estos algoritmos en scikit learn, pero puede implementarlos fácilmente usted mismo extendiéndolos KMeans
.
Tenga en cuenta que en ambos casos los centroides se vuelven bastante densos: más densos que el resto de los documentos en cada grupo, por lo que es posible que desee truncar los términos en los centroides, es decir, eliminar los "sin importancia". (ver [8]).
Agrupación espectral
Otra forma sería aplicar la agrupación espectral. Deberá proporcionar una matriz de similitud, que ya tiene, y encontrará grupos en ella.
Se implementa en la SpectralClustering
clase, ver ejemplos en [5] . Tenga en cuenta que, dado que ya tiene una matriz calculada previamente, debe usar el affinity='precumputed'
atributo al inicializar.
La agrupación espectral está relacionada con Kernel KMeans: hay papel (ver [7]) que muestra que son lo mismo. Recientemente encontré una implementación de Kernel KMeans que puede ser útil: https://gist.github.com/mblondel/6230787
Factorización matricial no negativa
Finalmente, puede agrupar su matriz de documentos a término con algunas técnicas de descomposición de Álgebra lineal, como SVD (esto se denominaría "Análisis semántico latente") o Factorización de matriz no negativa. Este último puede verse como agrupamiento, y puede agrupar tanto filas como columnas de la matriz al mismo tiempo.
Por ejemplo, puede extraer palabras clave haciendo
from sklearn.decomposition import NMF
nmf = NMF(n_components=k, random_state=1).fit(X)
feature_names = vectorizer.get_feature_names()
for topic_idx, topic in enumerate(nmf.components_):
print("Topic #%d:" % topic_idx)
print(" ".join([feature_names[i]
for i in topic.argsort()[:-10-1:-1]]))
print()
Fuente del código: [6]
Aunque aquí los ejemplos están en python scikit-learn, creo que no debería ser un gran problema encontrar algunos ejemplos para R
Fuentes