スペクトラル共クラスタリングアルゴリズムを用いた文書の二部クラスタリング

Machine LearningMachine LearningBeginner
今すぐ練習

This tutorial is from open-source community. Access the source code

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

この実験では、20つのニュースグループのデータセットに対してスペクトラル共クラスタリングアルゴリズムを使用して、文書を二部クラスタリングします。このデータセットには20種類の文書があり、データが含まれていない投稿が含まれているため、「comp.os.ms-windows.misc」カテゴリを除外します。TF-IDFベクトル化された投稿は単語頻度行列を形成し、その後、Dhillonのスペクトラル共クラスタリングアルゴリズムを使用して二部クラスタリングされます。得られた文書-単語の二部クラスタは、それらの文書のサブセットでより頻繁に使用される単語のサブセットを示します。比較のために、MiniBatchKMeansを使用して文書をクラスタリングすることも行います。

VMのヒント

VMの起動が完了したら、左上隅をクリックしてノートブックタブに切り替え、Jupyter Notebookを使用して練習します。

時々、Jupyter Notebookが読み込み終了するまで数秒待つ必要がある場合があります。Jupyter Notebookの制限により、操作の検証を自動化することはできません。

学習中に問題が発生した場合は、Labbyにお問い合わせください。セッション後にフィードバックを提供してください。すぐに問題を解決いたします。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL sklearn(("Sklearn")) -.-> sklearn/DataPreprocessingandFeatureEngineeringGroup(["Data Preprocessing and Feature Engineering"]) sklearn(("Sklearn")) -.-> sklearn/ModelSelectionandEvaluationGroup(["Model Selection and Evaluation"]) sklearn(("Sklearn")) -.-> sklearn/UtilitiesandDatasetsGroup(["Utilities and Datasets"]) ml(("Machine Learning")) -.-> ml/FrameworkandSoftwareGroup(["Framework and Software"]) sklearn(("Sklearn")) -.-> sklearn/CoreModelsandAlgorithmsGroup(["Core Models and Algorithms"]) sklearn/CoreModelsandAlgorithmsGroup -.-> sklearn/cluster("Clustering") sklearn/DataPreprocessingandFeatureEngineeringGroup -.-> sklearn/feature_extraction("Feature Extraction") sklearn/ModelSelectionandEvaluationGroup -.-> sklearn/metrics("Metrics") sklearn/UtilitiesandDatasetsGroup -.-> sklearn/datasets("Datasets") ml/FrameworkandSoftwareGroup -.-> ml/sklearn("scikit-learn") subgraph Lab Skills sklearn/cluster -.-> lab-49069{{"スペクトラル共クラスタリングアルゴリズムを用いた文書の二部クラスタリング"}} sklearn/feature_extraction -.-> lab-49069{{"スペクトラル共クラスタリングアルゴリズムを用いた文書の二部クラスタリング"}} sklearn/metrics -.-> lab-49069{{"スペクトラル共クラスタリングアルゴリズムを用いた文書の二部クラスタリング"}} sklearn/datasets -.-> lab-49069{{"スペクトラル共クラスタリングアルゴリズムを用いた文書の二部クラスタリング"}} ml/sklearn -.-> lab-49069{{"スペクトラル共クラスタリングアルゴリズムを用いた文書の二部クラスタリング"}} end

ライブラリのインポート

この実験に必要なライブラリをインポートします。

from collections import defaultdict
import operator
from time import time
import numpy as np
from sklearn.cluster import SpectralCoclustering
from sklearn.cluster import MiniBatchKMeans
from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.cluster import v_measure_score

数値正規化関数の定義

すべての数値トークンをプレースホルダにマッピングする関数number_normalizer()を定義します。これは次元削減に使用されます。

def number_normalizer(tokens):
    """Map all numeric tokens to a placeholder.

    For many applications, tokens that begin with a number are not directly
    useful, but the fact that such a token exists can be relevant.  By applying
    this form of dimensionality reduction, some methods may perform better.
    """
    return ("#NUMBER" if token[0].isdigit() else token for token in tokens)

数値正規化ベクトル化器の定義

先ほど定義したnumber_normalizer()関数を使用するトークナイザを構築するため、TfidfVectorizer()から継承するNumberNormalizingVectorizer()クラスを定義します。

class NumberNormalizingVectorizer(TfidfVectorizer):
    def build_tokenizer(self):
        tokenize = super().build_tokenizer()
        return lambda doc: list(number_normalizer(tokenize(doc)))

データの読み込みと準備

20つのニュースグループのデータセットを読み込み、「comp.os.ms-windows.misc」カテゴリを除外します。また、ベクトル化器も定義します。

categories = [
    "alt.atheism",
    "comp.graphics",
    "comp.sys.ibm.pc.hardware",
    "comp.sys.mac.hardware",
    "comp.windows.x",
    "misc.forsale",
    "rec.autos",
    "rec.motorcycles",
    "rec.sport.baseball",
    "rec.sport.hockey",
    "sci.crypt",
    "sci.electronics",
    "sci.med",
    "sci.space",
    "soc.religion.christian",
    "talk.politics.guns",
    "talk.politics.mideast",
    "talk.politics.misc",
    "talk.religion.misc",
]
newsgroups = fetch_20newsgroups(categories=categories)
y_true = newsgroups.target

vectorizer = NumberNormalizingVectorizer(stop_words="english", min_df=5)

データのベクトル化

先ほど定義したベクトル化器を使ってデータをベクトル化します。

X = vectorizer.fit_transform(newsgroups.data)

スペクトラル共クラスタリングアルゴリズムを用いた二部クラスタリング

共クラスタを定義し、データに適合させることで、スペクトラル共クラスタリングアルゴリズムを使って二部クラスタリングを行います。

cocluster = SpectralCoclustering(
    n_clusters=len(categories), svd_method="arpack", random_state=0
)
cocluster.fit(X)
y_cocluster = cocluster.row_labels_

MiniBatchKMeansを使ったクラスタリング

MiniBatchKMeansを使ってデータをクラスタリングします。

kmeans = MiniBatchKMeans(
    n_clusters=len(categories), batch_size=20000, random_state=0, n_init=3
)
y_kmeans = kmeans.fit_predict(X)

最適な二部クラスタを見つける

正規化カットを計算し、上位5つを選択することで、最適な二部クラスタを見つけます。

feature_names = vectorizer.get_feature_names_out()
document_names = list(newsgroups.target_names[i] for i in newsgroups.target)

def bicluster_ncut(i):
    rows, cols = cocluster.get_indices(i)
    if not (np.any(rows) and np.any(cols)):
        import sys
        return sys.float_info.max
    row_complement = np.nonzero(np.logical_not(cocluster.rows_[i]))[0]
    col_complement = np.nonzero(np.logical_not(cocluster.columns_[i]))[0]
    weight = X[rows][:, cols].sum()
    cut = X[row_complement][:, cols].sum() + X[rows][:, col_complement].sum()
    return cut / weight

bicluster_ncuts = list(bicluster_ncut(i) for i in range(len(newsgroups.target_names)))
best_idx = np.argsort(bicluster_ncuts)[:5]

結果を表示する

ステップ8で見つけた最適な二部クラスタの結果を表示します。

for idx, cluster in enumerate(best_idx):
    n_rows, n_cols = cocluster.get_shape(cluster)
    cluster_docs, cluster_words = cocluster.get_indices(cluster)
    if not len(cluster_docs) or not len(cluster_words):
        continue

    ## カテゴリ
    counter = defaultdict(int)
    for i in cluster_docs:
        counter[document_names[i]] += 1
    cat_string = ", ".join(
        "{:.0f}% {}".format(float(c) / n_rows * 100, name)
        for name, c in most_common(counter)[:3]
    )

    ## 単語
    out_of_cluster_docs = cocluster.row_labels_!= cluster
    out_of_cluster_docs = np.where(out_of_cluster_docs)[0]
    word_col = X[:, cluster_words]
    word_scores = np.array(
        word_col[cluster_docs, :].sum(axis=0)
        - word_col[out_of_cluster_docs, :].sum(axis=0)
    )
    word_scores = word_scores.ravel()
    important_words = list(
        feature_names[cluster_words[i]] for i in word_scores.argsort()[:-11:-1]
    )

    print("bicluster {} : {} documents, {} words".format(idx, n_rows, n_cols))
    print("categories   : {}".format(cat_string))
    print("words        : {}\n".format(", ".join(important_words)))

まとめ

この実験では、20つのニュースグループデータセットに対して、スペクトラル共クラスタリングアルゴリズムを使って二部クラスタリングを行う方法を学びました。また、比較のためにMiniBatchKMeansを使ってデータをクラスタリングする方法も学びました。最後に、正規化カットを計算し、上位5つを選択することで、最適な二部クラスタを見つけました。