← Назад к вопросам

Какие любимые алгоритмы кластеризации?

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 — плюс.

Какие любимые алгоритмы кластеризации? | PrepBro