LBB Unsupervised Learning
Introduction
Machine learning bertujuan untuk membuat mesin yang belajar berdasarkan data.
LBB ini akan menganalisa pengelompokan berdasarkan karakteristik fitur-fitur audio dalam lagu yang diputar di Spotify, menggunakan data dari link berikut: https://www.kaggle.com/zaheenhamidani/ultimate-spotify-tracks-db
Kita menggunakan pendekatan Unsupervised Learning yang mempunyai ciri: * Tidak memiliki target variable. * Tujuannya untuk mencari pola dalam data, yang berguna untuk menghasilkan informasi. * Tidak ada ground truth sehingga tidak ada evaluasi model
Set Up
library(tidyverse)
library(ggplot2)
library(GGally)
library(FactoMineR)
library(factoextra)
options(scipen=999)Read Data
spotify <- read.csv("SpotifyFeatures.csv")
head(spotify)## genre artist_name track_name
## 1 Movie Henri Salvador C'est beau de faire un Show
## 2 Movie Martin & les fées Perdu d'avance (par Gad Elmaleh)
## 3 Movie Joseph Williams Don't Let Me Be Lonely Tonight
## 4 Movie Henri Salvador Dis-moi Monsieur Gordon Cooper
## 5 Movie Fabien Nataf Ouverture
## 6 Movie Henri Salvador Le petit souper aux chandelles
## track_id popularity acousticness danceability duration_ms
## 1 0BRjO6ga9RKCKjfDqeFgWV 0 0.611 0.389 99373
## 2 0BjC1NfoEOOusryehmNudP 1 0.246 0.590 137373
## 3 0CoSDzoNIKCRs124s9uTVy 3 0.952 0.663 170267
## 4 0Gc6TVm52BwZD07Ki6tIvf 0 0.703 0.240 152427
## 5 0IuslXpMROHdEPvSl1fTQK 4 0.950 0.331 82625
## 6 0Mf1jKa8eNAf1a4PwTbizj 0 0.749 0.578 160627
## energy instrumentalness key liveness loudness mode speechiness tempo
## 1 0.9100 0.000 C# 0.3460 -1.828 Major 0.0525 166.969
## 2 0.7370 0.000 F# 0.1510 -5.559 Minor 0.0868 174.003
## 3 0.1310 0.000 C 0.1030 -13.879 Minor 0.0362 99.488
## 4 0.3260 0.000 C# 0.0985 -12.178 Major 0.0395 171.758
## 5 0.2250 0.123 F 0.2020 -21.150 Major 0.0456 140.576
## 6 0.0948 0.000 C# 0.1070 -14.970 Major 0.1430 87.479
## time_signature valence
## 1 4/4 0.814
## 2 4/4 0.816
## 3 5/4 0.368
## 4 4/4 0.227
## 5 4/4 0.390
## 6 4/4 0.358
str(spotify)## 'data.frame': 232725 obs. of 18 variables:
## $ genre : chr "Movie" "Movie" "Movie" "Movie" ...
## $ artist_name : chr "Henri Salvador" "Martin & les fées" "Joseph Williams" "Henri Salvador" ...
## $ track_name : chr "C'est beau de faire un Show" "Perdu d'avance (par Gad Elmaleh)" "Don't Let Me Be Lonely Tonight" "Dis-moi Monsieur Gordon Cooper" ...
## $ track_id : chr "0BRjO6ga9RKCKjfDqeFgWV" "0BjC1NfoEOOusryehmNudP" "0CoSDzoNIKCRs124s9uTVy" "0Gc6TVm52BwZD07Ki6tIvf" ...
## $ popularity : int 0 1 3 0 4 0 2 15 0 10 ...
## $ acousticness : num 0.611 0.246 0.952 0.703 0.95 0.749 0.344 0.939 0.00104 0.319 ...
## $ danceability : num 0.389 0.59 0.663 0.24 0.331 0.578 0.703 0.416 0.734 0.598 ...
## $ duration_ms : int 99373 137373 170267 152427 82625 160627 212293 240067 226200 152694 ...
## $ energy : num 0.91 0.737 0.131 0.326 0.225 0.0948 0.27 0.269 0.481 0.705 ...
## $ instrumentalness: num 0 0 0 0 0.123 0 0 0 0.00086 0.00125 ...
## $ key : chr "C#" "F#" "C" "C#" ...
## $ liveness : num 0.346 0.151 0.103 0.0985 0.202 0.107 0.105 0.113 0.0765 0.349 ...
## $ loudness : num -1.83 -5.56 -13.88 -12.18 -21.15 ...
## $ mode : chr "Major" "Minor" "Minor" "Major" ...
## $ speechiness : num 0.0525 0.0868 0.0362 0.0395 0.0456 0.143 0.953 0.0286 0.046 0.0281 ...
## $ tempo : num 167 174 99.5 171.8 140.6 ...
## $ time_signature : chr "4/4" "4/4" "5/4" "4/4" ...
## $ valence : num 0.814 0.816 0.368 0.227 0.39 0.358 0.533 0.274 0.765 0.718 ...
Data ini berisi lagu yang ada di streaming platform spotify yang diberikan fitur audio yang penjelasannya dapat dilihat pada link berikut : https://developer.spotify.com/documentation/web-api/reference/tracks/get-audio-features/
acousticness: A confidence measure from 0.0 to 1.0 of whether the track is acoustic. 1.0 represents high confidence the track is acoustic.danceability: Danceability describes how suitable a track is for dancing based on a combination of musical elements including tempo, rhythm stability, beat strength, and overall regularity. A value of 0.0 is least danceable and 1.0 is most danceable.energy: Energy is a measure from 0.0 to 1.0 and represents a perceptual measure of intensity and activity. Typically, energetic tracks feel fast, loud, and noisy. For example, death metal has high energy, while a Bach prelude scores low on the scale. Perceptual features contributing to this attribute include dynamic range, perceived loudness, timbre, onset rate, and general entropy.instrumentalness: Predicts whether a track contains no vocals. “Ooh” and “aah” sounds are treated as instrumental in this context. Rap or spoken word tracks are clearly “vocal”. The closer the instrumentalness value is to 1.0, the greater likelihood the track contains no vocal content. Values above 0.5 are intended to represent instrumental tracks, but confidence is higher as the value approaches 1.0.key: The key the track is in. Integers map to pitches using standard Pitch Class notation. E.g. 0 = C, 1 = C♯/D♭, 2 = D, and so on. If no key was detected, the value is -1.liveness: Detects the presence of an audience in the recording. Higher liveness values represent an increased probability that the track was performed live. A value above 0.8 provides strong likelihood that the track is live.loudness: The overall loudness of a track in decibels (dB). Loudness values are averaged across the entire track and are useful for comparing relative loudness of tracks. Loudness is the quality of a sound that is the primary psychological correlate of physical strength (amplitude). Values typically range between -60 and 0 db.mode: Mode indicates the modality (major or minor) of a track, the type of scale from which its melodic content is derived. Major is represented by 1 and minor is 0.speechiness: Speechiness detects the presence of spoken words in a track. The more exclusively speech-like the recording (e.g. talk show, audio book, poetry), the closer to 1.0 the attribute value. Values above 0.66 describe tracks that are probably made entirely of spoken words. Values between 0.33 and 0.66 describe tracks that may contain both music and speech, either in sections or layered, including such cases as rap music. Values below 0.33 most likely represent music and other non-speech-like tracks.tempo: The overall estimated tempo of a track in beats per minute (BPM). In musical terminology, tempo is the speed or pace of a given piece and derives directly from the average beat duration.time_signature: An estimated time signature. The time signature (meter) is a notational convention to specify how many beats are in each bar (or measure). The time signature ranges from 3 to 7 indicating time signatures of “3/4”, to “7/4”.valence: A measure from 0.0 to 1.0 describing the musical positiveness conveyed by a track. Tracks with high valence sound more positive (e.g. happy, cheerful, euphoric), while tracks with low valence sound more negative (e.g. sad, depressed, angry).
Exploratory Data Analysis
Coercion
- Membuang kolom yang tidak relevan untuk dianalisa:
track_id,track_name - Mengubah kolom yang tipe datanya belum sesuai :
genre,key,mode,time_signature(diubah menjadi factor)
# melakukan seleksi kolom dan mengubah tipe data
spotify_clean <- spotify %>%
# Mengeluarkan beberapa kolom
select(-c(track_id, track_name)) %>%
# Mengubah tipe data beberapa kolom secara bersamaan menjadi factor
mutate_at(vars(genre, key, mode, time_signature), as.factor) %>%
# Mengubah tipe data menjadi factor jika tipe data awalnya adalah character
mutate_if(is.character, as.factor)
glimpse(spotify_clean) ## Rows: 232,725
## Columns: 16
## $ genre <fct> Movie, Movie, Movie, Movie, Movie, Movie, Movie, Movi…
## $ artist_name <fct> "Henri Salvador", "Martin & les fées", "Joseph Willia…
## $ popularity <int> 0, 1, 3, 0, 4, 0, 2, 15, 0, 10, 0, 2, 4, 3, 0, 0, 0, …
## $ acousticness <dbl> 0.61100, 0.24600, 0.95200, 0.70300, 0.95000, 0.74900,…
## $ danceability <dbl> 0.389, 0.590, 0.663, 0.240, 0.331, 0.578, 0.703, 0.41…
## $ duration_ms <int> 99373, 137373, 170267, 152427, 82625, 160627, 212293,…
## $ energy <dbl> 0.9100, 0.7370, 0.1310, 0.3260, 0.2250, 0.0948, 0.270…
## $ instrumentalness <dbl> 0.00000000, 0.00000000, 0.00000000, 0.00000000, 0.123…
## $ key <fct> C#, F#, C, C#, F, C#, C#, F#, C, G, E, C, F#, D#, G, …
## $ liveness <dbl> 0.3460, 0.1510, 0.1030, 0.0985, 0.2020, 0.1070, 0.105…
## $ loudness <dbl> -1.828, -5.559, -13.879, -12.178, -21.150, -14.970, -…
## $ mode <fct> Major, Minor, Minor, Major, Major, Major, Major, Majo…
## $ speechiness <dbl> 0.0525, 0.0868, 0.0362, 0.0395, 0.0456, 0.1430, 0.953…
## $ tempo <dbl> 166.969, 174.003, 99.488, 171.758, 140.576, 87.479, 8…
## $ time_signature <fct> 4/4, 4/4, 5/4, 4/4, 4/4, 4/4, 4/4, 4/4, 4/4, 4/4, 4/4…
## $ valence <dbl> 0.8140, 0.8160, 0.3680, 0.2270, 0.3900, 0.3580, 0.533…
Cek missing values
is.na(spotify) %>% colSums()## genre artist_name track_name track_id
## 0 0 0 0
## popularity acousticness danceability duration_ms
## 0 0 0 0
## energy instrumentalness key liveness
## 0 0 0 0
## loudness mode speechiness tempo
## 0 0 0 0
## time_signature valence
## 0 0
Tidak terdapat missing values pada data spotify. Maka dapat dilanjutkan analisa berikutnya.
Dimensionality Reduction
Machine learning semakin banyak diadopsi di bidang yang berhubungan dengan high-dimensional data.
Kesulitan yang dihadapi pada high-dimensional data: - Menyulitkan pengolahan data (feature selection) - Memerlukan waktu dan komputasi yang besar dalam melakukan pemodelan - Melakukan visualisasi lebih dari tiga dimensi
Dimensionality reduction bertujuan untuk mereduksi dimensi data, namun tetap mempertahankan sebanyak mungkin informasi yang ada.
Principal Component Analysis (PCA)
Concept
Ide dasar dari PCA adalah untuk membuat sumbu (axis) baru yang dapat menangkap informasi (variance) sebesar mungkin dari variabel-variabel awal. Sumbu baru ini adalah yang dinamakan sebagai Principal Component (PC). Untuk melakukan dimensionality reduction, akan diambil beberapa PC saja yang merangkum jumlah informasi yang dibutuhkan.
💡 Highlight Points:
- PC dibuat untuk merangkum sebanyak mungkin informasi dari data.
- PC1 akan menangkap variansi paling tinggi dari data, dilanjutkan dengan PC2, dan seterusnya.
- PC yang dihasilkan adalah sebanyak jumlah variabel awal.
- antar PC yang dihasilkan tidak berkorelasi
- PCA cocok untuk data yang antar variabelnya saling berkorelasi
Kemudian, dikarenakan analisis PCA menggunakan nilai variance, kita hanya menggunakan kolom bertipe data numerik.
# data untuk PCA
spotify_num <- spotify_clean %>%
select_if(is.numeric)
glimpse(spotify_num)## Rows: 232,725
## Columns: 11
## $ popularity <int> 0, 1, 3, 0, 4, 0, 2, 15, 0, 10, 0, 2, 4, 3, 0, 0, 0, …
## $ acousticness <dbl> 0.61100, 0.24600, 0.95200, 0.70300, 0.95000, 0.74900,…
## $ danceability <dbl> 0.389, 0.590, 0.663, 0.240, 0.331, 0.578, 0.703, 0.41…
## $ duration_ms <int> 99373, 137373, 170267, 152427, 82625, 160627, 212293,…
## $ energy <dbl> 0.9100, 0.7370, 0.1310, 0.3260, 0.2250, 0.0948, 0.270…
## $ instrumentalness <dbl> 0.00000000, 0.00000000, 0.00000000, 0.00000000, 0.123…
## $ liveness <dbl> 0.3460, 0.1510, 0.1030, 0.0985, 0.2020, 0.1070, 0.105…
## $ loudness <dbl> -1.828, -5.559, -13.879, -12.178, -21.150, -14.970, -…
## $ speechiness <dbl> 0.0525, 0.0868, 0.0362, 0.0395, 0.0456, 0.1430, 0.953…
## $ tempo <dbl> 166.969, 174.003, 99.488, 171.758, 140.576, 87.479, 8…
## $ valence <dbl> 0.8140, 0.8160, 0.3680, 0.2270, 0.3900, 0.3580, 0.533…
Cek skala setiap variabel
Apakah antar variable sudah memiliki skala yang sama? Mari kita cek range untuk tiap kolom:
# cek summary data
summary(spotify_num)## popularity acousticness danceability duration_ms
## Min. : 0.00 Min. :0.0000 Min. :0.0569 Min. : 15387
## 1st Qu.: 29.00 1st Qu.:0.0376 1st Qu.:0.4350 1st Qu.: 182857
## Median : 43.00 Median :0.2320 Median :0.5710 Median : 220427
## Mean : 41.13 Mean :0.3686 Mean :0.5544 Mean : 235122
## 3rd Qu.: 55.00 3rd Qu.:0.7220 3rd Qu.:0.6920 3rd Qu.: 265768
## Max. :100.00 Max. :0.9960 Max. :0.9890 Max. :5552917
## energy instrumentalness liveness loudness
## Min. :0.0000203 Min. :0.0000000 Min. :0.00967 Min. :-52.457
## 1st Qu.:0.3850000 1st Qu.:0.0000000 1st Qu.:0.09740 1st Qu.:-11.771
## Median :0.6050000 Median :0.0000443 Median :0.12800 Median : -7.762
## Mean :0.5709577 Mean :0.1483012 Mean :0.21501 Mean : -9.570
## 3rd Qu.:0.7870000 3rd Qu.:0.0358000 3rd Qu.:0.26400 3rd Qu.: -5.501
## Max. :0.9990000 Max. :0.9990000 Max. :1.00000 Max. : 3.744
## speechiness tempo valence
## Min. :0.0222 Min. : 30.38 Min. :0.0000
## 1st Qu.:0.0367 1st Qu.: 92.96 1st Qu.:0.2370
## Median :0.0501 Median :115.78 Median :0.4440
## Mean :0.1208 Mean :117.67 Mean :0.4549
## 3rd Qu.:0.1050 3rd Qu.:139.05 3rd Qu.:0.6600
## Max. :0.9670 Max. :242.90 Max. :1.0000
Catatan: skala/satuan data spotify_num berbeda jauh, terutama pada data
duration_ms
Mari kita cek juga matriks covariance dari
spotify_num:
cov(spotify_num)## popularity acousticness danceability duration_ms
## popularity 330.8741927 -2.460579486 0.866213977 5079.7963
## acousticness -2.4605795 0.125860362 -0.024004549 472.7050
## danceability 0.8662140 -0.024004549 0.034450413 -2776.6700
## duration_ms 5079.7962942 472.705010446 -2776.670015161 14145750520.8082
## energy 1.1928936 -0.067816440 0.015931805 -957.2578
## instrumentalness -1.1619558 0.033958915 -0.020508345 2737.5056
## liveness -0.6058861 0.004853762 -0.001534008 560.8353
## loudness 39.6070158 -1.468729115 0.488376611 -33970.6429
## speechiness -0.5098157 0.009933929 0.004633400 -356.8187
## tempo 45.5478771 -2.611654392 0.125822789 -104575.8610
## valence 0.2841956 -0.030059094 0.026411285 -4386.3797
## energy instrumentalness liveness loudness
## popularity 1.192893559 -1.161955848 -0.605886064 39.607015849
## acousticness -0.067816440 0.033958915 0.004853762 -1.468729115
## danceability 0.015931805 -0.020508345 -0.001534008 0.488376611
## duration_ms -957.257831674 2737.505647036 560.835264134 -33970.642881913
## energy 0.069408833 -0.030227884 0.010071149 1.289631260
## instrumentalness -0.030227884 0.091668682 -0.008055978 -0.919510999
## liveness 0.010071149 -0.008055978 0.039312018 0.054333071
## loudness 1.289631260 -0.919510999 0.054333071 35.978446810
## speechiness 0.007092851 -0.009950208 0.018764818 -0.002529084
## tempo 1.862333254 -0.974186536 -0.314619135 42.324447453
## valence 0.029925682 -0.024214148 0.000608679 0.623816414
## speechiness tempo valence
## popularity -0.509815661 45.5478771 0.284195566
## acousticness 0.009933929 -2.6116544 -0.030059094
## danceability 0.004633400 0.1258228 0.026411285
## duration_ms -356.818722591 -104575.8610139 -4386.379669824
## energy 0.007092851 1.8623333 0.029925682
## instrumentalness -0.009950208 -0.9741865 -0.024214148
## liveness 0.018764818 -0.3146191 0.000608679
## loudness -0.002529084 42.3244475 0.623816414
## speechiness 0.034417042 -0.4674159 0.001150285
## tempo -0.467415886 954.7424276 1.083677477
## valence 0.001150285 1.0836775 0.067634056
Catatan: variansi dan covariance dari spotify_num skalanya juga berbeda jauh
Nilai variance dan covariance dipengaruhi oleh skala dari data. Semakin tinggi skala, nilai variance atau covariance akan semakin tinggi.
Data dengan perbedaan skala antar variabel yang tinggi tidak baik untuk langsung dianalisis PCA karena dapat menimbulkan bias. PC1 akan dianggap menangkap variansi tertinggi dan PC selanjutnya dianggap tidak memberikan informasi.
Kita dapat melihat seberapa besar variansi yang dirangkum tiap PC
menggunakan plot(prcomp(data)). Perhatikan plot berikut
yang menunjukkan bahwa semua informasi untuk data
spotify_num dirangkum oleh PC1.
Plot tersebut menunjukkan dominasi PC1 dalam menagkap variance. Hal ini terjadi jika kita tidak melakukan scaling pada data yang skalanya berbeda jauh. Mka kita harus melakukan proses scaling.
Data Pre-processing: Scaling
Scaling perlu dilakukan sebelum melakukan PCA agar antar variabel memiliki skala yang tidak jauh berbeda. Proses scaling yang digunakan adalah Z-score (mean = 0, standar deviasi = 1)
\[Z = \frac{x-mean}{sd}\]
# scaling
spotify_scaled <- scale(spotify_num)
summary(spotify_scaled)## popularity acousticness danceability duration_ms
## Min. :-2.2610 Min. :-1.0389 Min. :-2.68019 Min. :-1.8475
## 1st Qu.:-0.6667 1st Qu.:-0.9329 1st Qu.:-0.64310 1st Qu.:-0.4394
## Median : 0.1029 Median :-0.3849 Median : 0.08963 Median :-0.1236
## Mean : 0.0000 Mean : 0.0000 Mean : 0.00000 Mean : 0.0000
## 3rd Qu.: 0.7626 3rd Qu.: 0.9963 3rd Qu.: 0.74154 3rd Qu.: 0.2577
## Max. : 3.2365 Max. : 1.7686 Max. : 2.34168 Max. :44.7114
## energy instrumentalness liveness loudness
## Min. :-2.1671 Min. :-0.4898 Min. :-1.0356 Min. :-7.1500
## 1st Qu.:-0.7058 1st Qu.:-0.4898 1st Qu.:-0.5932 1st Qu.:-0.3670
## Median : 0.1292 Median :-0.4897 Median :-0.4388 Median : 0.3014
## Mean : 0.0000 Mean : 0.0000 Mean : 0.0000 Mean : 0.0000
## 3rd Qu.: 0.8200 3rd Qu.:-0.3716 3rd Qu.: 0.2471 3rd Qu.: 0.6784
## Max. : 1.6247 Max. : 2.8097 Max. : 3.9591 Max. : 2.2196
## speechiness tempo valence
## Min. :-0.53129 Min. :-2.82494 Min. :-1.74924
## 1st Qu.:-0.45314 1st Qu.:-0.79963 1st Qu.:-0.83793
## Median :-0.38091 Median :-0.06112 Median :-0.04198
## Mean : 0.00000 Mean : 0.00000 Mean : 0.00000
## 3rd Qu.:-0.08498 3rd Qu.: 0.69217 3rd Qu.: 0.78858
## Max. : 4.56146 Max. : 4.05310 Max. : 2.09595
head(spotify_num)## popularity acousticness danceability duration_ms energy instrumentalness
## 1 0 0.611 0.389 99373 0.9100 0.000
## 2 1 0.246 0.590 137373 0.7370 0.000
## 3 3 0.952 0.663 170267 0.1310 0.000
## 4 0 0.703 0.240 152427 0.3260 0.000
## 5 4 0.950 0.331 82625 0.2250 0.123
## 6 0 0.749 0.578 160627 0.0948 0.000
## liveness loudness speechiness tempo valence
## 1 0.3460 -1.828 0.0525 166.969 0.814
## 2 0.1510 -5.559 0.0868 174.003 0.816
## 3 0.1030 -13.879 0.0362 99.488 0.368
## 4 0.0985 -12.178 0.0395 171.758 0.227
## 5 0.2020 -21.150 0.0456 140.576 0.390
## 6 0.1070 -14.970 0.1430 87.479 0.358
head(as.data.frame(spotify_scaled))## popularity acousticness danceability duration_ms energy instrumentalness
## 1 -2.261002 0.6833748 -0.8909329 -1.1413655 1.2869052 -0.48981747
## 2 -2.206026 -0.3454664 0.1919933 -0.8218657 0.6302479 -0.48981747
## 3 -2.096075 1.6445663 0.5852948 -0.5452965 -1.6699502 -0.48981747
## 4 -2.261002 0.9426992 -1.6936990 -0.6952933 -0.9297874 -0.48981747
## 5 -2.041100 1.6389288 -1.2034190 -1.2821808 -1.3131538 -0.08356631
## 6 -2.261002 1.0723614 0.1273410 -0.6263486 -1.8073548 -0.48981747
## liveness loudness speechiness tempo valence
## 1 0.66065975 1.2907007 -0.3679692 1.5956039 1.3807413
## 2 -0.32283477 0.6686811 -0.1830817 1.8232495 1.3884316
## 3 -0.56492573 -0.7184009 -0.4558311 -0.5883245 -0.3342114
## 4 -0.58762176 -0.4348159 -0.4380431 1.7505932 -0.8763826
## 5 -0.06561313 -1.9305971 -0.4051623 0.7414313 -0.2496173
## 6 -0.54475148 -0.9002886 0.1198533 -0.9769791 -0.3726633
# melihat variance yang dirangkum tiap PC
plot(prcomp(spotify_scaled))Sekarang PC1 sudah tidak mendominasi PC lainnya dalam besaran variance yang ditangkap.
Principal Component Analysis using prcomp()
PCA dapat dilakukan menggunakan fungsi prcomp().
# buat PCA dengan prcomp(data)
pca <- prcomp(spotify_scaled)Terdapat tiga komponen utama dari fungsi prcomp():
1️⃣ pca$sdev: standar deviasi (akar variance) dari tiap
PC. Variance (eigen value) yang dirangkum oleh tiap PC
dapat dicari dengan mengkuadratkan nilai ini.
#Cek nilai eigen (variance)
pca$sdev## [1] 1.9001207 1.3076820 1.0822420 0.9999174 0.9282900 0.8699176 0.7986587
## [8] 0.6966911 0.6125288 0.5260656 0.3387878
pca$sdev^2## [1] 3.6104585 1.7100322 1.1712478 0.9998348 0.8617223 0.7567566 0.6378557
## [8] 0.4853785 0.3751915 0.2767450 0.1147772
Notes: PC1 akan secara otomatis merangkum paling banyak informasi (nilai variancenya paling besar), kemudian diikuti oleh PC2, PC3, …, dst.
2️⃣ pca$rotation: matrix rotasi, berisi eigen
vector yang akan menjadi formula untuk setiap PC, digunakan
untuk mengetahui kontribusi masing-masing variabel ke
PC.
#Cek eigen vector
pca$rotation## PC1 PC2 PC3 PC4 PC5
## popularity 0.23639321 -0.29846005 0.09943228 0.422119586 -0.4736815401
## acousticness -0.42022853 0.18772369 -0.20855119 0.006879475 0.0282681519
## danceability 0.33424065 0.06019282 -0.45070673 0.239688252 0.2376309068
## duration_ms -0.06002993 -0.03275554 0.59352497 0.418326167 0.6447009218
## energy 0.44628732 0.09692738 0.24698541 -0.097178416 0.0002462744
## instrumentalness -0.32180898 -0.18288404 0.06985215 -0.132956545 0.1569641273
## liveness 0.02965112 0.61932242 0.25373682 -0.056658396 -0.1249026942
## loudness 0.46703496 -0.02465578 0.15341481 0.011412322 -0.0633230456
## speechiness 0.02970675 0.64556159 0.02852151 0.068078940 -0.0954483000
## tempo 0.15717921 -0.14937864 0.25897753 -0.733221667 0.0571792098
## valence 0.32385768 0.07008504 -0.41173869 -0.128880686 0.4960754526
## PC6 PC7 PC8 PC9 PC10
## popularity 0.32083437 -0.42232755 0.31413684 0.24820465 0.01528871
## acousticness 0.30090066 0.04694641 0.15387384 0.26137273 -0.69955892
## danceability 0.22268142 -0.29141242 -0.18169713 -0.58512988 -0.14978489
## duration_ms 0.22709391 0.01628894 0.01447981 0.01538797 -0.01145835
## energy -0.35002606 -0.03904784 -0.11993763 0.22449855 -0.14230425
## instrumentalness -0.44386715 -0.75377712 -0.07019165 -0.01147147 -0.17749694
## liveness -0.11179760 -0.13086640 0.60551414 -0.36598616 -0.01034614
## loudness -0.15515093 0.14147365 -0.11624804 0.01293022 -0.62277521
## speechiness 0.21165146 -0.28954981 -0.51727247 0.33736400 0.15979238
## tempo 0.55013273 -0.18408344 -0.01084837 -0.08771153 -0.02238735
## valence -0.04261779 -0.09837511 0.42101780 0.47043909 0.14856079
## PC11
## popularity -0.0278823444
## acousticness -0.2640209720
## danceability -0.1878030923
## duration_ms -0.0008992083
## energy -0.7154782335
## instrumentalness 0.1184748572
## liveness 0.0451919382
## loudness 0.5549575890
## speechiness 0.1795962710
## tempo -0.0135260826
## valence 0.1607522457
Formula yang dihasilkan mirip seperti pada regresi linear, namun tanpa intercept:
PC1 = 0.236 * popularity + (-0.420) * acousticness + … + 0.323 * valence
Variabel yang memiliki kontribusi besar terhadap PC1 adalah loudness, energy, acousticness.
3️⃣ pca$x: nilai hasil proyeksi titik ke PC untuk tiap
baris (nilai data baru)
# perbandingan dengan data awal (spotify_scale) dan nilai baru di tiap PC
head(as.data.frame(spotify_scaled))## popularity acousticness danceability duration_ms energy instrumentalness
## 1 -2.261002 0.6833748 -0.8909329 -1.1413655 1.2869052 -0.48981747
## 2 -2.206026 -0.3454664 0.1919933 -0.8218657 0.6302479 -0.48981747
## 3 -2.096075 1.6445663 0.5852948 -0.5452965 -1.6699502 -0.48981747
## 4 -2.261002 0.9426992 -1.6936990 -0.6952933 -0.9297874 -0.48981747
## 5 -2.041100 1.6389288 -1.2034190 -1.2821808 -1.3131538 -0.08356631
## 6 -2.261002 1.0723614 0.1273410 -0.6263486 -1.8073548 -0.48981747
## liveness loudness speechiness tempo valence
## 1 0.66065975 1.2907007 -0.3679692 1.5956039 1.3807413
## 2 -0.32283477 0.6686811 -0.1830817 1.8232495 1.3884316
## 3 -0.56492573 -0.7184009 -0.4558311 -0.5883245 -0.3342114
## 4 -0.58762176 -0.4348159 -0.4380431 1.7505932 -0.8763826
## 5 -0.06561313 -1.9305971 -0.4051623 0.7414313 -0.2496173
## 6 -0.54475148 -0.9002886 0.1198533 -0.9769791 -0.3726633
head(as.data.frame(pca$x))## PC1 PC2 PC3 PC4 PC5 PC6 PC7
## 1 0.9904481 0.9993903 -0.1597105 -3.0962912 0.71325308 -0.74345195 1.3200974
## 2 1.2096105 0.2730414 -0.6842276 -2.7298245 1.28269932 -0.12134335 0.9083572
## 3 -2.1123978 0.3531611 -1.8668172 -0.2666744 0.70972338 0.39952609 1.4628733
## 4 -1.9545010 -0.1868432 0.2513141 -2.6613814 -0.02211554 0.60691571 1.7930776
## 5 -2.9355815 0.3915754 -1.1231315 -2.0937683 -0.02518811 0.41551544 1.1238702
## 6 -2.2612410 0.7007202 -1.7307093 -0.1446502 0.52331036 0.03778243 1.5234275
## PC8 PC9 PC10 PC11
## 1 0.4246202 0.576058781 -1.16234095 -0.04739096
## 2 -0.4478824 -0.057434104 -0.09104371 0.13059333
## 3 -0.4420655 -0.872496223 -0.59542626 0.09975048
## 4 -0.5882799 -0.041750169 -0.17564117 0.22897820
## 5 0.2555989 -0.007753993 0.30349575 -0.41629524
## 6 -0.7598055 -0.626642226 0.09946476 0.44224934
PCA untuk Dimensionality Reduction:
Kita ingin mereduksi 11 dimensi tersebut dengan mempertahankan
sebanyak mungkin informasi, Berapakah dimensi baru yaitu PC yang akan
digunakan? Hal ini dapat dilakukan dengan melihat cumulative
variance dengan fungsi summary().
summary(pca)## Importance of components:
## PC1 PC2 PC3 PC4 PC5 PC6 PC7
## Standard deviation 1.9001 1.3077 1.0822 0.99992 0.92829 0.8699 0.79866
## Proportion of Variance 0.3282 0.1555 0.1065 0.09089 0.07834 0.0688 0.05799
## Cumulative Proportion 0.3282 0.4837 0.5902 0.68105 0.75939 0.8282 0.88617
## PC8 PC9 PC10 PC11
## Standard deviation 0.69669 0.61253 0.52607 0.33879
## Proportion of Variance 0.04413 0.03411 0.02516 0.01043
## Cumulative Proportion 0.93030 0.96441 0.98957 1.00000
Keterangan:
- Standard deviation: standar deviasi yang ditangkap
oleh masing-masing PC (ekual
pca$sdev) - Proportion of Variance: informasi yang ditangkap oleh tiap PC.
- Cumulative Proportion: jumlah informasi yang ditangkap secara kumulatif dari PC1 hingga PC tersebut.
Jika ingin mempertahankan minimal 85% informasi dari data kita akan menggunakan 7 PC (PC1 sampai PC7)
# mengambil PC1 sampai PC4
pc_keep <- as.data.frame(pca$x[,1:7])Setelah dipilih PC yang merangkum informasi yang dibutuhkan, PC dapat digabung dengan data awal dan digunakan untuk analisis lebih lanjut (misalnya: supervised learning).
head(spotify_clean %>%
select_if(~!is.numeric(.)) %>% #Pilih kolom yang tipe datanya bukan numeric
cbind(pc_keep) )#Menggabungkan kolom dari pc_keep dan kolom data spotify yang bukan numeric## genre artist_name key mode time_signature PC1 PC2
## 1 Movie Henri Salvador C# Major 4/4 0.9904481 0.9993903
## 2 Movie Martin & les fées F# Minor 4/4 1.2096105 0.2730414
## 3 Movie Joseph Williams C Minor 5/4 -2.1123978 0.3531611
## 4 Movie Henri Salvador C# Major 4/4 -1.9545010 -0.1868432
## 5 Movie Fabien Nataf F Major 4/4 -2.9355815 0.3915754
## 6 Movie Henri Salvador C# Major 4/4 -2.2612410 0.7007202
## PC3 PC4 PC5 PC6 PC7
## 1 -0.1597105 -3.0962912 0.71325308 -0.74345195 1.3200974
## 2 -0.6842276 -2.7298245 1.28269932 -0.12134335 0.9083572
## 3 -1.8668172 -0.2666744 0.70972338 0.39952609 1.4628733
## 4 0.2513141 -2.6613814 -0.02211554 0.60691571 1.7930776
## 5 -1.1231315 -2.0937683 -0.02518811 0.41551544 1.1238702
## 6 -1.7307093 -0.1446502 0.52331036 0.03778243 1.5234275
Kelebihan dan kekurangan melakukan metode PCA:
- (+) Beban komputasi apabila dilakukan pemodelan relatif lebih rendah.
- (+) Bisa menjadi salah satu teknik untuk improve model, namun tidak selalu menjadi lebih baik.
- (+) Mengurangi resiko terjadinya multikolinearitas, karena nilai antar PC sudah tidak saling berkorelasi. Dibuktikan dengan tabel korelasi sebagai berikut:
library(GGally)
# korelasi sebelum PCA
ggcorr(spotify_num, label = T, hjust = 1)# korelasi setelah PCA
ggcorr(pc_keep, label = T)- (-) Model tidak dapat diinterpretasikan, karena nilai PC merupakan campuran dari beberapa variabel.
Biplot
Meskipun model tidak dapat diinterpretasikan, kita tetap dapat melihat kontribusi variabel terhadap PC dan juga korelasi antar variabel, yaitu dengan visualisasi biplot.
Parameter fungsi biplot():
x: objek hasil PCAcex: ukuran font di biplotscale: FALSE -> apabila objek hasil PCA kita sudah discaling
Sekarang kita coba melihat dengan observasi data sejumlah 100 baris (agar tidak terlalu menumpuk).
# subset 100 data pertama
library(dplyr)
spotify_100 <- spotify_num %>% head(100)
# melakukan PCA
pca_100 <- prcomp(spotify_100, scale = T)
# membuat biplot
biplot(x = pca_100,
cex = 0.6,
scale = F)Biplot menggunakan PC1 dan PC2 secara default, karena PC tersebut yang merangkum informasi terbanyak dari data sehingga mampu mewakili data kita.
observasi: index angka dari observasi. Semakin berdekatan maka karakteristiknya semakin mirip, sedangkan yang jauh dari gerombolan data dianggap sebagai outlier
loading score: panah merah yang menunjukkan kontribusi variabel tersebut terhadap PC, atau banyaknya informasi variabel tersebut yang dirangkum oleh PC.
Individual
Outlier detection: observasi yang jauh dari kumpulan observasi lainnya mengindikasikan outlier dari keseluruhan data. Observasi ini dapat ditandai untuk nantinya dicek karakteristik datanya untuk keperluan bisnis, atau apakah mempengaruhi performa model/clustering, dll.
Observasi searah panah mengindikasikan observasi tersebut nilainya tinggi pada variabel tersebut. Bila bertolak belakang, maka nilainya rendah pada variable tersebut.
Observasi berdekatan: observasi yang saling berdekatan memiliki karakteristik yang mirip.
Dari biplot di atas, tiga outlier terluar adalah observasi ke? 55, 8, 59
Variable
- Variable Contribution
#Cek Variable Factor Map
biplot(x = pca_100,
cex = 0.6,
scale = F)
Loading score dilihat dari jarak titik nol (pusat) ke ujung panah:
secara horizontal (PC1) / vertikal (PC2). Semakin panjang panah, semakin
banyak informasi yang dirangkum. Bila panah kearah negatif, maka bila
nilai variabel awal tinggi, nilai di PC akan rendah, dan sebaliknya.
Dari panah merah tersebut, kita tau variable mana yang paling banyak
berkontribusi untuk tiap PC. Namun kita kesulitan untuk mengurutkan
kontribusinya, mari kita gunakan fungsi fviz_contrib()
untuk melihat urutan kontribusi variabel ke tiap PC.
Kita ambil contoh untuk melihat kontribusi variabel di PC ke 1.
#install.packages("factoextra")
library(factoextra)
fviz_contrib(
X = pca_100, #model PCA
choice = "var", #menampilkan variable contribution
axes = 1 #mengacu pada PC ke-..
)
Note: garis putus-putus merah adalah batas nilai kontribusi yang
diharapkan apabila PC menangkap informasi dari tiap variable dengan sama
rata. Cara menghitungnya adalah 100%/jumlah variable awal. Pada kasus
ini 100/11 = 9.09%. Bila melebihi batas tersebut dapat dinilai variable
tersebut dirangkum banyak pada PC tersebut.
Variabel yang memberikan kontribusi paling besar di PC 4 secara berurutan: energy, loudness, valence, acousticness, dan seterusnya.
- Korelasi antar variabel dapat dilihat dari sudut antar panah
- Panah saling berdekatan (sudut antar panah mendekati 0 derajat), maka korelasi positif
- Panah saling tegak lurus (sudut antar panah = 90 derajat), maka tidak berkorelasi
- Panah saling bertolak belakang (sudut antar panah mendekati 180 derajat), maka korelasi negatif
Misalnya kita ingin melihat variabel yang berkorelasi dengan
popularity:
Panah yang berkorelasi positif dengan popularity:
tempo, loudness, energy,
instrumentalness. Panah yang berkorelasi negatif dengan
popularity: speechiness,
liveness, duration_ms.
Panah yang (hampir) tegak lurus (tidak punya korelasi) dengan
popularity: valence dan
accousticness
Clustering
K-means Clustering
Konsep
Clustering adalah pengelompokan data berdasarkan karakteristiknya. Clustering bertujuan untuk menghasilkan cluster dimana:
- Observasi di satu cluster yang sama yang memiliki karakteristik yang mirip
- Observasi dari cluster yang berbeda memiliki karakteristik yang berbeda
K-means Clustering K-means adalah centroid-based clustering algorithms, artinya tiap cluster memiliki satu centroid (titik pusat) yang mewakili cluster tersebut. K-means merupakan proses yang berulang dari:
- Random initialization: meletakkan \(k\) centroid secara random
- Cluster assignment: assign masing-masing observasi ke cluster terdekat, berdasarkan perhitungan jarak
- Centroid update: menggeser centroid ke rata-rata (means) dari cluster yang terbentuk
- Ulangi langkah 2 dan 3 sampai tidak ada observasi yang clusternya berubah lagi
💡 Banyaknya cluster \(k\) ditentukan oleh user.
Kita bisa melakukan K-means Clustering menggunakan fungsi
k-means().
Clustering karakteristik audio spotify
library(dplyr)
spotify_clean_pc <- spotify_clean %>%
select_if(~!is.numeric(.)) %>% #Pilih kolom yang tipe datanya bukan numeric
cbind(pc_keep) #Menggabungkan kolom dari pc_keep dan kolom data spotify yang bukan numeric
glimpse(spotify_clean_pc)## Rows: 232,725
## Columns: 12
## $ genre <fct> Movie, Movie, Movie, Movie, Movie, Movie, Movie, Movie,…
## $ artist_name <fct> "Henri Salvador", "Martin & les fées", "Joseph Williams…
## $ key <fct> C#, F#, C, C#, F, C#, C#, F#, C, G, E, C, F#, D#, G, G#…
## $ mode <fct> Major, Minor, Minor, Major, Major, Major, Major, Major,…
## $ time_signature <fct> 4/4, 4/4, 5/4, 4/4, 4/4, 4/4, 4/4, 4/4, 4/4, 4/4, 4/4, …
## $ PC1 <dbl> 0.99044808, 1.20961048, -2.11239776, -1.95450097, -2.93…
## $ PC2 <dbl> 0.999390326, 0.273041382, 0.353161149, -0.186843165, 0.…
## $ PC3 <dbl> -0.15971045, -0.68422763, -1.86681721, 0.25131406, -1.1…
## $ PC4 <dbl> -3.0962911862, -2.7298245089, -0.2666743501, -2.6613813…
## $ PC5 <dbl> 0.71325308, 1.28269932, 0.70972338, -0.02211554, -0.025…
## $ PC6 <dbl> -0.74345195, -0.12134335, 0.39952609, 0.60691571, 0.415…
## $ PC7 <dbl> 1.32009745, 0.90835720, 1.46287327, 1.79307763, 1.12387…
K-means
formula = kmeans(x, centers)
Parameter:
x: datasetcenters: banyaknya centroid \(k\)
Note: perlu dilakukan set.seed() karena terdapat random
initialization pada tahap awal k-means
RNGkind(sample.kind = "Rounding")## Warning in RNGkind(sample.kind = "Rounding"): non-uniform 'Rounding' sampler
## used
set.seed(100)
spotify_cluster <- kmeans(x = spotify_scaled,
centers = 3)Hasil k-means:
- Banyaknya observasi pada tiap cluster
# jumlah data tiap cluster
spotify_cluster$size## [1] 10347 170413 51965
- Letak pusat cluster/centroid, biasa digunakan untuk profiling cluster
# letak pusat cluster atau centroid
spotify_cluster$centers## popularity acousticness danceability duration_ms energy instrumentalness
## 1 -1.1225212 1.1835743 0.04146072 0.07412107 0.3346875 -0.4851339
## 2 0.2668908 -0.4652109 0.30807513 -0.03047521 0.3974330 -0.2755425
## 3 -0.6517258 1.2899362 -1.01855096 0.08518122 -1.3699753 1.0002059
## liveness loudness speechiness tempo valence
## 1 2.58008878 -0.4063925 4.0199624 -0.6222912 -0.1471545
## 2 -0.08061124 0.4354810 -0.1294428 0.1507078 0.2825528
## 3 -0.24937893 -1.3471891 -0.3759417 -0.3703210 -0.8972973
- Label cluster untuk tiap observasi
# hasil clustering (label cluster untuk tiap observasi)
head(spotify_cluster$cluster)## [1] 2 2 3 3 3 3
- Banyaknya pengulangan (iterasi) algoritma k-means sampai dihasilkan cluster yang stabil
# berapa kali pengulangan sampai menghasilkan kelompok yang stabil
spotify_cluster$iter## [1] 4
Goodness of Fit
Kebaikan hasil clustering dapat dilihat dari 3 nilai:
- Within Sum of Squares (
$withinss): jumlah jarak kuadrat dari tiap observasi ke centroid tiap cluster. - Between Sum of Squares (
$betweenss): jumlah jarak kuadrat terbobot dari tiap centroid ke rata-rata global. Dibobotkan berdasarkan banyaknya observasi pada cluster. - Total Sum of Squares (
$totss): jumlah jarak kuadrat dari tiap observasi ke rata-rata global.
# cek nilai wss
spotify_cluster$withinss## [1] 114723.6 1055292.7 491560.0
spotify_cluster$tot.withinss## [1] 1661576
# cek nilai bss
spotify_cluster$betweenss## [1] 898387.7
# cek nilai tss
spotify_cluster$totss## [1] 2559964
# cek rasio bss/totss
spotify_cluster$betweenss/spotify_cluster$totss## [1] 0.3509376
Clustering yang baik:
Clustering yang “baik”:
WSS semakin rendah: jarak observasi di 1 kelompok yang sama semakin rendah, artinya tiap cluster memiliki karakteristik yang semakin mirip
\(\frac{BSS}{TSS}\) mendekati 1, karena kelompok hasil clustering semakin mewakili persebaran data yang sesungguhnya
Pemilihan k (banyaknya cluster) sangat mempengaruhi performa clustering
Pemilihan banyak k akan membuat bss/tss bagus, namun tidak reprentatif karena bisa jadi ada satu cluster yang beranggotakan satu observasi sendiri (tujuan clustering tidak tercapai)
Pemilihan K Optimum
Semakin tinggi \(k\):
- WSS semakin mendekati 0
- BSS semakin mendekati TSS (atau BSS/TSS mendekati 1)
Kalau begitu apakah kita selalu memilih \(k\) = banyak observasi? Bagaimana menentukan \(k\) optimum?
- Kebutuhan dari segi bisnis, dibutuhkan menjadi berapa kelompok. Seperti yang sudah dikerjakan di atas, ditetapkan kelompok audio spotify dibagi enjadi 3 cluster.
- Secara objektif, jumlah cluster bisa ditentukan dengan Elbow method,
visualisasi dengan
fviz_nbclust()
Elbow Method
Elbow Plot merupakan plot antara banyak klaster dengan total dari simpangan/variasi per kluster (total WSS). Banyak klaster yang dipilih adalah bagian “siku” atau titik dimana terdapat penurunan yang tajam sebelum titik tersebut dan disusul penurunan yang tidak tajam setelah titik tersebut. Hal ini karena penambahan jumlah klaster tidak membawa pengaruh banyak atas variasi yang ada di dalam klaster tersebut.
library(factoextra)
#subset 300 data pertama
spotify_300 <- as.data.frame(spotify_scaled) %>% head(300)
fviz_nbclust(
x = spotify_300,
FUNcluster = kmeans,
method = "wss"
)Pilih nilai k dimana ketika k ditambah,
penurunan total within sum of squares tidak terlalu drastis
(atau dapat dikatakan sudah melandai atau bahkan mendatar).
K optimum dari data spotify adalah 6
Kontruksi kembali k-means clustering menggunakan k optimum
RNGkind(sample.kind = "Rounding")
set.seed(100)
# k-means dengan k optimum
spotify_cluster_op <- kmeans(x = spotify_scaled,
centers = 6)Interpretation: Cluster Profiling
Membuat kolom baru yang berisikan informasi label dari cluster yang terbentuk menggunakan k optimum
# membuat kolom baru berisi label cluster
df_spotify_scaled <- as.data.frame(spotify_scaled)
df_spotify_scaled$kelompok <- as.factor(spotify_cluster_op$cluster)
head(df_spotify_scaled,10)## popularity acousticness danceability duration_ms energy instrumentalness
## 1 -2.261002 0.68337483 -0.8909329 -1.14136546 1.2869052 -0.48981747
## 2 -2.206026 -0.34546644 0.1919933 -0.82186566 0.6302479 -0.48981747
## 3 -2.096075 1.64456626 0.5852948 -0.54529654 -1.6699502 -0.48981747
## 4 -2.261002 0.94269920 -1.6936990 -0.69529329 -0.9297874 -0.48981747
## 5 -2.041100 1.63892878 -1.2034190 -1.28218080 -1.3131538 -0.08356631
## 6 -2.261002 1.07236139 0.1273410 -0.62634859 -1.8073548 -0.48981747
## 7 -2.151051 -0.06922961 0.8008025 -0.19194657 -1.1423470 -0.48981747
## 8 -1.436370 1.60792260 -0.7454652 0.04157416 -1.1461427 -0.48981747
## 9 -2.261002 -1.03594578 0.9678210 -0.07501804 -0.3414529 -0.48697701
## 10 -1.711248 -0.13969819 0.2350948 -0.69304838 0.5087853 -0.48568890
## liveness loudness speechiness tempo valence kelompok
## 1 0.66065975 1.2907007 -0.3679692 1.5956039 1.3807413 1
## 2 -0.32283477 0.6686811 -0.1830817 1.8232495 1.3884316 1
## 3 -0.56492573 -0.7184009 -0.4558311 -0.5883245 -0.3342114 5
## 4 -0.58762176 -0.4348159 -0.4380431 1.7505932 -0.8763826 5
## 5 -0.06561313 -1.9305971 -0.4051623 0.7414313 -0.2496173 5
## 6 -0.54475148 -0.9002886 0.1198533 -0.9769791 -0.3726633 5
## 7 -0.55483861 -0.5176741 4.4859993 -1.1260458 0.3002442 4
## 8 -0.51449011 0.1035119 -0.4967974 -0.6744441 -0.6956589 5
## 9 -0.69858011 0.3075730 -0.4030061 0.2399248 1.1923272 1
## 10 0.67579043 0.2967364 -0.4994926 0.6417514 1.0116035 1
Grouping data based on cluster label
Melakukan grouping berdasarkan cluster yang terbentuk, untuk mengetahui karakter dari masing-masing cluster
# melakukan profiling cluster
spotify_centroid <- df_spotify_scaled %>%
group_by(kelompok) %>%
summarise_all(mean)
spotify_centroid## # A tibble: 6 × 12
## kelom…¹ popul…² acous…³ dance…⁴ durat…⁵ energy instr…⁶ liven…⁷ loudn…⁸ speec…⁹
## <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 -0.610 -0.291 0.743 -0.152 0.369 -0.110 -0.170 0.295 -0.188
## 2 2 0.882 -0.546 0.673 -0.0886 0.324 -0.399 -0.218 0.476 -0.0332
## 3 3 -0.700 1.33 -1.39 0.227 -1.52 2.03 -0.351 -1.88 -0.404
## 4 4 -1.13 1.20 0.0409 0.0752 0.342 -0.486 2.60 -0.416 4.08
## 5 5 -0.295 1.09 -0.435 -0.0422 -1.04 -0.313 -0.159 -0.545 -0.335
## 6 6 0.146 -0.753 -0.413 0.127 0.743 -0.148 0.195 0.594 -0.159
## # … with 2 more variables: tempo <dbl>, valence <dbl>, and abbreviated variable
## # names ¹kelompok, ²popularity, ³acousticness, ⁴danceability, ⁵duration_ms,
## # ⁶instrumentalness, ⁷liveness, ⁸loudness, ⁹speechiness
Kelompok 1 tinggi di karakteristik valence dan daceability.
Kelompok 2 tinggi di karakteristik popularity dan danceability.
Kelompok 3 tinggi di karakteristik instrumentalness dan loudness.
Kelompok 4 tinggi di karakteristik speechiness dan liveness.
Kelompok 5 tinggi di karakteristik energy dan acousticness.
Kelompok 6 tinggi di karakteristik tempo dan energy.
Karakteristik tiap cluster ada yang beririsan karakteristiknya. Jadi ada kemungkinan karakterisk audio spotify ini memang ada kecenderungan mirip-mirip.
Visualisasi dengan CLuster Plot:
fviz_cluster(object = spotify_cluster_op, # object kmeans
data = spotify_scaled)Cek kembali goodness of fit: nilai wss, bss dan tss.
# cek nilai wss
spotify_cluster_op$withinss## [1] 216871.1 248197.1 236492.7 108143.5 214272.5 311159.4
spotify_cluster_op$tot.withinss## [1] 1335136
# cek nilai bss
spotify_cluster_op$betweenss## [1] 1224828
# cek nilai tss
spotify_cluster_op$totss## [1] 2559964
# cek rasio bss/totss
spotify_cluster_op$betweenss/spotify_cluster_op$totss## [1] 0.4784551
Setelah menggunakan k optimum:
nilai wss semakin kecil, dari awalnya 1,661,576 menjadi 1,335,136. Semakin nilai wss kecil, semakin menunjukkan karakteristik di sebuah cluster semakin mirip/seragam.
rasio BSS/TSS naik menjadi 0.478 namun masih jauh dari ideal. Nilai rasio BSS/TSS yang diharapkan adalah mendekati 1 yang menunjukkan bahwa pengelompokan/clustering sudah mewakili persebaran data yang sesungguhnya.
Maka mungkin perlu dicoba tuning kembali dengan parameter jumlah clusternya.