Extraction automatique des mots clés: utilisation des similitudes cosinus comme fonctionnalités

12

J'ai une matrice de termes de document , et maintenant je voudrais extraire des mots-clés pour chaque document avec une méthode d'apprentissage supervisé (SVM, Naive Bayes, ...). Dans ce modèle, j'utilise déjà Tf-idf, Pos tag, ...M

Mais maintenant, je me pose des questions sur les voisins. J'ai une matrice avec les similitudes cosinus entre les termes.C

Est-il possible d'utiliser ces similitudes comme fonctionnalité pour mon modèle? Mon idée était pour le terme dans le document d , d'utiliser la moyenne des similitudes cosinus de tous les termes du document d avec le terme i . Est-ce utile?jeje

Silke
la source
Avez-vous fait une recherche sur Google? J'ai trouvé beaucoup de hits sous "extraction de mots-clés de similitude cosinus" qui semblent pouvoir vous
aider à
J'ai beaucoup cherché sur Google et j'ai lu de nombreux articles contenant les mots "similitude cosinus" et "extraction de mots clés". Mais je n'ai pas trouvé de papier où ils utilisent quelque chose comme la similitude cosinus pour extraire des mots clés
Silke

Réponses:

11

Je ne sais pas comment il est possible de faire l'extraction de mots clés avec un apprentissage supervisé, mais je sais comment le faire avec un apprentissage non supervisé.

Il existe plusieurs méthodes pour le faire, les voici donc:

Hiérarchique

Vous pouvez appliquer n'importe quelle méthode de clustering hiérarchique sur le terme matrice de similarité directement (avec n'importe quelle fonction de similarité, pas seulement cosinus)

Dans scikit-learn, vous feriez quelque chose comme ceci:

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_

Source: [1]

Mais comme il s'agit d'un cluster agglomératif, il est coûteux en calcul et le calcul prendra un certain temps.

K-Means

Une autre possibilité consiste à faire les k-moyennes habituelles sur les lignes de la matrice terme-document, puis à trouver les termes les plus courants pour chaque centroïde

Par exemple, dans scikit, apprenez que c'est la façon de procéder:

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='')

Source: [2]

Mais k-means s'appuie sur la distance euclidienne, ce qui est mauvais pour les données clairsemées de haute dimension. Il existe d'autres techniques qui fonctionnent mieux pour les textes et utilisent la similitude cosinus

Cosinus K-Means et Scatter / Gather

Il est possible d'utiliser le cosinus avec les moyennes K (voir par exemple [3] ): calculer les centroïdes comme moyenne sur tous les documents de chaque cluster, puis utiliser le cosinus pour calculer la distance au centroïde le plus proche.

À la fin, vous pouvez extraire des mots clés de la même manière que pour les k-means habituels.

Le calcul du centroïde moyen en tant que moyenne de tous les documents du cluster n'est pas toujours bon. Une autre approche est suggérée dans l'algorithme Scatter / Gather [4] : le centroïde d'un cluster est la concaténation de tous les documents de ce cluster.

Pour cette approche, vous devrez simplement prendre les termes les plus fréquents pour chaque cluster centroïde.

Il n'y a pas d'implémentation de ces algorithmes dans scikit learn, mais vous pouvez facilement les implémenter vous-même en les étendant KMeans.

Notez que dans les deux cas, les centroïdes deviennent assez denses: plus denses que le reste des documents dans chaque cluster, vous pouvez donc vouloir tronquer les termes dans les centroïdes, c'est-à-dire supprimer ceux "sans importance". (voir [8]).

Regroupement spectral

Une autre façon serait d'appliquer un regroupement spectral. Vous devrez fournir une matrice de similitude, que vous avez déjà, et elle y trouvera des clusters.

Il est implémenté dans la SpectralClusteringclasse, voir des exemples dans [5] . Notez que puisque vous avez déjà une matrice pré-calculée, vous devez utiliser l' affinity='precumputed'attribut lors de l'initialisation.

Le regroupement spectral est lié aux Kernel KMeans: il y a du papier (voir [7]) qui montre que c'est la même chose. J'ai récemment rencontré une implémentation de Kernel KMeans qui peut être utile: https://gist.github.com/mblondel/6230787

Factorisation matricielle non négative

Enfin, vous pouvez regrouper votre matrice terme-document avec certaines techniques de décomposition de l'algèbre linéaire, comme SVD (ce serait ce qu'on appelle "l'analyse sémantique latente") ou la factorisation matricielle non négative. Ce dernier peut être considéré comme un clustering, et il peut regrouper à la fois des lignes et des colonnes de la matrice.

Par exemple, vous pouvez extraire des mots clés en faisant

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()

Source du code: [6]

Même si ici les exemples sont en python scikit-learn, je pense que cela ne devrait pas être un gros problème de trouver des exemples pour R

Sources

Alexey Grigorev
la source
C'est une réponse d'une qualité incroyable. Merci! Avez-vous des idées sur l'utilisation de l'algorithme de propagation d'affinité de Scikit pour regrouper les mots? Les valeurs de similitude cosinus peuvent être utilisées (je pense que les similitudes seraient nécessaires, pas les distances) comme matrice d'affinité précalculée dans l'algorithme.
neelshiv