Introducción
En este laboratorio, usaremos el algoritmo de co-agrupamiento espectral en el conjunto de datos de veinte grupos de noticias para agrupar bicuadrados los documentos. El conjunto de datos tiene 20 categorías de documentos y excluiremos la categoría "comp.os.ms-windows.misc" ya que contiene publicaciones sin datos. Las publicaciones vectorizadas TF-IDF forman una matriz de frecuencia de palabras que luego se agrupan bicuadrados utilizando el algoritmo de co-agrupamiento espectral de Dhillon. Los co-agrupamientos de documentos-palabras resultantes indican subconjuntos de palabras usadas con más frecuencia en esos subconjuntos de documentos. También agruparemos los documentos utilizando MiniBatchKMeans para comparación.
Consejos sobre la VM
Después de que se inicie la VM, haga clic en la esquina superior izquierda para cambiar a la pestaña Cuaderno para acceder a Jupyter Notebook y practicar.
A veces, es posible que tenga que esperar unos segundos a que Jupyter Notebook termine de cargarse. La validación de las operaciones no se puede automatizar debido a las limitaciones de Jupyter Notebook.
Si tiene problemas durante el aprendizaje, no dude en preguntar a Labby. Deje comentarios después de la sesión y resolveremos rápidamente el problema para usted.
Importar bibliotecas
Importaremos las bibliotecas necesarias para este laboratorio.
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
Definir normalizador de números
Definiremos una función number_normalizer() para mapear todos los tokens numéricos a un marcador de posición. Esto se utiliza para la reducción de dimensionalidad.
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)
Definir NumberNormalizingVectorizer
Definiremos una clase NumberNormalizingVectorizer() que hereda de TfidfVectorizer() para construir un tokenizador que use la función number_normalizer() que definimos anteriormente.
class NumberNormalizingVectorizer(TfidfVectorizer):
def build_tokenizer(self):
tokenize = super().build_tokenizer()
return lambda doc: list(number_normalizer(tokenize(doc)))
Cargar y preparar datos
Cargaremos el conjunto de datos de veinte grupos de noticias y excluiremos la categoría "comp.os.ms-windows.misc". También definiremos el vectorizador.
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)
Vectorizar datos
Vectorizaremos los datos utilizando el vectorizador que definimos anteriormente.
X = vectorizer.fit_transform(newsgroups.data)
Biclustering utilizando el algoritmo de co-agrupamiento espectral
Realizaremos el biclustering utilizando el algoritmo de co-agrupamiento espectral definiendo el co-agrupamiento y ajustándolo a los datos.
cocluster = SpectralCoclustering(
n_clusters=len(categories), svd_method="arpack", random_state=0
)
cocluster.fit(X)
y_cocluster = cocluster.row_labels_
Agrupar utilizando MiniBatchKMeans
Agruparemos los datos utilizando MiniBatchKMeans.
kmeans = MiniBatchKMeans(
n_clusters=len(categories), batch_size=20000, random_state=0, n_init=3
)
y_kmeans = kmeans.fit_predict(X)
Encontrar los mejores biclusters
Encontraremos los mejores biclusters calculando su corte normalizado y seleccionando los cinco mejores.
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]
Imprimir los resultados
Imprimiremos los resultados de los mejores biclusters encontrados en el paso 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
## categorías
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]
)
## palabras
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 {} : {} documentos, {} palabras".format(idx, n_rows, n_cols))
print("categorías : {}".format(cat_string))
print("palabras : {}\n".format(", ".join(important_words)))
Resumen
En este laboratorio, aprendimos cómo realizar biclustering utilizando el algoritmo de co-agrupamiento espectral en el conjunto de datos de veinte grupos de noticias. También aprendimos cómo agrupar los datos utilizando MiniBatchKMeans para comparación. Finalmente, encontramos los mejores biclusters calculando su corte normalizado y seleccionando los cinco mejores.