{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "anaconda-cloud": "", "kernelspec": { "display_name": "R", "language": "R", "name": "ir" }, "language_info": { "codemirror_mode": "r", "file_extension": ".r", "mimetype": "text/x-r-source", "name": "R", "pygments_lexer": "r", "version": "3.4.1" }, "colab": { "name": "lesson_14.ipynb", "provenance": [], "collapsed_sections": [], "toc_visible": true }, "coopTranslator": { "original_hash": "ad65fb4aad0a156b42216e4929f490fc", "translation_date": "2025-08-29T23:37:13+00:00", "source_file": "5-Clustering/2-K-Means/solution/R/lesson_15-R.ipynb", "language_code": "ru" } }, "cells": [ { "cell_type": "markdown", "metadata": { "id": "GULATlQXLXyR" }, "source": [ "## Изучение кластеризации методом K-Means с использованием R и принципов \"tidy data\"\n", "\n", "### [**Тест перед лекцией**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/29/)\n", "\n", "В этом уроке вы научитесь создавать кластеры с использованием пакета Tidymodels и других пакетов из экосистемы R (назовем их друзьями 🧑‍🤝‍🧑), а также набора данных о нигерийской музыке, который вы импортировали ранее. Мы рассмотрим основы метода K-Means для кластеризации. Помните, как вы узнали в предыдущем уроке, существует множество способов работы с кластерами, и выбор метода зависит от ваших данных. Мы попробуем метод K-Means, так как это наиболее распространенная техника кластеризации. Давайте начнем!\n", "\n", "Термины, с которыми вы познакомитесь:\n", "\n", "- Оценка силуэта (Silhouette scoring)\n", "\n", "- Метод локтя (Elbow method)\n", "\n", "- Инерция (Inertia)\n", "\n", "- Дисперсия (Variance)\n", "\n", "### **Введение**\n", "\n", "[Кластеризация методом K-Means](https://wikipedia.org/wiki/K-means_clustering) — это метод, происходящий из области обработки сигналов. Он используется для разделения и группировки данных на `k кластеров` на основе сходства их характеристик.\n", "\n", "Кластеры можно визуализировать как [диаграммы Вороного](https://wikipedia.org/wiki/Voronoi_diagram), которые включают точку (или \"семя\") и соответствующую ей область.\n", "\n", "

\n", " \n", "

Инфографика от Джен Лупер
\n", "\n", "Метод K-Means включает следующие шаги:\n", "\n", "1. Дата-сайентист начинает с указания желаемого количества кластеров, которые нужно создать.\n", "\n", "2. Затем алгоритм случайным образом выбирает K наблюдений из набора данных, чтобы использовать их в качестве начальных центров кластеров (т.е. центроидов).\n", "\n", "3. Далее каждое из оставшихся наблюдений назначается к своему ближайшему центроиду.\n", "\n", "4. Затем вычисляется новое среднее значение для каждого кластера, и центроид перемещается к этому среднему.\n", "\n", "5. После пересчета центров каждое наблюдение снова проверяется, чтобы определить, не стало ли оно ближе к другому кластеру. Все объекты перераспределяются с использованием обновленных средних значений кластеров. Шаги перераспределения кластеров и обновления центроидов повторяются итеративно до тех пор, пока распределение кластеров не перестанет изменяться (т.е. пока не будет достигнута сходимость). Обычно алгоритм завершается, когда каждая новая итерация приводит к незначительному перемещению центроидов, и кластеры становятся статичными.\n", "\n", "
\n", "\n", "> Обратите внимание, что из-за случайного выбора начальных k наблюдений, используемых в качестве стартовых центроидов, мы можем получать немного разные результаты при каждом применении процедуры. По этой причине большинство алгоритмов используют несколько *случайных запусков* и выбирают итерацию с наименьшим WCSS. Таким образом, настоятельно рекомендуется всегда запускать K-Means с несколькими значениями *nstart*, чтобы избежать *нежелательного локального оптимума.*\n", "\n", "
\n", "\n", "Эта короткая анимация с использованием [иллюстраций](https://github.com/allisonhorst/stats-illustrations) Эллисон Хорст объясняет процесс кластеризации:\n", "\n", "

\n", " \n", "

Иллюстрация от @allison_horst
\n", "\n", "Основной вопрос, который возникает при кластеризации, заключается в следующем: как определить, на сколько кластеров разделить ваши данные? Один из недостатков метода K-Means заключается в том, что вам нужно заранее установить `k`, то есть количество `центроидов`. К счастью, `метод локтя` помогает оценить хорошее начальное значение для `k`. Вы попробуете это через минуту.\n", "\n", "### \n", "\n", "**Предварительные требования**\n", "\n", "Мы начнем с того места, где остановились в [предыдущем уроке](https://github.com/microsoft/ML-For-Beginners/blob/main/5-Clustering/1-Visualize/solution/R/lesson_14-R.ipynb), где мы анализировали набор данных, создавали множество визуализаций и фильтровали данные для интересующих нас наблюдений. Обязательно ознакомьтесь с ним!\n", "\n", "Нам понадобятся некоторые пакеты для выполнения этого модуля. Вы можете установить их с помощью команды: `install.packages(c('tidyverse', 'tidymodels', 'cluster', 'summarytools', 'plotly', 'paletteer', 'factoextra', 'patchwork'))`\n", "\n", "Или используйте следующий скрипт, который проверяет наличие необходимых пакетов и устанавливает их, если каких-то не хватает.\n" ] }, { "cell_type": "code", "metadata": { "id": "ah_tBi58LXyi" }, "source": [ "suppressWarnings(if(!require(\"pacman\")) install.packages(\"pacman\"))\n", "\n", "pacman::p_load('tidyverse', 'tidymodels', 'cluster', 'summarytools', 'plotly', 'paletteer', 'factoextra', 'patchwork')\n" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "7e--UCUTLXym" }, "source": [ "Давайте начнем!\n", "\n", "## 1. Танец с данными: Выберите 3 самых популярных музыкальных жанра\n", "\n", "Это краткое напоминание о том, что мы делали в предыдущем уроке. Давайте разберем данные!\n" ] }, { "cell_type": "code", "metadata": { "id": "Ycamx7GGLXyn" }, "source": [ "# Load the core tidyverse and make it available in your current R session\n", "library(tidyverse)\n", "\n", "# Import the data into a tibble\n", "df <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/5-Clustering/data/nigerian-songs.csv\", show_col_types = FALSE)\n", "\n", "# Narrow down to top 3 popular genres\n", "nigerian_songs <- df %>% \n", " # Concentrate on top 3 genres\n", " filter(artist_top_genre %in% c(\"afro dancehall\", \"afropop\",\"nigerian pop\")) %>% \n", " # Remove unclassified observations\n", " filter(popularity != 0)\n", "\n", "\n", "\n", "# Visualize popular genres using bar plots\n", "theme_set(theme_light())\n", "nigerian_songs %>%\n", " count(artist_top_genre) %>%\n", " ggplot(mapping = aes(x = artist_top_genre, y = n,\n", " fill = artist_top_genre)) +\n", " geom_col(alpha = 0.8) +\n", " paletteer::scale_fill_paletteer_d(\"ggsci::category10_d3\") +\n", " ggtitle(\"Top genres\") +\n", " theme(plot.title = element_text(hjust = 0.5))\n" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "b5h5zmkPLXyp" }, "source": [ "🤩 Это прошло отлично!\n", "\n", "## 2. Дополнительное исследование данных.\n", "\n", "Насколько чисты эти данные? Давайте проверим наличие выбросов с помощью ящиков с усами (boxplots). Мы сосредоточимся на числовых столбцах с меньшим количеством выбросов (хотя вы можете удалить выбросы). Ящики с усами могут показать диапазон данных и помогут выбрать, какие столбцы использовать. Обратите внимание, что ящики с усами не показывают дисперсию, которая является важным элементом для хорошо кластеризуемых данных. Пожалуйста, ознакомьтесь с [этим обсуждением](https://stats.stackexchange.com/questions/91536/deduce-variance-from-boxplot) для получения дополнительной информации.\n", "\n", "[Ящики с усами](https://en.wikipedia.org/wiki/Box_plot) используются для графического отображения распределения `числовых` данных, поэтому давайте начнем с *выбора* всех числовых столбцов вместе с популярными музыкальными жанрами.\n" ] }, { "cell_type": "code", "metadata": { "id": "HhNreJKLLXyq" }, "source": [ "# Select top genre column and all other numeric columns\n", "df_numeric <- nigerian_songs %>% \n", " select(artist_top_genre, where(is.numeric)) \n", "\n", "# Display the data\n", "df_numeric %>% \n", " slice_head(n = 5)\n" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "uYXrwJRaLXyq" }, "source": [ "Посмотрите, как удобно использовать помощник выбора `where` 💁? Исследуйте другие подобные функции [здесь](https://tidyselect.r-lib.org/).\n", "\n", "Поскольку мы будем создавать ящик с усами для каждой числовой переменной и хотим избежать использования циклов, давайте преобразуем наши данные в *длинный* формат, который позволит нам воспользоваться `facets` - подграфиками, каждый из которых отображает один поднабор данных.\n" ] }, { "cell_type": "code", "metadata": { "id": "gd5bR3f8LXys" }, "source": [ "# Pivot data from wide to long\n", "df_numeric_long <- df_numeric %>% \n", " pivot_longer(!artist_top_genre, names_to = \"feature_names\", values_to = \"values\") \n", "\n", "# Print out data\n", "df_numeric_long %>% \n", " slice_head(n = 15)\n" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "-7tE1swnLXyv" }, "source": [ "Теперь намного длиннее! А теперь время для `ggplots`! Какой `geom` мы будем использовать?\n" ] }, { "cell_type": "code", "metadata": { "id": "r88bIsyuLXyy" }, "source": [ "# Make a box plot\n", "df_numeric_long %>% \n", " ggplot(mapping = aes(x = feature_names, y = values, fill = feature_names)) +\n", " geom_boxplot() +\n", " facet_wrap(~ feature_names, ncol = 4, scales = \"free\") +\n", " theme(legend.position = \"none\")\n" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "EYVyKIUELXyz" }, "source": [ "Легко-gg!\n", "\n", "Теперь мы видим, что данные немного шумные: наблюдая каждый столбец в виде коробчатой диаграммы, можно заметить выбросы. Вы могли бы пройтись по набору данных и удалить эти выбросы, но тогда данные станут довольно минимальными.\n", "\n", "На данный момент давайте выберем, какие столбцы будем использовать для нашего упражнения по кластеризации. Выберем числовые столбцы с похожими диапазонами. Мы могли бы закодировать `artist_top_genre` как числовой, но пока исключим его.\n" ] }, { "cell_type": "code", "metadata": { "id": "-wkpINyZLXy0" }, "source": [ "# Select variables with similar ranges\n", "df_numeric_select <- df_numeric %>% \n", " select(popularity, danceability, acousticness, loudness, energy) \n", "\n", "# Normalize data\n", "# df_numeric_select <- scale(df_numeric_select)\n" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "D7dLzgpqLXy1" }, "source": [ "## 3. Вычисление кластеризации методом k-средних в R\n", "\n", "Мы можем вычислить метод k-средних в R с помощью встроенной функции `kmeans`, см. `help(\"kmeans()\")`. Функция `kmeans()` принимает на вход датафрейм, содержащий только числовые столбцы, в качестве основного аргумента.\n", "\n", "Первым шагом при использовании кластеризации методом k-средних является указание количества кластеров (k), которые будут созданы в итоговом решении. Мы знаем, что в наборе данных есть 3 музыкальных жанра, которые мы выделили, поэтому попробуем указать 3:\n" ] }, { "cell_type": "code", "metadata": { "id": "uC4EQ5w7LXy5" }, "source": [ "set.seed(2056)\n", "# Kmeans clustering for 3 clusters\n", "kclust <- kmeans(\n", " df_numeric_select,\n", " # Specify the number of clusters\n", " centers = 3,\n", " # How many random initial configurations\n", " nstart = 25\n", ")\n", "\n", "# Display clustering object\n", "kclust\n" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "hzfhscWrLXy-" }, "source": [ "Объект kmeans содержит несколько частей информации, которые хорошо объяснены в `help(\"kmeans()\")`. Сейчас давайте сосредоточимся на некоторых из них. Мы видим, что данные были сгруппированы в 3 кластера размером 65, 110 и 111. Вывод также содержит центры кластеров (средние значения) для 3 групп по 5 переменным.\n", "\n", "Вектор кластеризации — это назначение кластера для каждой наблюдаемой точки. Давайте используем функцию `augment`, чтобы добавить назначение кластера в исходный набор данных.\n" ] }, { "cell_type": "code", "metadata": { "id": "0XwwpFGQLXy_" }, "source": [ "# Add predicted cluster assignment to data set\n", "augment(kclust, df_numeric_select) %>% \n", " relocate(.cluster) %>% \n", " slice_head(n = 10)\n" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "NXIVXXACLXzA" }, "source": [ "Отлично, мы только что разделили наш набор данных на 3 группы. Итак, насколько хороша наша кластеризация 🤷? Давайте посмотрим на `Silhouette score`.\n", "\n", "### **Silhouette score**\n", "\n", "[Анализ силуэта](https://en.wikipedia.org/wiki/Silhouette_(clustering)) может быть использован для изучения расстояния между получившимися кластерами. Этот показатель варьируется от -1 до 1, и если значение близко к 1, кластер плотный и хорошо отделен от других кластеров. Значение, близкое к 0, указывает на пересекающиеся кластеры, где образцы находятся очень близко к границе разделения соседних кластеров. [Источник](https://dzone.com/articles/kmeans-silhouette-score-explained-with-python-exam).\n", "\n", "Метод среднего силуэта вычисляет средний силуэт наблюдений для различных значений *k*. Высокий средний показатель силуэта указывает на хорошую кластеризацию.\n", "\n", "Функция `silhouette` из пакета cluster используется для вычисления средней ширины силуэта.\n", "\n", "> Силуэт можно рассчитать с использованием любой [метрики расстояния](https://en.wikipedia.org/wiki/Distance \"Distance\"), такой как [евклидово расстояние](https://en.wikipedia.org/wiki/Euclidean_distance \"Euclidean distance\") или [манхэттенское расстояние](https://en.wikipedia.org/wiki/Manhattan_distance \"Manhattan distance\"), которые мы обсуждали в [предыдущем уроке](https://github.com/microsoft/ML-For-Beginners/blob/main/5-Clustering/1-Visualize/solution/R/lesson_14-R.ipynb).\n" ] }, { "cell_type": "code", "metadata": { "id": "Jn0McL28LXzB" }, "source": [ "# Load cluster package\n", "library(cluster)\n", "\n", "# Compute average silhouette score\n", "ss <- silhouette(kclust$cluster,\n", " # Compute euclidean distance\n", " dist = dist(df_numeric_select))\n", "mean(ss[, 3])\n" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "QyQRn97nLXzC" }, "source": [ "Наш результат — **0.549**, то есть прямо посередине. Это указывает на то, что наши данные не особенно хорошо подходят для такого типа кластеризации. Давайте проверим эту догадку визуально. Пакет [factoextra](https://rpkgs.datanovia.com/factoextra/index.html) предоставляет функции (`fviz_cluster()`) для визуализации кластеризации.\n" ] }, { "cell_type": "code", "metadata": { "id": "7a6Km1_FLXzD" }, "source": [ "library(factoextra)\n", "\n", "# Visualize clustering results\n", "fviz_cluster(kclust, df_numeric_select)\n" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "IBwCWt-0LXzD" }, "source": [ "Перекрытие кластеров указывает на то, что наши данные не очень хорошо подходят для такого типа кластеризации, но давайте продолжим.\n", "\n", "## 4. Определение оптимального количества кластеров\n", "\n", "Основной вопрос, который часто возникает при кластеризации методом K-Means, заключается в следующем: если у нас нет известных меток классов, как определить, на сколько кластеров нужно разделить данные?\n", "\n", "Один из способов выяснить это — использовать выборку данных, чтобы `создать серию моделей кластеризации` с увеличивающимся количеством кластеров (например, от 1 до 10) и оценить метрики кластеризации, такие как **силуэтный коэффициент**.\n", "\n", "Давайте определим оптимальное количество кластеров, вычислив алгоритм кластеризации для различных значений *k* и оценив **сумму квадратов внутри кластеров** (WCSS). Общая сумма квадратов внутри кластеров (WCSS) измеряет компактность кластеризации, и мы хотим, чтобы она была как можно меньше, так как более низкие значения означают, что точки данных находятся ближе друг к другу.\n", "\n", "Давайте исследуем влияние различных значений `k` от 1 до 10 на эту кластеризацию.\n" ] }, { "cell_type": "code", "metadata": { "id": "hSeIiylDLXzE" }, "source": [ "# Create a series of clustering models\n", "kclusts <- tibble(k = 1:10) %>% \n", " # Perform kmeans clustering for 1,2,3 ... ,10 clusters\n", " mutate(model = map(k, ~ kmeans(df_numeric_select, centers = .x, nstart = 25)),\n", " # Farm out clustering metrics eg WCSS\n", " glanced = map(model, ~ glance(.x))) %>% \n", " unnest(cols = glanced)\n", " \n", "\n", "# View clustering rsulsts\n", "kclusts\n" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "m7rS2U1eLXzE" }, "source": [ "Теперь, когда у нас есть общая сумма квадратов внутри кластеров (tot.withinss) для каждого алгоритма кластеризации с центром *k*, мы используем [метод локтя](https://en.wikipedia.org/wiki/Elbow_method_(clustering)), чтобы определить оптимальное количество кластеров. Этот метод заключается в построении графика WCSS в зависимости от количества кластеров и выборе [точки перегиба кривой](https://en.wikipedia.org/wiki/Elbow_of_the_curve \"Elbow of the curve\") в качестве количества кластеров для использования.\n" ] }, { "cell_type": "code", "metadata": { "id": "o_DjHGItLXzF" }, "source": [ "set.seed(2056)\n", "# Use elbow method to determine optimum number of clusters\n", "kclusts %>% \n", " ggplot(mapping = aes(x = k, y = tot.withinss)) +\n", " geom_line(size = 1.2, alpha = 0.8, color = \"#FF7F0EFF\") +\n", " geom_point(size = 2, color = \"#FF7F0EFF\")\n" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "pLYyt5XSLXzG" }, "source": [ "График показывает значительное снижение WCSS (то есть большую *сжатость*) при увеличении количества кластеров с одного до двух, а затем еще одно заметное снижение с двух до трех кластеров. После этого снижение становится менее выраженным, что приводит к появлению `локтя` 💪 на графике примерно при трех кластерах. Это хороший показатель того, что существует два-три достаточно хорошо разделенных кластера точек данных.\n", "\n", "Теперь мы можем извлечь модель кластеризации, где `k = 3`:\n", "\n", "> `pull()`: используется для извлечения одного столбца\n", ">\n", "> `pluck()`: используется для индексации структур данных, таких как списки\n" ] }, { "cell_type": "code", "metadata": { "id": "JP_JPKBILXzG" }, "source": [ "# Extract k = 3 clustering\n", "final_kmeans <- kclusts %>% \n", " filter(k == 3) %>% \n", " pull(model) %>% \n", " pluck(1)\n", "\n", "\n", "final_kmeans\n" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "l_PDTu8tLXzI" }, "source": [ "Отлично! Давайте визуализируем полученные кластеры. Хотите добавить немного интерактивности с помощью `plotly`?\n" ] }, { "cell_type": "code", "metadata": { "id": "dNcleFe-LXzJ" }, "source": [ "# Add predicted cluster assignment to data set\n", "results <- augment(final_kmeans, df_numeric_select) %>% \n", " bind_cols(df_numeric %>% select(artist_top_genre)) \n", "\n", "# Plot cluster assignments\n", "clust_plt <- results %>% \n", " ggplot(mapping = aes(x = popularity, y = danceability, color = .cluster, shape = artist_top_genre)) +\n", " geom_point(size = 2, alpha = 0.8) +\n", " paletteer::scale_color_paletteer_d(\"ggthemes::Tableau_10\")\n", "\n", "ggplotly(clust_plt)\n" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "6JUM_51VLXzK" }, "source": [ "Возможно, мы ожидали, что каждый кластер (представленный разными цветами) будет иметь четко различимые жанры (представленные разными формами).\n", "\n", "Давайте посмотрим на точность модели.\n" ] }, { "cell_type": "code", "metadata": { "id": "HdIMUGq7LXzL" }, "source": [ "# Assign genres to predefined integers\n", "label_count <- results %>% \n", " group_by(artist_top_genre) %>% \n", " mutate(id = cur_group_id()) %>% \n", " ungroup() %>% \n", " summarise(correct_labels = sum(.cluster == id))\n", "\n", "\n", "# Print results \n", "cat(\"Result:\", label_count$correct_labels, \"out of\", nrow(results), \"samples were correctly labeled.\")\n", "\n", "cat(\"\\nAccuracy score:\", label_count$correct_labels/nrow(results))\n" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "C50wvaAOLXzM" }, "source": [ "Точность этой модели неплохая, но и не выдающаяся. Возможно, данные не подходят для кластеризации методом K-Means. Эти данные слишком несбалансированы, слабо коррелируют и имеют слишком большую дисперсию между значениями столбцов, чтобы хорошо кластеризоваться. На самом деле, формирующиеся кластеры, вероятно, сильно зависят или искажены тремя категориями жанров, которые мы определили выше.\n", "\n", "Тем не менее, это был весьма познавательный процесс!\n", "\n", "В документации Scikit-learn можно увидеть, что модель, подобная этой, с плохо выраженными кластерами, имеет проблему \"дисперсии\":\n", "\n", "

\n", " \n", "

Инфографика из Scikit-learn
\n", "\n", "\n", "\n", "## **Дисперсия**\n", "\n", "Дисперсия определяется как \"среднее значение квадратов отклонений от среднего\" [источник](https://www.mathsisfun.com/data/standard-deviation.html). В контексте этой задачи кластеризации это означает, что значения в нашем наборе данных имеют тенденцию слишком сильно отклоняться от среднего.\n", "\n", "✅ Это отличный момент, чтобы подумать о всех способах исправления этой проблемы. Немного подкорректировать данные? Использовать другие столбцы? Применить другой алгоритм? Подсказка: попробуйте [масштабировать данные](https://www.mygreatlearning.com/blog/learning-data-science-with-k-means-clustering/), чтобы нормализовать их, и протестируйте другие столбцы.\n", "\n", "> Попробуйте этот '[калькулятор дисперсии](https://www.calculatorsoup.com/calculators/statistics/variance-calculator.php)', чтобы лучше понять концепцию.\n", "\n", "------------------------------------------------------------------------\n", "\n", "## **🚀Задание**\n", "\n", "Поработайте с этой тетрадью, изменяя параметры. Можете ли вы улучшить точность модели, очистив данные (например, удалив выбросы)? Вы можете использовать веса, чтобы придать больший вес определенным образцам данных. Что еще можно сделать, чтобы создать более качественные кластеры?\n", "\n", "Подсказка: попробуйте масштабировать данные. В тетради есть закомментированный код, который добавляет стандартное масштабирование, чтобы столбцы данных стали более похожими друг на друга по диапазону. Вы заметите, что, хотя коэффициент силуэта снижается, \"излом\" на графике локтя становится более плавным. Это связано с тем, что оставление данных без масштабирования позволяет данным с меньшей дисперсией иметь больший вес. Подробнее об этой проблеме можно прочитать [здесь](https://stats.stackexchange.com/questions/21222/are-mean-normalization-and-feature-scaling-needed-for-k-means-clustering/21226#21226).\n", "\n", "## [**Тест после лекции**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/30/)\n", "\n", "## **Обзор и самостоятельное изучение**\n", "\n", "- Ознакомьтесь с симулятором K-Means [например, с этим](https://user.ceng.metu.edu.tr/~akifakkus/courses/ceng574/k-means/). Вы можете использовать этот инструмент для визуализации образцов данных и определения их центроидов. Вы можете редактировать случайность данных, количество кластеров и центроидов. Помогает ли это лучше понять, как данные могут быть сгруппированы?\n", "\n", "- Также посмотрите [этот материал о K-Means](https://stanford.edu/~cpiech/cs221/handouts/kmeans.html) от Стэнфорда.\n", "\n", "Хотите попробовать свои новые навыки кластеризации на наборах данных, которые хорошо подходят для метода K-Means? Ознакомьтесь с:\n", "\n", "- [Обучение и оценка моделей кластеризации](https://rpubs.com/eR_ic/clustering) с использованием Tidymodels и других инструментов\n", "\n", "- [Анализ кластеров методом K-Means](https://uc-r.github.io/kmeans_clustering), Руководство по программированию на R для бизнес-аналитики UC\n", "\n", "- [Кластеризация методом K-Means с использованием принципов работы с tidy-данными](https://www.tidymodels.org/learn/statistics/k-means/)\n", "\n", "## **Задание**\n", "\n", "[Попробуйте разные методы кластеризации](https://github.com/microsoft/ML-For-Beginners/blob/main/5-Clustering/2-K-Means/assignment.md)\n", "\n", "## СПАСИБО:\n", "\n", "[Джен Лупер](https://www.twitter.com/jenlooper) за создание оригинальной версии этого модуля на Python ♥️\n", "\n", "[`Эллисон Хорст`](https://twitter.com/allison_horst/) за создание потрясающих иллюстраций, которые делают R более доступным и увлекательным. Найдите больше иллюстраций в ее [галерее](https://www.google.com/url?q=https://github.com/allisonhorst/stats-illustrations&sa=D&source=editors&ust=1626380772530000&usg=AOvVaw3zcfyCizFQZpkSLzxiiQEM).\n", "\n", "Приятного обучения,\n", "\n", "[Эрик](https://twitter.com/ericntay), Золотой посол Microsoft Learn Student.\n", "\n", "

\n", " \n", "

Иллюстрация от @allison_horst
\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n---\n\n**Отказ от ответственности**: \nЭтот документ был переведен с помощью сервиса автоматического перевода [Co-op Translator](https://github.com/Azure/co-op-translator). Несмотря на наши усилия обеспечить точность, автоматические переводы могут содержать ошибки или неточности. Оригинальный документ на его родном языке следует считать авторитетным источником. Для получения критически важной информации рекомендуется профессиональный перевод человеком. Мы не несем ответственности за любые недоразумения или неправильные интерпретации, возникающие в результате использования данного перевода.\n" ] } ] }