Ich weiß nicht, wie es möglich ist, Schlüsselwörter mit überwachtem Lernen zu extrahieren, aber ich weiß, wie man es mit unbeaufsichtigtem Lernen macht.
Hierfür gibt es verschiedene Methoden:
Hierarchisch
Sie können jede hierarchische Clustermethode direkt auf die Ähnlichkeitsmatrix anwenden (mit jeder Ähnlichkeitsfunktion, nicht nur mit dem Kosinus).
In scikit-learn würden Sie so etwas tun:
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_
Quelle: [1]
Da es sich jedoch um ein agglomeratives Clustering handelt, ist es rechenintensiv und die Berechnung dauert eine Weile.
K-Mittel
Eine andere Möglichkeit besteht darin, in den Zeilen der Term-Document-Matrix die üblichen k-Mittelwerte zu verwenden und dann für jeden Schwerpunkt die gebräuchlichsten Begriffe zu finden
In scikit learn ist dies beispielsweise die Vorgehensweise:
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='')
Quelle: [2]
K-means stützt sich jedoch auf die euklidische Distanz, die für spärliche hochdimensionale Daten schlecht ist. Es gibt andere Techniken, die für Texte besser funktionieren und Kosinusähnlichkeit verwenden
Kosinus K-Mittel und Scatter / Gather
Es ist möglich, Cosine mit K-Mitteln zu verwenden (siehe zB [3] ): Berechnen Sie Schwerpunkte als Mittelwert über alle Dokumente in jedem Cluster und verwenden Sie Cosinus, um den Abstand zum nächstgelegenen Schwerpunkt zu berechnen.
Am Ende können Sie Schlüsselwörter auf die gleiche Weise extrahieren wie für gewöhnliche k-means.
Die Berechnung des durchschnittlichen Schwerpunkts als Mittelwert aller Dokumente im Cluster ist nicht immer gut. Ein anderer Ansatz wird im Scatter / Gather-Algorithmus vorgeschlagen. [4] : Der Schwerpunkt eines Clusters ist die Verkettung aller Dokumente in diesem Cluster.
Für diesen Ansatz müssen Sie nur die häufigsten Begriffe für jeden Schwerpunktcluster verwenden.
Es gibt keine Implementierung dieser Algorithmen in scikit learn, aber Sie können sie einfach selbst implementieren, indem Sie sie erweitern KMeans
.
Beachten Sie, dass die Zentroide in beiden Fällen ziemlich dicht werden: dichter als die übrigen Dokumente in den einzelnen Clustern. Daher möchten Sie möglicherweise Begriffe in den Zentroiden abschneiden , dh "unwichtige" entfernen. (siehe [8]).
Spektrale Clusterbildung
Ein anderer Weg wäre, spektrale Clusterbildung anzuwenden. Sie müssen eine Ähnlichkeitsmatrix bereitstellen, über die Sie bereits verfügen. Darauf befinden sich Cluster.
Es ist in der SpectralClustering
Klasse implementiert , siehe Beispiele in [5] . Beachten Sie, dass Sie, da Sie bereits über eine vorberechnete Matrix verfügen, diese verwenden müssenaffinity='precumputed'
bei der Initialisierung das Attribut verwenden .
Spectral Clustering ist mit Kernel-KMeans verwandt: Es gibt Papier (siehe [7]), das zeigt, dass sie dasselbe sind. Ich bin kürzlich auf eine Implementierung von Kernel-KMeans gestoßen, die nützlich sein kann: https://gist.github.com/mblondel/6230787
Nicht negative Matrixfaktorisierung
Schließlich können Sie Ihre Term-Document-Matrix mit einigen Zerlegungstechniken aus der Linearen Algebra wie SVD (dies wäre die sogenannte "Latent Semantic Analysis") oder Non-Negative Matrix Factorization gruppieren. Letzteres kann als Clustering angesehen werden und sowohl Zeilen als auch Spalten der Matrix gleichzeitig gruppieren.
Beispielsweise können Sie Stichwörter extrahieren, indem Sie folgendermaßen vorgehen
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()
Code-Quelle: [6]
Obwohl hier die Beispiele in Python-Scikit-Learn sind, sollte es meines Erachtens kein großes Problem sein, einige Beispiele für R zu finden
Quellen