Evaluación empírica de la inicialización de K-Means

Beginner

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

Introducción

K-means es un algoritmo de agrupamiento que divide un conjunto de datos en k clusters, donde cada punto pertenece al cluster cuyo centroide está más cerca de él. La elección del método de inicialización para k-means puede afectar en gran medida el rendimiento y la convergencia del algoritmo. En este laboratorio, evaluaremos el impacto de diferentes métodos de inicialización en la robustez de convergencia del algoritmo de agrupamiento k-means.

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

Comenzaremos importando las bibliotecas necesarias para el laboratorio, que incluyen numpy, matplotlib, sklearn.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from sklearn.utils import shuffle
from sklearn.utils import check_random_state
from sklearn.cluster import MiniBatchKMeans
from sklearn.cluster import KMeans

Generar conjuntos de datos

Generaremos un conjunto de datos de clusters gaussianos isotrópicos ampliamente espaciados. Los parámetros de generación del conjunto de datos incluyen el número de muestras por centro, el tamaño de la cuadrícula, la escala y el número de clusters.

random_state = np.random.RandomState(0)
n_samples_per_center = 100
grid_size = 3
scale = 0.1
n_clusters = grid_size**2

def make_data(random_state, n_samples_per_center, grid_size, scale):
    random_state = check_random_state(random_state)
    centers = np.array([[i, j] for i in range(grid_size) for j in range(grid_size)])
    n_clusters_true, n_features = centers.shape

    noise = random_state.normal(
        scale=scale, size=(n_samples_per_center, centers.shape[1])
    )

    X = np.concatenate([c + noise for c in centers])
    y = np.concatenate([[i] * n_samples_per_center for i in range(n_clusters_true)])
    return shuffle(X, y, random_state=random_state)

X, y = make_data(random_state, n_samples_per_center, grid_size, scale)

Evaluación cuantitativa de los métodos de inicialización

Evaluaremos la capacidad de las estrategias de inicialización de k-means para hacer que el algoritmo converja de manera robusta. Mediremos la desviación estándar relativa de la inercia del agrupamiento, que es la suma de las distancias al cuadrado al centro del cluster más cercano. La primera gráfica muestra la mejor inercia alcanzada para cada combinación del modelo (KMeans o MiniBatchKMeans) y el método de inicialización (init="random" o init="k-means++") para valores crecientes del parámetro n_init que controla el número de inicializaciones.

n_runs = 5
n_init_range = np.array([1, 5, 10, 15, 20])

plt.figure()
plots = []
legends = []

cases = [
    (KMeans, "k-means++", {}, "^-"),
    (KMeans, "random", {}, "o-"),
    (MiniBatchKMeans, "k-means++", {"max_no_improvement": 3}, "x-"),
    (MiniBatchKMeans, "random", {"max_no_improvement": 3, "init_size": 500}, "d-"),
]

for factory, init, params, format in cases:
    print("Evaluación de %s con %s init" % (factory.__name__, init))
    inertia = np.empty((len(n_init_range), n_runs))

    for run_id in range(n_runs):
        X, y = make_data(run_id, n_samples_per_center, grid_size, scale)
        for i, n_init in enumerate(n_init_range):
            km = factory(
                n_clusters=n_clusters,
                init=init,
                random_state=run_id,
                n_init=n_init,
                **params,
            ).fit(X)
            inertia[i, run_id] = km.inertia_
    p = plt.errorbar(
        n_init_range, inertia.mean(axis=1), inertia.std(axis=1), fmt=format
    )
    plots.append(p[0])
    legends.append("%s con %s init" % (factory.__name__, init))

plt.xlabel("n_init")
plt.ylabel("inertia")
plt.legend(plots, legends)
plt.title("Mean inertia for various k-means init across %d runs" % n_runs)

Inspección visual cualitativa de la convergencia

Demostraremos una sola ejecución del estimador MiniBatchKMeans usando init="random" y n_init=1. Esta ejecución conduce a una mala convergencia (óptimo local), con los centros estimados atascados entre los clusters reales.

km = MiniBatchKMeans(
    n_clusters=n_clusters, init="random", n_init=1, random_state=random_state
).fit(X)

plt.figure()
for k in range(n_clusters):
    my_members = km.labels_ == k
    color = cm.nipy_spectral(float(k) / n_clusters, 1)
    plt.plot(X[my_members, 0], X[my_members, 1], ".", c=color)
    cluster_center = km.cluster_centers_[k]
    plt.plot(
        cluster_center[0],
        cluster_center[1],
        "o",
        markerfacecolor=color,
        markeredgecolor="k",
        markersize=6,
    )
    plt.title(
        "Example cluster allocation with a single random init\nwith MiniBatchKMeans"
    )

plt.show()

Resumen

En este laboratorio, evaluamos el impacto de diferentes métodos de inicialización en la robustez de la convergencia del algoritmo de agrupamiento k-means. Medimos la desviación estándar relativa de la inercia del agrupamiento y demostramos una sola ejecución del estimador MiniBatchKMeans usando init="random" y n_init=1. La elección del método de inicialización para k-means puede afectar en gran medida el rendimiento y la convergencia del algoritmo.