← Назад к вопросам
Какие любимые алгоритмы кластеризации?
2.2 Middle🔥 251 комментариев
#Машинное обучение
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Какие любимые алгоритмы кластеризации
Это вопрос про ваши предпочтения и опыт в unsupervised learning. Хороший ответ показывает практическое применение и глубокое понимание разных методов.
1. Основные алгоритмы кластеризации
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs, make_circles, make_moons
from sklearn.preprocessing import StandardScaler
class ClusteringAlgorithms:
"""Обзор основных алгоритмов кластеризации"""
def __init__(self):
# Генерируем разные типы данных для визуализации
self.X_blobs, _ = make_blobs(n_samples=300, centers=3, random_state=42)
self.X_circles = make_circles(n_samples=300, noise=0.05, random_state=42)[0]
self.X_moons = make_moons(n_samples=300, noise=0.05, random_state=42)[0]
def algorithms_overview(self):
return {
"Centroid-based": ["K-Means", "K-Medoids"],
"Hierarchical": ["Agglomerative", "Divisive"],
"Density-based": ["DBSCAN", "HDBSCAN"],
"Distribution-based": ["Gaussian Mixture Models (GMM)"],
"Other": ["Spectral Clustering", "Affinity Propagation"]
}
2. K-Means (самый популярный)
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
class KMeansExplained:
"""
K-Means — самый использованный алгоритм кластеризации
Преимущества:
- Очень быстрый O(n*k*i) где i — итерации
- Простой для понимания и реализации
- Масштабируется до больших данных
- Есть инициализация K-Means++
Недостатки:
- Нужно предварительно знать K (количество кластеров)
- Чувствителен к инициализации
- Не работает с произвольными формами кластеров
- Чувствителен к outliers
"""
def __init__(self, n_clusters=3):
self.n_clusters = n_clusters
self.model = KMeans(n_clusters=n_clusters, init='k-means++', random_state=42)
def how_it_works(self):
"""
Алгоритм:
1. Инициализация: выбираем K случайных центроидов
2. Assignment: присваиваем каждую точку ближайшему центроиду
3. Update: пересчитываем центроиды как среднее кластера
4. Повторяем шаги 2-3 до сходимости
"""
pass
def find_optimal_k(self, X, k_range=range(2, 11)):
"""Метод локтя (Elbow Method)"""
inertias = []
silhouette_scores = []
for k in k_range:
kmeans = KMeans(n_clusters=k, init='k-means++', random_state=42)
kmeans.fit(X)
inertias.append(kmeans.inertia_)
silhouette_scores.append(silhouette_score(X, kmeans.labels_))
# Оптимальное K там, где инертия не снижается
# или где Silhouette score максимален
optimal_k = k_range[np.argmax(silhouette_scores)]
return optimal_k, inertias, silhouette_scores
def train(self, X):
self.model.fit(X)
return self.model.labels_
def use_cases(self):
return [
"Сегментация клиентов (marketing)",
"Группировка документов",
"Сжатие изображений (цветовая квантизация)",
"Инициализация для других алгоритмов"
]
3. DBSCAN (мой любимый для реальных данных)
from sklearn.cluster import DBSCAN
from sklearn.neighbors import NearestNeighbors
class DBSCANExplained:
"""
DBSCAN — лучше всего работает с реальными данными
Преимущества:
- Находит кластеры произвольной формы
- Автоматически определяет количество кластеров
- Отлично находит outliers (помечает как -1)
- Масштабируется хорошо
- Не требует предварительного K
Недостатки:
- Два гиперпараметра: eps и min_samples
- Чувствителен к этим параметрам
- Медленнее K-Means на больших данных
- Проблемы с кластерами разной плотности
"""
def __init__(self, eps=0.5, min_samples=5):
self.eps = eps
self.min_samples = min_samples
self.model = DBSCAN(eps=eps, min_samples=min_samples)
def how_it_works(self):
"""
Алгоритм (density-based):
1. Для каждой точки считаем соседей в радиусе eps
2. Если соседей >= min_samples — это core point
3. Соединяем core points которые рядом
4. Остальные точки — border points или noise
"""
pass
def find_optimal_eps(self, X):
"""Метод k-distance graph"""
# Считаем расстояния до k-го соседа
neighbors = NearestNeighbors(n_neighbors=self.min_samples)
neighbors_fit = neighbors.fit(X)
distances, indices = neighbors_fit.kneighbors(X)
# Сортируем и рисуем
distances = np.sort(distances[:, -1], axis=0)
# Оптимальный eps — в "локте" графика
# Обычно это резкий скачок
return distances
def train(self, X):
self.model.fit(X)
return self.model.labels_
def analyze_clustering(self, labels):
n_clusters = len(set(labels)) - (1 if -1 in labels else 0)
n_noise = list(labels).count(-1)
return {
"n_clusters": n_clusters,
"n_noise": n_noise,
"noise_fraction": n_noise / len(labels)
}
def use_cases(self):
return [
"Обнаружение аномалий (noise points)",
"Кластеризация с неизвестным количеством групп",
"Анализ социальных сетей",
"Пространственная кластеризация географических данных",
"Поиск групп разной плотности"
]
4. Иерархическая кластеризация
from scipy.cluster.hierarchy import dendrogram, linkage
from sklearn.cluster import AgglomerativeClustering
class HierarchicalClusteringExplained:
"""
Hierarchical Clustering — визуальное дерево кластеров
Два подхода:
1. Agglomerative (bottom-up): начинаем с n кластеров, объединяем
2. Divisive (top-down): начинаем с 1, разделяем
Преимущества:
- Дендрограмма показывает иерархию кластеров
- Не нужно заранее знать K
- Интерпретируемо
Недостатки:
- Медленный O(n^2) или O(n^3)
- Жадный алгоритм (нет глобальной оптимизации)
- Не масштабируется на большие данные
"""
def __init__(self, n_clusters=3, linkage_method='ward'):
self.n_clusters = n_clusters
self.linkage_method = linkage_method # 'ward', 'complete', 'average'
self.model = AgglomerativeClustering(
n_clusters=n_clusters,
linkage=linkage_method
)
def linkage_methods(self):
return {
"ward": "Минимизирует дисперсию (по умолчанию)",
"complete": "Максимальное расстояние между кластерами",
"average": "Среднее расстояние между кластерами",
"single": "Минимальное расстояние (может быть шумным)"
}
def train(self, X):
self.model.fit(X)
return self.model.labels_
def plot_dendrogram(self, X):
"""Визуализация иерархии"""
Z = linkage(X, method=self.linkage_method)
dendrogram(Z)
# Горизонтальная линия показывает, где cut дерево на K кластеров
def use_cases(self):
return [
"Таксономия/классификация (biology, taxonomy)",
"Исследовательский анализ (посмотреть иерархию)",
"Когда нужна дендрограмма для презентации",
"Малые датасеты (< 10K)"
]
5. Gaussian Mixture Models (GMM)
from sklearn.mixture import GaussianMixture
from scipy.stats import multivariate_normal
class GaussianMixtureExplained:
"""
GMM — вероятностная модель кластеризации
Преимущества:
- Вероятностный подход (soft clustering, не hard)
- Каждая точка имеет вероятность принадлежности к кластеру
- Оценка BIC/AIC для выбора числа компонентов
- Теоретически обоснованно (expectation-maximization)
Недостатки:
- Медленнее K-Means
- Предполагает нормальное распределение
- Может застрять в локальном оптимуме
"""
def __init__(self, n_components=3):
self.model = GaussianMixture(n_components=n_components, random_state=42)
def train(self, X):
self.model.fit(X)
# Soft assignment: вероятность каждой точки для каждого компонента
soft_labels = self.model.predict_proba(X)
# Hard assignment: наиболее вероятный кластер
hard_labels = self.model.predict(X)
return soft_labels, hard_labels
def find_optimal_components(self, X, n_range=range(1, 11)):
"""Используем BIC или AIC для выбора K"""
bic_scores = []
aic_scores = []
for n in n_range:
gmm = GaussianMixture(n_components=n, random_state=42)
gmm.fit(X)
bic_scores.append(gmm.bic(X))
aic_scores.append(gmm.aic(X))
optimal_n = n_range[np.argmin(bic_scores)] # BIC часто лучше
return optimal_n, bic_scores, aic_scores
def use_cases(self):
return [
"Когда нужны soft probabilities (не hard labels)",
"Модель смеси (mixture modeling)",
"Когда нужно оценить неопределённость",
"Поиск числа компонентов через BIC"
]
6. Практическое сравнение на примере
class ClustersComparison:
"""Сравнение алгоритмов на одних данных"""
def compare_on_dataset(self, X, true_labels=None):
algorithms = {
'K-Means': KMeans(n_clusters=3),
'DBSCAN': DBSCAN(eps=0.5, min_samples=5),
'Hierarchical': AgglomerativeClustering(n_clusters=3),
'GMM': GaussianMixture(n_components=3)
}
results = {}
for name, model in algorithms.items():
if name == 'GMM':
model.fit(X)
labels = model.predict(X)
else:
labels = model.fit_predict(X)
results[name] = {
'labels': labels,
'n_clusters': len(set(labels)) - (1 if -1 in labels else 0),
'silhouette': silhouette_score(X, labels) if -1 not in labels else None
}
return results
# Матрица выбора
selection_matrix = """
┌──────────────┬──────────────┬─────────────┬──────────────┐
│ Алгоритм │ Скорость │ Гибкость │ Когда класть │
├──────────────┼──────────────┼─────────────┼──────────────┤
│ K-Means │ Быстро ⚡ │ Низкая │ Baseline │
│ DBSCAN │ Средне │ Высокая │ Реальные дан │
│ Иерархия │ Медленно │ Средняя │ Визуализация │
│ GMM │ Медленно │ Средняя │ Probabilities│
└──────────────┴──────────────┴─────────────┴──────────────┘
"""
7. Пример полного ответа на собеседовании
"Мои любимые алгоритмы кластеризации зависят от задачи:
1. **K-Means** — всегда начинаю отсюда
- Использую как baseline, быстрый результат
- Нахожу оптимальное K через Elbow Method
- Плюс: просто, быстро, масштабируется
- Минус: нужно знать K, работает лучше на сферических кластерах
2. **DBSCAN** — мой фаворит для реальных данных
- На практике данные часто не идеальны (разная плотность, шум)
- DBSCAN автоматически находит выбросы (noise points)
- Работает с кластерами произвольной формы
- На одном проекте был случай, когда DBSCAN нашёл fraud pattern,
который K-Means не увидел, потому что outliers были важны
- Минус: нужно правильно выбрать eps и min_samples
3. **Hierarchical** — когда нужна интерпретируемость
- Дендрограмма показывает иерархию кластеров
- Использовал для анализа сегментации пользователей
- Плюс: визуально понятно, можно cut на разные K
- Минус: медленный O(n^2), не масштабируется
4. **GMM** — когда нужны soft labels
- Когда важно знать вероятность принадлежности к кластеру
- Используется в Expectation-Maximization для EM algorithm
- Плюс: вероятностный подход, BIC для выбора K
Мой процесс на проекте:
1. Начинаю с K-Means (быстро понять структуру)
2. Потом пробую DBSCAN (реальные данные часто требуют outlier detection)
3. Если нужна интерпретируемость — добавляю Hierarchical
4. Выбираю лучший по бизнес-метрикам, не только по silhouette score
Важно помнить: нет идеального алгоритма, выбор зависит от данных."
8. Метрики оценки кластеризации
from sklearn.metrics import (
silhouette_score,
davies_bouldin_score,
calinski_harabasz_score,
adjusted_rand_score
)
class ClusteringMetrics:
# Silhouette Score: -1 to 1, чем выше тем лучше
silhouette = silhouette_score(X, labels)
# Davies-Bouldin Index: 0 to inf, чем ниже тем лучше
davies_bouldin = davies_bouldin_score(X, labels)
# Calinski-Harabasz Index: чем выше тем лучше
calinski = calinski_harabasz_score(X, labels)
# Если есть ground truth: Adjusted Rand Index
ari = adjusted_rand_score(true_labels, predicted_labels)
Вывод: На собеседовании важно показать: (1) знание разных алгоритмов, (2) понимание их плюсов-минусов, (3) практический опыт, (4) критерии выбора для разных задач. DBSCAN и K-Means — обязательны, Hierarchical и GMM — плюс.