|
|
<!--
|
|
|
CO_OP_TRANSLATOR_METADATA:
|
|
|
{
|
|
|
"original_hash": "7cdd17338d9bbd7e2171c2cd462eb081",
|
|
|
"translation_date": "2025-09-06T08:29:37+00:00",
|
|
|
"source_file": "5-Clustering/2-K-Means/README.md",
|
|
|
"language_code": "ru"
|
|
|
}
|
|
|
-->
|
|
|
# Кластеризация методом K-Means
|
|
|
|
|
|
## [Тест перед лекцией](https://ff-quizzes.netlify.app/en/ml/)
|
|
|
|
|
|
В этом уроке вы узнаете, как создавать кластеры с помощью Scikit-learn и набора данных о нигерийской музыке, который вы импортировали ранее. Мы рассмотрим основы метода K-Means для кластеризации. Помните, что, как вы узнали в предыдущем уроке, существует множество способов работы с кластерами, и выбор метода зависит от ваших данных. Мы попробуем K-Means, так как это самый распространенный метод кластеризации. Давайте начнем!
|
|
|
|
|
|
Термины, которые вы изучите:
|
|
|
|
|
|
- Оценка силуэта
|
|
|
- Метод "локтя"
|
|
|
- Инерция
|
|
|
- Дисперсия
|
|
|
|
|
|
## Введение
|
|
|
|
|
|
[Кластеризация методом K-Means](https://wikipedia.org/wiki/K-means_clustering) — это метод, происходящий из области обработки сигналов. Он используется для разделения и группировки данных на 'k' кластеров с помощью серии наблюдений. Каждое наблюдение помогает сгруппировать заданную точку данных ближе к ее ближайшему "среднему", или центральной точке кластера.
|
|
|
|
|
|
Кластеры можно визуализировать как [диаграммы Вороного](https://wikipedia.org/wiki/Voronoi_diagram), которые включают точку (или "семя") и соответствующую ей область.
|
|
|
|
|
|

|
|
|
|
|
|
> инфографика от [Jen Looper](https://twitter.com/jenlooper)
|
|
|
|
|
|
Процесс кластеризации методом K-Means [выполняется в три этапа](https://scikit-learn.org/stable/modules/clustering.html#k-means):
|
|
|
|
|
|
1. Алгоритм выбирает k-центральных точек, выбирая их из набора данных. После этого он выполняет цикл:
|
|
|
1. Назначает каждой выборке ближайший центроид.
|
|
|
2. Создает новые центроиды, вычисляя среднее значение всех выборок, назначенных предыдущим центроидам.
|
|
|
3. Затем вычисляет разницу между новыми и старыми центроидами и повторяет процесс, пока центроиды не стабилизируются.
|
|
|
|
|
|
Одним из недостатков использования K-Means является необходимость заранее определить 'k', то есть количество центроидов. К счастью, метод "локтя" помогает оценить хорошее начальное значение для 'k'. Вы попробуете его через минуту.
|
|
|
|
|
|
## Предварительные требования
|
|
|
|
|
|
Вы будете работать с файлом [_notebook.ipynb_](https://github.com/microsoft/ML-For-Beginners/blob/main/5-Clustering/2-K-Means/notebook.ipynb), который включает импорт данных и предварительную очистку, выполненную в предыдущем уроке.
|
|
|
|
|
|
## Упражнение - подготовка
|
|
|
|
|
|
Начните с повторного изучения данных о песнях.
|
|
|
|
|
|
1. Создайте boxplot, вызвав `boxplot()` для каждого столбца:
|
|
|
|
|
|
```python
|
|
|
plt.figure(figsize=(20,20), dpi=200)
|
|
|
|
|
|
plt.subplot(4,3,1)
|
|
|
sns.boxplot(x = 'popularity', data = df)
|
|
|
|
|
|
plt.subplot(4,3,2)
|
|
|
sns.boxplot(x = 'acousticness', data = df)
|
|
|
|
|
|
plt.subplot(4,3,3)
|
|
|
sns.boxplot(x = 'energy', data = df)
|
|
|
|
|
|
plt.subplot(4,3,4)
|
|
|
sns.boxplot(x = 'instrumentalness', data = df)
|
|
|
|
|
|
plt.subplot(4,3,5)
|
|
|
sns.boxplot(x = 'liveness', data = df)
|
|
|
|
|
|
plt.subplot(4,3,6)
|
|
|
sns.boxplot(x = 'loudness', data = df)
|
|
|
|
|
|
plt.subplot(4,3,7)
|
|
|
sns.boxplot(x = 'speechiness', data = df)
|
|
|
|
|
|
plt.subplot(4,3,8)
|
|
|
sns.boxplot(x = 'tempo', data = df)
|
|
|
|
|
|
plt.subplot(4,3,9)
|
|
|
sns.boxplot(x = 'time_signature', data = df)
|
|
|
|
|
|
plt.subplot(4,3,10)
|
|
|
sns.boxplot(x = 'danceability', data = df)
|
|
|
|
|
|
plt.subplot(4,3,11)
|
|
|
sns.boxplot(x = 'length', data = df)
|
|
|
|
|
|
plt.subplot(4,3,12)
|
|
|
sns.boxplot(x = 'release_date', data = df)
|
|
|
```
|
|
|
|
|
|
Эти данные немного шумные: наблюдая каждый столбец как boxplot, вы можете увидеть выбросы.
|
|
|
|
|
|

|
|
|
|
|
|
Вы могли бы пройтись по набору данных и удалить эти выбросы, но это сделает данные довольно минимальными.
|
|
|
|
|
|
1. На данный момент выберите столбцы, которые вы будете использовать для упражнения по кластеризации. Выберите те, у которых похожие диапазоны, и закодируйте столбец `artist_top_genre` как числовые данные:
|
|
|
|
|
|
```python
|
|
|
from sklearn.preprocessing import LabelEncoder
|
|
|
le = LabelEncoder()
|
|
|
|
|
|
X = df.loc[:, ('artist_top_genre','popularity','danceability','acousticness','loudness','energy')]
|
|
|
|
|
|
y = df['artist_top_genre']
|
|
|
|
|
|
X['artist_top_genre'] = le.fit_transform(X['artist_top_genre'])
|
|
|
|
|
|
y = le.transform(y)
|
|
|
```
|
|
|
|
|
|
1. Теперь вам нужно выбрать, сколько кластеров использовать. Вы знаете, что в наборе данных есть 3 жанра песен, поэтому попробуем 3:
|
|
|
|
|
|
```python
|
|
|
from sklearn.cluster import KMeans
|
|
|
|
|
|
nclusters = 3
|
|
|
seed = 0
|
|
|
|
|
|
km = KMeans(n_clusters=nclusters, random_state=seed)
|
|
|
km.fit(X)
|
|
|
|
|
|
# Predict the cluster for each data point
|
|
|
|
|
|
y_cluster_kmeans = km.predict(X)
|
|
|
y_cluster_kmeans
|
|
|
```
|
|
|
|
|
|
Вы увидите массив с предсказанными кластерами (0, 1 или 2) для каждой строки в датафрейме.
|
|
|
|
|
|
1. Используйте этот массив для вычисления "оценки силуэта":
|
|
|
|
|
|
```python
|
|
|
from sklearn import metrics
|
|
|
score = metrics.silhouette_score(X, y_cluster_kmeans)
|
|
|
score
|
|
|
```
|
|
|
|
|
|
## Оценка силуэта
|
|
|
|
|
|
Ищите оценку силуэта ближе к 1. Эта оценка варьируется от -1 до 1, и если оценка равна 1, кластер плотный и хорошо отделен от других кластеров. Значение около 0 представляет пересекающиеся кластеры, где выборки находятся очень близко к границе принятия решения соседних кластеров. [(Источник)](https://dzone.com/articles/kmeans-silhouette-score-explained-with-python-exam)
|
|
|
|
|
|
Наша оценка составляет **0.53**, то есть прямо посередине. Это указывает на то, что наши данные не особенно хорошо подходят для этого типа кластеризации, но давайте продолжим.
|
|
|
|
|
|
### Упражнение - создание модели
|
|
|
|
|
|
1. Импортируйте `KMeans` и начните процесс кластеризации.
|
|
|
|
|
|
```python
|
|
|
from sklearn.cluster import KMeans
|
|
|
wcss = []
|
|
|
|
|
|
for i in range(1, 11):
|
|
|
kmeans = KMeans(n_clusters = i, init = 'k-means++', random_state = 42)
|
|
|
kmeans.fit(X)
|
|
|
wcss.append(kmeans.inertia_)
|
|
|
|
|
|
```
|
|
|
|
|
|
Здесь есть несколько частей, которые стоит объяснить.
|
|
|
|
|
|
> 🎓 range: Это количество итераций процесса кластеризации.
|
|
|
|
|
|
> 🎓 random_state: "Определяет генерацию случайных чисел для инициализации центроидов." [Источник](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html#sklearn.cluster.KMeans)
|
|
|
|
|
|
> 🎓 WCSS: "сумма квадратов внутри кластеров" измеряет среднее квадратное расстояние всех точек внутри кластера до центроида кластера. [Источник](https://medium.com/@ODSC/unsupervised-learning-evaluating-clusters-bd47eed175ce).
|
|
|
|
|
|
> 🎓 Инерция: Алгоритмы K-Means пытаются выбрать центроиды, чтобы минимизировать "инерцию", "меру внутренней согласованности кластеров." [Источник](https://scikit-learn.org/stable/modules/clustering.html). Значение добавляется в переменную wcss на каждой итерации.
|
|
|
|
|
|
> 🎓 k-means++: В [Scikit-learn](https://scikit-learn.org/stable/modules/clustering.html#k-means) вы можете использовать оптимизацию 'k-means++', которая "инициализирует центроиды так, чтобы они (как правило) были удалены друг от друга, что приводит к, вероятно, лучшим результатам, чем случайная инициализация."
|
|
|
|
|
|
### Метод "локтя"
|
|
|
|
|
|
Ранее вы предположили, что, поскольку вы нацелились на 3 жанра песен, вам следует выбрать 3 кластера. Но так ли это?
|
|
|
|
|
|
1. Используйте метод "локтя", чтобы убедиться.
|
|
|
|
|
|
```python
|
|
|
plt.figure(figsize=(10,5))
|
|
|
sns.lineplot(x=range(1, 11), y=wcss, marker='o', color='red')
|
|
|
plt.title('Elbow')
|
|
|
plt.xlabel('Number of clusters')
|
|
|
plt.ylabel('WCSS')
|
|
|
plt.show()
|
|
|
```
|
|
|
|
|
|
Используйте переменную `wcss`, которую вы создали на предыдущем шаге, чтобы построить график, показывающий, где находится "изгиб" локтя, который указывает на оптимальное количество кластеров. Возможно, это **действительно** 3!
|
|
|
|
|
|

|
|
|
|
|
|
## Упражнение - отображение кластеров
|
|
|
|
|
|
1. Попробуйте процесс снова, на этот раз установив три кластера, и отобразите кластеры как диаграмму рассеяния:
|
|
|
|
|
|
```python
|
|
|
from sklearn.cluster import KMeans
|
|
|
kmeans = KMeans(n_clusters = 3)
|
|
|
kmeans.fit(X)
|
|
|
labels = kmeans.predict(X)
|
|
|
plt.scatter(df['popularity'],df['danceability'],c = labels)
|
|
|
plt.xlabel('popularity')
|
|
|
plt.ylabel('danceability')
|
|
|
plt.show()
|
|
|
```
|
|
|
|
|
|
1. Проверьте точность модели:
|
|
|
|
|
|
```python
|
|
|
labels = kmeans.labels_
|
|
|
|
|
|
correct_labels = sum(y == labels)
|
|
|
|
|
|
print("Result: %d out of %d samples were correctly labeled." % (correct_labels, y.size))
|
|
|
|
|
|
print('Accuracy score: {0:0.2f}'. format(correct_labels/float(y.size)))
|
|
|
```
|
|
|
|
|
|
Точность этой модели не очень хорошая, и форма кластеров дает вам подсказку, почему.
|
|
|
|
|
|

|
|
|
|
|
|
Эти данные слишком несбалансированы, слишком мало коррелируют, и между значениями столбцов слишком большая дисперсия, чтобы хорошо кластеризоваться. На самом деле, кластеры, которые формируются, вероятно, сильно зависят или искажены тремя категориями жанров, которые мы определили выше. Это был процесс обучения!
|
|
|
|
|
|
В документации Scikit-learn вы можете увидеть, что модель, подобная этой, с кластерами, которые не очень хорошо разграничены, имеет проблему "дисперсии":
|
|
|
|
|
|

|
|
|
> Инфографика из Scikit-learn
|
|
|
|
|
|
## Дисперсия
|
|
|
|
|
|
Дисперсия определяется как "среднее квадратов разностей от среднего" [(Источник)](https://www.mathsisfun.com/data/standard-deviation.html). В контексте этой задачи кластеризации это относится к данным, где значения нашего набора данных имеют тенденцию слишком сильно отклоняться от среднего.
|
|
|
|
|
|
✅ Это отличный момент, чтобы подумать обо всех способах, которыми вы могли бы исправить эту проблему. Немного изменить данные? Использовать другие столбцы? Применить другой алгоритм? Подсказка: попробуйте [масштабировать данные](https://www.mygreatlearning.com/blog/learning-data-science-with-k-means-clustering/), чтобы нормализовать их и протестировать другие столбцы.
|
|
|
|
|
|
> Попробуйте этот '[калькулятор дисперсии](https://www.calculatorsoup.com/calculators/statistics/variance-calculator.php)', чтобы лучше понять концепцию.
|
|
|
|
|
|
---
|
|
|
|
|
|
## 🚀Задача
|
|
|
|
|
|
Проведите некоторое время с этим ноутбуком, изменяя параметры. Можете ли вы улучшить точность модели, более тщательно очистив данные (например, удалив выбросы)? Вы можете использовать веса, чтобы придать больший вес определенным выборкам данных. Что еще вы можете сделать, чтобы создать лучшие кластеры?
|
|
|
|
|
|
Подсказка: попробуйте масштабировать данные. В ноутбуке есть закомментированный код, который добавляет стандартное масштабирование, чтобы столбцы данных больше походили друг на друга по диапазону. Вы обнаружите, что хотя оценка силуэта снижается, "изгиб" на графике локтя становится более плавным. Это связано с тем, что оставление данных без масштабирования позволяет данным с меньшей дисперсией иметь больший вес. Прочитайте немного больше об этой проблеме [здесь](https://stats.stackexchange.com/questions/21222/are-mean-normalization-and-feature-scaling-needed-for-k-means-clustering/21226#21226).
|
|
|
|
|
|
## [Тест после лекции](https://ff-quizzes.netlify.app/en/ml/)
|
|
|
|
|
|
## Обзор и самостоятельное изучение
|
|
|
|
|
|
Посмотрите симулятор K-Means [например, этот](https://user.ceng.metu.edu.tr/~akifakkus/courses/ceng574/k-means/). Вы можете использовать этот инструмент для визуализации точек данных и определения их центроидов. Вы можете редактировать случайность данных, количество кластеров и количество центроидов. Помогает ли это вам понять, как данные могут быть сгруппированы?
|
|
|
|
|
|
Также ознакомьтесь с [этим материалом о K-Means](https://stanford.edu/~cpiech/cs221/handouts/kmeans.html) от Стэнфорда.
|
|
|
|
|
|
## Задание
|
|
|
|
|
|
[Попробуйте разные методы кластеризации](assignment.md)
|
|
|
|
|
|
---
|
|
|
|
|
|
**Отказ от ответственности**:
|
|
|
Этот документ был переведен с помощью сервиса автоматического перевода [Co-op Translator](https://github.com/Azure/co-op-translator). Несмотря на наши усилия обеспечить точность, автоматические переводы могут содержать ошибки или неточности. Оригинальный документ на его родном языке следует считать авторитетным источником. Для получения критически важной информации рекомендуется профессиональный перевод человеком. Мы не несем ответственности за любые недоразумения или неправильные интерпретации, возникшие в результате использования данного перевода. |