Automatyczne wyodrębnianie słów kluczowych: użycie podobieństw cosinusu jako funkcji

12

Mam matrycę terminów dokumentowych , a teraz chciałbym wyodrębnić słowa kluczowe dla każdego dokumentu za pomocą nadzorowanej metody uczenia się (SVM, Naive Bayes, ...). W tym modelu używam już Tf-idf, znacznika Pos, ...M.

Ale teraz zastanawiam się nad kolejnymi. Mam macierz z podobieństwami cosinusowymi między warunkami.do

Czy istnieje możliwość wykorzystania tych podobieństw jako funkcji mojego modelu? Moim pomysłem było użycie terminu w dokumencie d , aby użyć średniej podobieństwa cosinusów wszystkich terminów w dokumencie d z terminem i . Czy to jest przydatne?jarereja

Silke
źródło
Czy szukałeś w Google? Znalazłem wiele trafień pod „ekstrakcją słowa kluczowego podobieństwa cosinus”, które wydają się być w stanie zacząć
Shadowtalker
Dużo szukałem w Google i czytałem wiele artykułów zawierających słowa „podobieństwo cosinus” i „ekstrakcja słów kluczowych”. Ale nie znalazłem artykułu, w którym wykorzystują coś w rodzaju podobieństwa cosinus jako funkcji do wyodrębnienia słów kluczowych
Silke

Odpowiedzi:

12

Nie wiem, jak można wyodrębnić słowa kluczowe z uczeniem nadzorowanym, ale wiem, jak to zrobić, ucząc się bez nadzoru.

Można to zrobić na kilka sposobów, więc oto one:

Hierarchiczny

Możesz zastosować dowolną hierarchiczną metodę klastrowania bezpośrednio do macierzy podobieństwa (z dowolną funkcją podobieństwa, nie tylko cosinus)

W scikit-learn możesz zrobić coś takiego:

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_

Źródło: [1]

Ale ponieważ jest to skupienie aglomeracyjne, jest ono drogie obliczeniowo i jego obliczenie zajmie trochę czasu.

K-oznacza

Inną możliwością jest wykonanie zwykłych średnich k w wierszach matrycy termin-dokument, a następnie znalezienie najczęstszych terminów dla każdego środka ciężkości

Na przykład w scikit dowiedz się, jak to zrobić:

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

Źródło: [2]

Ale k-średnie opiera się na odległości euklidesowej, co jest niekorzystne dla rzadkich danych wielowymiarowych. Istnieją inne techniki, które działają lepiej dla tekstów i wykorzystują podobieństwo cosinus

Cosine K-Means and Scatter / Gather

Możliwe jest użycie cosinusa ze średnimi K (patrz np. [3] ): oblicz centroidy jako średnią dla wszystkich dokumentów w każdym klastrze, a następnie użyj cosinusa, aby obliczyć odległość do najbliższego centroidu.

Na koniec możesz wyodrębnić słowa kluczowe w taki sam sposób, jak w przypadku zwykłych k-średnich.

Obliczanie średniego centroidu jako średniej dla wszystkich dokumentów w klastrze nie zawsze jest dobre. Inne podejście jest sugerowane w algorytmie Scatter / Gather [4] : środek ciężkości klastra stanowi połączenie wszystkich dokumentów w tym klastrze.

Aby zastosować to podejście, wystarczy wziąć najczęstsze terminy dla każdego klastra centroidów.

Nie ma implementacji tych algorytmów w scikit learn, ale możesz je łatwo zaimplementować samodzielnie KMeans.

Zauważ, że w obu przypadkach centroidy stają się dość gęste: gęstsze niż reszta dokumentów w poszczególnych klastrach, więc możesz chcieć obciąć terminy w centroidach, tj. Usunąć te „nieważne”. (patrz [8]).

Grupowanie widmowe

Innym sposobem byłoby zastosowanie grupowania widmowego. Będziesz musiał dostarczyć macierz podobieństwa, którą już masz, i znajdzie na niej klastry.

Jest zaimplementowany w SpectralClusteringklasie, patrz przykłady w [5] . Pamiętaj, że ponieważ masz już wstępnie obliczoną macierz, musisz użyć affinity='precumputed'atrybutu podczas inicjowania.

Grupowanie spektralne jest powiązane z KMeansami jądra: istnieje papier (patrz [7]), który pokazuje, że są one tym samym. Ostatnio natknąłem się na implementację KMeansów jądra, które mogą być przydatne: https://gist.github.com/mblondel/6230787

Faktoryzacja macierzy nieujemnej

Na koniec możesz grupować matrycę dokumentów termicznych za pomocą niektórych technik dekompozycji z Algebry Liniowej, takich jak SVD (byłaby to tak zwana „Latentna analiza semantyczna”) lub faktoryzacja macierzy nieujemnej. Ten ostatni może być postrzegany jako grupowanie i może grupować zarówno wiersze, jak i kolumny macierzy w tym samym czasie.

Na przykład możesz wyodrębnić słowa kluczowe, wykonując

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

Źródło kodu: [6]

Chociaż tutaj przykłady znajdują się w Python scikit-learn, myślę, że nie powinno być dużym problemem znalezienie niektórych przykładów dla R

Źródła

Aleksiej Grigoriew
źródło
1
To niewiarygodnie wysokiej jakości odpowiedź. Dzięki! Czy masz jakieś przemyślenia na temat używania algorytmu propagacji powinowactwa Scikit do grupowania słów? Wartości podobieństwa cosinus można wykorzystać (uważam, że podobieństwa byłyby potrzebne, a nie odległości) jako wstępnie obliczoną macierz powinowactwa w algorytmie.
neelshiv