
Кластеризация – это метод группировки объектов без предварительных меток классов. На практике её используют для сегментации пользователей, поиска аномалий, сжатия данных и подготовки признаков для моделей. В Python основными инструментами являются библиотеки scikit-learn, NumPy и matplotlib для визуализации результатов.
Алгоритм KMeans реализован в scikit-learn и подходит для числовых признаков. Перед применением требуется нормализация данных, например, с помощью StandardScaler. Параметр n_clusters задаёт количество групп. Его подбор можно автоматизировать через метод «локтя» или метрику силуэта.
При работе с текстами чаще используют TF-IDF и алгоритмы вроде DBSCAN или Agglomerative Clustering, которые не требуют предварительного указания числа кластеров. Они устойчивы к выбросам и полезны при анализе естественных языков и пользовательских отзывов.
Для оценки качества кластеризации применяют индекс Дейвиса–Булдина, коэффициент силуэта или визуализацию в пониженной размерности (t-SNE, PCA). Это позволяет убедиться, что кластеры действительно имеют смысл с точки зрения распределения данных.
В статье рассматриваются практические примеры на реальных датасетах, включая использование синтетических данных из make_blobs и кластеризацию данных о покупателях с платформы e-commerce. Все примеры снабжены пояснениями, кодом и графиками.
Как подготовить данные для кластеризации: масштабирование и очистка
Перед применением алгоритмов кластеризации необходимо привести данные к форме, при которой расстояния между объектами будут корректно отражать их сходство. Это включает удаление шума, обработку пропущенных значений и масштабирование признаков.
- Удалите строки с пропущенными значениями, если их доля невелика:
df = df.dropna() - Если пропущенные значения значимы, замените их средними, медианами или наиболее частыми значениями:
from sklearn.impute import SimpleImputer imputer = SimpleImputer(strategy='mean') df[['feature1', 'feature2']] = imputer.fit_transform(df[['feature1', 'feature2']]) - Удалите дубликаты:
df = df.drop_duplicates() - Исключите категориальные признаки или закодируйте их численно, если они важны:
df = pd.get_dummies(df, columns=['category_column']) - Нормализуйте числовые признаки, если алгоритм чувствителен к масштабу:
from sklearn.preprocessing import StandardScaler scaler = StandardScaler() df_scaled = scaler.fit_transform(df) - Если в данных есть выбросы, рассмотрите их устранение:
df = df[(df['feature'] > lower_bound) & (df['feature'] < upper_bound)] - Проверьте, что все признаки имеют числовой тип:
df = df.select_dtypes(include=['number'])
Подготовленные данные должны быть переданы в алгоритм кластеризации в виде массива или DataFrame с числовыми значениями, без пропусков и несоизмеримых признаков.
Когда использовать KMeans и как выбрать число кластеров
KMeans применим, когда данные компактно группируются в пространстве признаков, расстояния между объектами имеют смысл, а число кластеров не слишком велико. Алгоритм чувствителен к шкале признаков, поэтому перед кластеризацией необходима нормализация, например с помощью StandardScaler или MinMaxScaler.
Если признаки категориальные или данные имеют сложную форму распределения (например, кластеры с вытянутой или неплотной структурой), KMeans даст искажённые результаты. В таких случаях стоит рассмотреть DBSCAN или Gaussian Mixture Models.
Для выбора числа кластеров используют метод локтя. Он основывается на графике зависимости суммы внутрикластерных квадратов расстояний (inertia) от количества кластеров. Оптимальное число соответствует излому на графике. Альтернатива – силуэтный коэффициент: значение ближе к 1 говорит о чётко выраженной кластерной структуре. Его можно вычислить через sklearn.metrics.silhouette_score.
Пример определения оптимального k с помощью локтя:
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
inertia = []
X = ... # предварительно нормализованные данные
for k in range(1, 11):
model = KMeans(n_clusters=k, random_state=42, n_init='auto')
model.fit(X)
inertia.append(model.inertia_)
plt.plot(range(1, 11), inertia, marker='o')
plt.xlabel('Число кластеров')
plt.ylabel('Inertia')
plt.show()
Если результат неоднозначен, разумно дополнительно визуализировать кластеры с помощью PCA или t-SNE и проанализировать распределение вручную.
Как применить DBSCAN для кластеризации с шумами
Алгоритм DBSCAN (Density-Based Spatial Clustering of Applications with Noise) выделяет кластеры на основе плотности точек, эффективно обрабатывая шумы и выбросы. В отличие от KMeans, количество кластеров задавать не требуется.
Установка библиотеки:
pip install scikit-learn
Пример кода с пояснениями:
from sklearn.datasets import make_moons
from sklearn.cluster import DBSCAN
import matplotlib.pyplot as plt
Генерация данных с шумами
X, _ = make_moons(n_samples=300, noise=0.05, random_state=42)
Инициализация DBSCAN
dbscan = DBSCAN(eps=0.2, min_samples=5)
labels = dbscan.fit_predict(X)
Отображение результатов
plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='plasma', s=30)
plt.title('Кластеризация с DBSCAN')
plt.show()
eps – максимальное расстояние между точками, чтобы они считались соседями. min_samples – минимальное количество точек в области для формирования кластера. Шумовые точки получают метку -1.
Для выбора eps рекомендуется построить график расстояний до k-го соседа (обычно k = min_samples) и определить порог по излому кривой:
from sklearn.neighbors import NearestNeighbors
import numpy as np
neigh = NearestNeighbors(n_neighbors=5)
nbrs = neigh.fit(X)
distances, _ = nbrs.kneighbors(X)
distances = np.sort(distances[:, 4]) # индекс 4, так как 5-й сосед (с нуля)
plt.plot(distances)
plt.ylabel('Расстояние до 5-го соседа')
plt.xlabel('Точка')
plt.grid()
plt.show()
Алгоритм не чувствителен к форме кластеров и устойчив к выбросам, но чувствителен к масштабу признаков. Рекомендуется предварительно стандартизировать данные:
from sklearn.preprocessing import StandardScaler
X_scaled = StandardScaler().fit_transform(X)
Использование агломеративной кластеризации с визуализацией дендрограммы
Агломеративная кластеризация основана на иерархическом подходе: каждый объект изначально представляет собой отдельный кластер, затем пары кластеров последовательно объединяются. Для демонстрации используется датасет сгенерированных точек.
from sklearn.datasets import make_blobs
from scipy.cluster.hierarchy import dendrogram, linkage
import matplotlib.pyplot as plt
X, _ = make_blobs(n_samples=50, centers=3, cluster_std=0.60, random_state=0)
linked = linkage(X, method='ward')
plt.figure(figsize=(10, 5))
dendrogram(linked, orientation='top', distance_sort='descending', show_leaf_counts=True)
plt.title('Дендрограмма')
plt.xlabel('Индекс объекта')
plt.ylabel('Расстояние')
plt.tight_layout()
plt.show()
Метод ward минимизирует внутрикластерную дисперсию при объединении кластеров. На дендрограмме можно визуально определить количество кластеров, выбрав уровень разбиения, при котором вертикальные линии пересекаются горизонтальной без пересечений выше. Например, горизонтальная линия на уровне расстояния около 10 выделит 3 кластера.
Для формирования кластеров на основе полученной дендрограммы:
from scipy.cluster.hierarchy import fcluster
labels = fcluster(linked, t=3, criterion='maxclust')
Параметр t=3 указывает желаемое количество кластеров. Альтернатива – использование порога по расстоянию:
labels = fcluster(linked, t=10, criterion='distance')
Для оценки структуры данных перед выбором числа кластеров следует анализировать длину вертикальных отрезков на дендрограмме: большие расстояния между уровнями объединения сигнализируют о естественных границах между группами.
Как кластеризовать текстовые данные с помощью TF-IDF и KMeans
Для кластеризации текстов используется преобразование текста в числовое представление с помощью TF-IDF и последующее применение алгоритма KMeans. Ниже приведён пример на Python с использованием библиотек scikit-learn и nltk.
Подготовка данных начинается с токенизации и удаления стоп-слов. Для этого подключаются необходимые модули:
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
import nltk
nltk.download('punkt')
nltk.download('stopwords')
Исходный список документов может выглядеть так:
documents = [
"Кошки любят спать на солнце.",
"Собаки преданы своим хозяевам.",
"Солнце – источник света и тепла.",
"Хозяева выгуливают собак утром и вечером.",
"Кошки охотятся на мышей ночью."
]
Для векторизации текста используется TfidfVectorizer. Включается фильтрация по русским стоп-словам:
stop_words = stopwords.words('russian')
vectorizer = TfidfVectorizer(stop_words=stop_words)
X = vectorizer.fit_transform(documents)
После векторизации применяется кластеризация KMeans. Количество кластеров выбирается вручную или определяется с помощью эвристик (например, метод локтя):
k = 2
model = KMeans(n_clusters=k, random_state=42)
model.fit(X)
labels = model.labels_
Результаты можно сопоставить с исходными документами:
for i, label in enumerate(labels):
print(f"Документ {i}: кластер {label}")
Если требуется проанализировать содержимое кластеров, можно отобразить ключевые слова каждого из них:
import numpy as np
terms = vectorizer.get_feature_names_out()
order_centroids = model.cluster_centers_.argsort()[:, ::-1]
for i in range(k):
top_terms = [terms[ind] for ind in order_centroids[i, :5]]
print(f"Кластер {i}: {'; '.join(top_terms)}")
Этот подход применим для предварительной сортировки новостных статей, отзывов, заголовков и других текстов. При изменении количества кластеров меняется и группировка, поэтому рекомендуется проверять качество кластеризации вручную или с использованием метрик, таких как silhouette score.
Как интерпретировать результаты кластеризации с помощью PCA и t-SNE
Методы понижения размерности, такие как PCA (Principal Component Analysis) и t-SNE (t-distributed Stochastic Neighbor Embedding), позволяют визуализировать и анализировать результаты кластеризации, превращая многомерные данные в двух- или трехмерные представления. Они помогают понять, насколько хорошо алгоритм кластеризации разделил данные, и выявить структуры, которые могут быть неочевидны в исходном пространстве признаков.
PCA работает путем линейного преобразования данных, проектируя их на главные компоненты, которые объясняют наибольшую вариативность. Это полезно, когда требуется понять глобальную структуру данных и различия между кластерами. Однако PCA не всегда способен точно передать сложные нелинейные зависимости, что может ограничить его применимость для некоторых типов данных.
Чтобы интерпретировать результаты кластеризации с помощью PCA, выполните следующие шаги:
- Примените PCA для уменьшения размерности данных (обычно до 2 или 3 компонентов), сохраняя при этом как можно больше информации о вариативности.
- Постройте график, где оси будут представлять главные компоненты. Точки данных будут отображать, насколько они близки друг к другу в многомерном пространстве, что помогает визуально оценить группировки.
- Для каждого кластера можно выбрать уникальный цвет, чтобы выделить его на графике и оценить, насколько хорошо различные группы отделяются друг от друга.
t-SNE более эффективен в случае сложных, нелинейных зависимостей в данных. Этот метод сохраняет локальную структуру, что позволяет лучше отображать внутренние отношения между элементами внутри каждого кластера. Однако t-SNE может не всегда точно отражать глобальную структуру, так как он фокусируется на сохранении расстояний между ближайшими точками, а не на их расположении в целом.
Интерпретация результатов t-SNE также требует внимательности:
- После применения t-SNE постройте график с цветовой кодировкой кластеров, чтобы визуально оценить, насколько четко они разделены.
- Обратите внимание на плотность точек. Если они сгруппированы в компактные области, это может свидетельствовать о хорошей разделимости кластеров. Если данные имеют «пересечения», это может указывать на проблемы в кластеризации.
- Также важно помнить, что t-SNE иногда искажает расстояния между кластерами, поэтому результаты следует воспринимать с осторожностью.
Как оценить качество кластеризации с помощью силуэта и других метрик
Оценка качества кластеризации играет ключевую роль в понимании результатов работы алгоритмов. Метрики, такие как коэффициент силуэта, индекс Давидсона-Боулдена и индекс Вальда, помогают анализировать, насколько корректно и логично распределены объекты по кластерам. Рассмотрим наиболее важные из них.
Коэффициент силуэта
Коэффициент силуэта является одной из самых популярных метрик для оценки качества кластеризации. Он измеряет, насколько объекты внутри кластера близки друг к другу, а также насколько они удалены от объектов других кластеров.
- Значение силуэта варьируется от -1 до 1. Чем выше значение, тем лучше кластеризация.
- При значении близком к 1, объекты хорошо сгруппированы внутри кластеров и далеко от других кластеров.
- Если значение близко к 0, это значит, что объекты находятся на границе между кластерами.
- Отрицательное значение свидетельствует о том, что объекты могут быть неправильно отнесены к своему кластеру.
Пример расчёта коэффициента силуэта:
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
# Пример данных
X = [[1, 2], [1, 4], [1, 0], [4, 2], [4, 4], [4, 0]]
# Кластеризация с использованием KMeans
kmeans = KMeans(n_clusters=2)
kmeans.fit(X)
# Оценка качества кластеризации
score = silhouette_score(X, kmeans.labels_)
print("Коэффициент силуэта:", score)
Индекс Давидсона-Боулдена (DBI)

Индекс Давидсона-Боулдена оценивает компактность и разделимость кластеров. Чем ниже значение, тем лучше качество кластеризации.
- Индекс рассчитывается на основе расстояний между центрами кластеров и внутрикластерных расстояний.
- Идеальное значение – минимальное, равное 0.
Пример расчёта DBI:
from sklearn.metrics import davies_bouldin_score
# Расчёт DBI
dbi_score = davies_bouldin_score(X, kmeans.labels_)
print("Индекс Давидсона-Боулдена:", dbi_score)
Индекс Вальда
Индекс Вальда измеряет различие между плотностью кластеров и расстоянием между ними. Он полезен для выявления более сбалансированных кластеров.
- Чем меньше значение индекса, тем лучше разделение кластеров.
Пример расчёта индекса Вальда:
from sklearn.metrics import calinski_harabasz_score
# Расчёт индекса Вальда
walda_score = calinski_harabasz_score(X, kmeans.labels_)
print("Индекс Вальда:", wald_score)
Другие метрики
- Индекс Силуэтного анализа (Silhouette Analysis): Расширенная версия коэффициента силуэта для оценки кластеризации с дополнительным анализом контекста.
- Метрика Рандомизированного индекса: Измеряет схожесть между кластеризациями. Это полезно для сравнения различных методов кластеризации.
Каждая из этих метрик даёт разные перспективы на качество кластеризации, и использование их в совокупности позволяет более точно оценить результаты. Важно не полагаться на одну метрику, а анализировать несколько для объективной оценки качества кластеризации.
Кластеризация изображений с использованием признаков из нейросети

Кластеризация изображений на основе признаков, извлечённых нейросетью, позволяет эффективно группировать визуальные данные, основываясь на их содержимом. Вместо использования прямых признаков, таких как цвет или текстура, нейросети извлекают более сложные и информативные признаки, которые могут быть использованы для кластеризации.
Для выполнения кластеризации необходимо использовать предварительно обученную нейросеть, такую как ResNet, VGG или EfficientNet. Эти модели способны извлекать высокоуровневые признаки изображений, которые могут быть затем использованы в алгоритмах кластеризации, таких как K-средних или DBSCAN.
Важным моментом является выбор признаков, которые нейросеть извлекает из изображения. Обычно это выходные активации из последнего слоя перед выходом классификатора, так как они содержат сжатыми информацию о важных элементах изображения. Для этого можно использовать такие библиотеки как PyTorch или TensorFlow.
Пример кода для извлечения признаков с использованием модели ResNet в PyTorch:
import torch
from torchvision import models, transforms
from PIL import Image
# Загружаем модель ResNet
model = models.resnet18(pretrained=True)
model.eval()
# Преобразования для изображения
transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
# Загружаем изображение
img = Image.open('image.jpg')
img_tensor = transform(img).unsqueeze(0)
# Извлекаем признаки
with torch.no_grad():
features = model(img_tensor)
# Получаем только последние слои перед классификатором
features = features.view(features.size(0), -1)
После извлечения признаков изображения можно применить любой алгоритм кластеризации, например, K-средние. Алгоритм K-средних хорошо работает, если изображения можно разделить на несколько чётких групп. Пример применения K-средних:
from sklearn.cluster import KMeans
import numpy as np
# Преобразуем признаки в формат, пригодный для кластеризации
features_array = features.numpy()
# Применяем K-средние
kmeans = KMeans(n_clusters=5)
kmeans.fit(features_array)
# Получаем метки кластеров
labels = kmeans.labels_
Для других типов данных, таких как изображения с высокой вариативностью (например, фотографии с множеством объектов), может быть полезен алгоритм DBSCAN, который не требует заранее заданного числа кластеров. DBSCAN может выявить произвольные формы кластеров, что важно при работе с изображениями с неоднородными структурами.
Важно отметить, что качество кластеризации зависит от качества выбранной модели нейросети и корректности извлечения признаков. Оптимизация моделей или использование более глубоких нейросетей, например, VGG16 или InceptionV3, может улучшить результаты кластеризации, так как они обеспечивают более точные и информативные признаки.
Вопрос-ответ:
Что такое кластеризация и как она используется в анализе данных?
Кластеризация — это метод машинного обучения, который позволяет разделить данные на группы, или кластеры, таким образом, чтобы элементы внутри одного кластера были похожи друг на друга, а элементы из разных кластеров — различались. Этот метод часто применяется в задачах, где важно выявить скрытые структуры или закономерности в данных. Например, кластеризация используется в маркетинговых исследованиях для сегментации потребителей или в биоинформатике для группировки генов с похожими функциями.
