You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ML-For-Beginners/translations/km/5-Clustering/2-K-Means/solution/R/lesson_15-R.ipynb

636 lines
45 KiB

{
"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
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "GULATlQXLXyR"
},
"source": [
"## ស្វែងយល់អំពីការបែងចែកក្រុម K-Means ដោយប្រើប្រាស់ R និងគោលការណ៍ទិន្នន័យ Tidy។ \n",
"\n",
"### [**សំណួរពិចារណា មុនមុខវិជ្ជា**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/29/)\n",
"\n",
"ក្នុងមុខវិជ្ជានេះ អ្នកនឹងរៀនពីរបៀបបង្កើតក្រុម cluster ដោយប្រើកញ្ចប់ Tidymodels និងកញ្ចប់ផ្សេងទៀតក្នុងប្រព័ន្ធអិខូស៊ីស្ទឹម R (យើងនឹងហៅពួកវាថា មិត្ត 🧑‍🤝‍🧑) និងទិន្នន័យតន្រ្តីនៃប្រទេសនីហ្សេរីយ៉ាដែលអ្នកបាននាំចូលមុននេះ។ យើងនឹងគ្របដណ្តប់ពីមូលដ្ឋានរបស់ K-Means សម្រាប់ការបែងចែកក្រុម។ សូមចំណាំថា ចំនុចដែលអ្នកបានរៀនក្នុងមុខវិជ្ជាមុន មានរបៀបជាច្រើនក្នុងការដំណើរការជាមួយក្រុម ហើយវិធីដែលអ្នកប្រើប្រាស់អាស្រ័យលើទិន្នន័យរបស់អ្នក។ យើងនឹងសាកល្បង K-Means ព្រោះវាជាវិធីសាស្ត្របែងចែកក្រុមដែលពេញនិយមបំផុត។ ចាប់ផ្តើមទៅ!\n",
"\n",
"ពាក្យដែលអ្នកនឹងរៀន៖\n",
"\n",
"- ការវាយតម្លៃ Silhouette\n",
"\n",
"- វិធីសាស្រ្ត Elbow\n",
"\n",
"- កម្លាំងរឹង (Inertia)\n",
"\n",
"- ភាពចម្រុះ (Variance)\n",
"\n",
"### **ការណែនាំ**\n",
"\n",
"[K-Means Clustering](https://wikipedia.org/wiki/K-means_clustering) គឺជាវិធីសាស្ត្រដែលបានផ្សំនឹងពីដែនសញ្ញាស្រាវជ្រាវ។ វាត្រូវបានប្រើសម្រាប់បែងចែកនិងចែកជាក្រុមនៃទិន្នន័យទៅជា `k clusters` ដោយផ្អែកលើសមាធីនៅលើលក្ខណៈពិសេសរបស់វា។ \n",
"\n",
"ក្រុម cluster អាចត្រូវបានបង្ហាញជារូបភាព [Voronoi diagrams](https://wikipedia.org/wiki/Voronoi_diagram) ដែលរួមមានចំណុចមួយ (ឬ 'គ្រាប់ពូជា') និងតំបន់ដែលពាក់ព័ន្ធរបស់វា។\n",
"\n",
"<p >\n",
" <img src=\"../../../../../../translated_images/km/voronoi.1dc1613fb0439b95.webp\"\n",
" width=\"500\"/>\n",
" <figcaption>រូបភាពព័ត៌មានដោយ Jen Looper</figcaption>\n",
"\n",
"\n",
"ការបែងចែកក្រុម K-Means មានជំហានដូចខាងក្រោម៖\n",
"\n",
"1. អ្នកវិទ្យាសាស្ត្រទិន្នន័យចាប់ផ្តើមដោយកំណត់ចំនួនក្រុមដែលចង់បង្កើត។\n",
"\n",
"2. បន្ទាប់មក, អាល់ហ្គូរិធម៍ជ្រើសរើសរាប់ K អារម្មណ៍ជាប់ចៃដន្យពីទិន្នន័យ ដើម្បីបម្រើជាមជ្ឈមណ្ឌលដំបូង (centroids) សម្រាប់ក្រុម cluster ។\n",
"\n",
"3. បន្ទាប់មក, រាល់អារម្មណ៍នៅសល់ត្រូវបានចាត់ទុកទៅកាន់ centroid ដែលជិតបំផុត។\n",
"\n",
"4. បន្ទាប់មក, គណនាមធ្យមថ្មីនៃរាល់ក្រុម ហើយផ្លាស់ទី centroid ទៅកាន់មធ្យមនោះ។\n",
"\n",
"5. ឥឡូវនេះដែលមជ្ឈមណ្ឌលត្រូវបានគណនាឡើងវិញ អារម្មណ៍រាល់មួយត្រូវបានពិនិត្យម្តងទៀតថាតើវាអាចជិតក្រុមផ្សេងទៀតខ្លះឬទេ។ អ្នកនឹងចាត់ទុកវាឡើងវិញដោយប្រើមធ្យមក្រុមថ្មី។ ជំហានចាត់តាំងក្រុម និងធ្វើបច្ចុប្បន្នភាព centroid នឹងធ្វើឡើងជារយៈពេលមួយរហូតដល់ការបែងចែកក្រុមឈប់ផ្លាស់ប្តូរ (ឧ. នៅពេលដែលការរួមបញ្ចូលបានជោគជ័យ)។ ជាទូទៅ អាល់ហ្គូរិធម៍នឹងបញ្ចប់នៅពេលរៀងរាល់វដ្តថ្មីមានចលនាតិចឡើងនៃចំណុចកណ្តាល ហើយក្រុមក្លាយទៅជាស្ថិតិ។\n",
"\n",
"<div>\n",
"\n",
"> សូមចំណាំថា ដោយសារតែការចៃដន្យនៃអារម្មណ៍ដំបូង k ដែលត្រូវបានប្រើជាចំណុចកណ្តាលចាប់ផ្តើម អ្នកអាចទទួលបានលទ្ធផលខុសពីម្តងៗ។ ដូច្នេះ អាល់ហ្គូរិធម៍ភាគច្រើនប្រើ *random starts* ច្រើន និងជ្រើសវដ្តដែលមាន WCSS ទាបបំផុត។ ដូច្នេះ សូមណែនាំឱ្យដំណើរការ K-Means ជាមួយតម្លៃ *nstart* ច្រើន ដើម្បីជៀសវាង *local optimum* មិនចង់បាន។\n",
"\n",
"</div>\n",
"\n",
"រូបភាពធ្វើចលនាខ្លីនេះ ដោយប្រើ [ស្នាដៃសិល្បៈ](https://github.com/allisonhorst/stats-illustrations) របស់ Allison Horst សូមពន្យល់ដំណើរការបែងចែកក្រុម៖\n",
"\n",
"<p >\n",
" <img src=\"../../images/kmeans.gif\"\n",
" width=\"550\"/>\n",
" <figcaption>ស្នាដៃដោយ @allison_horst</figcaption>\n",
"\n",
"\n",
"\n",
"សំណួរមូលដ្ឋានមួយដែលកើតឡើងក្នុងការបែងចែកក្រុម គឺ៖ តើធ្វើដូចម្តេចដើម្បីដឹងថាត្រូវបែងចែកទិន្នន័យរបស់អ្នកទៅជាចំនួនក្រុមប៉ុន្មាន? ខុសជំនាញមួយនៃការប្រើប្រាស់ K-Means គឺអ្នកត្រូវការបង្កើត `k` ដែលជាចំនួន `centroids` ។ សំណាងល្អវិធីសាស្រ្ត `elbow method` ជួយឲ្យប៉ាន់ប្រមាណតម្លៃបើកផ្លាស់ចាប់ផ្តើមល្អសម្រាប់ `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",
"ម្យ៉ាងទៀត script ខាងក្រោមនេះពិនិត្យថាទោះបីអ្នកមានកញ្ចប់ត្រូវការដែរឬអត់សម្រាប់បញ្ចប់មេរៀននេះ ហើយដំឡើងសម្រាប់អ្នក ប្រសិនបើមានខ្វះខាត។\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",
"ទិន្នន័យនេះស្អាតប៉ុណ្ណាដែរ? យាងពិនិត្យសម្រាប់ outliers ដោយប្រើ box plots។ ពួកយើងនឹងផ្ដោតលើជួរឈរផ្នែកលេខដែលមាន outliers តិចជាង (បើទោះបីជាអ្នកអាចសម្អាត outliers បានក៏ដោយ)។ Boxplots អាចបង្ហាញជួរនៃទិន្នន័យ និងជួយជ្រើសរើសជួរឈរណាដើម្បីប្រើ។ សម្គាល់, Boxplots មិនបង្ហាញភាពផ្សេងគ្នាទេ, ដែលជាធាតុសំខាន់នៃទិន្នន័យអាចបែងចែកបានល្អ។ សូមមើល [ការពិភាក្សានេះ](https://stats.stackexchange.com/questions/91536/deduce-variance-from-boxplot) សម្រាប់ការអានបន្ថែម។\n",
"\n",
"[Boxplots](https://en.wikipedia.org/wiki/Box_plot) ត្រូវបានប្រើដើម្បីបង្ហាញភាពចែកចាយយ៉ាងក្រាហ្វិកនៃទិន្នន័យ `numeric` ដូច្នេះ យើងចាប់ផ្តើមដោយ *ជ្រើសរើស* ជួរឈរលេខទាំងអស់រួមជាមួយប្រភេទតន្ត្រីពេញនិយម។\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` ធ្វើឲ្យ​ងាយស្រួល​នេះ 💁? ស្វែងយល់​អំពី​មុខងារ​ផ្សេងទៀត​ទីនេះ [here](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": [
"Easy-gg!\n",
"\n",
"ឥឡូវនេះយើងអាចមើលឃើញទិន្នន័យនេះមានសំឡេងរំខានបន្តិច៖ ដោយការពិនិត្យមើលជួរដេកនីមួយៗជារាងប្រអប់ អ្នកអាចឃើញតម្លៃចំម្លង។ អ្នកអាចត្រួតពិនិត្យតារាងទិន្នន័យហើយដកតម្លៃចំម្លងទាំងនេះចេញ ប៉ុន្តែវានឹងធ្វើឱ្យទិន្នន័យមានតិចតួច។\n",
"\n",
"សម្រាប់ពេលនេះ យើងមកជ្រើសរើសជួរដេកដែលយើងនឹងប្រើសម្រាប់ហាត់ clustering របស់យើង។ យើងនឹងជ្រើសរើសជួរដេកជាចំនួនដែលមានជួរដូចគ្នា។ យើងអាចបម្លែង `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-means ក្នុង R\n",
"\n",
"យើងអាចកំណត់ក្រុមតាមវិធី k-means ក្នុង R ជាមួយមុខងារ `kmeans` ដែលមានមុនហើយ សូមមើល `help(\"kmeans()\")`។ មុខងារ `kmeans()` ទទួលបាន data frame ដែលមានជួរឈរផ្ទាល់ខ្លួនទាំងអស់ជាឈ្មោះបញ្ចូលដើមរបស់វា។\n",
"\n",
"ជំហានដំបូង នៅពេលប្រើក្រុមតាមវិធី k-means គឺត្រូវកំណត់ចំនួនក្រុម (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()\")`។ សម្រាប់ពេលនេះ យើងនឹងផ្តោតលើខ្លះៗប៉ុណ្ណោះ។ យើងឃើញថា ទិន្នន័យត្រូវបានក្រុម into 3 ក្រុមមានទំហំ 65, 110, 111។ លទ្ធផលនោះក៏មានមជ្ឈំដ្ឋានក្រុម (means) សម្រាប់ក្រុមទាំង 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`\n",
"\n",
"### **ពិន្ទុ Silhouette**\n",
"\n",
"[ការ​វិភាគ Silhouette](https://en.wikipedia.org/wiki/Silhouette_(clustering)) អាចត្រូវបានប្រើដើម្បីសិក្សាចម្ងាយបំបែករវាងក្រុមដែលទទួលបាន។ ពិន្ទុនេះផ្លាស់ប្តូរពី -1 ទៅ 1 ហើយបើពិន្ទុជិត 1 នោះក្រុមនោះមានភាពសម្បូរបែប និងបំបែកចេញពីក្រុមផ្សេងទៀតយ៉ាងច្បាស់។ តម្លៃជិត 0 ជាតំណាងឱ្យក្រុមឈ្លោះគ្នាមានគំរូដែលនៅជិតស្និទ្ធដល់ស្រមោលសម្រេចចិត្តរវាងក្រុមជិតខាង។[ប្រភព](https://dzone.com/articles/kmeans-silhouette-score-explained-with-python-exam)។\n",
"\n",
"វិធីសាស្រ្ត silhouette មធ្យមគិតពិន្ទុ silhouette មធ្យមនៃការសង្កេតសម្រាប់តម្លៃ *k* ផ្សេងៗគ្នា។ ពិន្ទុ silhouette មធ្យមខ្ពស់បង្ហាញពីការបែងចែកក្រុមល្អ។\n",
"\n",
"មុខងារ `silhouette` ក្នុងកញ្ចប់ cluster ត្រូវបានប្រើដើម្បីគណនាល្បះ silhouette មធ្យម។\n",
"\n",
"> silhouette អាចត្រូវបានគណนาด้วยវិធីសាស្រ្ត [ចម្ងាយ](https://en.wikipedia.org/wiki/Distance \"ចម្ងាយ\") ផ្សេងៗដូចជា [ចម្ងាយ Euclidean](https://en.wikipedia.org/wiki/Euclidean_distance \"ចម្ងាយ Euclidean\") ឬ [ចម្ងាយ Manhattan](https://en.wikipedia.org/wiki/Manhattan_distance \"ចម្ងាយ Manhattan\") ដែលយើងបានពិភាក្សានៅក្នុង [មេរៀនមុន](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": [
"ពិន្ទុរបស់យើងគឺ **.549**, ដូច្នេះគឺនៅកណ្តាល។ នេះបង្ហាញថាដាតារបស់យើងមិនសមស្របជាពិសេសសម្រាប់ប្រភេទ clustering នេះទេ។ យើងមកមើលថាតើយើងអាចបញ្ជាក់សង្ស័យនេះតាមរូបមន្តវិជ្ជាមានទេឬនៅ។ កញ្ចប់ [factoextra package](https://rpkgs.datanovia.com/factoextra/index.html) ផ្តល់នូវមុខងារ (`fviz_cluster()`) ដើម្បីបង្ហាញ clustering។\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) ហើយវាយតម្លៃមាត្រដ្ឋានបែងចែកក្រុមដូចជា **ពិន្ទុ Silhouette។**\n",
"\n",
"មកកំណត់ចំនួនក្រុមល្អបំផុតដោយគណនាវិធីសាស្ត្របែងចែកក្រុមសម្រាប់តម្លៃ *k* ផ្សេងៗ ហើយវាយតម្លៃ **ផលបូកក្នុងចំណោមក្រុម (Within Cluster Sum of Squares)** (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) សម្រាប់ជAlgorithms ការបែងចែកនីមួយៗដោយមានមជ្ឈមណ្ឌល *k* យើងប្រើវិធី [elbow method](https://en.wikipedia.org/wiki/Elbow_method_(clustering)) ដើម្បីស្វែងរកចំនួនក្រុមដែលល្អបំផុត។ វិធីនេះរួមមានការរៀបចំក្រាប WCSS ជាអនុគមន៍នៃចំនួនក្រុម ហើយជ្រើសយក [elbow of the curve](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 សំខាន់មួយ (ដូច្នេះ​មាន *ភាពតឹង*) ខណៈដែលចំនួនក្លុស្ទឺរកើនពីមួយទៅពីរ ហើយមានការកាត់បន្ថយច្បាស់លាស់បន្ថែមទៀតពីពីរទៅបីក្លុស្ទឺរ។ បន្ទាប់មក ការកាត់បន្ថយកាន់តែតិចបន្ថយ អោយមាន `elbow` 💪 នៅក្នុងតារាងនៅជិតបីក្លុស្ទឺរ។ នេះជាសញ្ញាល្អថាមានពីរដល់បីក្លុស្ទឺរដែលបំបែកបានល្អនៃចំណុចទិន្នន័យ។\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": [
"សូមអរគុណ! ឲ្យយើងបន្តបង្ហាញ cluster ដែលបានទទួល។ តើចង់មានអន្តរកម្មមួយប្រើ `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": [
"ប្រហែលជាយើងបានរំពឹងថាclusterនីមួយៗ(ដែលតំណាងដោយពណ៌ផ្សេងៗ)នឹងមានប្រភេទភែនខុសគ្នា(ដែលតំណាងដោយរាងធាតុផ្សេងៗ)។\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",
"<p >\n",
" <img src=\"../../../../../../translated_images/km/problems.f7fb539ccd80608e.webp\"\n",
" width=\"500\"/>\n",
" <figcaption>ព័ត៌មានក្រាហ្វិចពី Scikit-learn</figcaption>\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",
"ការជូនដំណឹង៖ សូមព្យាយាមបង្រួមទិន្នន័យរបស់អ្នក។ មានកូដដែលមិនបានដំណើរការបង្ហាញក្នុងសៀវភៅកំណត់ត្រា ដែលបន្ថែមការបង្រួមស្តង់ដារ ដើម្បីធ្វើឲ្យជួរឈរទិន្នន័យមានស្រដៀងគ្នាជា range។ អ្នកនឹងសង្កេតឃើញថា ខណៈពេលដែលពិន្ទុនៃសំណុំបែបវិលកាត់ធ្លាក់ចុះ ការបង្ហាញរូបភាពលំនាំកោងកភាគច្រើនទន់ភ្លន់ឡើង។ នេះដោយសារតែការរិះគន់ទិន្នន័យដែលមិនបានបង្រួមអនុញ្ញាតឲ្យទិន្នន័យដែលមានចម្រុះតិចមានទំងន់ធំជាង។ អានបន្ថែមពីបញ្ហានេះ [នៅទីនេះ](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/). អ្នកអាចប្រើឧបករណ៍នេះដើម្បីមើលទិន្នន័យឧទាហរណ៍ និងកំណត់អំពែកម្ពុជា (centroids) របស់វា។ អ្នកអាចកែប្រែភាពចៃដន្យនៃទិន្នន័យ ចំនួនក្រុម និងចំនួនអំពែកម្ពុជា។ វាមានប្រយោជន៍ក្នុងការជួយអ្នកយល់ពីរបៀបដែលទិន្នន័យអាចត្រូវបានភ្ជាប់ក្រុមអ្វីមួយ?\n",
"\n",
"- ផងដែរ មើលឯកសារនេះ [អំពី K-Means](https://stanford.edu/~cpiech/cs221/handouts/kmeans.html) ពីសាកលវិទ្យាល័យ Stanford។\n",
"\n",
"ចង់សាកល្បងជំនាញបែងចែកក្រុមថ្មីរបស់អ្នកទៅជាសំណុំទិន្នន័យដែលសមស្របសម្រាប់ K-Means ដែរឬទេ? សូមមើល៖\n",
"\n",
"- [បណ្តុះបណ្តាល និងវាយតម្លៃម៉ូដែលបែងចែកក្រុម](https://rpubs.com/eR_ic/clustering) ដោយប្រើ Tidymodels និងមិត្តភក្តិ\n",
"\n",
"- [វិភាគក្រុម K-means](https://uc-r.github.io/kmeans_clustering), គណនីវិទ្យាជំនាញរបស់ 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",
"[Jen Looper](https://www.twitter.com/jenlooper) សម្រាប់បង្កើតកំណែ Pythonដើមនៃមុខងារនេះ ♥️\n",
"\n",
"[`Allison Horst`](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",
"[Eric](https://twitter.com/ericntay), ស្ថាប័នរៀនសង្កេត Microsoft Learn Gold Student Ambassador ។\n",
"\n",
"<p >\n",
" <img src=\"../../../../../../translated_images/km/r_learners_sm.e4a71b113ffbedfe.webp\"\n",
" width=\"500\"/>\n",
" <figcaption>សិល្បៈដោយ @allison_horst</figcaption>\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n\n<!-- CO-OP TRANSLATOR DISCLAIMER START -->\n**ការបដិសេធ**៖ \nឯកសារនេះត្រូវបានបំលែងដោយប្រើសេវាកម្មបកប្រែកម្មវិធី AI [Co-op Translator](https://github.com/Azure/co-op-translator)។ ខណៈពេលដែលយើងខិតខំប្រឹងប្រែងឲ្យបានច្បាស់លាស់ សូមព្រមានថាការបកប្រែដោយស្វ័យប្រវត្តិក៏អាចមានកំហុស ឬអក្សរបាត់បង់ត្រូវមិនបានផ្ទៀងផ្ទាត់។\n\nឯកសារដើមជាភាសាសូម្បីជាតិក្នុងការប្រើប្រាស់គួរតែត្រូវបានគេចាត់ទុកជាមូលដ្ឋានត្រឹមត្រូវ។ សម្រាប់ព័ត៌មានសំខាន់ៗ យើងណែនាំឲ្យប្រើការបកប្រែដោយមនុស្សជំនាញវិជ្ជាជីវៈ។ យើងមិនទទួលខុសត្រូវចំពោះការយល់ច្រឡំ ឬការបកស្រាយខុសពីការប្រើប្រាស់ការបកប្រែនេះឡើយ។\n<!-- CO-OP TRANSLATOR DISCLAIMER END -->\n"
]
}
]
}