Spotify adalah salah satu platform streaming musik digital yang berbasis di Swedia. Spotify memungkinkan pengguna untuk memutar musik secara online dan juga menawarkan layanan download musik. Pengguna dapat mengakses koleksi lagu Spotify dari berbagai genre musik dan album dari seluruh dunia, baik yang dirilis oleh perusahaan rekaman besar maupun yang independen. Selain itu, Spotify juga menawarkan layanan podcast dan buku audio yang dapat diakses oleh pengguna dari berbagai negara. Spotify tersedia dalam berbagai platform seperti desktop, web, dan aplikasi mobile untuk iOS dan Android. Spotify menawarkan dua jenis akun pengguna, yaitu akun gratis dengan iklan dan akun berbayar tanpa iklan yang disebut sebagai “Spotify Premium”.

1 Welcome to Anthony’s Unsupervised

1.1 Paket R “Unsupervised”

suppressMessages(library(tidyverse))
suppressMessages(library(lubridate))
suppressMessages(library(DT))
suppressMessages(library(ggplot2))
suppressMessages(library(cluster))
suppressMessages(library(factoextra))

1.2 INFO DATA

Dataset bersumber dari www.Kaggle.com, untuk data lainnya dapat diakses melalui Web-API spotify. Data spotify yang akan diolah memiliki baris : 232,725 dengan 18 kolom antara lain :

  • genre : Nama genre musik
  • artist_name : Nama artis
  • track_name : Nama track lagu
  • track_id : Id track lagu
  • popularity : Nilai popularitas berkisar antara 0 hingga 100, semakin tinggi nilai populatitas, maka semakin populer pula lagu tersebut. Popularity score dihitung dari beberapa faktor seperti jumlah pendengar, jumlah pemutaran, dan interaksi pengguna lainnya dengan lagu tersebut di Spotify.
  • acousticness : Nilai Akustik memiliki rentang nilai antara 0.0 hingga 1.0, di mana semakin tinggi nilainya, semakin besar andil instrumen akustik dalam rekaman.
  • danceability : Nilai keinginan menari dinormalisasi antara 0 dan 1 yang mengukur seberapa mudah lagu tersebut untuk diberi tarian. Fitur ini mempertimbangkan beberapa elemen musik seperti tempo, stabilitas ritmis, kekuatan taktil, dan kesederhanaan. Semakin tinggi nilai danceability, semakin mudah lagu tersebut untuk diberi tarian.
  • duration_ms : durasi lagu dalam milidetik (ms). Durasi lagu adalah waktu total lagu dari awal hingga akhir dalam bentuk bilangan bulat.
  • energy : Nilai tingkat energi dalam lagu dengan skala 0 hingga 1. Semakin tinggi nilai variabel “energy”, semakin tinggi tingkat energi dalam lagu.
  • instrumentalness : Nilai instrumen semakin mendekati 1 semakin banyak instrumen di dalam musik apabila mendekati 0 maka lagu lebih banyak unsur vokal, range nilai dari 0 (unsur vokal) hingga 1 (unsur instrumen).
  • key : kunci nada pada alat music seperi C, C#, D, D#,G, G#, dan lainnya.
  • liveness : Nilai keaslian suara lagi, Nilai mendekati 0 menunjukkan kemungkinan besar rekaman berasal dari studio atau berasal dari rekaman yang sudah diolah secara digital, sedangkan nilai mendekati 1 menunjukkan kemungkinan besar rekaman tersebut diambil secara langsung dari konser atau penampilan live music.
  • loudness : Pengukuran tingkat kebisingan audio dalam lagu, diukur dalam desibel (dB). Semakin besar nilai dB, semakin keras kebisingan lagu yang merupakan besaran frequensi suara yang mengganggu kejernihan lagu.
  • mode : Mode mayor (mode = 1) atau mode minor (mode = 0). Mode adalah istilah dalam teori musik yang mengacu pada kumpulan nada atau skala nada yang digunakan dalam sebuah lagu.
  • speechiness : Nilai bervariasi dari 0 hingga 1, nilai yang lebih tinggi menunjukkan bahwa lagu tersebut memiliki lebih banyak vokal. Nilai yang rendah menunjukkan bahwa lagu tersebut lebih banyak instrumental atau memiliki lebih sedikit vokal.
  • tempo :Nilai tempo dari lagu dalam satuan bpm (beats per minute), yaitu kecepatan atau tempo yang digunakan pada lagu. Semakin tinggi nilainya, semakin cepat tempo dari lagu tersebut.
  • time_signature :Nilai jumlah ketukan dalam satu bar atau dalam satu siklus irama lagu. Contohnya, dalam sebuah lagu dengan time signature 4/4, setiap bar terdiri dari 4 ketukan atau tekanan. umumnya digunakan oleh musisi dan produser untuk mengatur ritme lagu dan menentukan bagaimana komponen lagu akan diatur dalam seluruh lagu.
  • valence : Nilai yang mempengaruhi suasana hati, range nilai dari 0 (sangat negatif/sedih) hingga 1 (sangat positif/bahagia).

Berikut ini adalah sample dari 100 data teratas berdasarkan data utama :

Tipe data spotify :

glimpse(spotify1)
#> Rows: 232,725
#> Columns: 18
#> $ genre            <chr> "Movie", "Movie", "Movie", "Movie", "Movie", "Movie",…
#> $ artist_name      <chr> "Henri Salvador", "Martin & les fées", "Joseph Willia…
#> $ track_name       <chr> "C'est beau de faire un Show", "Perdu d'avance (par G…
#> $ track_id         <chr> "0BRjO6ga9RKCKjfDqeFgWV", "0BjC1NfoEOOusryehmNudP", "…
#> $ 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              <chr> "C#", "F#", "C", "C#", "F", "C#", "C#", "F#", "C", "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             <chr> "Major", "Minor", "Minor", "Major", "Major", "Major",…
#> $ 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   <chr> "4/4", "4/4", "5/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…

1.3 APA ITU UNSUPERVISED ?

Unsupervised learning adalah salah satu jenis pembelajaran mesin di mana model tidak diberikan label atau target output tertentu. Sebaliknya, model harus mengenali pola atau struktur yang tersembunyi dalam data untuk mengidentifikasi kategori atau kelompok yang berbeda. Dalam unsupervised learning, tujuan utama adalah menemukan hubungan dan struktur data yang tersembunyi, sehingga dapat digunakan untuk mengambil keputusan atau membuat prediksi di masa depan. Algoritma clustering dan reduksi dimensi adalah contoh dari metode unsupervised learning.

1.4 Bagaimana cata kerjanya ?

Pada dasarnya, dalam unsupervised learning, komputer mencoba menemukan pola dalam data tanpa dipandu oleh label atau informasi eksternal. Oleh karena itu, algoritma unsupervised harus mampu mengenali pola, struktur, atau kelompok-kelompok yang muncul dalam data tersebut tanpa disediakan informasi tambahan.

Untuk melakukan tugas ini, algoritma unsupervised umumnya melakukan pengelompokan (clustering) atau reduksi dimensi (dimensionality reduction) dari data. Dalam pengelompokan, data dikelompokkan ke dalam kelompok-kelompok (clusters) berdasarkan kesamaan karakteristik. Sementara dalam reduksi dimensi, data diubah menjadi representasi yang lebih sederhana dengan tetap mempertahankan fitur penting dari data asli.

Dalam kedua kasus tersebut, algoritma unsupervised mencoba menemukan pola dan struktur dalam data yang mungkin tidak dapat dilihat dengan mudah oleh manusia. Kemudian, hasil dari pengelompokan atau reduksi dimensi dapat digunakan untuk analisis lebih lanjut, seperti visualisasi atau pemodelan.

2 PERSIAPAN DATA

spotify <-  read.csv("Asuperv/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

Check Tipe Data untuk proses penyesuaian dan eksplorasi :

glimpse(spotify)
#> Rows: 232,725
#> Columns: 18
#> $ genre            <chr> "Movie", "Movie", "Movie", "Movie", "Movie", "Movie",…
#> $ artist_name      <chr> "Henri Salvador", "Martin & les fées", "Joseph Willia…
#> $ track_name       <chr> "C'est beau de faire un Show", "Perdu d'avance (par G…
#> $ track_id         <chr> "0BRjO6ga9RKCKjfDqeFgWV", "0BjC1NfoEOOusryehmNudP", "…
#> $ 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              <chr> "C#", "F#", "C", "C#", "F", "C#", "C#", "F#", "C", "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             <chr> "Major", "Minor", "Minor", "Major", "Major", "Major",…
#> $ 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   <chr> "4/4", "4/4", "5/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…

Pastikan paket (library R) sudah terinstall sesuai dengan kebutuhan project.

2.1 CEK DATA HILANG

colSums(is.na(spotify))
#>            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

2.2 EKSPLORASI DATA

spotify <- spotify %>% select(-c(genre, artist_name, track_name, track_id))
# mengubah kolom time_signature menjadi numerik
spotify$time_signature <- as.numeric(eval(parse(text=gsub('/', '/', spotify$time_signature))))
head(spotify)
#>   popularity acousticness danceability duration_ms energy instrumentalness key
#> 1          0        0.611        0.389       99373 0.9100            0.000  C#
#> 2          1        0.246        0.590      137373 0.7370            0.000  F#
#> 3          3        0.952        0.663      170267 0.1310            0.000   C
#> 4          0        0.703        0.240      152427 0.3260            0.000  C#
#> 5          4        0.950        0.331       82625 0.2250            0.123   F
#> 6          0        0.749        0.578      160627 0.0948            0.000  C#
#>   liveness loudness  mode speechiness   tempo time_signature valence
#> 1   0.3460   -1.828 Major      0.0525 166.969              1   0.814
#> 2   0.1510   -5.559 Minor      0.0868 174.003              1   0.816
#> 3   0.1030  -13.879 Minor      0.0362  99.488              1   0.368
#> 4   0.0985  -12.178 Major      0.0395 171.758              1   0.227
#> 5   0.2020  -21.150 Major      0.0456 140.576              1   0.390
#> 6   0.1070  -14.970 Major      0.1430  87.479              1   0.358

Setelah melakukan konversi kolom time_signature , Anda dapat melanjutkan menjalankan kode untuk clustering.

# Prepare data
spotifyc <- spotify %>% select (c("popularity", "acousticness", "danceability", "duration_ms", "energy", "instrumentalness", "liveness", "loudness", "speechiness", "tempo", "valence"))
colSums(is.na(spotifyc))
#>       popularity     acousticness     danceability      duration_ms 
#>                0                0                0                0 
#>           energy instrumentalness         liveness         loudness 
#>                0                0                0                0 
#>      speechiness            tempo          valence 
#>                0                0                0

3 Clustering

3.1 Metode ELBOW

# Determine the optimal number of clusters using elbow method
ras <- (nrow(spotifyc)-1) * sum(apply(spotifyc, 2, var))
for (i in 2:10) ras[i] <- sum(kmeans(spotifyc, centers=i)$withinss)
  plot(1:10, ras, type="b", xlab="Jumlah Cluster", ylab="Kelompok Jumlah Kuadrat", main = "Plot Metode Elbow")

# standarkan dataset
spotifyc_std <- scale(spotifyc)
# membuat plot elbow
wss <- c()
for(i in 1:10){
  kmeans_model <- kmeans(spotifyc_std, centers=i, nstart=10)
  wss[i] <- kmeans_model$tot.withinss
}

plot(1:10, wss, type="b", xlab="Number of clusters (k)", ylab="Total within-clusters sum of squares (WSS)")

Dari hasil plot elbow, kita bisa melihat bahwa ada elbow di k = 4, yang menandakan bahwa k = 4 adalah jumlah klaster yang optimal untuk dataset kita.

Membuat Model K-Means Clustering Setelah menentukan jumlah klaster yang optimal, selanjutnya kita membuat model k-means clustering menggunakan fungsi kmeans().

# membuat model k-means clustering
kmeans_model <- kmeans(spotifyc_std, centers=4, nstart=10)

Analisis Hasil Model - Setelah membuat model k-means clustering, kita dapat menganalisis hasilnya dengan melihat klasterisasi yang dihasilkan dan karakteristik musik dari setiap klaster.

# menambahkan informasi klaster ke dataset
spotifyc$cluster <- as.factor(kmeans_model$cluster)

# melihat jumlah observasi di setiap klaster
table(spotifyc$cluster)
#> 
#>      1      2      3      4 
#>  32610 131837  58052  10226
ggplot(spotifyc, aes(x=acousticness, y=energy, color=cluster)) + 
  geom_point(alpha=0.6) +
  labs(title="K-Means Clustering of Spotify Songs", x="Acousticness", y="Energy")

Dari visualisasi klasterisasi di atas, kita bisa melihat bahwa lagu-lagu tercluster menjadi 4 kelompok berbeda berdasarkan karakteristik musik mereka. Selanjutnya, kita dapat menganalisis karakteristik musik dari setiap klaster dengan melihat nilai rata-rata dari setiap variabel dalam setiap klaster.

# melihat rata-rata karakteristik musik dalam setiap klaster
aggregate(spotifyc[,-12], by=list(cluster=spotifyc$cluster), FUN=mean)
#>   cluster popularity acousticness danceability duration_ms    energy
#> 1       1   26.06201    0.8603983    0.2924477    257755.3 0.1636982
#> 2       2   46.86402    0.1195544    0.6144489    232056.5 0.7408002
#> 3       3   40.15571    0.5835412    0.5637639    227849.6 0.3980758
#> 4       4   20.73000    0.7899686    0.5616100    243759.5 0.6614463
#>   instrumentalness  liveness   loudness speechiness     tempo   valence
#> 1      0.624383841 0.1608299 -20.478722  0.04847878 102.62538 0.1566394
#> 2      0.063525815 0.2091872  -6.155886  0.10186225 124.63398 0.5530565
#> 3      0.099265981 0.1680953 -10.764159  0.07195485 113.70376 0.4067052
#> 4      0.001428316 0.7291698 -12.017005  0.87207208  98.30254 0.4145462

Dari hasil analisis di atas, kita bisa melihat bahwa:

Klaster 1 (warna biru) memiliki nilai acousticness yang tinggi dan nilai energy yang rendah, sehingga dapat dianggap sebagai lagu-lagu yang lebih santai dan akustik. Klaster 2 (warna hijau) memiliki nilai danceability dan energy yang tinggi, sehingga dapat dianggap sebagai lagu-lagu yang lebih upbeat dan dansa. Klaster 3 (warna merah) memiliki nilai instrumentalness yang tinggi dan nilai liveness yang rendah, sehingga dapat dianggap sebagai lagu-lagu instrumental atau musik latar belakang. Klaster 4 (warna ungu) memiliki nilai loudness dan energy yang tinggi, sehingga dapat dianggap sebagai lagu-lagu yang lebih keras dan energetik. Dengan menganalisis karakteristik musik dalam setiap klaster, kita dapat mengambil insight yang berguna untuk industri musik, seperti jenis lagu apa yang paling populer atau mana karakteristik musik yang paling menarik bagi pendengar.

Dari hasil ini, dapat dilihat bahwa elbow method digunakan untuk menentukan jumlah cluster yang optimal untuk k-means clustering. Dalam kasus ini, grafik menunjukkan bahwa jumlah cluster yang optimal adalah sekitar 4 karena setelah jumlah cluster ini, penurunan dalam within groups sum of squares mulai menurun secara bertahap.

Setelah jumlah cluster optimal ditentukan, k-means clustering diterapkan pada data dengan menggunakan jumlah cluster tersebut. Hasilnya adalah cluster assignments untuk setiap observasi dalam data.

# Terapkan k-means clustering dengan jumlah cluster yang optimal
k <- 4 # Ubah ini ke jumlah cluster yang ingin Anda gunakan
set.seed(20)
model <- kmeans(spotifyc, centers = k)

Dari output yang diberikan, kita bisa lihat bahwa data terbagi menjadi empat kelompok (clusters). Kelompok pertama memiliki jumlah data terbanyak dengan ukuran 129,566 dan cluster ke-3 merupakan kelompok dengan jumlah data terkecil dengan ukuran 115. Setiap kelompok memiliki rata-rata fitur lagu yang berbeda.

Cluster 1 memiliki rata-rata:

Popularity: 40.69268 Acousticness: 0.3802910 Danceability: 0.5705717 Duration_ms: 176472.5 Energy: 0.5711263 Instrumentalness: 0.1361338 Liveness: 0.2135926 Loudness: -9.542015 Speechiness: 0.1296443 Tempo: 117.8519 Valence: 0.4874573 Cluster 2 memiliki rata-rata:

Popularity: 32.12592 Acousticness: 0.5861549 Danceability: 0.4058451 Duration_ms: 562663.7 Energy: 0.4184123 Instrumentalness: 0.3812524 Liveness: 0.2691024 Loudness: -14.387389 Speechiness: 0.1474051 Tempo: 110.6541 Valence: 0.2762702 Cluster 3 memiliki rata-rata:

Popularity: 19.12174 Acousticness: 0.7057021 Danceability: 0.5084670 Duration_ms: 3001668.3 Energy: 0.4586758 Instrumentalness: 0.1608238 Liveness: 0.3628626 Loudness: -13.732765 Speechiness: 0.5578791 Tempo: 92.3562 Valence: 0.4440817 Cluster 4 memiliki rata-rata:

Popularity: 42.61470 Acousticness: 0.3311685 Danceability: 0.5463020 Duration_ms: 281202.5 Energy: 0.5854576 Instrumentalness: 0.1427608 Liveness: 0.2116047 Loudness: -9.142269 Speechiness: 0.1054488 Tempo: 118.1132 Valence: 0.4271918 Output selanjutnya adalah clustering vector, yaitu sebuah vektor berisi angka yang menunjukkan ke kelompok mana setiap data pada dataset telah diklasifikasikan. Contohnya, data pertama pada dataset termasuk ke dalam kelompok 1, data kedua pada dataset termasuk ke dalam kelompok 1, dan seterusnya.

# Dapatkan tugas cluster untuk setiap observasi
cluster <- model$cluster

# Tambahkan penetapan cluster ke kumpulan data asli
spotifyc$cluster <- as.factor(cluster)

# Visualisasikan cluster menggunakan scatter plot
library(ggplot2)
ggplot(spotifyc, aes(x = acousticness, y = energy, color = cluster)) +
  geom_point(size = 2) +
  labs(title = "Clusters of Songs by Acousticness and Energy") +
  theme(plot.title = element_text(hjust = 0.5))

Pada scater plot diatas digunakan untuk memvisualisasikan cluster-cluster pada data lagu di Spotify berdasarkan atribut akustik dan energi. Scatter plot menunjukkan bahwa cluster-cluster tersebut berbeda dalam distribusi akustik dan energi, sehingga dapat membantu dalam analisis data lebih lanjut dan pemahaman karakteristik musik di setiap cluster. Selain itu, plot ini juga membantu dalam mengidentifikasi adanya pola atau tren dalam data yang dapat menjadi fokus penelitian lebih lanjut.


Apabila anda tertarik untuk sharing terkait Data Science & AI (Artificial Intelligence) dapat menghubungi saya di Linkedin Anthony & silahkan kunjungi Github Anthony untuk melihat project lainnya.