Penelitian ini bertujuan untuk membandingkan kinerja dua metode klasifikasi multiclass, yaitu Linear Discriminant Analysis (LDA) dan Multinomial Logistic Regression (MLR), dalam mengklasifikasikan data makanan berdasarkan kandungan gizi.

MLR

Melakukan pembacaan file cvs yang didapatkan dari hasil scrapping di website FatSecret dimana kami melakukan pengambilan data pada beberapa tipe yaitu makanan energi, makanan low-fat, makanan pembentuk otot dan makanan ringan

library(nnet)
data <- read.csv("C:\\Users\\lenovo\\Documents\\Semester 4\\Multivariat\\UAS\\Dataset Gizi FIXX.csv")
str(data)
## 'data.frame':    327 obs. of  14 variables:
##  $ Nama            : chr  "Kentang Goreng" "Mie" "Nasi Putih" "Roti Putih" ...
##  $ karbohidrat     : num  35.7 25 27.9 50.6 48 ...
##  $ protein         : num  3.48 4.51 2.66 7.64 5 ...
##  $ kalori          : int  274 137 129 266 474 157 301 307 197 260 ...
##  $ lemak           : num  14.06 2.06 0.28 3.29 31 ...
##  $ energi          : int  1146 573 540 1113 1983 657 1259 1283 824 1090 ...
##  $ lemak.jenuh     : num  3.28 0.42 0.08 0.72 8.11 0.18 5.49 0.84 1.38 8.96 ...
##  $ kolestrol       : num  0 29 0 0 61 0 24 0 8 57 ...
##  $ serat           : num  3.3 1.2 0.4 2.4 2 1.8 1.6 6.4 1 1.4 ...
##  $ gula            : num  0.58 0.4 0.05 4.31 23.37 ...
##  $ sodium          : num  300 236 365 681 429 232 693 372 128 350 ...
##  $ kalium          : int  527 38 35 100 196 45 206 330 180 323 ...
##  $ kategori.makanan: chr  "nabati" "nabati" "nabati" "nabati" ...
##  $ label           : chr  "makanan energi" "makanan energi" "makanan energi" "makanan energi" ...

Setelah melakukan pembacaan data dilakukan proses penghapusan kolom non-numerik yang tidak relevan menggunakan MLR

data$Nama <- NULL
data$kategori.makanan <- NULL

Melakukan pengecekan data dengan melakukan ringkasan serta melakukan pengubahan kolom variabel label pada data menjadi tipe faktor.

str(data)
## 'data.frame':    327 obs. of  12 variables:
##  $ karbohidrat: num  35.7 25 27.9 50.6 48 ...
##  $ protein    : num  3.48 4.51 2.66 7.64 5 ...
##  $ kalori     : int  274 137 129 266 474 157 301 307 197 260 ...
##  $ lemak      : num  14.06 2.06 0.28 3.29 31 ...
##  $ energi     : int  1146 573 540 1113 1983 657 1259 1283 824 1090 ...
##  $ lemak.jenuh: num  3.28 0.42 0.08 0.72 8.11 0.18 5.49 0.84 1.38 8.96 ...
##  $ kolestrol  : num  0 29 0 0 61 0 24 0 8 57 ...
##  $ serat      : num  3.3 1.2 0.4 2.4 2 1.8 1.6 6.4 1 1.4 ...
##  $ gula       : num  0.58 0.4 0.05 4.31 23.37 ...
##  $ sodium     : num  300 236 365 681 429 232 693 372 128 350 ...
##  $ kalium     : int  527 38 35 100 196 45 206 330 180 323 ...
##  $ label      : chr  "makanan energi" "makanan energi" "makanan energi" "makanan energi" ...
data$label <- as.factor(data$label)

Output yang dihasilkan terdapat 327 baris data observasi serta 11 kolom variabel yaitu karbohidrat, protein, kalori, lemak, energi, lemak jenuh, kolestrol, serat, gula, sodium, dan kalium dari output yang dihasilkan akan digunakan untuk menjadi dasar penting sebelum dilakukannya modeling.

Setelah melakukan peringkasan data dan menentukan variabe mana yang dijadikan target maka langkah selanjutnya adalah melakukan uji serentak serta melakukan fit model dan uji parsial pada data.

model_null <- multinom(label ~ 1, data = data, trace = FALSE)
model_full <- multinom(label ~ karbohidrat + protein + kalori + lemak + energi + lemak.jenuh + kolestrol + serat + gula + sodium + kalium,
                       data = data, trace = FALSE)
lrtest(model_null, model_full)
## Likelihood ratio test
## 
## Model 1: label ~ 1
## Model 2: label ~ karbohidrat + protein + kalori + lemak + energi + lemak.jenuh + 
##     kolestrol + serat + gula + sodium + kalium
##   #Df  LogLik Df  Chisq Pr(>Chisq)    
## 1   3 -452.94                         
## 2  36 -190.61 33 524.66  < 2.2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Dari hasil uji ini menunjukkan bahwa model multinomial logistik yang menggunakan sebelas variabel prediktor lebih baik dalam menjelaskan variabel abel dibandingkan dengan model yang hanya memuat interceot dengan nilai statistik Chi-Square yang didapatkan 524.66 dengan derajat bebas 33 serta p-value kurang dari 2.2e-16. dapat disimpulkan bahwa kandungan nutrisi yang digunakan sebagai prediksi memiliki pengaruh yang signifikan terhadap pengelompokan kategori makanan dalam data yang digunakan.

Selanjutnya kita melakukan pelatihan model regresi logistik multinomial serta melihat variabel prediktor berdasarkan kelas target.

model_mlr <- multinom(label ~ karbohidrat + protein + kalori + lemak + energi + kolestrol + serat + gula + sodium + kalium, data = data)
## # weights:  48 (33 variable)
## initial  value 453.318256 
## iter  10 value 338.055643
## iter  20 value 303.711602
## iter  30 value 205.863167
## iter  40 value 191.289397
## iter  50 value 190.997290
## iter  60 value 190.985586
## final  value 190.985562 
## converged
summary(model_mlr)
## Call:
## multinom(formula = label ~ karbohidrat + protein + kalori + lemak + 
##     energi + kolestrol + serat + gula + sodium + kalium, data = data)
## 
## Coefficients:
##                        (Intercept) karbohidrat     protein     kalori
## makanan low-fat           1.516986  0.14127082 -0.07943267 -1.9432774
## makanan pembentuk otot   -3.391066  0.08067081  0.43770903 -0.7686755
## makanan ringan           -2.041255 -0.17042688 -0.34972079  2.0344782
##                             lemak     energi   kolestrol       serat       gula
## makanan low-fat         0.4339562  0.4521069 -0.01048595 -0.06440660 0.07615717
## makanan pembentuk otot  0.4790793  0.1704845  0.02259873  0.04806559 0.11039821
## makanan ringan         -0.3213874 -0.4744159  0.01973076  0.05038109 0.05872350
##                               sodium       kalium
## makanan low-fat        -0.0016478940 0.0043856400
## makanan pembentuk otot  0.0040633605 0.0025570292
## makanan ringan         -0.0005683729 0.0003732306
## 
## Std. Errors:
##                        (Intercept) karbohidrat   protein     kalori     lemak
## makanan low-fat         0.46885483   0.0807476 0.1629985 0.02868622 0.1981852
## makanan pembentuk otot  0.08261517   0.2297233 0.2623263 0.00755073 0.5103634
## makanan ringan          0.54029759   0.1244845 0.1414823 0.07253874 0.2718647
##                             energi   kolestrol      serat       gula
## makanan low-fat        0.009440971 0.015737012 0.07894466 0.02904542
## makanan pembentuk otot 0.012602460 0.009896429 0.02916676 0.07875991
## makanan ringan         0.019216402 0.008740515 0.02678299 0.02691098
##                             sodium       kalium
## makanan low-fat        0.002175226 0.0011719279
## makanan pembentuk otot 0.001891537 0.0024525132
## makanan ringan         0.001009324 0.0009889493
## 
## Residual Deviance: 381.9711 
## AIC: 447.9711
tidy(model_mlr, conf.int = TRUE) %>%
  kable() %>%
  kable_styling("basic", full_width = FALSE)
y.level term estimate std.error statistic p.value conf.low conf.high
makanan low-fat (Intercept) 1.5169864 0.4688548 3.2355142 0.0012142 0.5980479 2.4359250
makanan low-fat karbohidrat 0.1412708 0.0807476 1.7495358 0.0801985 -0.0169916 0.2995332
makanan low-fat protein -0.0794327 0.1629985 -0.4873214 0.6260306 -0.3989039 0.2400386
makanan low-fat kalori -1.9432774 0.0286862 -67.7425317 0.0000000 -1.9995013 -1.8870534
makanan low-fat lemak 0.4339562 0.1981852 2.1896499 0.0285496 0.0455204 0.8223921
makanan low-fat energi 0.4521069 0.0094410 47.8877569 0.0000000 0.4336029 0.4706109
makanan low-fat kolestrol -0.0104859 0.0157370 -0.6663239 0.5052041 -0.0413299 0.0203580
makanan low-fat serat -0.0644066 0.0789447 -0.8158449 0.4145889 -0.2191353 0.0903221
makanan low-fat gula 0.0761572 0.0290454 2.6220030 0.0087415 0.0192292 0.1330851
makanan low-fat sodium -0.0016479 0.0021752 -0.7575735 0.4487063 -0.0059113 0.0026155
makanan low-fat kalium 0.0043856 0.0011719 3.7422439 0.0001824 0.0020887 0.0066826
makanan pembentuk otot (Intercept) -3.3910664 0.0826152 -41.0465325 0.0000000 -3.5529892 -3.2291437
makanan pembentuk otot karbohidrat 0.0806708 0.2297233 0.3511652 0.7254644 -0.3695785 0.5309201
makanan pembentuk otot protein 0.4377090 0.2623263 1.6685671 0.0952032 -0.0764411 0.9518591
makanan pembentuk otot kalori -0.7686755 0.0075507 -101.8014784 0.0000000 -0.7834746 -0.7538763
makanan pembentuk otot lemak 0.4790793 0.5103634 0.9387024 0.3478836 -0.5212145 1.4793731
makanan pembentuk otot energi 0.1704845 0.0126025 13.5278765 0.0000000 0.1457842 0.1951849
makanan pembentuk otot kolestrol 0.0225987 0.0098964 2.2835234 0.0223996 0.0032021 0.0419954
makanan pembentuk otot serat 0.0480656 0.0291668 1.6479577 0.0993613 -0.0091002 0.1052314
makanan pembentuk otot gula 0.1103982 0.0787599 1.4017056 0.1610032 -0.0439684 0.2647648
makanan pembentuk otot sodium 0.0040634 0.0018915 2.1481789 0.0316995 0.0003560 0.0077707
makanan pembentuk otot kalium 0.0025570 0.0024525 1.0426159 0.2971262 -0.0022498 0.0073639
makanan ringan (Intercept) -2.0412552 0.5402976 -3.7780201 0.0001581 -3.1002190 -0.9822914
makanan ringan karbohidrat -0.1704269 0.1244845 -1.3690607 0.1709803 -0.4144121 0.0735583
makanan ringan protein -0.3497208 0.1414823 -2.4718348 0.0134422 -0.6270209 -0.0724206
makanan ringan kalori 2.0344782 0.0725387 28.0467803 0.0000000 1.8923049 2.1766515
makanan ringan lemak -0.3213874 0.2718647 -1.1821593 0.2371425 -0.8542326 0.2114577
makanan ringan energi -0.4744159 0.0192164 -24.6880724 0.0000000 -0.5120794 -0.4367525
makanan ringan kolestrol 0.0197308 0.0087405 2.2573906 0.0239837 0.0025997 0.0368618
makanan ringan serat 0.0503811 0.0267830 1.8810853 0.0599603 -0.0021126 0.1028748
makanan ringan gula 0.0587235 0.0269110 2.1821395 0.0290992 0.0059790 0.1114680
makanan ringan sodium -0.0005684 0.0010093 -0.5631224 0.5733515 -0.0025466 0.0014099
makanan ringan kalium 0.0003732 0.0009889 0.3774012 0.7058755 -0.0015651 0.0023115

Hasil yang didapatkan dalam model ini adalah masing-masing variabel nutrisi saling memengaruhi serta nilai deviance serta AIC yang dihasilkan mengidektifikasikan adanya kecocokan model secara keseluruhan dan model dapat membantu memahami faktor nutrisi yang membedakan jenis makanan berdasarkan tujuannya.

Sebelum melakukan evaluasi model kita harus melakukan pengubahan log-odds ke odds ratio untuk memberi interpretasi seberapa besar peluang yang diperoleh.

exp(coef(model_mlr))
##                        (Intercept) karbohidrat   protein    kalori     lemak
## makanan low-fat         4.55846725   1.1517365 0.9236402 0.1432337 1.5433513
## makanan pembentuk otot  0.03367275   1.0840140 1.5491541 0.4636267 1.6145872
## makanan ringan          0.12986560   0.8433047 0.7048849 7.6482604 0.7251422
##                           energi kolestrol     serat     gula    sodium
## makanan low-fat        1.5716199 0.9895688 0.9376237 1.079132 0.9983535
## makanan pembentuk otot 1.1858793 1.0228560 1.0492395 1.116723 1.0040716
## makanan ringan         0.6222484 1.0199267 1.0516718 1.060482 0.9994318
##                          kalium
## makanan low-fat        1.004395
## makanan pembentuk otot 1.002560
## makanan ringan         1.000373
tidy(model_mlr, conf.int = TRUE, exponentiate = TRUE) %>%
  kable() %>%
  kable_styling("basic", full_width = FALSE)
y.level term estimate std.error statistic p.value conf.low conf.high
makanan low-fat (Intercept) 4.5584673 0.4688548 3.2355142 0.0012142 1.8185652 11.4263834
makanan low-fat karbohidrat 1.1517365 0.0807476 1.7495358 0.0801985 0.9831520 1.3492289
makanan low-fat protein 0.9236402 0.1629985 -0.4873214 0.6260306 0.6710552 1.2712982
makanan low-fat kalori 0.1432337 0.0286862 -67.7425317 0.0000000 0.1354028 0.1515176
makanan low-fat lemak 1.5433513 0.1981852 2.1896499 0.0285496 1.0465723 2.2759377
makanan low-fat energi 1.5716199 0.0094410 47.8877569 0.0000000 1.5428062 1.6009719
makanan low-fat kolestrol 0.9895688 0.0157370 -0.6663239 0.5052041 0.9595125 1.0205667
makanan low-fat serat 0.9376237 0.0789447 -0.8158449 0.4145889 0.8032130 1.0945268
makanan low-fat gula 1.0791322 0.0290454 2.6220030 0.0087415 1.0194153 1.1423473
makanan low-fat sodium 0.9983535 0.0021752 -0.7575735 0.4487063 0.9941062 1.0026189
makanan low-fat kalium 1.0043953 0.0011719 3.7422439 0.0001824 1.0020909 1.0067050
makanan pembentuk otot (Intercept) 0.0336727 0.0826152 -41.0465325 0.0000000 0.0286389 0.0395914
makanan pembentuk otot karbohidrat 1.0840140 0.2297233 0.3511652 0.7254644 0.6910255 1.7004963
makanan pembentuk otot protein 1.5491541 0.2623263 1.6685671 0.0952032 0.9264075 2.5905213
makanan pembentuk otot kalori 0.4636267 0.0075507 -101.8014784 0.0000000 0.4568160 0.4705391
makanan pembentuk otot lemak 1.6145872 0.5103634 0.9387024 0.3478836 0.5937989 4.3901926
makanan pembentuk otot energi 1.1858793 0.0126025 13.5278765 0.0000000 1.1569464 1.2155357
makanan pembentuk otot kolestrol 1.0228560 0.0098964 2.2835234 0.0223996 1.0032072 1.0428897
makanan pembentuk otot serat 1.0492395 0.0291668 1.6479577 0.0993613 0.9909411 1.1109676
makanan pembentuk otot gula 1.1167227 0.0787599 1.4017056 0.1610032 0.9569842 1.3031244
makanan pembentuk otot sodium 1.0040716 0.0018915 2.1481789 0.0316995 1.0003561 1.0078010
makanan pembentuk otot kalium 1.0025603 0.0024525 1.0426159 0.2971262 0.9977527 1.0073910
makanan ringan (Intercept) 0.1298656 0.5402976 -3.7780201 0.0001581 0.0450393 0.3744521
makanan ringan karbohidrat 0.8433047 0.1244845 -1.3690607 0.1709803 0.6607286 1.0763313
makanan ringan protein 0.7048849 0.1414823 -2.4718348 0.0134422 0.5341808 0.9301396
makanan ringan kalori 7.6482604 0.0725387 28.0467803 0.0000000 6.6346432 8.8167344
makanan ringan lemak 0.7251422 0.2718647 -1.1821593 0.2371425 0.4256097 1.2354777
makanan ringan energi 0.6222484 0.0192164 -24.6880724 0.0000000 0.5992482 0.6461314
makanan ringan kolestrol 1.0199267 0.0087405 2.2573906 0.0239837 1.0026030 1.0375497
makanan ringan serat 1.0516718 0.0267830 1.8810853 0.0599603 0.9978896 1.1083526
makanan ringan gula 1.0604820 0.0269110 2.1821395 0.0290992 1.0059969 1.1179180
makanan ringan sodium 0.9994318 0.0010093 -0.5631224 0.5733515 0.9974566 1.0014109
makanan ringan kalium 1.0003733 0.0009889 0.3774012 0.7058755 0.9984361 1.0023142

Output yang dihasilkan menunjukkan bahwa variabel-variabel memiliki pengaruh yang relatif kecil terhadap klasifikasi makanan.

Evaluasi model dilakukan guna melihat hasil prediksi dari model yang sudah dilatih.

library(caret)
## Loading required package: lattice
## 
## Attaching package: 'caret'
## The following object is masked from 'package:purrr':
## 
##     lift
library(ggplot2)
library(reshape2)
## 
## Attaching package: 'reshape2'
## The following object is masked from 'package:tidyr':
## 
##     smiths
predicted <- predict(model_mlr, newdata = data)
actual <- as.factor(data$label)

cm <- confusionMatrix(data = as.factor(predicted), reference = actual)
print(cm)
## Confusion Matrix and Statistics
## 
##                         Reference
## Prediction               makanan energi makanan low-fat makanan pembentuk otot
##   makanan energi                     55               7                      5
##   makanan low-fat                    14              71                      0
##   makanan pembentuk otot              3               1                     69
##   makanan ringan                     12               5                      1
##                         Reference
## Prediction               makanan ringan
##   makanan energi                     15
##   makanan low-fat                     8
##   makanan pembentuk otot              3
##   makanan ringan                     58
## 
## Overall Statistics
##                                           
##                Accuracy : 0.7737          
##                  95% CI : (0.7244, 0.8179)
##     No Information Rate : 0.2569          
##     P-Value [Acc > NIR] : <2e-16          
##                                           
##                   Kappa : 0.6981          
##                                           
##  Mcnemar's Test P-Value : 0.4392          
## 
## Statistics by Class:
## 
##                      Class: makanan energi Class: makanan low-fat
## Sensitivity                         0.6548                 0.8452
## Specificity                         0.8889                 0.9095
## Pos Pred Value                      0.6707                 0.7634
## Neg Pred Value                      0.8816                 0.9444
## Prevalence                          0.2569                 0.2569
## Detection Rate                      0.1682                 0.2171
## Detection Prevalence                0.2508                 0.2844
## Balanced Accuracy                   0.7718                 0.8774
##                      Class: makanan pembentuk otot Class: makanan ringan
## Sensitivity                                 0.9200                0.6905
## Specificity                                 0.9722                0.9259
## Pos Pred Value                              0.9079                0.7632
## Neg Pred Value                              0.9761                0.8964
## Prevalence                                  0.2294                0.2569
## Detection Rate                              0.2110                0.1774
## Detection Prevalence                        0.2324                0.2324
## Balanced Accuracy                           0.9461                0.8082
cm_table <- as.table(cm$table)
cm_df <- as.data.frame(cm_table)
colnames(cm_df) <- c("Actual", "Predicted", "Freq")

Hasil evaluasi model confusion matrix menunjukkan bahwa model multinomial logistic regression memiliki akurasi 77.37% dan nilai kappa 0.6981 dimana hasil yang diperoleh menunjukkan performa klasifikasi yang cukup baik.

ggplot(cm_df, aes(x = Actual, y = Predicted, fill = Freq)) +
  geom_tile(color = "white") +
  geom_text(aes(label = Freq), size = 5) +
  scale_fill_gradient(low = "white", high = "blue") +
  labs(title = "Confusion Matrix", x = "Actual Label", y = "Predicted Label") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Hasil visualisasi confusion matrix menunjukkan bahwa model paling akurat dalam mengklasifikasi makanan low-fat dan makanan pembentuk otot. Namun, terjadi banyak kesalahan antara makanan energi dan makanan ringan, yang sering tertukar. Hal ini menunjukkan bahwa kedua kategori tersebut memiliki karakteristik yang mirip dan sulit dibedakan oleh model.

LDA

Melakukan pembacaan file cvs yang didapatkan dari hasil scrapping di website FatSecret dimana kami melakukan pengambilan data pada beberapa tipe yaitu makanan energi, makanan low-fat, makanan pembentuk otot dan makanan ringan

data <- read.csv("C:\\Users\\lenovo\\Documents\\Semester 4\\Multivariat\\UAS\\Dataset Gizi FIXX.csv")
data[, 2:12] <- lapply(data[, 2:12], function(x) as.numeric(as.character(x)))
data$label <- as.factor(data$label)
data$Nama <- NULL
data$kategori.makanan <- NULL
str(data)
## 'data.frame':    327 obs. of  12 variables:
##  $ karbohidrat: num  35.7 25 27.9 50.6 48 ...
##  $ protein    : num  3.48 4.51 2.66 7.64 5 ...
##  $ kalori     : num  274 137 129 266 474 157 301 307 197 260 ...
##  $ lemak      : num  14.06 2.06 0.28 3.29 31 ...
##  $ energi     : num  1146 573 540 1113 1983 ...
##  $ lemak.jenuh: num  3.28 0.42 0.08 0.72 8.11 0.18 5.49 0.84 1.38 8.96 ...
##  $ kolestrol  : num  0 29 0 0 61 0 24 0 8 57 ...
##  $ serat      : num  3.3 1.2 0.4 2.4 2 1.8 1.6 6.4 1 1.4 ...
##  $ gula       : num  0.58 0.4 0.05 4.31 23.37 ...
##  $ sodium     : num  300 236 365 681 429 232 693 372 128 350 ...
##  $ kalium     : num  527 38 35 100 196 45 206 330 180 323 ...
##  $ label      : Factor w/ 4 levels "makanan energi",..: 1 1 1 1 1 1 1 1 1 3 ...

Melakukan pengecekan data untuk memastikan tidak ada data yang kosong (NA)

cat("Jumlah NA:\n")
## Jumlah NA:
print(colSums(is.na(data)))
## karbohidrat     protein      kalori       lemak      energi lemak.jenuh 
##           0           0           0           0           0           0 
##   kolestrol       serat        gula      sodium      kalium       label 
##           0           0           0           0           0           0

Melakukan analisis untuk melihat perbandingan distribusi berbagai variabel antar kelas makanan dan hasil visualisasi yang didapatkan pada setiap kelasnya memiliki ciri khas distribusi nutrisi yang berbeda-beda.

library(ggplot2)
vars <- c("karbohidrat", "protein", "kalori", "lemak", "energi", 
          "lemak.jenuh", "kolestrol", "serat", "gula", "sodium", "kalium")

data_long <- data %>%
  dplyr::select(all_of(vars), label) %>%
  pivot_longer(cols = all_of(vars), names_to = "Nutrisi", values_to = "Nilai")

ggplot(data_long, aes(x = Nilai, fill = label)) +
  geom_histogram(alpha = 0.6, bins = 30, position = "identity") +
  facet_wrap(~ Nutrisi, scales = "free") +
  theme_minimal() +
  labs(title = "Distribusi Nutrisi per Kelas Makanan",
       x = "Nilai Nutrisi",
       y = "Frekuensi",
       fill = "Kelas Makanan")

Lakukan standarisasi data untuk melihat korelasi antar variabel tanpa memasukkan label data.

library(lattice)
library(caret)
preProcValues <- preProcess(dplyr::select(data, -label), method = c("center", "scale"))
data_scaled <- predict(preProcValues, newdata = dplyr::select(data, -label))
data_scaled$label <- data$label

cor_matrix <- cor(data_scaled[, -which(names(data_scaled) == "label")])
library(corrplot)
## corrplot 0.95 loaded
corrplot(cor_matrix, method = "color")

Lakukan kalsifikasi model LDA berdasarkan data yang sudah diproses.diperoleh beberapa output yang oertama ada prior probabilities of grups dengan masih rata-rata 25% yang menunjukkan bahwa dataset cukup seimbang, selanjutnya ada grup means per kelas, selanjutnya ada coefficients of linear discriminants LD1, LD2, LD3 pada setiap kelas dan yang terakhir niali proportion of trace dimana LD1 73.3%, LD2 21.0% dan LD3 5.7% dimana LD1 sangan dominan

library(dplyr)
library(MASS)
## 
## Attaching package: 'MASS'
## The following object is masked from 'package:dplyr':
## 
##     select
lda_model <- lda(label ~ ., data = data_scaled)
print(lda_model)
## Call:
## lda(label ~ ., data = data_scaled)
## 
## Prior probabilities of groups:
##         makanan energi        makanan low-fat makanan pembentuk otot 
##              0.2568807              0.2568807              0.2293578 
##         makanan ringan 
##              0.2568807 
## 
## Group means:
##                        karbohidrat    protein      kalori      lemak
## makanan energi           0.3238541 -0.1848959 -0.02338361 -0.3241319
## makanan low-fat         -0.1239382 -0.8324875 -0.78418742 -0.6843374
## makanan pembentuk otot  -0.9823925  1.4476429  0.07105225  0.5328204
## makanan ringan           0.6772203 -0.2751549  0.74413152  0.5327367
##                             energi lemak.jenuh  kolestrol       serat
## makanan energi         -0.02339547  -0.3216662 -0.2763402 -0.07293848
## makanan low-fat        -0.78401655  -0.5417830 -0.4069607 -0.13340596
## makanan pembentuk otot  0.07104870   0.3904986  0.8115496 -0.01785298
## makanan ringan          0.74397569   0.5147897 -0.0412969  0.22228459
##                              gula     sodium      kalium
## makanan energi         -0.3133346  0.2716713 -0.24877236
## makanan low-fat         0.4284466 -0.7215896  0.11232712
## makanan pembentuk otot -0.5512094  0.3638302  0.20942382
## makanan ringan          0.3770392  0.1250699 -0.05054032
## 
## Coefficients of linear discriminants:
##                     LD1          LD2          LD3
## karbohidrat  0.68730962   -3.3853604  -1.47406022
## protein      2.08661897   -1.5504750  -0.69144738
## kalori      -1.65984463  148.0625580  63.13723121
## lemak        1.31232322   -3.9089333  -0.02117724
## energi      -0.35378244 -141.3656395 -61.75234352
## lemak.jenuh -0.04810644    0.3105622  -0.09423941
## kolestrol    0.33467839    0.1278817   0.14993641
## serat        0.03851340    0.2371136   0.16559464
## gula         0.21719246   -0.3686203   0.87610085
## sodium       0.20335145   -0.0213199  -0.23708520
## kalium      -0.01390272   -0.4559236   0.11500442
## 
## Proportion of trace:
##    LD1    LD2    LD3 
## 0.7332 0.2103 0.0565

Melakukan analisis dengan asumsi homogenitas matriks kovarian antar kelas makanan yang tidak terpenuhi didapatkan hasil Box’s M-test dengan nilai p < 2.2e-16, yang sangat signifikan. Artinya, variansi-kovarians antar kelas makanan berbeda secara signifikan. Namun, hasil MANOVA dengan uji Wilks Lambda juga sangat signifikan (p < 2.2e-16), menunjukkan bahwa secara keseluruhan terdapat perbedaan yang signifikan dalam kombinasi fitur nutrisi antar kelas makanan.

library(biotools)
## Warning: package 'biotools' was built under R version 4.4.3
## ---
## biotools version 4.3
boxM(data_scaled[, -which(names(data_scaled) == "label")], data_scaled$label)
## 
##  Box's M-test for Homogeneity of Covariance Matrices
## 
## data:  data_scaled[, -which(names(data_scaled) == "label")]
## Chi-Sq (approx.) = 2223.2, df = 198, p-value < 2.2e-16
manova_model <- manova(as.matrix(data_scaled[, -which(names(data_scaled) == "label")]) ~ data_scaled$label)
summary(manova_model, test = "Wilks")
##                    Df   Wilks approx F num Df den Df    Pr(>F)    
## data_scaled$label   3 0.11076   31.052     33 922.86 < 2.2e-16 ***
## Residuals         323                                             
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Hasil visualisasi LDA menunjukkan bahwa makanan pembentuk otot (hijau) paling jelas terpisah dari kelas lain, menandakan fitur gizinya sangat berbeda. Sementara itu, kelas makanan energi, low-fat, dan ringan cenderung tumpang tindih, sehingga lebih sulit dibedakan. Ini menunjukkan bahwa model LDA efektif membedakan kelas tertentu tetapi bisa mengalami kesalahan pada kelas yang fitur gizinya mirip.

lda_pred <- predict(lda_model)
lda_df <- as.data.frame(lda_pred$x)
lda_df$label <- data_scaled$label

ggplot(lda_df, aes(x = LD1, y = LD2, color = label)) +
  geom_point(alpha = 0.8, size = 2.5) +
  theme_minimal() +
  labs(title = "Visualisasi LDA: Klasifikasi Makanan Berdasarkan Gizi",
       x = "LD1", y = "LD2") +
  scale_color_brewer(palette = "Set1")

pred <- predict(lda_model)$class
table(pred, data_scaled$label)
##                         
## pred                     makanan energi makanan low-fat makanan pembentuk otot
##   makanan energi                     57               7                      7
##   makanan low-fat                    17              72                      0
##   makanan pembentuk otot              2               1                     68
##   makanan ringan                      8               4                      0
##                         
## pred                     makanan ringan
##   makanan energi                     18
##   makanan low-fat                    13
##   makanan pembentuk otot              3
##   makanan ringan                     50
ggplot(lda_df, aes(x = LD1, y = LD2, color = label)) +
  geom_point(alpha = 0.8, size = 2.5) +
  theme_minimal() +
  labs(title = "Visualisasi LDA: Klasifikasi Makanan Berdasarkan Gizi",
       x = "LD1", y = "LD2") +
  scale_color_brewer(palette = "Set1")

pred <- predict(lda_model)$class
table(pred, data_scaled$label)
##                         
## pred                     makanan energi makanan low-fat makanan pembentuk otot
##   makanan energi                     57               7                      7
##   makanan low-fat                    17              72                      0
##   makanan pembentuk otot              2               1                     68
##   makanan ringan                      8               4                      0
##                         
## pred                     makanan ringan
##   makanan energi                     18
##   makanan low-fat                    13
##   makanan pembentuk otot              3
##   makanan ringan                     50

Melakukan rata-rata oada kandungan gizi pada setiap kategori makanan dengan menampilkan visualisasi dalam bentuk heatmap Pada plot, sumbu-x menunjukkan jenis kandungan gizi, sumbu-y menunjukkan kategori makanan, dan warna kotak (dari biru ke merah) merepresentasikan nilai rata-rata nutrisi—merah untuk nilai tinggi, biru untuk nilai rendah, dan putih untuk nilai mendekati rata-rata keseluruhan.

library(tidyr)
library(reshape2)
means <- aggregate(. ~ label, data = data_scaled, mean)
means_long <- melt(means, id.vars = "label")

ggplot(means_long, aes(x = variable, y = label, fill = value)) +
  geom_tile(color = "white") +
  scale_fill_gradient2(low = "blue", mid = "white", high = "red", midpoint = 0) +
  theme_minimal() +
  labs(title = "Heatmap Rata-rata Kandungan Gizi per Kategori Makanan",
       x = "Kandungan Gizi", y = "Kategori Makanan")

Visualisai untuk melihat perbandingan rata-rata kandungan gizi beberapa kategori makanan pada berbagai variabel nutrisi. Setiap warna mewakili satu kategori makanan, dan pola garis menunjukkan keunggulan relatif tiap nutrisi.

library(tidyr)
library(fmsb)
## Warning: package 'fmsb' was built under R version 4.4.3
## Registered S3 methods overwritten by 'fmsb':
##   method    from
##   print.roc pROC
##   plot.roc  pROC
means_scaled <- rbind(
  max = apply(means[,-1], 2, max),
  min = apply(means[,-1], 2, min),
  means[,-1]
)
rownames(means_scaled) <- c("max", "min", as.character(means$label))

radarchart(means_scaled,
           axistype = 1,
           pcol = c("red", "orange", "blue", "green", "purple"),
           plwd = 2,
           plty = 1,
           title = "Profil Gizi Kategori Makanan (Radar Chart)",
           cglcol = "grey", cglty = 1, axislabcol = "grey",
           vlcex = 0.8)
legend("topright", legend = as.character(means$label), col = c("red", "orange", "blue", "green", "purple"),
       lty = 1, lwd = 2, cex = 0.8)

Setelah dilakukan modeling pada data hasil yang didapatkan berdasarkan confusion matrix pada model LDA dapat mengklasifikasikan data ke dalam kategori makanan secara benar dengan tingkat akurasi sebesar 75,54%. Kategori ‘makanan low-fat’ menunjukkan tingkat klasifikasi tertinggi, sementara kesalahan klasifikasi banyak terjadi antara kategori ‘makanan ringan’.

conf_mat <- table(Predicted = lda_pred$class, Actual = data_scaled$label)
print(conf_mat)
##                         Actual
## Predicted                makanan energi makanan low-fat makanan pembentuk otot
##   makanan energi                     57               7                      7
##   makanan low-fat                    17              72                      0
##   makanan pembentuk otot              2               1                     68
##   makanan ringan                      8               4                      0
##                         Actual
## Predicted                makanan ringan
##   makanan energi                     18
##   makanan low-fat                    13
##   makanan pembentuk otot              3
##   makanan ringan                     50
cat("Akurasi Training:", mean(lda_pred$class == data_scaled$label), "\n")
## Akurasi Training: 0.7553517
conf_mat <- table(Predicted = lda_pred$class, Actual = data_scaled$label)
conf_df <- as.data.frame(conf_mat)
colnames(conf_df) <- c("Predicted", "Actual", "Freq")

ggplot(conf_df, aes(x = Actual, y = Predicted, fill = Freq)) +
  geom_tile(color = "white") +
  geom_text(aes(label = Freq), color = "black", size = 4) +
  scale_fill_gradient(low = "white", high = "steelblue") +
  theme_minimal() +
  labs(title = "Confusion Matrix LDA (Heatmap)",
       x = "Kelas Aktual", y = "Kelas Prediksi")

Kesimpulan

Berdasarkan hasil analisis yang telah dilakukan, kedua model mempunyai akurasi yang tidak terlalu berbeda jauh. Model Linear Discriminant Analysis (LDA) berhasil mengklasifikasikan jenis makanan berdasarkan kandungan gizinya dengan nilai akurasi sebesar 75,54% sedangkan model Multinomial Logistic Regression (MLR) menghasilkan akurasi yang lebih tinggi yaitu 77,37%.

Hasil uji serentak pada kedua model menunjukkan bahwa kombinasi variabel kandungan gizi secara signifikan mampu membedakan kategori makanan. Dari hasil uji parsial pada model MLR, diketahui bahwa variabel kalori merupakan faktor yang paling membedakan antara kategori, diikuti oleh protein dan karbohidrat. Kalori sangat berperan dalam membedakan makanan ringan dari kategori lainnya, sementara protein berpengaruh besar terhadap makanan pembentuk otot, dan karbohidrat berperan besar dalam kategori makanan low-fat. Selain itu, nilai Kappa pada model MLR lebih tinggi dibandingkan LDA, menunjukkan bahwa MLR memiliki tingkat kesesuaian prediksi yang sedikit lebih kuat.

Oleh karena itu, dari hasil perbandingan kedua metode yang dilakukan dapat disimpulkan bahwa MLR dianggap sebagai metode yang lebih efektif dan efisien dalam melakukan klasifikasi kategori makanan berdasarkan kandungan gizi.