Artificial Neural Network (ANN) merupakan metode machine learning yang terinspirasi dari cara kerja jaringan saraf biologis. ANN terdiri atas neuron-neuron yang saling terhubung untuk mempelajari pola hubungan antara variabel prediktor dan variabel respons. Metode ini dapat digunakan untuk permasalahan regresi maupun klasifikasi.
Pada klasifikasi, ANN mempelajari pola dari data berlabel untuk menentukan kelas suatu pengamatan berdasarkan karakteristik prediktornya. Proses pembelajaran dilakukan dengan memperbarui bobot dan bias jaringan agar kesalahan prediksi semakin kecil.
Salah satu arsitektur ANN yang umum digunakan adalah Multilayer Perceptron (MLP), yang terdiri atas lapisan input, satu atau lebih lapisan tersembunyi (hidden layer), dan lapisan output. Jumlah neuron pada lapisan tersembunyi merupakan salah satu parameter penting karena dapat memengaruhi kemampuan model dalam mengenali pola data.
Pada praktikum Pertemuan VI, ANN digunakan untuk mengklasifikasikan spesies bunga Iris berdasarkan empat karakteristik, yaitu panjang sepal, lebar sepal, panjang petal, dan lebar petal. Klasifikasi dilakukan menggunakan tiga jumlah neuron tersembunyi, yaitu 10, 20, dan 30 neuron.
Eksperimen menggunakan dua skenario pembagian data, yaitu 80% training dan 20% testing serta 60% training dan 40% testing. Dengan demikian, terdapat enam model ANN yang dibandingkan. Evaluasi dilakukan menggunakan confusion matrix, akurasi, error rate, precision, recall, dan F1-score.
Praktikum ini diharapkan dapat meningkatkan pemahaman mengenai penerapan ANN pada permasalahan klasifikasi, proses pelatihan jaringan saraf, pengaruh jumlah neuron tersembunyi, serta perbedaan hasil evaluasi akibat perubahan proporsi data training dan testing.
iris yang
tersedia pada R.Sepal.Length,
Sepal.Width, Petal.Length, dan
Petal.Width.Species.nnet() dari paket
nnet.Laporan ini terdiri atas lima bab. Bab I membahas pendahuluan, Bab II menjelaskan tinjauan pustaka, Bab III menguraikan metode penelitian, Bab IV menyajikan hasil dan pembahasan, dan Bab V memuat kesimpulan serta saran. Bagian akhir dilengkapi daftar pustaka dan kode program.
Artificial Neural Network merupakan metode pembelajaran komputasi yang tersusun atas neuron-neuron yang saling terhubung. Setiap neuron menerima masukan, mengalikannya dengan bobot, menambahkan bias, kemudian menerapkan fungsi aktivasi untuk menghasilkan keluaran.
Secara matematis, keluaran suatu neuron dapat dituliskan sebagai:
\[ z_j=\sum_{i=1}^{p}w_{ij}x_i+b_j \]
\[ a_j=f(z_j) \]
dengan \(x_i\) merupakan nilai input, \(w_{ij}\) merupakan bobot koneksi, \(b_j\) merupakan bias, dan \(f\) merupakan fungsi aktivasi.
Dalam ANN, bobot dan bias diperbarui selama pelatihan untuk meminimalkan fungsi kesalahan. Setelah proses pelatihan selesai, jaringan digunakan untuk memprediksi kelas pada data baru.
MLP merupakan arsitektur ANN yang memiliki lapisan input, lapisan tersembunyi, dan lapisan output.
Pada praktikum ini digunakan satu hidden layer. Arsitektur tersebut dibandingkan dengan 10, 20, dan 30 neuron tersembunyi, sedangkan jumlah variabel input dan kelas output tetap sama.
Pelatihan ANN dilakukan dengan memberikan data training kepada jaringan. Jaringan menghasilkan prediksi, kemudian kesalahan prediksi digunakan untuk memperbarui bobot dan bias.
Secara umum, tahapan pelatihan ANN meliputi:
Pada fungsi nnet(), proses optimasi dilakukan
menggunakan algoritma BFGS. Ketika respons berupa faktor dengan lebih
dari dua kelas, jaringan menggunakan keluaran softmax untuk klasifikasi
multikelas.
Dataset Iris merupakan dataset klasik untuk analisis klasifikasi. Dataset ini terdiri atas 150 pengamatan bunga dengan tiga kelas, yaitu setosa, versicolor, dan virginica.
Empat variabel prediktor yang digunakan adalah:
Sepal.Length: panjang sepal.Sepal.Width: lebar sepal.Petal.Length: panjang petal.Petal.Width: lebar petal.Variabel respons Species menunjukkan spesies bunga.
Karena memiliki tiga kelas, permasalahan ini termasuk klasifikasi
multikelas.
Data training digunakan untuk mempelajari pola dan membentuk model, sedangkan data testing digunakan untuk mengevaluasi kemampuan model terhadap pengamatan yang tidak digunakan dalam pelatihan.
Pada praktikum ini terdapat dua skenario pembagian data:
Perbandingan kedua skenario dapat menunjukkan bagaimana jumlah data yang tersedia untuk pelatihan berkaitan dengan performa klasifikasi.
Confusion matrix merupakan tabel yang membandingkan kelas aktual dengan kelas hasil prediksi. Pada klasifikasi tiga kelas, matriks ini memiliki tiga baris dan tiga kolom.
Elemen diagonal menunjukkan jumlah prediksi yang benar, sedangkan elemen di luar diagonal menunjukkan kesalahan klasifikasi.
Confusion matrix dapat digunakan untuk mengidentifikasi kelas yang mudah diklasifikasikan serta kelas yang sering tertukar dengan kelas lain.
Accuracy merupakan proporsi prediksi yang benar terhadap seluruh pengamatan testing.
\[ Accuracy=\frac{\text{Jumlah prediksi benar}}{n} \]
Nilai accuracy yang mendekati 1 menunjukkan proporsi klasifikasi benar yang lebih tinggi.
Error rate merupakan proporsi prediksi yang salah.
\[ Error\ Rate=1-Accuracy \]
Semakin kecil error rate, semakin rendah proporsi kesalahan klasifikasi.
Precision menunjukkan proporsi prediksi suatu kelas yang benar-benar berasal dari kelas tersebut.
\[ Precision_k=\frac{TP_k}{TP_k+FP_k} \]
Precision yang tinggi menunjukkan bahwa sebagian besar pengamatan yang diprediksi sebagai kelas \(k\) memang termasuk kelas tersebut.
Recall menunjukkan proporsi pengamatan aktual suatu kelas yang berhasil dikenali dengan benar.
\[ Recall_k=\frac{TP_k}{TP_k+FN_k} \]
Recall yang tinggi menunjukkan bahwa model mampu mengenali sebagian besar pengamatan dari kelas tersebut.
F1-score merupakan rata-rata harmonik precision dan recall.
\[ F1_k=2\frac{Precision_k\times Recall_k} {Precision_k+Recall_k} \]
F1-score mempertimbangkan precision dan recall secara bersamaan. Dalam laporan ini, F1-score dihitung untuk masing-masing kelas.
Data yang digunakan adalah dataset iris yang tersedia
secara bawaan dalam R. Dataset ini berisi 150 pengamatan bunga dari tiga
spesies. Setiap pengamatan memiliki empat variabel prediktor numerik dan
satu variabel respons kategorik.
tabel_variabel <- data.frame(
Variabel = c(
"Sepal.Length",
"Sepal.Width",
"Petal.Length",
"Petal.Width",
"Species"
),
Peran = c(
"Prediktor",
"Prediktor",
"Prediktor",
"Prediktor",
"Respons"
),
Keterangan = c(
"Panjang sepal bunga",
"Lebar sepal bunga",
"Panjang petal bunga",
"Lebar petal bunga",
"Spesies bunga: setosa, versicolor, virginica"
)
)
knitr::kable(
tabel_variabel,
caption = "Tabel 3.1 Variabel penelitian"
)
| Variabel | Peran | Keterangan |
|---|---|---|
| Sepal.Length | Prediktor | Panjang sepal bunga |
| Sepal.Width | Prediktor | Lebar sepal bunga |
| Petal.Length | Prediktor | Panjang petal bunga |
| Petal.Width | Prediktor | Lebar petal bunga |
| Species | Respons | Spesies bunga: setosa, versicolor, virginica |
Eksperimen menggunakan dua proporsi data dan tiga jumlah hidden neuron, sehingga terdapat enam model ANN.
rancangan <- expand.grid(
Proporsi = c("80:20", "60:40"),
Hidden_Neuron = c(10, 20, 30),
stringsAsFactors = FALSE
)
rancangan$Model <- paste0(
"ANN_", gsub(":", "_", rancangan$Proporsi),
"_H", rancangan$Hidden_Neuron
)
rancangan <- rancangan[
order(
match(rancangan$Proporsi, c("80:20", "60:40")),
rancangan$Hidden_Neuron
),
]
rownames(rancangan) <- NULL
knitr::kable(
rancangan[, c("Model", "Proporsi", "Hidden_Neuron")],
caption = "Tabel 3.2 Rancangan enam model ANN klasifikasi"
)
| Model | Proporsi | Hidden_Neuron |
|---|---|---|
| ANN_80_20_H10 | 80:20 | 10 |
| ANN_80_20_H20 | 80:20 | 20 |
| ANN_80_20_H30 | 80:20 | 30 |
| ANN_60_40_H10 | 60:40 | 10 |
| ANN_60_40_H20 | 60:40 | 20 |
| ANN_60_40_H30 | 60:40 | 30 |
Tahapan analisis yang dilakukan adalah:
Gambar 3.1. Diagram alir penelitian ANN klasifikasi.
data_iris <- datasets::iris
cat("Jumlah pengamatan:", nrow(data_iris), "\n")
## Jumlah pengamatan: 150
cat("Jumlah variabel:", ncol(data_iris), "\n")
## Jumlah variabel: 5
cat("Jumlah prediktor:", ncol(data_iris) - 1, "\n")
## Jumlah prediktor: 4
cat("Jumlah kelas:", nlevels(data_iris$Species), "\n\n")
## Jumlah kelas: 3
str(data_iris)
## 'data.frame': 150 obs. of 5 variables:
## $ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
## $ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
## $ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
## $ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
## $ Species : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
Output menunjukkan bahwa dataset terdiri atas 150 pengamatan, empat variabel prediktor numerik, dan satu variabel respons berupa faktor dengan tiga kategori. Struktur ini sesuai untuk klasifikasi multikelas menggunakan ANN.
knitr::kable(
head(data_iris, 6),
caption = "Tabel 4.1 Enam pengamatan pertama dataset Iris"
)
| Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species |
|---|---|---|---|---|
| 5.1 | 3.5 | 1.4 | 0.2 | setosa |
| 4.9 | 3.0 | 1.4 | 0.2 | setosa |
| 4.7 | 3.2 | 1.3 | 0.2 | setosa |
| 4.6 | 3.1 | 1.5 | 0.2 | setosa |
| 5.0 | 3.6 | 1.4 | 0.2 | setosa |
| 5.4 | 3.9 | 1.7 | 0.4 | setosa |
knitr::kable(
as.data.frame(table(data_iris$Species)),
col.names = c("Spesies", "Jumlah"),
caption = "Tabel 4.2 Distribusi kelas pada dataset Iris"
)
| Spesies | Jumlah |
|---|---|
| setosa | 50 |
| versicolor | 50 |
| virginica | 50 |
Setiap spesies pada dataset Iris memiliki 50 pengamatan. Dengan demikian, distribusi kelas keseluruhan seimbang. Pembagian data secara terstratifikasi digunakan agar proporsi kelas pada training dan testing tetap mendekati distribusi aslinya.
Data dibagi menggunakan dua skenario. Pembagian dilakukan secara
terstratifikasi berdasarkan Species, sehingga setiap
spesies memiliki representasi pada data training dan testing.
Seed ditetapkan agar pembagian data dapat direproduksi. Pembagian yang sama digunakan untuk seluruh konfigurasi hidden neuron pada setiap skenario.
bagi_stratifikasi <- function(data, proporsi_train, seed) {
set.seed(seed)
indeks_train <- unlist(
lapply(
split(seq_len(nrow(data)), data$Species),
function(indeks) {
sample(
indeks,
size = floor(length(indeks) * proporsi_train)
)
}
),
use.names = FALSE
)
indeks_train <- sort(indeks_train)
list(
train = data[indeks_train, , drop = FALSE],
test = data[-indeks_train, , drop = FALSE]
)
}
split_80 <- bagi_stratifikasi(
data_iris, proporsi_train = 0.80, seed = 917
)
split_60 <- bagi_stratifikasi(
data_iris, proporsi_train = 0.60, seed = 918
)
pembagian <- data.frame(
Skenario = c("80:20", "60:40"),
Training = c(
nrow(split_80$train),
nrow(split_60$train)
),
Testing = c(
nrow(split_80$test),
nrow(split_60$test)
),
Persentase_Training = c(
100 * nrow(split_80$train) / nrow(data_iris),
100 * nrow(split_60$train) / nrow(data_iris)
),
Persentase_Testing = c(
100 * nrow(split_80$test) / nrow(data_iris),
100 * nrow(split_60$test) / nrow(data_iris)
)
)
knitr::kable(
pembagian,
digits = 2,
caption = "Tabel 4.3 Pembagian data training dan testing"
)
| Skenario | Training | Testing | Persentase_Training | Persentase_Testing |
|---|---|---|---|---|
| 80:20 | 120 | 30 | 80 | 20 |
| 60:40 | 90 | 60 | 60 | 40 |
Pada skenario 80:20, sebanyak 120 pengamatan digunakan untuk training dan 30 pengamatan untuk testing. Pada skenario 60:40, sebanyak 90 pengamatan digunakan untuk training dan 60 pengamatan untuk testing.
Skenario 80:20 menyediakan lebih banyak data untuk pembelajaran jaringan, sedangkan skenario 60:40 menyediakan lebih banyak pengamatan untuk mengevaluasi prediksi. Perbedaan ini memungkinkan pengamatan terhadap perubahan performa model ketika jumlah data pelatihan dikurangi.
Model ANN dibangun menggunakan fungsi nnet() dengan satu
hidden layer. Jumlah hidden neuron yang diuji adalah 10, 20, dan 30.
Parameter maxit ditetapkan sebesar 1000 sebagai batas
maksimum iterasi optimasi, sedangkan decay ditetapkan
sebesar 0,01 untuk regularisasi bobot.
Karena Species merupakan faktor dengan tiga kelas, model
melakukan klasifikasi multikelas. Prediksi testing diperoleh menggunakan
predict() dengan type = "class".
hidden_values <- c(10, 20, 30)
split_list <- list(
"80:20" = split_80,
"60:40" = split_60
)
model_list <- list()
prediksi_list <- list()
confusion_list <- list()
metrik_kelas_list <- list()
hasil_model <- list()
hitung_metrik_kelas <- function(aktual, prediksi, kelas) {
hasil <- lapply(kelas, function(k) {
tp <- sum(aktual == k & prediksi == k)
fp <- sum(aktual != k & prediksi == k)
fn <- sum(aktual == k & prediksi != k)
precision <- if ((tp + fp) == 0) {
0
} else {
tp / (tp + fp)
}
recall <- if ((tp + fn) == 0) {
0
} else {
tp / (tp + fn)
}
f1 <- if ((precision + recall) == 0) {
0
} else {
2 * precision * recall / (precision + recall)
}
data.frame(
Kelas = as.character(k),
Precision = precision,
Recall = recall,
F1_Score = f1
)
})
do.call(rbind, hasil)
}
for (prop in names(split_list)) {
data_train <- split_list[[prop]]$train
data_test <- split_list[[prop]]$test
form <- Species ~
Sepal.Length +
Sepal.Width +
Petal.Length +
Petal.Width
for (h in hidden_values) {
nama_model <- paste0(
"ANN_", gsub(":", "_", prop),
"_H", h
)
# Seed model dibedakan berdasarkan skenario dan hidden neuron.
seed_model <- if (prop == "80:20") 1000 else 2000
seed_model <- seed_model + h
set.seed(seed_model)
model <- nnet::nnet(
formula = form,
data = data_train,
size = h,
maxit = 1000,
decay = 0.01,
trace = FALSE,
MaxNWts = 10000
)
prediksi <- predict(
model,
newdata = data_test,
type = "class"
)
prediksi <- factor(
as.character(prediksi),
levels = levels(data_iris$Species)
)
aktual <- factor(
data_test$Species,
levels = levels(data_iris$Species)
)
cm <- table(
Aktual = aktual,
Prediksi = prediksi
)
akurasi <- sum(diag(cm)) / sum(cm)
error_rate <- 1 - akurasi
metrik_kelas <- hitung_metrik_kelas(
aktual,
prediksi,
levels(data_iris$Species)
)
macro_precision <- mean(metrik_kelas$Precision)
macro_recall <- mean(metrik_kelas$Recall)
macro_f1 <- mean(metrik_kelas$F1_Score)
model_list[[nama_model]] <- model
prediksi_list[[nama_model]] <- prediksi
confusion_list[[nama_model]] <- cm
metrik_kelas_list[[nama_model]] <- metrik_kelas
hasil_model[[nama_model]] <- data.frame(
Model = nama_model,
Proporsi = prop,
Training = nrow(data_train),
Testing = nrow(data_test),
Hidden_Neuron = h,
Accuracy = akurasi,
Error_Rate = error_rate,
Macro_Precision = macro_precision,
Macro_Recall = macro_recall,
Macro_F1 = macro_f1
)
}
}
tabel_hasil <- do.call(rbind, hasil_model)
rownames(tabel_hasil) <- NULL
tabel_hasil <- tabel_hasil[
order(
match(tabel_hasil$Proporsi, c("80:20", "60:40")),
tabel_hasil$Hidden_Neuron
),
]
tabel_hasil_tampil <- tabel_hasil
kolom_metrik <- c(
"Accuracy", "Error_Rate",
"Macro_Precision", "Macro_Recall", "Macro_F1"
)
tabel_hasil_tampil[kolom_metrik] <- lapply(
tabel_hasil_tampil[kolom_metrik],
fmt
)
knitr::kable(
tabel_hasil_tampil,
caption = "Tabel 4.4 Hasil evaluasi enam model ANN"
)
| Model | Proporsi | Training | Testing | Hidden_Neuron | Accuracy | Error_Rate | Macro_Precision | Macro_Recall | Macro_F1 |
|---|---|---|---|---|---|---|---|---|---|
| ANN_80_20_H10 | 80:20 | 120 | 30 | 10 | 0.9667 | 0.0333 | 0.9697 | 0.9667 | 0.9666 |
| ANN_80_20_H20 | 80:20 | 120 | 30 | 20 | 0.9667 | 0.0333 | 0.9697 | 0.9667 | 0.9666 |
| ANN_80_20_H30 | 80:20 | 120 | 30 | 30 | 0.9667 | 0.0333 | 0.9697 | 0.9667 | 0.9666 |
| ANN_60_40_H10 | 60:40 | 90 | 60 | 10 | 0.9167 | 0.0833 | 0.9173 | 0.9167 | 0.9166 |
| ANN_60_40_H20 | 60:40 | 90 | 60 | 20 | 0.9167 | 0.0833 | 0.9173 | 0.9167 | 0.9166 |
| ANN_60_40_H30 | 60:40 | 90 | 60 | 30 | 0.9167 | 0.0833 | 0.9173 | 0.9167 | 0.9166 |
Tabel 4.4 menyajikan hasil evaluasi enam model ANN. Accuracy menunjukkan proporsi prediksi yang benar, sedangkan error rate menunjukkan proporsi prediksi yang salah. Macro-precision, macro-recall, dan macro-F1 merupakan rata-rata sederhana dari metrik ketiga kelas, sehingga setiap spesies memperoleh bobot yang sama dalam ringkasan tersebut.
Model dengan accuracy lebih tinggi dan error rate lebih rendah memiliki performa klasifikasi keseluruhan yang lebih baik pada data testing yang digunakan. Macro-F1 juga membantu melihat keseimbangan precision dan recall di antara ketiga spesies.
Perlu diperhatikan bahwa hasil setiap model dipengaruhi oleh inisialisasi bobot secara acak. Oleh karena itu, hasil pada satu pembagian data merupakan evaluasi untuk eksperimen ini, bukan jaminan bahwa model akan selalu menghasilkan performa yang sama pada pembagian data lainnya.
Confusion matrix digunakan untuk mengetahui jumlah prediksi benar dan kesalahan klasifikasi pada masing-masing spesies.
for (nama_model in names(confusion_list)) {
cat("\n\n### ", nama_model, "\n\n", sep = "")
cat(
"Baris menunjukkan kelas aktual, sedangkan kolom menunjukkan ",
"kelas hasil prediksi.\n\n",
sep = ""
)
cm <- confusion_list[[nama_model]]
print(
knitr::kable(
as.data.frame.matrix(cm),
caption = paste("Confusion matrix", nama_model),
format = "html"
)
)
benar <- sum(diag(cm))
total <- sum(cm)
salah <- total - benar
cat(
"\n\nJumlah prediksi benar: **", benar,
" dari ", total, "**.\n\n",
sep = ""
)
cat(
"Jumlah prediksi salah: **", salah,
" dari ", total, "**.\n\n",
sep = ""
)
cat(
"Akurasi model: **",
round(100 * benar / total, 2),
"%**.\n\n",
sep = ""
)
}
Baris menunjukkan kelas aktual, sedangkan kolom menunjukkan kelas hasil prediksi.
| setosa | versicolor | virginica | |
|---|---|---|---|
| setosa | 10 | 0 | 0 |
| versicolor | 0 | 9 | 1 |
| virginica | 0 | 0 | 10 |
Jumlah prediksi benar: 29 dari 30.
Jumlah prediksi salah: 1 dari 30.
Akurasi model: 96.67%.
Baris menunjukkan kelas aktual, sedangkan kolom menunjukkan kelas hasil prediksi.
| setosa | versicolor | virginica | |
|---|---|---|---|
| setosa | 10 | 0 | 0 |
| versicolor | 0 | 9 | 1 |
| virginica | 0 | 0 | 10 |
Jumlah prediksi benar: 29 dari 30.
Jumlah prediksi salah: 1 dari 30.
Akurasi model: 96.67%.
Baris menunjukkan kelas aktual, sedangkan kolom menunjukkan kelas hasil prediksi.
| setosa | versicolor | virginica | |
|---|---|---|---|
| setosa | 10 | 0 | 0 |
| versicolor | 0 | 9 | 1 |
| virginica | 0 | 0 | 10 |
Jumlah prediksi benar: 29 dari 30.
Jumlah prediksi salah: 1 dari 30.
Akurasi model: 96.67%.
Baris menunjukkan kelas aktual, sedangkan kolom menunjukkan kelas hasil prediksi.
| setosa | versicolor | virginica | |
|---|---|---|---|
| setosa | 20 | 0 | 0 |
| versicolor | 0 | 17 | 3 |
| virginica | 0 | 2 | 18 |
Jumlah prediksi benar: 55 dari 60.
Jumlah prediksi salah: 5 dari 60.
Akurasi model: 91.67%.
Baris menunjukkan kelas aktual, sedangkan kolom menunjukkan kelas hasil prediksi.
| setosa | versicolor | virginica | |
|---|---|---|---|
| setosa | 20 | 0 | 0 |
| versicolor | 0 | 17 | 3 |
| virginica | 0 | 2 | 18 |
Jumlah prediksi benar: 55 dari 60.
Jumlah prediksi salah: 5 dari 60.
Akurasi model: 91.67%.
Baris menunjukkan kelas aktual, sedangkan kolom menunjukkan kelas hasil prediksi.
| setosa | versicolor | virginica | |
|---|---|---|---|
| setosa | 20 | 0 | 0 |
| versicolor | 0 | 17 | 3 |
| virginica | 0 | 2 | 18 |
Jumlah prediksi benar: 55 dari 60.
Jumlah prediksi salah: 5 dari 60.
Akurasi model: 91.67%.
Interpretasi confusion matrix dilakukan dengan memperhatikan elemen diagonal dan elemen di luar diagonal.
Elemen diagonal menunjukkan pengamatan yang berhasil diklasifikasikan dengan benar. Sebagai contoh, apabila nilai pada baris setosa dan kolom setosa adalah 10, berarti terdapat 10 bunga setosa yang diprediksi benar sebagai setosa.
Sebaliknya, apabila nilai pada baris versicolor dan kolom virginica adalah 2, berarti terdapat dua bunga versicolor yang salah diprediksi sebagai virginica.
Pada setiap model, jumlah elemen diagonal dibagi jumlah seluruh pengamatan testing untuk memperoleh accuracy. Perbedaan jumlah kesalahan pada ketiga spesies membantu menjelaskan mengapa dua model dengan accuracy yang hampir sama dapat mempunyai karakteristik klasifikasi yang berbeda.
for (nama_model in names(metrik_kelas_list)) {
cat("\n\n### ", nama_model, "\n\n", sep = "")
metrik <- metrik_kelas_list[[nama_model]]
metrik_tampil <- metrik
metrik_tampil[, c(
"Precision", "Recall", "F1_Score"
)] <- lapply(
metrik_tampil[, c(
"Precision", "Recall", "F1_Score"
)],
fmt
)
print(
knitr::kable(
metrik_tampil,
caption = paste("Metrik klasifikasi", nama_model),
format = "html"
)
)
}
| Kelas | Precision | Recall | F1_Score |
|---|---|---|---|
| setosa | 1.0000 | 1.0 | 1.0000 |
| versicolor | 1.0000 | 0.9 | 0.9474 |
| virginica | 0.9091 | 1.0 | 0.9524 |
| Kelas | Precision | Recall | F1_Score |
|---|---|---|---|
| setosa | 1.0000 | 1.0 | 1.0000 |
| versicolor | 1.0000 | 0.9 | 0.9474 |
| virginica | 0.9091 | 1.0 | 0.9524 |
| Kelas | Precision | Recall | F1_Score |
|---|---|---|---|
| setosa | 1.0000 | 1.0 | 1.0000 |
| versicolor | 1.0000 | 0.9 | 0.9474 |
| virginica | 0.9091 | 1.0 | 0.9524 |
| Kelas | Precision | Recall | F1_Score |
|---|---|---|---|
| setosa | 1.0000 | 1.00 | 1.0000 |
| versicolor | 0.8947 | 0.85 | 0.8718 |
| virginica | 0.8571 | 0.90 | 0.8780 |
| Kelas | Precision | Recall | F1_Score |
|---|---|---|---|
| setosa | 1.0000 | 1.00 | 1.0000 |
| versicolor | 0.8947 | 0.85 | 0.8718 |
| virginica | 0.8571 | 0.90 | 0.8780 |
| Kelas | Precision | Recall | F1_Score |
|---|---|---|---|
| setosa | 1.0000 | 1.00 | 1.0000 |
| versicolor | 0.8947 | 0.85 | 0.8718 |
| virginica | 0.8571 | 0.90 | 0.8780 |
Tabel pada bagian ini memperlihatkan performa klasifikasi setiap spesies pada masing-masing model.
Interpretasi precision. Precision yang tinggi pada suatu spesies menunjukkan bahwa prediksi model untuk spesies tersebut sebagian besar benar. Precision rendah menunjukkan bahwa lebih banyak pengamatan dari spesies lain ikut diprediksi sebagai spesies tersebut.
Interpretasi recall. Recall yang tinggi menunjukkan bahwa model berhasil mengenali sebagian besar pengamatan aktual pada spesies terkait. Recall rendah menunjukkan masih banyak pengamatan spesies tersebut yang salah diklasifikasikan.
Interpretasi F1-score. F1-score yang tinggi menunjukkan keseimbangan yang baik antara precision dan recall. Nilai ini berguna ketika ingin menilai performa suatu kelas tanpa hanya mengandalkan accuracy keseluruhan.
Karena dataset Iris memiliki jumlah pengamatan yang sama pada setiap spesies sebelum pembagian, macro-average dapat digunakan untuk merangkum performa ketiga kelas secara seimbang.
data_grafik <- rbind(
data.frame(
Model = tabel_hasil$Model,
Proporsi = tabel_hasil$Proporsi,
Hidden_Neuron = factor(tabel_hasil$Hidden_Neuron),
Metrik = "Accuracy",
Nilai = tabel_hasil$Accuracy
),
data.frame(
Model = tabel_hasil$Model,
Proporsi = tabel_hasil$Proporsi,
Hidden_Neuron = factor(tabel_hasil$Hidden_Neuron),
Metrik = "Error Rate",
Nilai = tabel_hasil$Error_Rate
)
)
ggplot(
data_grafik,
aes(
x = Hidden_Neuron,
y = Nilai,
group = Proporsi,
color = Proporsi
)
) +
geom_line(linewidth = 0.9) +
geom_point(size = 3) +
facet_wrap(~ Metrik, scales = "free_y") +
labs(
title = "Perbandingan Accuracy dan Error Rate ANN",
x = "Jumlah hidden neuron",
y = "Nilai metrik",
color = "Training:Testing"
) +
scale_y_continuous(
labels = function(x) paste0(round(100 * x, 1), "%")
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(
face = "bold",
hjust = 0.5
),
legend.position = "bottom"
)
Gambar 4.1. Perbandingan accuracy dan error rate pada enam model ANN.
Grafik digunakan untuk mengamati perubahan accuracy dan error rate ketika jumlah hidden neuron meningkat dari 10 menjadi 20 dan 30. Kedua skenario pembagian data ditampilkan agar perbedaannya dapat diamati.
Apabila garis accuracy meningkat, hal tersebut menunjukkan bahwa proporsi klasifikasi benar meningkat pada konfigurasi tersebut. Sebaliknya, apabila error rate meningkat, proporsi kesalahan klasifikasi menjadi lebih besar.
Penambahan hidden neuron tidak selalu meningkatkan accuracy. Jumlah neuron yang lebih besar meningkatkan kapasitas jaringan, tetapi hasil akhirnya juga bergantung pada karakteristik data, inisialisasi bobot, dan proses optimasi.
ggplot(
tabel_hasil,
aes(
x = factor(Hidden_Neuron),
y = Macro_F1,
group = Proporsi,
color = Proporsi
)
) +
geom_line(linewidth = 0.9) +
geom_point(size = 3) +
labs(
title = "Perbandingan Macro-F1 ANN",
x = "Jumlah hidden neuron",
y = "Macro-F1",
color = "Training:Testing"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(
face = "bold",
hjust = 0.5
),
legend.position = "bottom"
)
Gambar 4.2. Perbandingan macro-F1 pada enam model ANN.
Macro-F1 merupakan rata-rata F1-score dari ketiga spesies. Nilai yang lebih tinggi menunjukkan bahwa model mempunyai keseimbangan precision dan recall yang lebih baik secara rata-rata.
Grafik ini melengkapi perbandingan accuracy. Jika dua model mempunyai accuracy yang sama, model dengan macro-F1 lebih tinggi dapat memberikan performa yang lebih seimbang di antara ketiga spesies. Namun, pemilihan model utama pada praktikum ini tetap mengikuti kriteria accuracy tertinggi yang telah ditetapkan.
Model terbaik dipilih berdasarkan accuracy testing tertinggi. Jika terdapat beberapa model dengan accuracy sama, error rate terendah digunakan sebagai pembanding, kemudian macro-F1 tertinggi sebagai kriteria berikutnya.
peringkat <- tabel_hasil[
order(
-tabel_hasil$Accuracy,
tabel_hasil$Error_Rate,
-tabel_hasil$Macro_F1
),
]
rownames(peringkat) <- NULL
peringkat_tampil <- peringkat
peringkat_tampil[kolom_metrik] <- lapply(
peringkat_tampil[kolom_metrik],
fmt
)
knitr::kable(
peringkat_tampil,
caption = "Tabel 4.5 Peringkat model ANN berdasarkan hasil testing"
)
| Model | Proporsi | Training | Testing | Hidden_Neuron | Accuracy | Error_Rate | Macro_Precision | Macro_Recall | Macro_F1 |
|---|---|---|---|---|---|---|---|---|---|
| ANN_80_20_H10 | 80:20 | 120 | 30 | 10 | 0.9667 | 0.0333 | 0.9697 | 0.9667 | 0.9666 |
| ANN_80_20_H20 | 80:20 | 120 | 30 | 20 | 0.9667 | 0.0333 | 0.9697 | 0.9667 | 0.9666 |
| ANN_80_20_H30 | 80:20 | 120 | 30 | 30 | 0.9667 | 0.0333 | 0.9697 | 0.9667 | 0.9666 |
| ANN_60_40_H10 | 60:40 | 90 | 60 | 10 | 0.9167 | 0.0833 | 0.9173 | 0.9167 | 0.9166 |
| ANN_60_40_H20 | 60:40 | 90 | 60 | 20 | 0.9167 | 0.0833 | 0.9173 | 0.9167 | 0.9166 |
| ANN_60_40_H30 | 60:40 | 90 | 60 | 30 | 0.9167 | 0.0833 | 0.9173 | 0.9167 | 0.9166 |
model_terbaik_nama <- peringkat$Model[1]
cat(
"\nModel terbaik:", model_terbaik_nama,
"\nProporsi training:testing:", peringkat$Proporsi[1],
"\nHidden neuron:", peringkat$Hidden_Neuron[1],
"\nJumlah data testing:", peringkat$Testing[1],
"\nAccuracy:", round(peringkat$Accuracy[1], 4),
"\nError rate:", round(peringkat$Error_Rate[1], 4),
"\nMacro-precision:", round(peringkat$Macro_Precision[1], 4),
"\nMacro-recall:", round(peringkat$Macro_Recall[1], 4),
"\nMacro-F1:", round(peringkat$Macro_F1[1], 4),
"\n"
)
##
## Model terbaik: ANN_80_20_H10
## Proporsi training:testing: 80:20
## Hidden neuron: 10
## Jumlah data testing: 30
## Accuracy: 0.9667
## Error rate: 0.0333
## Macro-precision: 0.9697
## Macro-recall: 0.9667
## Macro-F1: 0.9666
Berdasarkan aturan pemeringkatan, model pada urutan pertama merupakan model dengan accuracy testing tertinggi. Jika beberapa model memiliki accuracy yang sama, error rate dan macro-F1 digunakan untuk menentukan urutan berikutnya.
Model terbaik pada eksperimen ini tidak otomatis menjadi konfigurasi terbaik untuk seluruh kondisi. Hasil tersebut berlaku untuk pembagian data, seed, dan pengaturan pelatihan yang digunakan dalam praktikum.
cm_terbaik <- confusion_list[[model_terbaik_nama]]
cat("Confusion matrix model terbaik:\n")
## Confusion matrix model terbaik:
knitr::kable(
as.data.frame.matrix(cm_terbaik),
caption = paste(
"Tabel 4.6 Confusion matrix model terbaik:",
model_terbaik_nama
)
)
| setosa | versicolor | virginica | |
|---|---|---|---|
| setosa | 10 | 0 | 0 |
| versicolor | 0 | 9 | 1 |
| virginica | 0 | 0 | 10 |
metrik_terbaik <- metrik_kelas_list[[model_terbaik_nama]]
knitr::kable(
transform(
metrik_terbaik,
Precision = round(Precision, 4),
Recall = round(Recall, 4),
F1_Score = round(F1_Score, 4)
),
caption = "Tabel 4.7 Metrik per kelas model terbaik"
)
| Kelas | Precision | Recall | F1_Score |
|---|---|---|---|
| setosa | 1.0000 | 1.0 | 1.0000 |
| versicolor | 1.0000 | 0.9 | 0.9474 |
| virginica | 0.9091 | 1.0 | 0.9524 |
Confusion matrix model terbaik digunakan untuk mengetahui spesies yang paling banyak salah diklasifikasikan. Apabila seluruh nilai diagonal tinggi dan nilai di luar diagonal kecil, model mampu membedakan ketiga spesies dengan baik.
Sebaliknya, apabila kesalahan terkonsentrasi pada pasangan spesies tertentu, hal tersebut menunjukkan bahwa karakteristik kedua spesies tersebut lebih sulit dibedakan oleh model berdasarkan prediktor yang digunakan.
Precision, recall, dan F1-score per kelas digunakan untuk memperjelas hasil tersebut. Spesies dengan recall terendah merupakan kelas yang paling banyak gagal dikenali dari seluruh pengamatan aktual kelas tersebut. Spesies dengan precision terendah memiliki proporsi prediksi benar yang relatif rendah di antara seluruh prediksi untuk kelas tersebut.
cat("### Interpretasi skenario 80% training dan 20% testing\n\n")
hasil_80 <- tabel_hasil[
tabel_hasil$Proporsi == "80:20",
]
for (i in seq_len(nrow(hasil_80))) {
baris <- hasil_80[i, ]
cat(
"**Hidden neuron ", baris$Hidden_Neuron, ":** ",
"accuracy sebesar ",
round(100 * baris$Accuracy, 2),
"% dan error rate sebesar ",
round(100 * baris$Error_Rate, 2),
"%. Macro-F1 sebesar ",
round(baris$Macro_F1, 4),
". ",
sep = ""
)
if (i == 1) {
cat(
"Hasil ini merupakan evaluasi model dengan 10 neuron ",
"tersembunyi pada skenario 80:20.\n\n",
sep = ""
)
} else {
cat(
"Nilai tersebut dibandingkan dengan konfigurasi hidden ",
"neuron lainnya untuk melihat perubahan performa.\n\n",
sep = ""
)
}
}
Hidden neuron 10: accuracy sebesar 96.67% dan error rate sebesar 3.33%. Macro-F1 sebesar 0.9666. Hasil ini merupakan evaluasi model dengan 10 neuron tersembunyi pada skenario 80:20.
Hidden neuron 20: accuracy sebesar 96.67% dan error rate sebesar 3.33%. Macro-F1 sebesar 0.9666. Nilai tersebut dibandingkan dengan konfigurasi hidden neuron lainnya untuk melihat perubahan performa.
Hidden neuron 30: accuracy sebesar 96.67% dan error rate sebesar 3.33%. Macro-F1 sebesar 0.9666. Nilai tersebut dibandingkan dengan konfigurasi hidden neuron lainnya untuk melihat perubahan performa.
cat("### Interpretasi skenario 60% training dan 40% testing\n\n")
hasil_60 <- tabel_hasil[
tabel_hasil$Proporsi == "60:40",
]
for (i in seq_len(nrow(hasil_60))) {
baris <- hasil_60[i, ]
cat(
"**Hidden neuron ", baris$Hidden_Neuron, ":** ",
"accuracy sebesar ",
round(100 * baris$Accuracy, 2),
"% dan error rate sebesar ",
round(100 * baris$Error_Rate, 2),
"%. Macro-F1 sebesar ",
round(baris$Macro_F1, 4),
". ",
sep = ""
)
if (i == 1) {
cat(
"Hasil ini merupakan evaluasi model dengan 10 neuron ",
"tersembunyi pada skenario 60:40.\n\n",
sep = ""
)
} else {
cat(
"Nilai tersebut dibandingkan dengan konfigurasi hidden ",
"neuron lainnya pada skenario pembagian data yang sama.\n\n",
sep = ""
)
}
}
Hidden neuron 10: accuracy sebesar 91.67% dan error rate sebesar 8.33%. Macro-F1 sebesar 0.9166. Hasil ini merupakan evaluasi model dengan 10 neuron tersembunyi pada skenario 60:40.
Hidden neuron 20: accuracy sebesar 91.67% dan error rate sebesar 8.33%. Macro-F1 sebesar 0.9166. Nilai tersebut dibandingkan dengan konfigurasi hidden neuron lainnya pada skenario pembagian data yang sama.
Hidden neuron 30: accuracy sebesar 91.67% dan error rate sebesar 8.33%. Macro-F1 sebesar 0.9166. Nilai tersebut dibandingkan dengan konfigurasi hidden neuron lainnya pada skenario pembagian data yang sama.
akurasi_80 <- mean(hasil_80$Accuracy)
akurasi_60 <- mean(hasil_60$Accuracy)
cat("### Perbandingan rata-rata kedua skenario\n\n")
cat(
"Rata-rata accuracy skenario 80:20 adalah **",
round(100 * akurasi_80, 2),
"%**, sedangkan rata-rata accuracy skenario 60:40 adalah **",
round(100 * akurasi_60, 2),
"%**.\n\n",
sep = ""
)
Rata-rata accuracy skenario 80:20 adalah 96.67%, sedangkan rata-rata accuracy skenario 60:40 adalah 91.67%.
if (akurasi_80 > akurasi_60) {
cat(
"Dalam eksperimen ini, rata-rata accuracy skenario 80:20 ",
"lebih tinggi. Hasil tersebut konsisten dengan kemungkinan ",
"bahwa tambahan data training membantu jaringan mempelajari ",
"pola kelas, tetapi tidak membuktikan bahwa proporsi 80:20 ",
"akan selalu lebih unggul pada pembagian data lain.\n\n",
sep = ""
)
} else if (akurasi_60 > akurasi_80) {
cat(
"Dalam eksperimen ini, rata-rata accuracy skenario 60:40 ",
"lebih tinggi. Hasil tersebut menunjukkan bahwa pada ",
"pembagian data dan inisialisasi yang digunakan, skenario ",
"60:40 menghasilkan rata-rata accuracy yang lebih baik. ",
"Hasil ini tidak berarti bahwa lebih sedikit data training ",
"selalu menghasilkan model yang lebih baik.\n\n",
sep = ""
)
} else {
cat(
"Kedua skenario memiliki rata-rata accuracy yang sama ",
"pada eksperimen ini. Perbandingan berikutnya perlu ",
"memperhatikan variasi performa masing-masing hidden neuron ",
"serta metrik per kelas.\n\n",
sep = ""
)
}
Dalam eksperimen ini, rata-rata accuracy skenario 80:20 lebih tinggi. Hasil tersebut konsisten dengan kemungkinan bahwa tambahan data training membantu jaringan mempelajari pola kelas, tetapi tidak membuktikan bahwa proporsi 80:20 akan selalu lebih unggul pada pembagian data lain.
Bagian ini menyajikan interpretasi numerik berdasarkan hasil perhitungan aktual, bukan angka yang ditentukan sebelumnya. Dengan demikian, narasi accuracy, error rate, macro-F1, dan rata-rata antarskenario akan menyesuaikan hasil model ketika dokumen dijalankan.
Perbandingan kedua skenario harus dilakukan secara hati-hati karena jumlah data testing berbeda. Skenario 60:40 memiliki lebih banyak pengamatan testing sehingga evaluasinya didasarkan pada lebih banyak observasi, sedangkan skenario 80:20 menyediakan lebih banyak pengamatan untuk pelatihan jaringan.
ANN mempelajari pola klasifikasi dengan menyesuaikan bobot koneksi pada jaringan. Pada dataset Iris, empat variabel pengukuran bunga digunakan untuk membedakan tiga spesies.
Perubahan jumlah hidden neuron dapat mengubah kemampuan jaringan dalam mempelajari hubungan antara prediktor dan kelas. Jumlah neuron yang terlalu sedikit dapat membatasi kompleksitas pola yang dipelajari, sedangkan jumlah neuron yang lebih besar dapat menambah kompleksitas model.
Perbedaan proporsi training dan testing juga memengaruhi eksperimen. Pembagian 80:20 memberikan lebih banyak data untuk pembelajaran, sedangkan pembagian 60:40 menyediakan lebih banyak data untuk evaluasi. Hasil keduanya dapat berbeda akibat variasi pengamatan dan proses optimasi jaringan.
Accuracy dan error rate memberikan gambaran performa klasifikasi keseluruhan. Sementara itu, precision, recall, F1-score, dan confusion matrix membantu mengidentifikasi karakteristik kesalahan pada setiap spesies. Oleh karena itu, penentuan model terbaik sebaiknya tetap disertai pemeriksaan hasil per kelas.
Kesimpulan numerik akhir mengikuti tabel dan grafik yang dihasilkan oleh program. Model dengan accuracy tertinggi merupakan model terbaik berdasarkan kriteria utama praktikum ini, tetapi hasil satu eksperimen belum cukup untuk menyatakan bahwa model tersebut selalu lebih unggul pada pembagian data lain.
Artificial Neural Network berhasil dirancang untuk permasalahan klasifikasi multikelas pada dataset Iris menggunakan empat variabel prediktor dan tiga kategori spesies. Eksperimen dilakukan dengan dua proporsi pembagian data, yaitu 80% training dan 20% testing serta 60% training dan 40% testing.
Pada setiap skenario, model dibangun menggunakan 10, 20, dan 30 hidden neuron sehingga menghasilkan enam konfigurasi ANN. Evaluasi dilakukan menggunakan confusion matrix, accuracy, error rate, precision, recall, dan F1-score.
Perbandingan keenam model digunakan untuk mengetahui hubungan jumlah hidden neuron dan proporsi data terhadap hasil klasifikasi. Model terbaik ditentukan berdasarkan accuracy testing tertinggi, dengan error rate dan macro-F1 sebagai kriteria pembanding jika diperlukan.
Nama model terbaik, nilai accuracy, error rate, dan metrik lainnya diperoleh secara otomatis dari hasil komputasi pada Tabel 4.5. Dengan demikian, kesimpulan numerik akhir harus mengikuti output aktual ketika laporan dijalankan.
Penelitian selanjutnya dapat menguji beberapa nilai
decay, jumlah iterasi, dan konfigurasi arsitektur jaringan
lainnya untuk melihat pengaruh pengaturan model terhadap performa
klasifikasi.
Pengulangan pembagian data atau penggunaan validasi silang juga disarankan untuk mengevaluasi kestabilan performa ANN. Selain itu, hasil klasifikasi dapat dibandingkan dengan metode lain seperti Decision Tree, Random Forest, atau Support Vector Machine untuk mengetahui performa relatif setiap metode pada dataset yang sama.
Bishop, C. M. (2006). Pattern recognition and machine learning. Springer.
Goodfellow, I., Bengio, Y., & Courville, A. (2016). Deep learning. MIT Press.
James, G., Witten, D., Hastie, T., & Tibshirani, R. (2021). An introduction to statistical learning: With applications in R (2nd ed.). Springer.
Ripley, B. D. (1996). Pattern recognition and neural networks. Cambridge University Press.
Venables, W. N., & Ripley, B. D. (2002). Modern applied statistics with S (4th ed.). Springer.
R Core Team. (2026). R: A language and environment for statistical computing. R Foundation for Statistical Computing.
Kode program terdapat pada setiap bagian laporan ini. Jalankan dokumen melalui tombol Knit di RStudio untuk menghasilkan laporan HTML yang berisi pembentukan data, pembagian training dan testing, enam model ANN, confusion matrix, metrik klasifikasi, grafik perbandingan, dan interpretasi otomatis berdasarkan hasil perhitungan aktual.