Não sei como é possível extrair palavras-chave com aprendizado supervisionado, mas sei como fazê-lo com aprendizado não supervisionado.
Existem vários métodos para fazer isso, então aqui estão eles:
Hierárquico
Você pode aplicar qualquer método de cluster hierárquico diretamente ao termo matriz de similaridade (com qualquer função de similaridade, não apenas cosseno)
No scikit-learn, você faria algo assim:
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_
Fonte: [1]
Mas como é um cluster aglomerado, é computacionalmente caro e levará um tempo para computar.
K-Means
Outra possibilidade é fazer k-means comuns em linhas da matriz termo-documento e, em seguida, encontrar os termos mais comuns para cada centróide
Por exemplo, no scikit learn, é assim que se faz:
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='')
Fonte: [2]
Mas o k-means depende da distância euclidiana, o que é ruim para dados esparsos de alta dimensão. Existem outras técnicas que funcionam melhor para textos e usam similaridade de cosseno
Cosine K-Meios e Dispersão / Coleta
É possível usar o Cosine com meios K (veja, por exemplo, [3] ): calcule os centróides como uma média em todos os documentos em cada cluster e, em seguida, use o co-seno para calcular a distância do centróide mais próximo.
No final, você pode extrair palavras-chave da mesma maneira que para os k-médias comuns.
Calcular o centróide médio como uma média de todos os documentos no cluster nem sempre é bom. Outra abordagem é sugerida no algoritmo Scatter / Gather [4] : o centróide de um cluster é a concatenação de todos os documentos desse cluster.
Para esta abordagem, você só precisará usar os termos mais frequentes para cada cluster de centróide.
Não há implementação desses algoritmos no scikit learn, mas você pode implementá-los facilmente ampliando KMeans
.
Observe que, em ambos os casos, os centróides se tornam bastante densos: mais densos que o restante dos documentos em cada cluster, portanto, você pode truncar termos nos centróides, ou seja, remover os "sem importância". (veja [8]).
Clustering espectral
Outra maneira seria aplicar o agrupamento espectral. Você precisará fornecer uma matriz de similaridade, que você já possui, e ela encontrará clusters nela.
É implementado na SpectralClustering
classe, veja exemplos em [5] . Observe que, como você já possui uma matriz pré-calculada, é necessário usar o affinity='precumputed'
atributo ao inicializar.
O agrupamento espectral está relacionado ao Kernel KMeans: existe um documento (veja [7]) que mostra que eles são a mesma coisa. Recentemente, deparei com uma implementação do Kernel KMeans que pode ser útil: https://gist.github.com/mblondel/6230787
Fatoração matricial não negativa
Finalmente, você pode agrupar sua matriz termo-documento com algumas técnicas de decomposição da Álgebra Linear, como SVD (isso seria chamado "Análise Semântica Latente") ou Fatoração de Matriz Não Negativa. O último pode ser visto como agrupamento e pode agrupar linhas e colunas da matriz ao mesmo tempo.
Por exemplo, você pode extrair palavras-chave fazendo
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()
Fonte do código: [6]
Embora aqui os exemplos estejam no python scikit-learn, acho que não deve ser um grande problema encontrar alguns exemplos para R
Fontes