Бикластеризация документов с использованием алгоритма спектральной кокластеризации

Machine LearningMachine LearningBeginner
Практиковаться сейчас

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

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

В этом лабораторном задании мы будем использовать алгоритм спектрального ко-кластеризации на наборе данных "двадцать новостных групп" для бикластеризации документов. В наборе данных есть 20 категорий документов, и мы исключим категорию "comp.os.ms-windows.misc", так как она содержит сообщения без данных. Посты, векторизованные с использованием TF-IDF, формируют матрицу частот слов, которая затем бикластеризуется с использованием алгоритма спектрального ко-кластеризации Диллеона. Полученные документ-словарные бикластеры показывают подмножества слов, которые чаще используются в этих подмножествах документов. Мы также сгруппируем документы с использованием MiniBatchKMeans для сравнения.

Советы по использованию ВМ

После запуска ВМ нажмите в левом верхнем углу, чтобы переключиться на вкладку Notebook и получить доступ к Jupyter Notebook для практики.

Иногда вам может потребоваться подождать несколько секунд, пока Jupyter Notebook загрузится. Валидация операций не может быть автоматизирована из-за ограничений в Jupyter Notebook.

Если вы сталкиваетесь с проблемами во время обучения, не стесняйтесь обращаться к Labby. Оставьте отзыв после занятия, и мы оперативно решим проблему для вас.

Импорт библиотек

Мы импортируем необходимые библиотеки для этого лабораторного задания.

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)

Определение NumberNormalizingVectorizer

Мы определим класс NumberNormalizingVectorizer(), который наследуется от TfidfVectorizer(), чтобы создать токенизатор, который использует функцию number_normalizer(), определенную нами ранее.

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

Загрузка и подготовка данных

Мы загрузим набор данных "двадцать новостных групп" и исключим категорию "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)

Найти наилучшие бикластеры

Мы найдем наилучшие бикластеры, вычислив их нормализованный разрез и выбрав топ-five.

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("бикластер {} : {} документов, {} слов".format(idx, n_rows, n_cols))
    print("категории   : {}".format(cat_string))
    print("слова        : {}\n".format(", ".join(important_words)))

Резюме

В этом практическом занятии мы узнали, как выполнить бикластеризацию с использованием алгоритма спектральной кокластеризации на наборе данных "двадцать новостных групп". Мы также узнали, как кластеризовать данные с использованием MiniBatchKMeans для сравнения. Наконец, мы нашли наилучшие бикластеры, вычислив их нормализованный разрез и выбрав топ-five.