Agrupamiento jerárquico con Scikit-Learn

Beginner

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

Introducción

En este laboratorio, usaremos la biblioteca scikit-learn de Python para realizar un agrupamiento jerárquico en algunos conjuntos de datos de muestra. El agrupamiento jerárquico es un método de agrupamiento en el que se construye una jerarquía de clusters, ya sea de forma top-down o bottom-up. El objetivo del agrupamiento jerárquico es encontrar clusters de puntos que se parezcan entre sí y sean diferentes de los puntos de otros clusters.

Consejos sobre la VM

Una vez que se haya iniciado la VM, haga clic en la esquina superior izquierda para cambiar a la pestaña Cuaderno y acceder a Jupyter Notebook para 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 sus comentarios después de la sesión y lo resolveremos rápidamente para usted.

Importar bibliotecas y cargar datos

Comenzaremos importando las bibliotecas necesarias y cargando los conjuntos de datos de muestra que usaremos para nuestros ejemplos de agrupamiento jerárquico.

import time
import warnings

import numpy as np
import matplotlib.pyplot as plt

from sklearn import cluster, datasets
from sklearn.preprocessing import StandardScaler
from itertools import cycle, islice

np.random.seed(0)

## %%
## Generar conjuntos de datos. Elegimos un tamaño lo suficientemente grande
## para ver la escalabilidad de los algoritmos, pero no demasiado grande
## para evitar tiempos de ejecución demasiado largos

n_samples = 1500
noisy_circles = datasets.make_circles(n_samples=n_samples, factor=0.5, noise=0.05)
noisy_moons = datasets.make_moons(n_samples=n_samples, noise=0.05)
blobs = datasets.make_blobs(n_samples=n_samples, random_state=8)
no_structure = np.random.rand(n_samples, 2), None

## Datos distribuidos anisotrópicamente
random_state = 170
X, y = datasets.make_blobs(n_samples=n_samples, random_state=random_state)
transformation = [[0.6, -0.6], [-0.4, 0.8]]
X_aniso = np.dot(X, transformation)
aniso = (X_aniso, y)

## Blobs con varianzas variadas
varied = datasets.make_blobs(
    n_samples=n_samples, cluster_std=[1.0, 2.5, 0.5], random_state=random_state
)

Realizar agrupamiento jerárquico

Ahora realizaremos el agrupamiento jerárquico en los conjuntos de datos de muestra que cargamos en el paso 1. Usaremos diferentes métodos de enlace, como single, average, complete y ward, para construir nuestros clusters.

## Establecer parámetros del cluster
plt.figure(figsize=(9 * 1.3 + 2, 14.5))
plt.subplots_adjust(
    left=0.02, right=0.98, bottom=0.001, top=0.96, wspace=0.05, hspace=0.01
)

plot_num = 1

default_base = {"n_neighbors": 10, "n_clusters": 3}

datasets = [
    (noisy_circles, {"n_clusters": 2}),
    (noisy_moons, {"n_clusters": 2}),
    (varied, {"n_neighbors": 2}),
    (aniso, {"n_neighbors": 2}),
    (blobs, {}),
    (no_structure, {}),
]

for i_dataset, (dataset, algo_params) in enumerate(datasets):
    ## actualizar parámetros con valores específicos del conjunto de datos
    params = default_base.copy()
    params.update(algo_params)

    X, y = dataset

    ## normalizar el conjunto de datos para una selección de parámetros más fácil
    X = StandardScaler().fit_transform(X)

    ## ============
    ## Crear objetos de cluster
    ## ============
    ward = cluster.AgglomerativeClustering(
        n_clusters=params["n_clusters"], linkage="ward"
    )
    complete = cluster.AgglomerativeClustering(
        n_clusters=params["n_clusters"], linkage="complete"
    )
    average = cluster.AgglomerativeClustering(
        n_clusters=params["n_clusters"], linkage="average"
    )
    single = cluster.AgglomerativeClustering(
        n_clusters=params["n_clusters"], linkage="single"
    )

    clustering_algorithms = (
        ("Single Linkage", single),
        ("Average Linkage", average),
        ("Complete Linkage", complete),
        ("Ward Linkage", ward),
    )

    for name, algorithm in clustering_algorithms:
        t0 = time.time()

        ## capturar advertencias relacionadas con kneighbors_graph
        with warnings.catch_warnings():
            warnings.filterwarnings(
                "ignore",
                message="the number of connected components of the "
                + "connectivity matrix is [0-9]{1,2}"
                + " > 1. Completing it to avoid stopping the tree early.",
                category=UserWarning,
            )
            algorithm.fit(X)

        t1 = time.time()
        if hasattr(algorithm, "labels_"):
            y_pred = algorithm.labels_.astype(int)
        else:
            y_pred = algorithm.predict(X)

        plt.subplot(len(datasets), len(clustering_algorithms), plot_num)
        if i_dataset == 0:
            plt.title(name, size=18)

        colors = np.array(
            list(
                islice(
                    cycle(
                        [
                            "#377eb8",
                            "#ff7f00",
                            "#4daf4a",
                            "#f781bf",
                            "#a65628",
                            "#984ea3",
                            "#999999",
                            "#e41a1c",
                            "#dede00",
                        ]
                    ),
                    int(max(y_pred) + 1),
                )
            )
        )
        plt.scatter(X[:, 0], X[:, 1], s=10, color=colors[y_pred])

        plt.xlim(-2.5, 2.5)
        plt.ylim(-2.5, 2.5)
        plt.xticks(())
        plt.yticks(())
        plt.text(
            0.99,
            0.01,
            ("%.2fs" % (t1 - t0)).lstrip("0"),
            transform=plt.gca().transAxes,
            size=15,
            horizontalalignment="right",
        )
        plot_num += 1

plt.show()

Analizar los resultados

Ahora analizaremos los resultados de nuestro agrupamiento jerárquico. Basados en los conjuntos de datos de muestra que usamos, podemos hacer las siguientes observaciones:

  • El enlace simple es rápido y puede funcionar bien con datos no globulares, pero funciona mal en presencia de ruido.
  • El enlace promedio y el enlace completo funcionan bien con clusters globulares claramente separados, pero tienen resultados mixtos en caso contrario.
  • Ward es el método más efectivo para datos ruidosos.

Es importante destacar que aunque estas observaciones nos dan alguna intuición sobre los algoritmos, esta intuición puede no aplicarse a datos de dimensión muy alta.

Resumen

En este laboratorio, aprendimos cómo realizar un agrupamiento jerárquico utilizando la biblioteca scikit-learn de Python. Usamos diferentes métodos de enlace, como single, average, complete y ward, para construir nuestros clusters y analizamos los resultados basados en algunos conjuntos de datos de muestra. El agrupamiento jerárquico es una técnica poderosa que se puede utilizar para identificar clusters de puntos de datos similares y puede ser útil en una variedad de campos, como biología, marketing y finanzas.