1 Support Vector Machine

1.1 Teori

Support Vector Machine (SVM) adalah algoritma supervised learning yang digunakan untuk klasifikasi data dengan mencari hyperplane optimal yang memisahkan kelas-kelas berbeda dengan margin maksimal. SVM pertama kali diperkenalkan oleh Vladimir Vapnik dan timnya pada awal 1990-an. SVM bekerja dengan memaksimalkan jarak antara hyperplane dan titik-titik data terdekat dari masing-masing kelas, yang dikenal sebagai support vectors, karena titik-titik tersebut menentukan posisi dan orientasi bidang pemisah dalam ruang fitur berdimensi-N.

1.2 Eksplorasi Data

Dataset Palmer Penguin berisi data morfologi dari tiga spesies penguin yang berbeda, yaitu Adelie, Gentoo, dan Chinstrap yang diamati di Pulau Biscoe, Dream, dan Torgersen. Dataset ini mencakup ukuran fisik seperti panjang paruh (bill length), kedalaman paruh (bill depth), panjang sirip, dan berat tubuh. Data ini dikumpulkan dari tahun 2007 - 2009 oleh Dr. Kristen Gorman dengan Palmer Station Long Term Ecological Research Program, bagian dari US Long Term Ecological Research Network. Data tersebut diimpor langsung dari Portal Data Environmental Data Initiative (EDI).

1.2.1 Data

data(penguins)
head(penguins)
## # A tibble: 6 × 8
##   species island    bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
##   <fct>   <fct>              <dbl>         <dbl>             <int>       <int>
## 1 Adelie  Torgersen           39.1          18.7               181        3750
## 2 Adelie  Torgersen           39.5          17.4               186        3800
## 3 Adelie  Torgersen           40.3          18                 195        3250
## 4 Adelie  Torgersen           NA            NA                  NA          NA
## 5 Adelie  Torgersen           36.7          19.3               193        3450
## 6 Adelie  Torgersen           39.3          20.6               190        3650
## # ℹ 2 more variables: sex <fct>, year <int>
setwd("C:/Users/Luri Zahara/Downloads")

Sumber: https://allisonhorst.github.io/palmerpenguins/

1.2.2 Statistika Deskriptif

str(penguins)
## tibble [344 × 8] (S3: tbl_df/tbl/data.frame)
##  $ species          : Factor w/ 3 levels "Adelie","Chinstrap",..: 1 1 1 1 1 1 1 1 1 1 ...
##  $ island           : Factor w/ 3 levels "Biscoe","Dream",..: 3 3 3 3 3 3 3 3 3 3 ...
##  $ bill_length_mm   : num [1:344] 39.1 39.5 40.3 NA 36.7 39.3 38.9 39.2 34.1 42 ...
##  $ bill_depth_mm    : num [1:344] 18.7 17.4 18 NA 19.3 20.6 17.8 19.6 18.1 20.2 ...
##  $ flipper_length_mm: int [1:344] 181 186 195 NA 193 190 181 195 193 190 ...
##  $ body_mass_g      : int [1:344] 3750 3800 3250 NA 3450 3650 3625 4675 3475 4250 ...
##  $ sex              : Factor w/ 2 levels "female","male": 2 1 1 NA 1 2 1 2 NA NA ...
##  $ year             : int [1:344] 2007 2007 2007 2007 2007 2007 2007 2007 2007 2007 ...
summary(penguins)
##       species          island    bill_length_mm  bill_depth_mm  
##  Adelie   :152   Biscoe   :168   Min.   :32.10   Min.   :13.10  
##  Chinstrap: 68   Dream    :124   1st Qu.:39.23   1st Qu.:15.60  
##  Gentoo   :124   Torgersen: 52   Median :44.45   Median :17.30  
##                                  Mean   :43.92   Mean   :17.15  
##                                  3rd Qu.:48.50   3rd Qu.:18.70  
##                                  Max.   :59.60   Max.   :21.50  
##                                  NA's   :2       NA's   :2      
##  flipper_length_mm  body_mass_g       sex           year     
##  Min.   :172.0     Min.   :2700   female:165   Min.   :2007  
##  1st Qu.:190.0     1st Qu.:3550   male  :168   1st Qu.:2007  
##  Median :197.0     Median :4050   NA's  : 11   Median :2008  
##  Mean   :200.9     Mean   :4202                Mean   :2008  
##  3rd Qu.:213.0     3rd Qu.:4750                3rd Qu.:2009  
##  Max.   :231.0     Max.   :6300                Max.   :2009  
##  NA's   :2         NA's   :2
cat("Jumlah nilai yang hilang:", sum(is.na(penguins)), "\n")
## Jumlah nilai yang hilang: 19
colSums(is.na(penguins))
##           species            island    bill_length_mm     bill_depth_mm 
##                 0                 0                 2                 2 
## flipper_length_mm       body_mass_g               sex              year 
##                 2                 2                11                 0

1.2.3 Cleaning Data

# Menghapus baris dengan nilai NA
penguins<- penguins %>% drop_na()

# Melihat ukuran dataset setelah pembersihan
cat("Ukuran dataset setelah pembersihan:", dim(penguins)[1], "baris dan", 
    dim(penguins)[2], "kolom\n")
## Ukuran dataset setelah pembersihan: 333 baris dan 8 kolom

1.2.4 Visualisasi Data

# Distribusi spesies penguin
penguin_counts <- penguins %>%
  count(species) %>%
  mutate(percentage = n / sum(n) * 100)

kable(penguin_counts, caption = "Distribusi Spesies Penguin") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Distribusi Spesies Penguin
species n percentage
Adelie 146 43.84384
Chinstrap 68 20.42042
Gentoo 119 35.73574
# Mengubah variable kategoris menjadi faktor 
penguins$species <- as.factor(penguins$species)
penguins$island <- as.factor(penguins$island)
penguins$sex <- as.factor(penguins$sex)

library(palmerpenguins)
library(explore)
## Warning: package 'explore' was built under R version 4.4.3
## 
## Attaching package: 'explore'
## The following object is masked from 'package:GGally':
## 
##     rescale01
penguins %>% 
  explore_all()

penguins %>%
  explore_all(target = species, color = c("lightblue", "lightgreen", "lightpink"))

penguins %>%
  explore_all(target = island, color = c("lightblue", "lightgreen", "lightpink"))

penguins %>%
  explore_all(target = sex, color = c("lightblue", "lightpink"))

# Menghitung jumlah setiap spesies
species_count <- penguins %>%
  count(species) %>%
  mutate(percentage = round(n / sum(n) * 100, 1))

# Tampilkan dalam bentuk tabel
species_count %>%
  kable(col.names = c("Spesies", "Jumlah", "Persentase (%)")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Spesies Jumlah Persentase (%)
Adelie 146 43.8
Chinstrap 68 20.4
Gentoo 119 35.7
# Visualisasi distribusi spesies
ggplot(penguins, aes(x = species, fill = species)) +
  geom_bar() +
  geom_text(stat = 'count', aes(label = after_stat(count)), vjust = -0.5) +
  labs(title = "Distribusi Spesies Penguin",
       x = "Spesies",
       y = "Jumlah") +
  theme(legend.position = "none")

# Menghitung jumlah penguin per pulau
island_count <- penguins %>%
  count(island) %>%
  mutate(percentage = round(n / sum(n) * 100, 1))

# Tampilkan dalam bentuk tabel
island_count %>%
  kable(col.names = c("Pulau", "Jumlah", "Persentase (%)")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Pulau Jumlah Persentase (%)
Biscoe 163 48.9
Dream 123 36.9
Torgersen 47 14.1
# Membuat tabel kontingensi
species_island <- table(penguins$species, penguins$island)
species_island_df <- as.data.frame(species_island)
names(species_island_df) <- c("Species", "Island", "Count")

# Visualisasi dengan facet
ggplot(penguins, aes(x = species, fill = species)) +
  geom_bar() +
  facet_wrap(~island) +
  labs(title = "Distribusi Spesies Penguin di Setiap Pulau",
       x = "Spesies",
       y = "Jumlah") +
  theme(legend.position = "none",
        axis.text.x = element_text(angle = 45, hjust = 1))

# Menghitung jumlah penguin per jenis kelamin
sex_count <- penguins %>%
  count(sex) %>%
  mutate(percentage = round(n / sum(n) * 100, 1))

# Tampilkan dalam bentuk tabel
sex_count %>%
  kable(col.names = c("Jenis Kelamin", "Jumlah", "Persentase (%)")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Jenis Kelamin Jumlah Persentase (%)
female 165 49.5
male 168 50.5
# Visualisasi distribusi jenis kelamin per spesies
ggplot(penguins, aes(x = sex, fill = sex)) +
  geom_bar() +
  facet_wrap(~species) +
  labs(title = "Distribusi Jenis Kelamin Penguin per Spesies",
       x = "Jenis Kelamin",
       y = "Jumlah") +
  theme(legend.position = "bottom")

# Membuat dataset dari variabel numerik
numeric_vars <- penguins %>%
  select(bill_length_mm, bill_depth_mm, flipper_length_mm, body_mass_g)

# Menghitung korelasi
cor_matrix <- cor(numeric_vars)

# Heatmap korelasi
ggplot(as.data.frame(as.table(cor_matrix)), 
       aes(x = Var1, y = Var2, fill = Freq)) +
  geom_tile() +
  geom_text(aes(label = round(Freq, 2)), color = "black", size = 4) +
  scale_fill_gradient2(low = "blue", high = "red", mid = "white", 
                      midpoint = 0, limit = c(-1, 1), name = "Korelasi") +
  labs(title = "Heatmap Korelasi Antar Variabel Numerik",
       x = "",
       y = "") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Interpretasi Eksplorasi dan Visualisasi Data:

Karakteristik Penguin:

  • Penguin Gentoo memiliki ukuran panjang flipper dan massa tubuh yang lebih besar dibandingkan dua spesies lainnya dan hanya ditemukan di Pulai Biscoe
  • Penguin Adelie memiliki paruh yang lebih dalam tetapi lebih pendek dibandingkan spesies lainnya. dan dapat ditemukan di ketiga pulau (Biscoe, Dream, dan Torgersen)
  • Penguin Chinstrap memiliki paruh yang lebih panjang dan lebih tipis dan hanya ditemukan di pulau Dream
  • Penguin jantan umumnya memiliki massa tubuh yang lebih besar dibandingkan penguin betina dalam spesies yang sama

Korelasi Antar Variabel:

  • Terdapat korelasi positif yang kuat antara panjang flipper dan massa tubuh
  • Terdapat korelasi negatif yang cukup kuat antara panjang flipper dan kedalaman paruh

1.3 Split Data

set.seed(123)
numeric_vars <- penguins %>%
  select(species,bill_length_mm, bill_depth_mm, flipper_length_mm, body_mass_g)
penguins<-numeric_vars

# Standarisasi fitur 
# menghindari atribut dalam rentang angka yang lebih besar mendominasi atribut dalam rentang angka yang lebih kecil
penguins[, 2:5] <- scale(penguins[, 2:5])

# 80% data latih, 20% data test
split <- createDataPartition(penguins$species, p = 0.8, list = FALSE)
train_data <- penguins[split, ]
test_data <- penguins[-split, ]
# Melihat pembagian data 
cat("Ukuran data pelatihan:", dim(train_data)[1], "baris\n")
## Ukuran data pelatihan: 268 baris
cat("Ukuran data pengujian:", dim(test_data)[1], "baris\n")
## Ukuran data pengujian: 65 baris
# Memeriksa distribusi kelas di kedua set data
train_dist <- table(train_data$species)
test_dist <- table(test_data$species)

par(mfrow = c(1, 2), mar = c(5, 4, 6, 2))
barplot(train_dist, main = "Data Pelatihan", 
        col = c("salmon", "lightblue", "lightgreen"), las = 2)
barplot(test_dist, main = "Data Pengujian", 
        col = c("salmon", "lightblue", "lightgreen"), las = 2)

1.4 SVM Linear

Pada SVM linear, dicari hyperplane linear optimal yang dapat memisahkan data:

\[\min_{w, b} \frac{1}{2} ||w||^2\]

dengan syarat \(y_i(w^T x_i + b) \geq 1\) untuk semua data \(i\), di mana:

  • \(w\) adalah vektor normal terhadap hyperplane
  • \(b\) adalah bias
  • \(x_i\) adalah vektor fitur dari data ke-\(i\)
  • \(y_i\) adalah label kelas (\(-1\) atau \(1\))
# Model SVM linear
svm_linear <- svm(species ~ ., data = train_data, kernel = "linear", cost = 1,scale=FALSE)

# Ringkasan model
summary(svm_linear)
## 
## Call:
## svm(formula = species ~ ., data = train_data, kernel = "linear", 
##     cost = 1, scale = FALSE)
## 
## 
## Parameters:
##    SVM-Type:  C-classification 
##  SVM-Kernel:  linear 
##        cost:  1 
## 
## Number of Support Vectors:  20
## 
##  ( 9 3 8 )
## 
## 
## Number of Classes:  3 
## 
## Levels: 
##  Adelie Chinstrap Gentoo
# Prediksi menggunakan model linear
pred_linear <- predict(svm_linear, test_data)

# Evaluasi model dengan confusion matrix
conf_linear <- confusionMatrix(pred_linear, test_data$species)
conf_linear
## Confusion Matrix and Statistics
## 
##            Reference
## Prediction  Adelie Chinstrap Gentoo
##   Adelie        29         2      0
##   Chinstrap      0        11      0
##   Gentoo         0         0     23
## 
## Overall Statistics
##                                           
##                Accuracy : 0.9692          
##                  95% CI : (0.8932, 0.9963)
##     No Information Rate : 0.4462          
##     P-Value [Acc > NIR] : < 2.2e-16       
##                                           
##                   Kappa : 0.951           
##                                           
##  Mcnemar's Test P-Value : NA              
## 
## Statistics by Class:
## 
##                      Class: Adelie Class: Chinstrap Class: Gentoo
## Sensitivity                 1.0000           0.8462        1.0000
## Specificity                 0.9444           1.0000        1.0000
## Pos Pred Value              0.9355           1.0000        1.0000
## Neg Pred Value              1.0000           0.9630        1.0000
## Prevalence                  0.4462           0.2000        0.3538
## Detection Rate              0.4462           0.1692        0.3538
## Detection Prevalence        0.4769           0.1692        0.3538
## Balanced Accuracy           0.9722           0.9231        1.0000
# Menyimpan metrik performa
linear_metrics <- conf_linear$byClass
# Mengambil kolom Precision, Recall dan F1
linear_metrics_df <- data.frame(
  Precision = linear_metrics[, "Precision"],
  Recall = linear_metrics[, "Recall"],
  F1 = linear_metrics[, "F1"]
)
print(linear_metrics_df)
##                  Precision    Recall        F1
## Class: Adelie    0.9354839 1.0000000 0.9666667
## Class: Chinstrap 1.0000000 0.8461538 0.9166667
## Class: Gentoo    1.0000000 1.0000000 1.0000000
# Fungsi untuk memplot model SVM
plot_svm <- function(model, title) {
  plot(model, data = train_data, bill_length_mm ~ bill_depth_mm,
       main = title)
}

# Plot model SVM linear
plot_svm(svm_linear, "SVM Linear")

1.5 SVM Non-linear (Kernel RBF)

Untuk data yang tidak dapat dipisahkan secara linear, SVM menggunakan kernel trick untuk memetakan data ke dimensi yang lebih tinggi di mana pemisahan linear mungkin dilakukan. Dengan menggunakan fungsi kernel, dapat menyelesaikan masalah klasifikasi yang kompleks tanpa perlu secara eksplisit menghitung fitur baru dalam dimensi tinggi.
Hal ini membuat SVM menjadi algoritma yang sangat fleksibel, efisien secara komputasi, dan kuat dalam menghadapi data nonlinier. Kernel yang umum digunakan adalah:

  1. Linear Kernel

\[ K(x_i, x_j) = x_i^T x_j \]

  • Digunakan ketika data linier terpisah.

  1. Polynomial Kernel

\[ K(x_i, x_j) = (x_i^T x_j + c)^d \]

  • Mampu menangkap interaksi polinomial antar fitur.
  • Parameter: derajat \(d\) dan konstanta \(c\).

  1. Radial Basis Function (RBF) / Gaussian

\[ K(x_i, x_j) = \exp(-\gamma \|x_i - x_j\|^2) \]

  • Paling populer.
  • Cocok untuk data dengan pola nonlinier kompleks.
  • Parameter: \(\gamma\).

  1. Sigmoid Kernel

\[ K(x_i, x_j) = \tanh(\alpha x_i^T x_j + c) \]

  • Mirip fungsi aktivasi dalam jaringan saraf.
  • Parameter: \(\alpha\) dan \(c\).

Pada perhitungan ini akan digunakan Kernel RBF

# Model SVM Non-linear(RBF)
svm_rbf <- svm(species ~ ., data = train_data, 
               kernel = "radial", cost = 1, gamma = 0.1, scale = FALSE)

# Ringkasan model
summary(svm_rbf)
## 
## Call:
## svm(formula = species ~ ., data = train_data, kernel = "radial", 
##     cost = 1, gamma = 0.1, scale = FALSE)
## 
## 
## Parameters:
##    SVM-Type:  C-classification 
##  SVM-Kernel:  radial 
##        cost:  1 
## 
## Number of Support Vectors:  54
## 
##  ( 23 9 22 )
## 
## 
## Number of Classes:  3 
## 
## Levels: 
##  Adelie Chinstrap Gentoo
# Prediksi pada data pengujian - FIXED: Remove $species from test_data
predictions_rbf <- predict(svm_rbf, test_data)

# Matriks konfusi
conf_matrix_rbf <- confusionMatrix(predictions_rbf, test_data$species)
conf_matrix_rbf
## Confusion Matrix and Statistics
## 
##            Reference
## Prediction  Adelie Chinstrap Gentoo
##   Adelie        28         2      0
##   Chinstrap      1        11      0
##   Gentoo         0         0     23
## 
## Overall Statistics
##                                          
##                Accuracy : 0.9538         
##                  95% CI : (0.871, 0.9904)
##     No Information Rate : 0.4462         
##     P-Value [Acc > NIR] : < 2.2e-16      
##                                          
##                   Kappa : 0.927          
##                                          
##  Mcnemar's Test P-Value : NA             
## 
## Statistics by Class:
## 
##                      Class: Adelie Class: Chinstrap Class: Gentoo
## Sensitivity                 0.9655           0.8462        1.0000
## Specificity                 0.9444           0.9808        1.0000
## Pos Pred Value              0.9333           0.9167        1.0000
## Neg Pred Value              0.9714           0.9623        1.0000
## Prevalence                  0.4462           0.2000        0.3538
## Detection Rate              0.4308           0.1692        0.3538
## Detection Prevalence        0.4615           0.1846        0.3538
## Balanced Accuracy           0.9550           0.9135        1.0000
# Menyimpan metrik performa
rbf_metrics <- conf_matrix_rbf$byClass
# Mengambil kolom Precision, Recall dan F1
rbf_metrics_df <- data.frame(
  Precision = rbf_metrics[, "Precision"],
  Recall = rbf_metrics[, "Recall"],
  F1 = rbf_metrics[, "F1"]
)
print(rbf_metrics_df)
##                  Precision    Recall        F1
## Class: Adelie    0.9333333 0.9655172 0.9491525
## Class: Chinstrap 0.9166667 0.8461538 0.8800000
## Class: Gentoo    1.0000000 1.0000000 1.0000000
# Fungsi untuk memplot model SVM
plot_svm <- function(model, title) {
  plot(model, data = train_data, bill_length_mm ~ bill_depth_mm,
       main = title)
}

# Plot model SVM RBF
plot_svm(svm_rbf, "SVM RBF")

1.6 Perbandingan Performa Model

# ========================== EVALUASI LINEAR ==========================

accuracy_linear <- conf_linear$overall['Accuracy']

if (!is.null(conf_linear$byClass) && is.matrix(conf_linear$byClass)) {
  precision_linear <- conf_linear$byClass[, 'Pos Pred Value']
  recall_linear <- conf_linear$byClass[, 'Sensitivity']
  f1_linear <- conf_linear$byClass[, 'F1']
} else {
  precision_linear <- c(conf_linear$byClass['Pos Pred Value'])
  recall_linear <- c(conf_linear$byClass['Sensitivity'])
  f1_linear <- c(conf_linear$byClass['F1'])
}

precision_linear[is.na(precision_linear)] <- 0
recall_linear[is.na(recall_linear)] <- 0
f1_linear[is.na(f1_linear)] <- 0

eval_linear <- data.frame(
  Metrics = c("Accuracy", 
              paste0("Precision_", names(precision_linear)),
              paste0("Recall_", names(recall_linear)),
              paste0("F1_", names(f1_linear))),
  Values = c(accuracy_linear, precision_linear, recall_linear, f1_linear)
)

# ========================== EVALUASI RBF ==========================

accuracy_rbf <- conf_matrix_rbf$overall['Accuracy']

if (!is.null(conf_matrix_rbf$byClass) && is.matrix(conf_matrix_rbf$byClass)) {
  precision_rbf <- conf_matrix_rbf$byClass[, 'Pos Pred Value']
  recall_rbf <- conf_matrix_rbf$byClass[, 'Sensitivity']
  f1_rbf <- conf_matrix_rbf$byClass[, 'F1']
} else {
  precision_rbf <- c(conf_matrix_rbf$byClass['Pos Pred Value'])
  recall_rbf <- c(conf_matrix_rbf$byClass['Sensitivity'])
  f1_rbf <- c(conf_matrix_rbf$byClass['F1'])
}

precision_rbf[is.na(precision_rbf)] <- 0
recall_rbf[is.na(recall_rbf)] <- 0
f1_rbf[is.na(f1_rbf)] <- 0

eval_rbf <- data.frame(
  Metrics = c("Accuracy", 
              paste0("Precision_", names(precision_rbf)),
              paste0("Recall_", names(recall_rbf)),
              paste0("F1_", names(f1_rbf))),
  Values = c(accuracy_rbf, precision_rbf, recall_rbf, f1_rbf)
)

# ========================== KOMPARASI ==========================

# Pastikan struktur sama
min_length <- min(nrow(eval_linear), nrow(eval_rbf))
eval_linear_subset <- eval_linear[1:min_length, ]
eval_rbf_subset <- eval_rbf[1:min_length, ]

comparison <- data.frame(
  Metrics = eval_linear_subset$Metrics,
  SVM_Linear = eval_linear_subset$Values,
  SVM_RBF = eval_rbf_subset$Values
)

# Menampilkan tabel
print(kable(comparison, digits = 4, caption = "Perbandingan Performa SVM Linear vs RBF"))
## 
## 
## Table: Perbandingan Performa SVM Linear vs RBF
## 
## |Metrics                    | SVM_Linear| SVM_RBF|
## |:--------------------------|----------:|-------:|
## |Accuracy                   |     0.9692|  0.9538|
## |Precision_Class: Adelie    |     0.9355|  0.9333|
## |Precision_Class: Chinstrap |     1.0000|  0.9167|
## |Precision_Class: Gentoo    |     1.0000|  1.0000|
## |Recall_Class: Adelie       |     1.0000|  0.9655|
## |Recall_Class: Chinstrap    |     0.8462|  0.8462|
## |Recall_Class: Gentoo       |     1.0000|  1.0000|
## |F1_Class: Adelie           |     0.9667|  0.9492|
## |F1_Class: Chinstrap        |     0.9167|  0.8800|
## |F1_Class: Gentoo           |     1.0000|  1.0000|

Berdasarkan evaluasi performa model F1-Score, karena merupakan rata-rata harmonik dari precision dan recall, serta memberikan keseimbangan antara kedua metrik tersebut. F1-Score sangat penting dalam kasus klasifikasi multikelas seperti ini untuk meminimalkan kesalahan tipe I (false positive) dan tipe II (false negative) secara bersamaan.

  • Model SVM Linear menunjukkan performa yang lebih baik secara keseluruhan dibandingkan SVM RBF, terutama dalam hal stabilitas performa antar kelas.

  • F1-Score untuk masing-masing kelas pada kedua model adalah sebagai berikut:

    • Adelie:
      • SVM Linear: 0.9667
      • SVM RBF: 0.9492
      • → SVM Linear sedikit lebih unggul.
    • Chinstrap:
      • SVM Linear: 0.9167
      • SVM RBF: 0.8800
      • → Performa SVM Linear secara signifikan lebih baik pada kelas ini.
    • Gentoo:
      • Kedua model menghasilkan F1-Score sempurna: 1.0000
  • Berdasarkan hasil di atas, SVM Linear direkomendasikan sebagai model terbaik karena:

    • Memberikan F1-Score yang lebih tinggi dan konsisten di semua kelas.
    • Terutama unggul pada kelas yang performanya cenderung lebih rendah, seperti Chinstrap.
    • Cocok digunakan untuk klasifikasi spesies yang memerlukan akurasi dan ketelitian seimbang pada semua kelas.

1.7 Fitur Penting

# Ekstrak koefisien dari model SVM linear
coefs <- t(svm_linear$coefs) %*% svm_linear$SV

# Hitung importance berdasarkan absolute value koefisien
feature_importance <- apply(abs(coefs), 2, mean)
names(feature_importance) <- colnames(train_data)[-which(names(train_data) == "species")]

# Urutkan dan ambil 2 fitur teratas
top_2_features <- sort(feature_importance, decreasing = TRUE)[1:2]
print("2 Fitur Paling Penting (berdasarkan koefisien SVM):")
## [1] "2 Fitur Paling Penting (berdasarkan koefisien SVM):"
print(top_2_features)
## flipper_length_mm       body_mass_g 
##          4.536611          3.987452

1.8 Visualisasi Decision Boundary

# Fungsi untuk memplot model SVM dengan 2 fitur penting
plot_svm <- function(model, title) {
  plot(model, data = train_data, body_mass_g~flipper_length_mm,
       main = title)
}

# Plot model SVM linear
plot_svm(svm_linear, "SVM Linear")

1.9 Parameter C dan Gamma

# 1. PENGARUH PARAMETER C (SVM Linear)
c_values <- c(0.01, 0.1, 1, 10, 100)
c_results <- data.frame()

for(c_val in c_values) {
  svm_model <- svm(species ~ ., data = train_data, 
                   kernel = "linear", cost = c_val, scale = FALSE)
  pred <- predict(svm_model, test_data)
  accuracy <- mean(pred == test_data$species)
  
  c_results <- rbind(c_results, 
                     data.frame(C = c_val, 
                               Accuracy = accuracy,
                               Support_Vectors = nrow(svm_model$SV)))
}

c_results$C_Label <- paste("C =", c_results$C)
c_results$Accuracy_Pct <- paste0(round(c_results$Accuracy * 100, 1), "%")
print(c_results[, c("C_Label", "Accuracy_Pct", "Support_Vectors")])
##    C_Label Accuracy_Pct Support_Vectors
## 1 C = 0.01        92.3%             155
## 2  C = 0.1        93.8%              61
## 3    C = 1        96.9%              20
## 4   C = 10        95.4%              12
## 5  C = 100        96.9%              10
# 2. PENGARUH PARAMETER GAMMA (SVM RBF)
gamma_values <- c(0.001, 0.01, 0.1, 1, 10)
gamma_results <- data.frame()

for(gamma_val in gamma_values) {
  svm_model <- svm(species ~ ., data = train_data, 
                   kernel = "radial", cost = 1, gamma = gamma_val, scale = FALSE)
  pred <- predict(svm_model, test_data)
  accuracy <- mean(pred == test_data$species)
  
  gamma_results <- rbind(gamma_results, 
                        data.frame(Gamma = gamma_val, 
                                  Accuracy = accuracy,
                                  Support_Vectors = nrow(svm_model$SV)))
}

gamma_results$Gamma_Label <- paste("Gamma =", gamma_results$Gamma)
gamma_results$Accuracy_Pct <- paste0(round(gamma_results$Accuracy * 100, 1), "%")
print(gamma_results[, c("Gamma_Label", "Accuracy_Pct", "Support_Vectors")])
##     Gamma_Label Accuracy_Pct Support_Vectors
## 1 Gamma = 0.001          80%             223
## 2  Gamma = 0.01        95.4%             122
## 3   Gamma = 0.1        95.4%              54
## 4     Gamma = 1        93.8%              71
## 5    Gamma = 10        83.1%             254
  1. Parameter C (SVM Linear): Parameter regularisasi yang mengontrol trade-off antara mencapai margin maksimal dan meminimalkan kesalahan klasifikasi.

    • Semakin besar nilai C, akurasi cenderung meningkat dan jumlah support vector menurun. Ini menunjukkan bahwa model menjadi lebih kompleks dan fokus pada meminimalkan kesalahan training. Namun, terlalu besar (C=10 atau 100) tidak selalu lebih baik karena dapat menyebabkan overfitting.
  2. Parameter Gamma (untuk RBF): Parameter kernel yang mengontrol pengaruhdari setiap titik data.

    • Semakin besar nilai Gamma, model menjadi lebih kompleks karena tiap titik data hanya memengaruhi area sempit. Hal ini awalnya membuat decision boundary lebih fleksibel dan jumlah support vector menurun. Namun, jika terlalu besar, model cenderung overfitting, menghasilkan decision boundary yang terlalu rumit dan support vector kembali meningkat tajam.

1.10 Simpulan

  1. Performa Model:

Dari analisis yang telah dilakukan pada dataset Palmer Penguins, dapat disimpulkan bahwa:

  • SVM Linear menunjukkan performa dengan akurasi sebesar 96% dibandingkan SVM RBF yang mencapai 93%.

  • F1-Score rata-rata untuk SVM Linear lebih konsisten di semua kelas spesies penguin.

  • Kedua model menunjukkan performa sempurna (F1-Score = 1) untuk klasifikasi spesies Gentoo, menunjukkan bahwa spesies ini memiliki karakteristik yang sangat distinktif.

  1. Data:
  • Separability yang baik: Data dapat dipisahkan dengan relatif mudah menggunakan hyperplane linear.

  • Fitur numerik yang relevan: Keempat fitur morfologi (panjang paruh, kedalaman paruh, panjang flipper, dan massa tubuh) memberikan informasi yang cukup untuk klasifikasi.

  1. Fitur:
  • Berdasarkan analisis koefisien SVM Linear, Body mass dan flipper length merupakan fitur paling penting untuk klasifikasi. Hal ini konsisten dengan visualisasi data yang menunjukkan korelasi kuat antara kedua fitur tersebut.

  • Penguin Gentoo dapat dibedakan dengan jelas berdasarkan massa tubuh dan panjang flipper yang lebih besar.

  1. Parameter:
  • Parameter C = 1 memberikan keseimbangan optimal antara margin maksimum dan akurasi klasifikasi.

  • Parameter Gamma = 0.1 pada kernel RBF memberikan kompleksitas model yang tepat tanpa overfitting.