Artificial Neural Network (ANN) atau Jaringan Syaraf Tiruan (JST) adalah model komputasi yang terinspirasi dari cara kerja otak manusia, yaitu sejumlah neuron yang saling terhubung untuk memproses informasi dan mempelajari pola dari data (Haykin, 2009). Kemampuan ANN dalam menangkap hubungan nonlinier menjadikannya populer dalam berbagai persoalan prediksi dan klasifikasi. Di Indonesia, ANN dengan algoritma backpropagation telah digunakan, misalnya, untuk memprediksi hasil panen tanaman sayuran (Hutabarat dkk., 2021), mengklasifikasikan jenis biji gandum (Tanjung, 2021; Anggraini dkk., 2026), memprediksi tingkat kelulusan mahasiswa (Muamar & Muhajirin, 2024), serta memprediksi dini risiko penyakit diabetes dengan dua hidden layer yang masing-masing berisi 10 neuron (Nisa dkk., 2025).
Meskipun fleksibel, kinerja ANN sangat dipengaruhi oleh konfigurasi jaringan, terutama jumlah neuron pada hidden layer, jumlah iterasi pelatihan, serta bobot awal yang dibangkitkan secara acak (Muamar & Muhajirin, 2024; Mustafidah & Rohman, 2023; Anggraini dkk., 2026). Jumlah neuron yang terlalu sedikit berisiko underfitting, sedangkan jumlah neuron yang terlalu banyak berisiko overfitting, yaitu model sangat baik pada data training tetapi menurun pada data baru. Selain itu, proporsi pembagian data training dan testing menentukan seberapa banyak informasi yang dipelajari model dan seberapa andal evaluasinya.
Oleh karena itu, praktikum ini menerapkan ANN klasifikasi pada data
Iris menggunakan paket nnet di R, dengan
membandingkan tiga ukuran hidden layer (10, 20, dan 30 neuron)
pada dua proporsi pembagian data (80:20 dan 60:40). Kinerja model
dievaluasi menggunakan confusion matrix, akurasi, dan presisi
(serta recall dan F1-score sebagai pelengkap) (Pambudi
dkk., 2025).
Soal: Lakukan ANN Klasifikasi dengan Hidden Neuron = c(10, 20, 30) dengan data training 80% dan testing 20% serta data training 60% dan testing 40%, kemudian interpretasikan masing-masing output dengan jelas.
Data pilihan: Iris (150 pengamatan, 4 prediktor numerik, 1 respons kategorik 3 kelas).
Batasan yang digunakan: (1) arsitektur satu hidden layer
sesuai kemampuan paket nnet; (2) set.seed(917)
untuk pembagian data dan pelatihan agar hasil dapat direproduksi; (3)
jumlah iterasi maksimum maxit = 500; (4) total terdapat
6 skenario model (3 ukuran hidden layer × 2
proporsi data).
ANN tersusun atas tiga jenis lapisan: lapisan masukan (input layer), lapisan tersembunyi (hidden layer), dan lapisan keluaran (output layer). Setiap neuron menerima masukan yang dikalikan bobot, ditambah bias, lalu diproses oleh fungsi aktivasi (Fausett, 1994):
\[ y = f\left(\sum_{i=1}^{p} w_i x_i + b\right) \]
dengan \(x_i\) masukan ke-\(i\), \(w_i\) bobot, \(b\) bias, \(f\) fungsi aktivasi, dan \(y\) keluaran neuron. Tiga komponen utama ANN adalah arsitektur jaringan, algoritma pembelajaran, dan fungsi aktivasi.
| Arsitektur | Ciri | Kemampuan |
|---|---|---|
| Single Layer Perceptron (SLP) | Tanpa hidden layer | Hubungan linear / klasifikasi yang dapat dipisahkan secara linear |
| Multi-Layer Perceptron (MLP) | Satu atau lebih hidden layer | Hubungan nonlinier untuk regresi dan klasifikasi (Goodfellow dkk., 2016) |
Paket nnet membangun MLP dengan satu
hidden layer. Untuk \(p\)
prediktor, \(H\) neuron tersembunyi,
dan \(K\) kelas, banyaknya bobot
(termasuk bias) yang harus diestimasi adalah:
\[ \text{Jumlah bobot} = (p + 1)\,H + (H + 1)\,K \]
Backpropagation menyesuaikan bobot berdasarkan kesalahan prediksi melalui tiga tahap (Rumelhart dkk., 1986; Haykin, 2009):
\[ w_{ij}^{(t+1)} = w_{ij}^{(t)} - \eta \,\frac{\partial L}{\partial w_{ij}} \]
dengan \(\eta\) adalah learning
rate dan \(L\) fungsi kerugian.
Pada praktiknya, nnet meminimalkan fungsi kerugian dengan
algoritma optimasi BFGS, sehingga tidak memiliki argumen learning
rate seperti pada gradient descent murni. Karena bobot
awal dibangkitkan acak, hasil pelatihan dapat berbeda antarpercobaan
(Mustafidah & Rohman, 2023) sehingga set.seed()
diperlukan.
| Fungsi | Rumus | Keterangan |
|---|---|---|
| Sigmoid | \(f(z)=\dfrac{1}{1+e^{-z}}\) | Keluaran 0–1; cocok untuk klasifikasi biner dan umum dipakai pada hidden layer |
| Tanh | \(f(z)=\dfrac{1-e^{-2z}}{1+e^{-2z}}\) | Keluaran −1 hingga 1 |
| ReLU | \(f(z)=\max(0,z)\) | Mempercepat konvergensi, mengurangi masalah vanishing gradient |
| Softmax | \(f(z_k)=\dfrac{e^{z_k}}{\sum_{j=1}^{K}e^{z_j}}\) | Probabilitas tiap kelas, jumlahnya 1; untuk klasifikasi multikelas |
Pada klasifikasi biner, lapisan keluaran memakai satu neuron sigmoid. Pada klasifikasi multikelas (seperti Iris, \(K=3\)), lapisan keluaran memakai softmax dan fungsi kerugian categorical cross-entropy (Bishop, 2006):
\[ L = -\frac{1}{n}\sum_{i=1}^{n}\sum_{k=1}^{K} y_{ik}\,\log(\hat{y}_{ik}) \]
Ketika variabel respons berupa factor dengan lebih dari
dua level, fungsi nnet.formula() secara otomatis membentuk
keluaran softmax dengan satu neuron per kelas.
| Prediksi Positif | Prediksi Negatif | |
|---|---|---|
| Aktual Positif | True Positive (TP) | False Negative (FN) |
| Aktual Negatif | False Positive (FP) | True Negative (TN) |
\[ \text{Akurasi}=\frac{TP+TN}{TP+TN+FP+FN},\quad \text{Presisi}=\frac{TP}{TP+FP},\quad \text{Recall}=\frac{TP}{TP+FN},\quad F_1=2\cdot\frac{\text{Presisi}\times\text{Recall}}{\text{Presisi}+\text{Recall}} \]
Pada klasifikasi multikelas, presisi, recall, dan \(F_1\) dihitung per kelas (one-vs-rest) lalu dirata-ratakan (macro average). Metrik ini lazim dipakai dalam penelitian klasifikasi di Indonesia (Pambudi dkk., 2025; Anggraini dkk., 2026).
nnet| Argumen | Fungsi |
|---|---|
size |
Banyaknya neuron pada hidden layer (10, 20, 30 pada praktikum ini) |
maxit |
Jumlah iterasi maksimum optimasi (bawaan 100; dipakai 500 di sini) |
decay |
Penalti bobot (weight decay) untuk mengurangi overfitting (bawaan 0) |
linout |
TRUE untuk keluaran linear (regresi);
tidak dipakai pada klasifikasi |
trace |
Menampilkan/menyembunyikan log iterasi |
Visualisasi dan interpretasi model dilakukan dengan paket
NeuralNetTools (Beck, 2018): plotnet() untuk
diagram jaringan, neuralweights() untuk bobot, dan
olden() untuk kepentingan variabel (Olden dkk., 2004).
Data yang digunakan adalah data kuantitatif Iris
(bawaan R: data(iris)) yang terdiri dari 150 pengamatan,
masing-masing 50 pengamatan untuk spesies setosa,
versicolor, dan virginica.
| No | Variabel | Keterangan | Tipe | Peran |
|---|---|---|---|---|
| 1 | Species |
Spesies bunga (setosa, versicolor, virginica) | Kategorik (3 kelas) | Respons |
| 2 | Sepal.Length |
Panjang kelopak (cm) | Numerik | Prediktor |
| 3 | Sepal.Width |
Lebar kelopak (cm) | Numerik | Prediktor |
| 4 | Petal.Length |
Panjang mahkota (cm) | Numerik | Prediktor |
| 5 | Petal.Width |
Lebar mahkota (cm) | Numerik | Prediktor |
| Kode | Data training | Data testing | Hidden neuron | Arsitektur |
|---|---|---|---|---|
| 80_10 | 80% | 20% | 10 | 4-10-3 |
| 80_20 | 80% | 20% | 20 | 4-20-3 |
| 80_30 | 80% | 20% | 30 | 4-30-3 |
| 60_10 | 60% | 40% | 10 | 4-10-3 |
| 60_20 | 60% | 40% | 20 | 4-20-3 |
| 60_30 | 60% | 40% | 30 | 4-30-3 |
nnet, NeuralNetTools,
ggplot2, dan knitr.head,
summary, grafik).set.seed(917).Species ~ . dan melatih ANN dengan
nnet.formula() untuk size = 10, 20, 30.type = "class") dan menyusun confusion
matrix.plotnet(),
neuralweights(), olden().Tahap awal adalah memanggil paket yang dibutuhkan, memuat data Iris, dan memeriksa strukturnya.
# install.packages(c("nnet", "NeuralNetTools", "ggplot2", "knitr", "DiagrammeR")) # jalankan sekali bila belum ada
library(nnet)
library(NeuralNetTools)
library(ggplot2)
library(knitr)
data(iris)
dim(iris)## [1] 150 5
## '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 ...
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## Min. :4,30 Min. :2,00 Min. :1,00 Min. :0,1 setosa :50
## 1st Qu.:5,10 1st Qu.:2,80 1st Qu.:1,60 1st Qu.:0,3 versicolor:50
## Median :5,80 Median :3,00 Median :4,35 Median :1,3 virginica :50
## Mean :5,84 Mean :3,06 Mean :3,76 Mean :1,2
## 3rd Qu.:6,40 3rd Qu.:3,30 3rd Qu.:5,10 3rd Qu.:1,8
## Max. :7,90 Max. :4,40 Max. :6,90 Max. :2,5
##
## setosa versicolor virginica
## 50 50 50
long <- data.frame(
Species = rep(iris$Species, 4),
Variabel = rep(names(iris)[1:4], each = nrow(iris)),
Nilai = unlist(iris[, 1:4], use.names = FALSE)
)
ggplot(long, aes(x = Species, y = Nilai, fill = Species)) +
geom_boxplot(alpha = 0.85, outlier.colour = "#be123c") +
facet_wrap(~ Variabel, scales = "free_y") +
scale_fill_manual(values = c("#14b8a6", "#6366f1", "#f59e0b")) +
labs(x = NULL, y = "Nilai (cm)") +
theme_minimal(base_size = 12) +
theme(legend.position = "none", strip.text = element_text(face = "bold"))Sebaran setiap prediktor menurut spesies
ggplot(iris, aes(Petal.Length, Petal.Width, colour = Species)) +
geom_point(size = 2.6, alpha = 0.85) +
scale_colour_manual(values = c("#14b8a6", "#6366f1", "#f59e0b")) +
labs(x = "Petal.Length (cm)", y = "Petal.Width (cm)") +
theme_minimal(base_size = 12)Diagram pencar Petal.Length vs Petal.Width
Data Iris terdiri atas 150 pengamatan dan 5
variabel (4 prediktor numerik dan 1 respons kategorik dengan 3
kelas yang seimbang, masing-masing 50 pengamatan). Pada grafik terlihat
bahwa spesies setosa terpisah jelas dari dua spesies lain,
terutama pada Petal.Length dan Petal.Width,
sedangkan versicolor dan virginica saling beririsan.
Dengan demikian, kesalahan klasifikasi—bila ada—umumnya akan muncul di
antara versicolor dan virginica.
Agar kode ringkas dan konsisten pada keenam skenario, dibuat dua
fungsi: hitung_metrik() untuk menghitung confusion
matrix beserta metrik evaluasi, dan latih_ann() untuk
membagi data, melatih ANN, dan memprediksi. Sintaks inti mengikuti modul
praktikum
(nnet.formula(form, size = ..., data = train)).
SEED_SPLIT <- 917 # seed untuk pembagian data (sesuai modul)
SEED_FIT <- 917 # seed untuk bobot awal jaringan
MAXIT <- 500 # iterasi maksimum (bawaan nnet = 100)
# Formula: Species ~ semua prediktor lain (sama seperti modul)
i <- names(iris)
form <- as.formula(paste("Species ~", paste(i[!i %in% "Species"], collapse = " + ")))
form## Species ~ Sepal.Length + Sepal.Width + Petal.Length + Petal.Width
# Confusion matrix + metrik per kelas dan rata-rata (macro)
hitung_metrik <- function(aktual, prediksi) {
kelas <- levels(aktual)
prediksi <- factor(as.character(prediksi), levels = kelas)
cm <- table(Aktual = aktual, Prediksi = prediksi)
tp <- diag(cm)
kol <- colSums(cm) # total prediksi per kelas
bar <- rowSums(cm) # total aktual per kelas
presisi <- ifelse(kol == 0, NA, tp / kol)
recall <- ifelse(bar == 0, NA, tp / bar)
f1 <- ifelse(is.na(presisi) | is.na(recall) | (presisi + recall) == 0,
NA, 2 * presisi * recall / (presisi + recall))
list(cm = cm, akurasi = sum(tp) / sum(cm),
presisi = unname(presisi), recall = unname(recall), f1 = unname(f1),
presisi_macro = mean(presisi, na.rm = TRUE),
recall_macro = mean(recall, na.rm = TRUE),
f1_macro = mean(f1, na.rm = TRUE))
}
# Split data -> latih ANN -> prediksi -> evaluasi
latih_ann <- function(prop, size, seed_split = SEED_SPLIT, seed_fit = SEED_FIT, maxit = MAXIT) {
set.seed(seed_split)
index <- sample(seq_len(nrow(iris)), round(prop * nrow(iris)))
train <- iris[index, ]
test <- iris[-index, ]
set.seed(seed_fit)
nn <- nnet::nnet.formula(form, data = train, size = size, maxit = maxit, trace = FALSE)
pred_train <- predict(nn, newdata = train, type = "class")
pred_test <- predict(nn, newdata = test, type = "class")
list(prop = prop, size = size,
n_train = nrow(train), n_test = nrow(test),
model = nn, train = train, test = test,
m_train = hitung_metrik(train$Species, pred_train),
m_test = hitung_metrik(test$Species, pred_test),
bobot = length(nn$wts), konvergen = (nn$convergence == 0), loss = nn$value)
}Selanjutnya keenam model dilatih sekaligus.
skenario <- expand.grid(size = c(10, 20, 30), prop = c(0.8, 0.6))
skenario$kode <- sprintf("%d_%d", round(skenario$prop * 100), skenario$size)
hasil <- lapply(seq_len(nrow(skenario)), function(k) latih_ann(skenario$prop[k], skenario$size[k]))
names(hasil) <- skenario$kode
names(hasil)## [1] "80_10" "80_20" "80_30" "60_10" "60_20" "60_30"
tabel <- data.frame(
Prop = sapply(hasil, function(h) h$prop),
Split = sapply(hasil, function(h) paste0(round(h$prop * 100), ":", round((1 - h$prop) * 100))),
Hidden = sapply(hasil, function(h) h$size),
n_train = sapply(hasil, function(h) h$n_train),
n_test = sapply(hasil, function(h) h$n_test),
Bobot = sapply(hasil, function(h) h$bobot),
Konvergen = sapply(hasil, function(h) ifelse(h$konvergen, "Ya", "Tidak (maxit)")),
Loss = sapply(hasil, function(h) h$loss),
Acc_train = sapply(hasil, function(h) h$m_train$akurasi),
Acc_test = sapply(hasil, function(h) h$m_test$akurasi),
Presisi = sapply(hasil, function(h) h$m_test$presisi_macro),
Recall = sapply(hasil, function(h) h$m_test$recall_macro),
F1 = sapply(hasil, function(h) h$m_test$f1_macro),
stringsAsFactors = FALSE
)
tabel$Selisih <- tabel$Acc_train - tabel$Acc_test
tampil <- data.frame(
Skenario = rownames(tabel),
`Split (train:test)` = tabel$Split,
`Hidden neuron` = tabel$Hidden,
`Jumlah bobot` = tabel$Bobot,
Konvergen = tabel$Konvergen,
`Akurasi train (%)` = round(100 * tabel$Acc_train, 2),
`Akurasi test (%)` = round(100 * tabel$Acc_test, 2),
`Presisi (%)` = round(100 * tabel$Presisi, 2),
`Recall (%)` = round(100 * tabel$Recall, 2),
`F1 (%)` = round(100 * tabel$F1, 2),
check.names = FALSE
)
kable(tampil, row.names = FALSE, align = "lcccccccc",
caption = "Tabel 1. Ringkasan kinerja seluruh skenario ANN (presisi, recall, dan F1 = rata-rata macro pada data testing)")| Skenario | Split (train:test) | Hidden neuron | Jumlah bobot | Konvergen | Akurasi train (%) | Akurasi test (%) | Presisi (%) | Recall (%) | F1 (%) |
|---|---|---|---|---|---|---|---|---|---|
| 80_10 | 80:20 | 10 | 83 | Ya | 100 | 96,67 | 96,97 | 97,22 | 96,96 |
| 80_20 | 80:20 | 20 | 163 | Ya | 100 | 90,00 | 92,31 | 91,67 | 90,89 |
| 80_30 | 80:20 | 30 | 243 | Ya | 100 | 90,00 | 91,17 | 90,56 | 90,74 |
| 60_10 | 60:40 | 10 | 83 | Ya | 100 | 95,00 | 95,48 | 95,10 | 95,26 |
| 60_20 | 60:40 | 20 | 163 | Ya | 100 | 95,00 | 95,48 | 95,10 | 95,26 |
| 60_30 | 60:40 | 30 | 243 | Ya | 100 | 95,00 | 96,30 | 94,74 | 95,18 |
# Model terbaik: akurasi testing tertinggi -> F1 tertinggi -> jumlah bobot paling sedikit (paling sederhana)
ord <- order(-tabel$Acc_test, -tabel$F1, tabel$Bobot)
kode_best <- rownames(tabel)[ord[1]]
best <- hasil[[kode_best]]
kode_best## [1] "80_10"
Ringkasan cepat. Akurasi testing tertinggi adalah
96,67%, dicapai oleh skenario 80_10. Model
yang dipilih sebagai model terbaik (kriteria: akurasi testing, lalu F1,
lalu model paling sederhana) adalah 80_10
(10 hidden neuron, split 80:20).
perf <- rbind(
data.frame(Split = tabel$Split, Hidden = tabel$Hidden, Data = "Training", Akurasi = tabel$Acc_train),
data.frame(Split = tabel$Split, Hidden = tabel$Hidden, Data = "Testing", Akurasi = tabel$Acc_test)
)
perf$Split <- factor(perf$Split, levels = c("80:20", "60:40"),
labels = c("Split 80:20", "Split 60:40"))
batas_bawah <- max(0, floor(min(perf$Akurasi) * 10) * 10 - 10)
ggplot(perf, aes(x = factor(Hidden), y = Akurasi * 100, fill = Data)) +
geom_col(position = position_dodge(width = 0.85), width = 0.78) +
geom_text(aes(label = format(round(Akurasi * 100, 1), nsmall = 1)),
position = position_dodge(width = 0.85), vjust = -0.4, size = 3.2) +
facet_wrap(~ Split) +
coord_cartesian(ylim = c(batas_bawah, 104)) +
scale_fill_manual(values = c(Training = "#6366f1", Testing = "#14b8a6")) +
labs(x = "Jumlah hidden neuron", y = "Akurasi (%)",
caption = paste0("Catatan: sumbu-y dimulai dari ", batas_bawah, "%")) +
theme_minimal(base_size = 12) +
theme(legend.position = "top", strip.text = element_text(face = "bold"))Perbandingan akurasi training vs testing pada setiap skenario
cm_long <- do.call(rbind, lapply(hasil, function(h) {
d <- as.data.frame(h$m_test$cm, stringsAsFactors = FALSE)
d$Split <- paste0("Split ", round(h$prop * 100), ":", round((1 - h$prop) * 100))
d$Hidden <- paste0("H = ", h$size)
d
}))
cm_long$Split <- factor(cm_long$Split, levels = c("Split 80:20", "Split 60:40"))
cm_long$Hidden <- factor(cm_long$Hidden, levels = c("H = 10", "H = 20", "H = 30"))
ggplot(cm_long, aes(x = Prediksi, y = Aktual, fill = Freq)) +
geom_tile(colour = "white", linewidth = 1) +
geom_text(aes(label = Freq), fontface = "bold", size = 4.2) +
facet_grid(Split ~ Hidden) +
scale_y_discrete(limits = rev(levels(iris$Species))) +
scale_fill_gradient(low = "#f1f5f9", high = "#0d9488") +
labs(x = "Kelas prediksi", y = "Kelas aktual", fill = "Jumlah") +
theme_minimal(base_size = 11) +
theme(axis.text.x = element_text(angle = 30, hjust = 1), strip.text = element_text(face = "bold"))Confusion matrix data testing untuk keenam skenario
Setiap tab berikut menyajikan: informasi arsitektur dan pelatihan, confusion matrix data testing, metrik per kelas, serta interpretasi yang disusun otomatis dari hasil model.
a) Pengaruh jumlah hidden neuron (pada split yang sama)
b) Pengaruh proporsi data training
c) Kompleksitas model vs. jumlah data
Eksplorasi dilakukan pada model terbaik (kode_best)
menggunakan paket NeuralNetTools.
plotnet)Diagram ANN model terbaik (garis: bobot positif/negatif; ketebalan menunjukkan besar bobot)
neuralweights) — contoh pada arsitektur
4-10-3 (split 80:20)## $struct
## [1] 4 10 3
##
## $wts
## $wts$`hidden 1 1`
## [1] 7,1698 41,2248 16,3565 32,7017 9,9819
##
## $wts$`hidden 1 2`
## [1] -1,7707 -4,7789 -4,5566 3,3066 1,3412
##
## $wts$`hidden 1 3`
## [1] 69847 15337 17221 -33084 -31284
##
## $wts$`hidden 1 4`
## [1] -0,137197 2,342256 1,569855 0,078722 0,669239
##
## $wts$`hidden 1 5`
## [1] 2,7734 3,6479 14,6938 -27,1665 -13,2884
##
## $wts$`hidden 1 6`
## [1] 147,023 48,841 -107,387 107,546 -407,669
##
## $wts$`hidden 1 7`
## [1] 1,1914 4,8146 2,6996 2,4197 1,0239
##
## $wts$`hidden 1 8`
## [1] 52,7541 -22,8494 16,7570 4,1767 13,0790
##
## $wts$`hidden 1 9`
## [1] 1,4494 5,0222 1,7877 2,9949 1,6670
##
## $wts$`hidden 1 10`
## [1] 83,763 1737,955 933,949 815,524 1141,024
##
## $wts$`out 1`
## [1] -113,39105 -113,96990 -8,68070 5769,98814 -112,98335 5818,11690
## [7] 0,52101 -109,59830 7,07234 -114,39508 -111,67810
##
## $wts$`out 2`
## [1] 43,809 42,683 3,933 13417,863 43,344 -5804,518 80,323
## [8] 41,261 10,383 45,729 32,668
##
## $wts$`out 3`
## [1] 70,7553 72,4886 4,1251 -19188,6049 69,4389 -13,8554
## [7] -81,8143 67,1558 -17,4905 69,3547 79,0614
olden)kelas_out <- levels(iris$Species)
berhasil <- 0
for (k in kelas_out) {
g <- tryCatch(olden(best$model, out_var = k) + ggtitle(paste("Kelas keluaran:", k)),
error = function(e) NULL)
if (!is.null(g)) { print(g); berhasil <- berhasil + 1 }
}Kepentingan variabel (metode Olden) untuk tiap kelas keluaran pada model terbaik
Kepentingan variabel (metode Olden) untuk tiap kelas keluaran pada model terbaik
Kepentingan variabel (metode Olden) untuk tiap kelas keluaran pada model terbaik
Pada diagram plotnet, lapisan kiri adalah 4 prediktor,
lapisan tengah adalah hidden neuron, dan lapisan kanan adalah 3
kelas keluaran; garis dengan warna berbeda menunjukkan bobot positif dan
negatif, sedangkan garis yang lebih tebal menunjukkan bobot yang lebih
besar. Pada grafik olden, batang positif
berarti kenaikan nilai variabel meningkatkan skor kelas keluaran yang
bersangkutan, sedangkan batang negatif berarti
sebaliknya; semakin panjang batang, semakin besar kontribusi variabel.
Karena Petal.Length dan Petal.Width paling
membedakan spesies pada eksplorasi data, kedua variabel ini umumnya
muncul sebagai kontributor terbesar—periksa grafik di atas untuk
memastikannya pada model yang terpilih.
Karena data testing Iris sangat kecil dan bobot awal acak, hasil dari satu kali split bisa kebetulan baik atau buruk. Sebagai pelengkap, setiap kombinasi (split × hidden neuron) diulang 30 kali dengan pembagian data dan bobot awal yang berbeda, lalu akurasi testing-nya diringkas.
ulangi_split <- function(prop, size, B = 30) {
akurasi <- numeric(B)
for (b in seq_len(B)) {
set.seed(1000 + b)
idx <- sample(seq_len(nrow(iris)), round(prop * nrow(iris)))
set.seed(5000 + b)
nn <- nnet::nnet.formula(form, data = iris[idx, ], size = size, maxit = MAXIT, trace = FALSE)
pr <- predict(nn, newdata = iris[-idx, ], type = "class")
akurasi[b] <- mean(pr == as.character(iris$Species[-idx]))
}
akurasi
}
rep_df <- do.call(rbind, lapply(seq_len(nrow(skenario)), function(k) {
data.frame(Split = paste0(round(skenario$prop[k] * 100), ":", round((1 - skenario$prop[k]) * 100)),
Hidden = skenario$size[k],
Akurasi = ulangi_split(skenario$prop[k], skenario$size[k]))
}))
rep_df$Split <- factor(rep_df$Split, levels = c("80:20", "60:40"))
rep_df$Hidden <- factor(rep_df$Hidden, levels = c(10, 20, 30))
rep_tab <- do.call(rbind, lapply(split(rep_df, list(rep_df$Split, rep_df$Hidden), drop = TRUE), function(d) {
data.frame(Split = as.character(d$Split[1]), Hidden = as.character(d$Hidden[1]),
`Rata-rata (%)` = round(100 * mean(d$Akurasi), 2),
`Simpangan baku (%)` = round(100 * sd(d$Akurasi), 2),
`Min (%)` = round(100 * min(d$Akurasi), 2),
`Maks (%)` = round(100 * max(d$Akurasi), 2),
check.names = FALSE)
}))
rep_tab <- rep_tab[order(factor(rep_tab$Split, levels = c("80:20", "60:40")), as.numeric(rep_tab$Hidden)), ]
kable(rep_tab, row.names = FALSE, align = "ccrrrr",
caption = "Tabel 2. Ringkasan akurasi testing dari 30 kali pengulangan")| Split | Hidden | Rata-rata (%) | Simpangan baku (%) | Min (%) | Maks (%) |
|---|---|---|---|---|---|
| 80:20 | 10 | 96,33 | 3,65 | 90,00 | 100 |
| 80:20 | 20 | 95,44 | 3,66 | 90,00 | 100 |
| 80:20 | 30 | 93,89 | 5,26 | 76,67 | 100 |
| 60:40 | 10 | 94,72 | 5,89 | 66,67 | 100 |
| 60:40 | 20 | 94,78 | 2,86 | 88,33 | 100 |
| 60:40 | 30 | 95,44 | 2,70 | 90,00 | 100 |
ggplot(rep_df, aes(x = Hidden, y = Akurasi * 100, fill = Hidden)) +
geom_boxplot(alpha = 0.85, outlier.colour = "#be123c") +
geom_jitter(width = 0.12, alpha = 0.45, size = 1.5) +
stat_summary(fun = mean, geom = "point", shape = 23, size = 3, fill = "white") +
facet_wrap(~ Split, labeller = labeller(Split = function(x) paste("Split", x))) +
scale_fill_manual(values = c("#14b8a6", "#6366f1", "#f59e0b")) +
labs(x = "Jumlah hidden neuron", y = "Akurasi testing (%)",
caption = "Belah ketupat putih = rata-rata") +
theme_minimal(base_size = 12) +
theme(legend.position = "none", strip.text = element_text(face = "bold"))Sebaran akurasi testing dari 30 kali pengulangan
Pada split 80:20, rata-rata akurasi testing tertinggi dicapai oleh 10 hidden neuron (96,33%), sedangkan hasil paling stabil (simpangan baku terkecil) pada 10 hidden neuron (3,65 poin). Pada split 60:40, rata-rata akurasi testing tertinggi dicapai oleh 30 hidden neuron (95,44%), sedangkan hasil paling stabil (simpangan baku terkecil) pada 30 hidden neuron (2,70 poin).
Simpangan baku yang kecil menunjukkan kinerja model tidak banyak bergantung pada pembagian data tertentu; sebaliknya nilai minimum yang rendah menandakan ada pembagian data atau bobot awal yang menyebabkan model kurang baik. Jika rata-rata antarukuran hidden layer hanya berbeda tipis dibandingkan simpangan bakunya, perbedaan tersebut tidak cukup kuat untuk menyatakan satu ukuran jauh lebih baik.
set.seed(917) menjamin hasil dapat direproduksi, dan uji
kestabilan memperlihatkan seberapa besar variasi yang terjadi.nnet hanya mendukung satu
hidden layer dan tidak menyediakan pengaturan learning
rate, batch size, maupun fungsi aktivasi hidden
layer lain; untuk arsitektur lebih kompleks dapat digunakan paket
keras/torch.80_10 (10 hidden neuron, split 80:20)
dengan akurasi testing 96,67%, presisi rata-rata
96,97%, recall rata-rata 97,22%, dan F1-score rata-rata
96,96%.80_20) dan terkecil 3,33% poin, sehingga tingkat
overfitting dapat dinilai dari Tabel 1.decay (regularisasi) dan
melakukan tuning size/decay melalui
validasi silang (k-fold cross validation) agar pemilihan model
lebih objektif.Anggraini, R., Hafiz, M., Lestari, W. A., & Pangesti, R. D. (2026). Penerapan Artificial Neural Network (ANN) untuk klasifikasi jenis biji gandum. MATHunesa: Jurnal Ilmiah Matematika, 14(1), 542–548.
Hutabarat, D., Solikhun, Fauzan, M., Windarto, A. P., & Rizki, F. (2021). Penerapan algoritma backpropagation dalam memprediksi hasil panen tanaman sayuran. BIOS: Jurnal Teknologi Informasi dan Rekayasa Komputer, 2(1), 21–29. https://doi.org/10.37148/bios.v2i1.18
Muamar, Y., & Muhajirin, A. (2024). Penerapan jaringan saraf tiruan dengan metode backpropagation untuk memprediksi tingkat kelulusan mahasiswa perguruan tinggi. Digital Transformation Technology, 4(1), 214–224. https://doi.org/10.47709/digitech.v4i1.3810
Mustafidah, H., & Rohman, S. N. (2023). Mean square error pada metode random dan Nguyen Widrow dalam jaringan syaraf tiruan. Sainteks, 20(2), 133–142. https://doi.org/10.30595/sainteks.v20i2.19516
Nisa, N. K., Sani, D. A., dkk. (2025). Prediksi dini resiko penyakit diabetes menggunakan jaringan syaraf tiruan backpropagation. JATI (Jurnal Mahasiswa Teknik Informatika), 9(5).
Pambudi, R. E., Purnomo, H., & Aglasia, A. (2025). Analisis klasifikasi sentimen pengguna MyPertamina menggunakan metode evaluasi precision, recall, dan F1-score. Aisyah Journal of Informatics and Electrical Engineering, 7(2), 17–22.
Tanjung, J. P. (2021). Classification of wheat seeds using neural network backpropagation algorithm. Journal of Informatics and Telecommunication Engineering, 4(2), 335–342. https://doi.org/10.31289/jite.v4i2.4449
Rujukan teori dan perangkat lunak (sesuai modul praktikum)
Beck, M. W. (2018). NeuralNetTools: Visualization and analysis tools for neural networks. Journal of Statistical Software, 85(11), 1–20.
Bishop, C. M. (2006). Pattern recognition and machine learning. Springer.
Fausett, L. (1994). Fundamentals of neural networks: Architectures, algorithms, and applications. Prentice Hall.
Goodfellow, I., Bengio, Y., & Courville, A. (2016). Deep learning. MIT Press.
Haykin, S. (2009). Neural networks and learning machines (3rd ed.). Pearson.
Olden, J. D., Joy, M. K., & Death, R. G. (2004). An accurate comparison of methods for quantifying variable importance in artificial neural networks using simulated data. Ecological Modelling, 178(3–4), 389–397.
Rumelhart, D. E., Hinton, G. E., & Williams, R. J. (1986). Learning representations by back-propagating errors. Nature, 323, 533–536.
Modul Praktikum Machine Learning. (2026). Pertemuan VI: Artificial Neural Network (ANN) untuk regresi dan klasifikasi. Universitas Bengkulu.
## R version 4.5.3 (2026-03-11 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 26200)
##
## Matrix products: default
## LAPACK version 3.12.1
##
## locale:
## [1] LC_COLLATE=English_Indonesia.utf8 LC_CTYPE=English_Indonesia.utf8
## [3] LC_MONETARY=English_Indonesia.utf8 LC_NUMERIC=C
## [5] LC_TIME=English_Indonesia.utf8
##
## time zone: Asia/Jakarta
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] knitr_1.51 ggplot2_4.0.3 NeuralNetTools_1.5.3
## [4] nnet_7.3-21
##
## loaded via a namespace (and not attached):
## [1] gtable_0.3.6 jsonlite_2.0.0 dplyr_1.2.1 compiler_4.5.3
## [5] Rcpp_1.1.1 tidyselect_1.2.1 stringr_1.6.0 tidyr_1.3.2
## [9] DiagrammeR_1.0.12 jquerylib_0.1.4 scales_1.4.0 yaml_2.3.12
## [13] fastmap_1.2.0 plyr_1.8.9 R6_2.6.1 labeling_0.4.3
## [17] generics_0.1.4 htmlwidgets_1.6.4 visNetwork_2.1.4 tibble_3.3.1
## [21] bslib_0.10.0 pillar_1.11.1 RColorBrewer_1.1-3 rlang_1.2.0
## [25] stringi_1.8.7 cachem_1.1.0 xfun_0.57 sass_0.4.10
## [29] S7_0.2.1-1 otel_0.2.0 cli_3.6.6 withr_3.0.2
## [33] magrittr_2.0.5 digest_0.6.39 grid_4.5.3 rstudioapi_0.18.0
## [37] lifecycle_1.0.5 vctrs_0.7.3 evaluate_1.0.5 glue_1.8.1
## [41] farver_2.1.2 purrr_1.2.2 reshape2_1.4.5 rmarkdown_2.31
## [45] tools_4.5.3 pkgconfig_2.0.3 htmltools_0.5.9