Введение
В этом лабораторном задании мы будем использовать алгоритм спектрального ко-кластеризации на наборе данных "двадцать новостных групп" для бикластеризации документов. В наборе данных есть 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.