|
Кластеризация — выбор оптимального числа кластеров
ОП.10 Машинное обучение
Лабораторная работа №3
Тема: Кластеризация — выбор оптимального числа кластеров
Цель работы: Экспериментально исследовать метод K-means, научиться выбирать оптимальное число кластеров с помощью метода локтя и силуэтного анализа.
Время выполнения: 2 академических часа
Тип работы: Лабораторная (эксперимент с кластеризацией)
ЗАДАНИЕ ДЛЯ СТУДЕНТА
Этап 1. Создание данных и базовая кластеризация (15 минут)
Создадим искусственный датасет для эксперимента:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs, make_moons, load_iris
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score, silhouette_samples
from sklearn.preprocessing import StandardScaler
# Создаём датасет с 4 кластерами
X, y_true = make_blobs(n_samples=300, centers=4, cluster_std=0.8, random_state=42)
# Нормализация
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
print(f"Размер данных: {X_scaled.shape}")
print(f"Реальное число кластеров: {len(np.unique(y_true))}")
# Визуализация исходных данных
plt.figure(figsize=(10, 4))
plt.subplot(1, 2, 1)
plt.scatter(X[:, 0], X[:, 1], c=y_true, cmap='viridis', s=50)
plt.title('Истинная разметка (4 кластера)')
plt.colorbar()
plt.subplot(1, 2, 2)
plt.scatter(X[:, 0], X[:, 1], s=50)
plt.title('Данные без разметки')
plt.tight_layout()
plt.show()
Этап 2. Метод локтя (Elbow method) (20 минут)
Определите оптимальное число кластеров по сумме квадратов расстояний:
# Расчёт инерции для разного числа кластеров
inertias = []
K_range = range(1, 11)
for k in K_range:
kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
kmeans.fit(X_scaled)
inertias.append(kmeans.inertia_)
# Визуализация метода локтя
plt.figure(figsize=(10, 5))
plt.plot(K_range, inertias, 'o-', linewidth=2, markersize=8)
plt.xlabel('Число кластеров (k)')
plt.ylabel('Сумма квадратов расстояний (Inertia)')
plt.title('Метод локтя для выбора числа кластеров')
plt.xticks(K_range)
plt.grid(True, alpha=0.3)
# Отмечаем точку "локтя"
# Находим точку максимального изгиба (упрощённо)
plt.axvline(x=4, color='r', linestyle='--', label='Оптимальное k=4')
plt.legend()
plt.show()
Вопрос: При каком значении k наблюдается «локоть»? Сколько кластеров оптимально?
Этап 3. Силуэтный анализ (Silhouette analysis) (20 минут)
Используйте силуэтный коэффициент для оценки качества кластеризации:
# Расчёт силуэтного коэффициента
silhouette_scores = []
for k in range(2, 11):
kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
labels = kmeans.fit_predict(X_scaled)
score = silhouette_score(X_scaled, labels)
silhouette_scores.append(score)
print(f"k={k}: Silhouette Score = {score:.4f}")
# Визуализация
plt.figure(figsize=(10, 5))
plt.plot(range(2, 11), silhouette_scores, 'o-', linewidth=2, markersize=8)
plt.xlabel('Число кластеров (k)')
plt.ylabel('Силуэтный коэффициент')
plt.title('Силуэтный анализ для выбора числа кластеров')
plt.xticks(range(2, 11))
plt.grid(True, alpha=0.3)
best_k = range(2, 11)[np.argmax(silhouette_scores)]
plt.axvline(x=best_k, color='r', linestyle='--', label=f'Оптимальное k={best_k}')
plt.legend()
plt.show()
Вопрос: Какое значение k даёт максимальный силуэтный коэффициент?
Этап 4. Визуализация кластеризации для разных k (15 минут)
Посмотрите, как меняется разбиение при разном количестве кластеров:
# Кластеризация для разных k
k_values = [2, 3, 4, 5]
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
for i, k in enumerate(k_values):
kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
labels = kmeans.fit_predict(X_scaled)
row, col = i // 2, i % 2
axes[row, col].scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis', s=50)
axes[row, col].scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1],
c='red', marker='X', s=200, edgecolors='black')
axes[row, col].set_title(f'k = {k}, Silhouette = {silhouette_score(X_scaled, labels):.3f}')
axes[row, col].set_xlabel('Признак 1')
axes[row, col].set_ylabel('Признак 2')
plt.tight_layout()
plt.show()
Вопросы:
• Что происходит при k=2? Как разделены данные?
• Что происходит при k=5? Есть ли лишние кластеры?
Этап 5. Эксперимент со сложной формой кластеров (15 минут)
Проверьте K-means на данных с нешарообразной формой:
# Создаём датасет в форме полумесяцев
X_moons, y_moons = make_moons(n_samples=300, noise=0.05, random_state=42)
# Нормализация
X_moons_scaled = scaler.fit_transform(X_moons)
# K-means на этих данных
kmeans_moons = KMeans(n_clusters=2, random_state=42, n_init=10)
labels_moons = kmeans_moons.fit_predict(X_moons_scaled)
# Визуализация
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
plt.scatter(X_moons[:, 0], X_moons[:, 1], c=y_moons, cmap='viridis', s=50)
plt.title('Истинная разметка (два полумесяца)')
plt.subplot(1, 2, 2)
plt.scatter(X_moons[:, 0], X_moons[:, 1], c=labels_moons, cmap='viridis', s=50)
plt.title(f'K-means (k=2), Silhouette = {silhouette_score(X_moons_scaled, labels_moons):.3f}')
plt.tight_layout()
plt.show()
print("K-means не справился с формой полумесяцев!")
print("Силуэтный коэффициент ниже, чем для blob-данных.")
Вопрос: Почему K-means плохо работает на данных в форме полумесяцев?
Этап 6. Практическое задание: кластеризация ирисов Фишера (10 минут)
Примените изученные методы к реальному датасету Iris:
# Загрузка данных Iris
iris = load_iris()
X_iris = iris.data
y_iris = iris.target
# Нормализация
X_iris_scaled = scaler.fit_transform(X_iris)
# Определение оптимального числа кластеров
inertias_iris = []
silhouette_iris = []
for k in range(2, 8):
kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
labels = kmeans.fit_predict(X_iris_scaled)
inertias_iris.append(kmeans.inertia_)
silhouette_iris.append(silhouette_score(X_iris_scaled, labels))
# Визуализация
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
plt.plot(range(2, 8), inertias_iris, 'o-')
plt.xlabel('k')
plt.ylabel('Inertia')
plt.title('Метод локтя для Iris')
plt.subplot(1, 2, 2)
plt.plot(range(2, 8), silhouette_iris, 'o-')
plt.xlabel('k')
plt.ylabel('Silhouette Score')
plt.title('Силуэтный анализ для Iris')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
best_k_iris = range(2, 8)[np.argmax(silhouette_iris)]
print(f"Оптимальное число кластеров для Iris: {best_k_iris}")
print(f"Реальное число классов в Iris: {len(np.unique(y_iris))}")
Вопрос: Совпадает ли оптимальное число кластеров с реальным числом видов ирисов?
Этап 7. Выводы по лабораторной работе (10 минут)
Оформите отчёт, включив в него:
1. Графики метода локтя и силуэтного анализа
2. Результаты кластеризации для разных k
3. Сравнение K-means на данных разной формы (blobs vs moons)
4. Анализ датасета Iris
5. Выводы о методах выбора числа кластеров
КРИТЕРИИ ОЦЕНКИ
| Критерий | Макс. балл |
|---|
| Метод локтя выполнен и проанализирован | 3 | | Силуэтный анализ выполнен | 3 | Эксперимент с разными k визуализирован | 2 | Анализ Iris и moons выполнен | 2 | | Итого | 10 |
ОТВЕТ ДЛЯ ПРЕПОДАВАТЕЛЯ (эталонный результат)
Нажмите, чтобы увидеть ответы
Этап 2. Метод локтя:
• Локоть наблюдается при k=4 (совпадает с реальным числом кластеров)
Этап 3. Силуэтный анализ:
• Максимальный силуэтный коэффициент также при k=4
• Значение силуэта > 0.5 указывает на хорошую кластеризацию
Этап 4. Визуализация:
• k=2 — объединяет несколько кластеров в один
• k=5 — разбивает один кластер на два (избыточность)
Этап 5. Полумесяцы:
• K-means предполагает сферические кластеры одинакового размера
• Для сложных форм (полумесяцы) нужны другие алгоритмы (DBSCAN, спектральная кластеризация)
Этап 6. Iris:
• Оптимальное k по методу локтя — 3 (совпадает с реальностью)
• Силуэтный анализ также показывает лучший результат при k=3
Этап 7. Вывод:
Метод локтя и силуэтный анализ — эффективные инструменты для выбора k в K-means. Лучший результат достигается, когда оба метода указывают на одно и то же значение k.
Автор: УМК СПО
Лицензия: Бесплатное использование с указанием источника
|
|
|