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”.
suppressMessages(library(tidyverse))
suppressMessages(library(lubridate))
suppressMessages(library(DT))
suppressMessages(library(ggplot2))
suppressMessages(library(cluster))
suppressMessages(library(factoextra))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 :
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…
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.
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.
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.
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
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
# 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.