教師あり学習でキーワード抽出を行う方法がわかりませんが、教師なし学習でキーワード抽出を行う方法は知っています。
これを行うにはいくつかの方法がありますので、ここにあります:
階層的
用語の類似性行列に任意の階層クラスタリング手法を直接適用できます(コサインだけでなく、任意の類似性関数を使用)
scikit-learnでは、次のようなことをします。
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_
出典:[1]
しかし、それは凝集型のクラスタリングなので、計算コストが高く、計算に時間がかかります。
K-平均
もう1つの可能性は、用語ドキュメントマトリックスの行で通常のk-meansを実行し、各重心の最も一般的な用語を見つけることです。
たとえば、scikitでこれを行う方法を学習します。
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='')
出典:[2]
ただし、k-meansはユークリッド距離に依存します。これは、スパースな高次元データには不適切です。テキストに対してよりうまく機能し、コサイン類似性を使用する他の手法があります
コサインK平均と散布/収集
K-meansでコサインを使用することができます(例[3]を参照)。各クラスター内のすべてのドキュメントの平均として重心を計算し、次にコサインを使用して最も近い重心までの距離を計算します。
最後に、通常のk-meansと同じ方法でキーワードを抽出できます。
クラスタ内のすべてのドキュメントの平均として平均重心を計算することは、常に良いとは限りません。Scatter / Gatherアルゴリズムでは別のアプローチが提案されています[4]:クラスターの重心は、このクラスター内のすべてのドキュメントの連結です。
このアプローチでは、各重心クラスターに対して最も頻繁に用語を使用する必要があります。
scikit learnにはこれらのアルゴリズムの実装はありませんが、を拡張することで簡単に実装できますKMeans
。
どちらの場合でも、重心は非常に密集することに注意してください。各クラスターの残りのドキュメントよりも密集しているため、重心の用語を切り捨てる、つまり「重要でない」用語を削除することができます。([8]を参照)。
スペクトルクラスタリング
別の方法は、スペクトルクラスタリングを適用することです。既に持っている類似度マトリックスを提供する必要があります、そしてそれはそれでクラスターを見つけます。
SpectralClustering
クラスに実装されています。[5]の例を参照してください。既に計算済みのマトリックスがあるためaffinity='precumputed'
、初期化時に属性を使用する必要があることに注意してください。
スペクトルクラスタリングはカーネルKMeansに関連しています。それらが同じものであることを示す論文([7]を参照)があります。最近、役に立つかもしれないカーネルKMeansの実装に出会いました:https ://gist.github.com/mblondel/6230787
非負行列因子分解
最後に、SVD(いわゆる「潜在意味解析」)または非負行列因子分解などの線形代数からのいくつかの分解手法を使用して、用語ドキュメント行列をクラスター化できます。後者はクラスタリングと見なすことができ、マトリックスの行と列の両方を同時にクラスタリングできます。
たとえば、次のようにしてキーワードを抽出できます
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()
コードソース:[6]
ここでは例はpython scikit-learnにありますが、Rの例を見つけることは大きな問題ではないと思います
ソース