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

Что ищут в данных при кластеризации?

1.8 Middle🔥 231 комментариев
#Машинное обучение

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что ищут в данных при кластеризации: цели и инсайты

Кластеризация — это метод неконтролируемого обучения, который ищет скрытую структуру в данных. Рассмотрим, что именно мы пытаемся найти.

1. Естественные группировки (Intrinsic Clusters)

Это сегменты, которые существуют в данных физически.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans

# Пример: Сегментация клиентов по поведению
from sklearn.preprocessing import StandardScaler

# Данные: (Расход, Частота покупок, Средний чек)
X = np.array([
    [100, 2, 50],     # Экономные покупатели
    [110, 3, 45],      # Экономные покупатели
    [1000, 50, 20],    # Активные покупатели
    [1100, 48, 22],    # Активные покупатели
    [200, 10, 100],    # Премиум клиенты
    [190, 12, 95],     # Премиум клиенты
])

scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

kmeans = KMeans(n_clusters=3, random_state=42)
km_labels = kmeans.fit_predict(X_scaled)

print(f'Кластеры найдены: {set(km_labels)}')
# Результат: 3 естественных сегмента
# Кластер 0: Экономные
# Кластер 1: Активные
# Кластер 2: Премиум

Что ищем:

  • Группы похожих объектов
  • Отсутствие заранее известных меток
  • Внутри-групповую сходство (high intra-cluster similarity)
  • Между-групповую различие (low inter-cluster similarity)

2. Аномалии и outliers

from sklearn.cluster import DBSCAN
from sklearn.preprocessing import StandardScaler

# DBSCAN обнаруживает outliers как noise (-1 метка)
data = np.array([
    [1, 1], [1, 2], [2, 1], [2, 2],  # Нормальный кластер
    [10, 10], [10, 11], [11, 10],     # Второй кластер
    [100, 100]  # OUTLIER — изолированная точка
])

scaler = StandardScaler()
data_scaled = scaler.fit_transform(data)

dbscan = DBSCAN(eps=0.5, min_samples=2)
labels = dbscan.fit_predict(data_scaled)

outliers_indices = np.where(labels == -1)[0]
print(f'Найденные аномалии (индексы): {outliers_indices}')  # [7]

Практическое применение:

  • Обнаружение мошеннических транзакций
  • Выявление неисправного оборудования (sensor anomalies)
  • Выбросы в научных данных

3. Структура многомерных данных

from sklearn.decomposition import PCA
from sklearn.cluster import AgglomerativeClustering
import pandas as pd

# Данные: признаки пациентов (болезни, симптомы, тесты)
patient_data = pd.DataFrame({
    'age': [25, 65, 30, 70, 28, 68],
    'blood_pressure': [120, 150, 118, 160, 122, 155],
    'glucose': [100, 180, 95, 200, 105, 190],
    'bmi': [22, 28, 21, 30, 23, 29]
})

# Стандартизация
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
data_scaled = scaler.fit_transform(patient_data)

# Иерархическая кластеризация
model = AgglomerativeClustering(n_clusters=2, linkage='ward')
clusters = model.fit_predict(data_scaled)

# Выводы
print(f'Кластер 0: {set(np.where(clusters == 0)[0])}')
print(f'Кластер 1: {set(np.where(clusters == 1)[0])}')
# Может выявить группы: "здоровые vs. группа риска"

4. Иерархическая структура

from scipy.cluster.hierarchy import dendrogram, linkage
import matplotlib.pyplot as plt

# Данные о видах животных (признаки)
animals = np.array([
    [1, 1, 1],  # Кот
    [1, 1, 1],  # Собака
    [0, 0, 1],  # Птица
    [0, 0, 1],  # Попугай
    [1, 0, 0],  # Рыба
    [1, 0, 0]   # Акула
])

Z = linkage(animals, method='ward')
dendrogram(Z, labels=['Кот', 'Собака', 'Птица', 'Попугай', 'Рыба', 'Акула'])
plt.show()

# Дендрограмма показывает:
# - Млекопитающие (Кот, Собака) близки
# - Птицы (Птица, Попугай) близки
# - Рыбы (Рыба, Акула) близки
# - Млекопитающие vs Птицы vs Рыбы — разные ветви

Ищем:

  • Иерархию групп
  • На каком уровне детализации есть естественные кластеры
  • Как связаны объекты на разных уровнях

5. Плотность-зависимые паттерны

from sklearn.cluster import DBSCAN
from sklearn.preprocessing import StandardScaler

# Пример: Выявление скопления пользователей в городах
users_locations = np.array([
    [55.7558, 37.6173],   # Москва центр
    [55.7639, 37.6452],   # Москва центр
    [55.7800, 37.7000],   # Москва центр
    [59.9311, 30.3609],   # Санкт-Петербург центр
    [59.9508, 30.3609],   # Санкт-Петербург центр
    [55.0, 35.0],         # Между городами (outlier)
])

dbscan = DBSCAN(eps=0.1, min_samples=2)
clusters = dbscan.fit_predict(users_locations)

print(f'Кластеры: {set(clusters)}')
# Результат: {0, 1, -1}
# 0 = Москва, 1 = СПб, -1 = Outlier

6. Выявление подобных товаров/документов

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import MiniBatchKMeans

# Кластеризация документов (например, отзывы о товарах)
documents = [
    "Отличный товар, быстро пришёл",
    "Супер качество, рекомендую",
    "Плохое качество, не работает",
    "Сломался сразу после покупки",
    "Хороший товар за деньги",
    "Не стоит покупать, развод"
]

vectorizer = TfidfVectorizer(max_features=100, ngram_range=(1, 2))
X = vectorizer.fit_transform(documents)

kmeans = MiniBatchKMeans(n_clusters=2, random_state=42)
kmeans.fit(X)

print(f'Положительные отзывы: {set(np.where(kmeans.labels_ == 0)[0])}')
print(f'Отрицательные отзывы: {set(np.where(kmeans.labels_ == 1)[0])}')

7. Сжатие информации и представление

from sklearn.cluster import KMeans

# Использование центроидов кластеров как compressed representation
X = np.random.randn(10000, 50)  # 10К точек в 50-мерном пространстве

kmeans = KMeans(n_clusters=100, random_state=42)
kmeans.fit(X)

# Вместо хранения 10К точек, храним 100 центроидов
centroids = kmeans.cluster_centers_  # Shape: (100, 50)

print(f'Сжатие: {10000 * 50 / (100 * 50)} раз')
# 100x сжатие с приемлемой потерей информации

8. Подготовка к supervised learning

from sklearn.cluster import KMeans
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier

# Пример: Unsupervised -> Supervised
iris = load_iris()
X, y = iris.data, iris.target

# Шаг 1: Кластеризация (unsupervised)
kmeans = KMeans(n_clusters=3, random_state=42)
cluster_labels = kmeans.fit_predict(X)

# Шаг 2: Проверяем, соответствуют ли кластеры истинным классам
from sklearn.metrics import adjusted_rand_score
ari = adjusted_rand_score(y, cluster_labels)
print(f'ARI (соответствие кластеров истинным классам): {ari:.3f}')
# Высокий ARI = кластеры хорошо разделяют классы

# Шаг 3: Используем кластеры как новый признак для supervised learning
X_with_clusters = np.column_stack([X, cluster_labels])
X_train, X_test, y_train, y_test = train_test_split(X_with_clusters, y, test_size=0.2)

rf = RandomForestClassifier()
rf.fit(X_train, y_train)
accuracy = rf.score(X_test, y_test)
print(f'Точность с кластерным признаком: {accuracy:.3f}')

Резюме: Что именно ищем при кластеризации

Что ищемКогда применяетсяМетрика оценки
Естественные группыСегментация клиентов, типологияSilhouette Score
АномалииFraud detection, QCIsolation Forest score
ИерархияТаксономия, классификацияDendrogram
Плотные регионыГеолокация, скопленияDavies-Bouldin Index
Подобие объектовРекомендации, дедупликацияInertia (для K-means)
Compressed representationDimensionality reductionReconstruction error
Подготовка к supervisedFeature engineeringDownstream model performance

Вывод: Кластеризация ищет скрытую структуру в данных без заранее известных меток. Главное — понять, что именно вы ищете в контексте вашей задачи, и выбрать метрики оценки, которые это проверяют.