Dataset yang digunakan dalam pemodelan machine learning unsupervised ini diambil dari Wine Data Set https://archive.ics.uci.edu/ml/datasets/wine dengan menghilangkan informasi tentang tipe wine.
Data ini adalah hasil dari analisis kimia dari wine yang tumbuh di suatu daerah yang di Italia, tapi berasal dari 3 kelompok tumbuhan yang berbeda, analisis ditentukan dari 13 konstituen yang ditemukan di masing-masing dari tiga jenis anggur.
Attributnya adalah :
Set up chunk di awal untuk mengatur format chunk pada markdown
options(scipen = 9999)
rm(list=ls())
Setup library yang akan digunakan
library(tidyverse)
library(lubridate)
library(cluster)
library(factoextra)
library(GGally)
library(scales)
library(cowplot)
library(FactoMineR)
library(factoextra)
library(plotly)
library(gridExtra)
wine <- read.csv("wine-clustering.csv")
head(wine)
Karena kolom type merupakan jenis dari wine dan berupa kategorikal, maka diubah type datanya
wine <- wine %>%
mutate(type = as.factor(type))
glimpse(wine)
## Rows: 178
## Columns: 14
## $ type <fct> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1~
## $ Alcohol <dbl> 14.23, 13.20, 13.16, 14.37, 13.24, 14.20, 14.39, ~
## $ Malic_Acid <dbl> 1.71, 1.78, 2.36, 1.95, 2.59, 1.76, 1.87, 2.15, 1~
## $ Ash <dbl> 2.43, 2.14, 2.67, 2.50, 2.87, 2.45, 2.45, 2.61, 2~
## $ Ash_Alcanity <dbl> 15.6, 11.2, 18.6, 16.8, 21.0, 15.2, 14.6, 17.6, 1~
## $ Magnesium <int> 127, 100, 101, 113, 118, 112, 96, 121, 97, 98, 10~
## $ Total_Phenols <dbl> 2.80, 2.65, 2.80, 3.85, 2.80, 3.27, 2.50, 2.60, 2~
## $ Flavanoids <dbl> 3.06, 2.76, 3.24, 3.49, 2.69, 3.39, 2.52, 2.51, 2~
## $ Nonflavanoid_Phenols <dbl> 0.28, 0.26, 0.30, 0.24, 0.39, 0.34, 0.30, 0.31, 0~
## $ Proanthocyanins <dbl> 2.29, 1.28, 2.81, 2.18, 1.82, 1.97, 1.98, 1.25, 1~
## $ Color_Intensity <dbl> 5.64, 4.38, 5.68, 7.80, 4.32, 6.75, 5.25, 5.05, 5~
## $ Hue <dbl> 1.04, 1.05, 1.03, 0.86, 1.04, 1.05, 1.02, 1.06, 1~
## $ OD280 <dbl> 3.92, 3.40, 3.17, 3.45, 2.93, 2.85, 3.58, 3.58, 2~
## $ Proline <int> 1065, 1050, 1185, 1480, 735, 1450, 1290, 1295, 10~
anyNA(wine)
## [1] FALSE
Dari hasil diatas didapat bahwa data memiliki 178 baris data dan 14 kolom, dan data tidak memiliki missing value
Kita akan coba visualisasikan data berdasarkan kadar alkohol dan jumlah magnesium.
ggplot(wine, aes(Alcohol, Magnesium, color = type, size=Color_Intensity)) +
geom_point(alpha = 0.5) + theme_minimal()
Pada plot diatas terlihat bahwa tiap type saling berkelompok berdasarkan type nya jika di plot berdasarkan kadar alkoholnya dimana type 1 lebih tinggi kadar alkoholnya dengan tingkatan 2<3<1.
Lalu kita cek beberapa atribut lain diantara type type wine.
p1 <- ggplot(wine, aes(type, Alcohol, fill = type)) + geom_boxplot(show.legend = F) +
theme_minimal() + labs(title = "Alcohol")
p2 <- ggplot(wine, aes(type, Magnesium, fill = type)) + geom_boxplot(show.legend = F) +
theme_minimal() + labs(title = "Magnesium")
p3 <- ggplot(wine, aes(type, Ash, fill = type)) + geom_boxplot(show.legend = F) +
theme_minimal() + labs(title = "Ash")
p4 <- ggplot(wine, aes(type, Total_Phenols, fill = type)) + geom_boxplot() +
theme_minimal() + theme(legend.position = "bottom") + labs(title = "Total Phenols")
plot_grid(p1, p2, p3, p4)
Pada plot diatas terlihat wine type 1 memiliki kandungan lebih banyak di tiap attributnya dibanding type lain. Dari exploratory diatas, dapat disimpulkan kita bisa melakukan clustering terhadap data wine berdasarkan atribut-atributnya. Untuk mendapatkan pola-pola tersembunyi dari data, kita lakukan clustering dengan k-means.
Kita akan cek apakah ada high correlation antara variabel numerik. Korelasi yang kuat dapat menandakan bahwa kita bisa mengurangi dimensi data menggunakan PCA.
ggcorr(wine)
## Warning in ggcorr(wine): data in column(s) 'type' are not numeric and were
## ignored
Terdapat korelasi yang kuat antara Total_Phenols dengan Flavanoids, Flavanoids dengan OD280, dll. Menandakan bahwa dimensi masih bisa dikurangi lagi menggunakan PCA.
Sebelum melakukan clustering, lakukan scale untuk menyamakan skala data
z_wine <- scale(wine %>% select(-type))
Untuk menentukan berapa K yang diperlukan dalam pemodelan, kita akan gunakan elbow method dimana kita memilih cluster area di area siku.
fviz_nbclust(z_wine, kmeans, method = "wss") + labs(subtitle = "Elbow method")
Dari hasil elbow method, ditentukan K = 3, karena dari 3 ke 4 tidak terjadi penurunan yang signifikan.
Selain elbow method, kita juga bisa menggunakan Gap Statistic untuk menentukan K yang tepat. Metode ini membandingkan total dalam variasi intra-cluster untuk nilai k yang berbeda dengan nilai yang diharapkan di bawah distribusi nol dari data. K cluster yang optimal akan menjadi nilai yang memaksimalkan Gap Statistic
fviz_nbclust(z_wine, kmeans, "gap_stat") + labs(subtitle = "Gap Statistic method")
Dari hasil Gap Statistic ditentukan K optimal adalah 3.
Silhouette Method mengukur koefisien siluet, dengan menghitung rata-rata jarak intra-cluster dan rata-rata jarak cluster terdekat untuk setiap observasi, jumlah k didapatkan dengan memilih nilai siluet tertinggi.
fviz_nbclust(z_wine, kmeans, "silhouette") + labs(subtitle = "Silhouette method")
Dari hasil Silhouette Method ditentukan K=3
Dari hasil diatas, 3 dari 3 metode menentukan K Optimal adalah 3, maka kita tentukan K = 3. Maka selanjutnya kita lakukan clustering.
# k-means clustering
set.seed(13)
model_wine <- kmeans(z_wine, 3)
# result analysis
model_wine
## K-means clustering with 3 clusters of sizes 62, 51, 65
##
## Cluster means:
## Alcohol Malic_Acid Ash Ash_Alcanity Magnesium Total_Phenols
## 1 0.8328826 -0.3029551 0.3636801 -0.6084749 0.57596208 0.88274724
## 2 0.1644436 0.8690954 0.1863726 0.5228924 -0.07526047 -0.97657548
## 3 -0.9234669 -0.3929331 -0.4931257 0.1701220 -0.49032869 -0.07576891
## Flavanoids Nonflavanoid_Phenols Proanthocyanins Color_Intensity Hue
## 1 0.97506900 -0.56050853 0.57865427 0.1705823 0.4726504
## 2 -1.21182921 0.72402116 -0.77751312 0.9388902 -1.1615122
## 3 0.02075402 -0.03343924 0.05810161 -0.8993770 0.4605046
## OD280 Proline
## 1 0.7770551 1.1220202
## 2 -1.2887761 -0.4059428
## 3 0.2700025 -0.7517257
##
## Clustering vector:
## [1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## [38] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 2 3 3 3 3 3 3 3 3 3 3 3 1
## [75] 3 3 3 3 3 3 3 3 3 2 3 3 3 3 3 3 3 3 3 3 3 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
## [112] 3 3 3 3 3 3 3 2 3 3 1 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
## [149] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
##
## Within cluster sum of squares by cluster:
## [1] 385.6983 326.3537 558.6971
## (between_SS / total_SS = 44.8 %)
##
## Available components:
##
## [1] "cluster" "centers" "totss" "withinss" "tot.withinss"
## [6] "betweenss" "size" "iter" "ifault"
Kita akan coba bandingkan data awal dengan data hasil clustering
wine$type
## [1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## [38] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
## [75] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
## [112] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
## [149] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
## Levels: 1 2 3
model_wine$cluster
## [1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## [38] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 2 3 3 3 3 3 3 3 3 3 3 3 1
## [75] 3 3 3 3 3 3 3 3 3 2 3 3 3 3 3 3 3 3 3 3 3 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
## [112] 3 3 3 3 3 3 3 2 3 3 1 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
## [149] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
(6/178)*100 # percentage of miss-class from the data
## [1] 3.370787
Terdapat 6 atau 3.37% data yang di clusterkan di kelas yang tidak seharusnya.
# additional information
model_wine$tot.withinss # total within sum of squares
## [1] 1270.749
model_wine$betweenss # between sum of squares
## [1] 1030.251
model_wine$totss # total sum of squares
## [1] 2301
model_wine$iter # number of iteration needed to obtain optimum clustering
## [1] 4
Kita akan coba masukkan data cluster ke data awal dan coba lakukan cluster profiling
# melakukan profiling dengan summarise data
wine_profile <- wine %>%
mutate(type = as.factor(model_wine$cluster)) %>%
group_by(type) %>%
summarise_all(.funs = "mean")
wine_profile
Profiling :
- Cluster 1 : Memiliki kadar alcohol rendah dan warna tidak terlalu pekat
- Cluster 2 : Memiliki kadar alkohol, magnesium, Flavanoids, Ash, Proanthocyanins, dan OD280 paling tinggi, Ash Alcanity rendah
- Cluster 3 : Memiliki Malic Acid, Ash, Ash Alcanity, Nonflavanoid tinggi, berwarna paling pekat, dan Flavanoids yang rendah
Dan apabila di visualisasikan clusternya, dengan fungsi fviz_cluster akan menjadi
fviz_cluster(object = model_wine,
data = wine %>% select(-type))
wine_pca <- PCA(wine %>% select(-type) ,
graph = F)
fviz_eig(wine_pca, ncp = 13, addlabels = T, main = "Variance explained by each dimensions")
Pada proses PCA, kita dapat mempertahankan beberapa komponen utama yang informatif dari dataset untuk melakukan pengurangan dimensi. Dengan melakukan PCA, kita dapat mengurangi dimensi sekaligus menyimpan informasi sebanyak mungkin.
Kali ini, kita akan menyimpan setidaknya 90% informasi dari data. Dari ringkasan PCA (wine_pca$eig), kita pilih PC1-PC8 dari total 13 PC. Dengan melakukan ini, kita dapat mengurangi ~30% dimensi dari data asli kita sambil mempertahankan 92% informasi dari data.
Kita ekstrak data dari PC1-8 lalu dimasukkan ke data frame baru. Yang mana data frame ini dapat digunakan untuk analisis menggunakan supervised learning atau tujuan lain.
wine_x <- PCA(wine[,2:14], graph = F, ncp = 8)$ind$coord
wine_x <- cbind(wine_x, type = wine$type) %>% as.data.frame()
head(wine_x)
Lalu kita coba visualisasi kan data pca dengan hasil cluster
wine_xc <- cbind(wine_x, cluster = model_wine$cluster)
plot_ly(wine_xc, x = ~Dim.1, y = ~Dim.2, z = ~Dim.3, color = ~cluster, colors = c("black",
"red", "green", "blue")) %>% add_markers() %>% layout(scene = list(xaxis = list(title = "Dim.1"),
yaxis = list(title = "Dim.2"), zaxis = list(title = "Dim.3")))
Dari hasil unsupervised learning diatas, dapat disimpulkan bahwa :
- K-means clustering bisa dilakukan dengan dataset wine ini. Dataset dipecah menjadi 3 Cluster dan hanya 3,4% data yang salah prediksi.
- Pengurangan dimensi dapat dilakukan dengan dataset ini. Dari 13 PC yang ada, bisa diambil 7 PC saja dengan tetap mempertahan 92% informasi.
- Cluster 2 memiliki profiling kandungan yang cenderung lebih tinggi dibanding yang lain.