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

  1. Membuang kolom yang tidak relevan untuk dianalisa: track_id, track_name
  2. 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 PCA
  • cex: ukuran font di biplot
  • scale : 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

  1. 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.

  2. Observasi searah panah mengindikasikan observasi tersebut nilainya tinggi pada variabel tersebut. Bila bertolak belakang, maka nilainya rendah pada variable tersebut.

  3. Observasi berdekatan: observasi yang saling berdekatan memiliki karakteristik yang mirip.

Dari biplot di atas, tiga outlier terluar adalah observasi ke? 55, 8, 59

Variable

  1. 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.

  1. 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:

  1. Random initialization: meletakkan \(k\) centroid secara random
  2. Cluster assignment: assign masing-masing observasi ke cluster terdekat, berdasarkan perhitungan jarak
  3. Centroid update: menggeser centroid ke rata-rata (means) dari cluster yang terbentuk
  4. 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: dataset
  • centers: 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:

  1. Banyaknya observasi pada tiap cluster
# jumlah data tiap cluster
spotify_cluster$size
## [1]  10347 170413  51965
  1. 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
  1. Label cluster untuk tiap observasi
# hasil clustering (label cluster untuk tiap observasi)
head(spotify_cluster$cluster)
## [1] 2 2 3 3 3 3
  1. 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.