Saya Briandamar Kencana seorang data enthusiast. Saya lulus dengan gelar sarjana statistik. Saya memiliki beberapa pengalaman kerja di bidang data, seperti magang di momobil.id, independent research and advisory Indonesia, staf data analis di Alif Aza Asia dan asisten peneliti di Bank Indonesia, dan kemudian saya melanjutkan karir saya sebagai analis di sebuah bank komersial di Indonesia. Selain itu, saya telah berpartisipasi dalam beberapa kursus pelatihan data di Algoritma Data Science School, Coursera, Udemy dan Dicoding.
Data ini merupakan data SMS yang saya peroleh dari algoritma data science school, yang berisikan 3 variabel yaitu status sms tersebut spam/ham, text sms, dan tanggal waktu sms dikirimkan.
SMS-SPAM
Komunikasi merupakan hal yang penting bagi kehidupan manusia, khususnya komunikasi menggunakan ponsel pintar. Semakin berkembangnya zaman maka komunikasi juga ikut berkembang. Perkembangan komunikasi tidak membuat pengguna Short Message Service (SMS) berkurang. Salah satu alasannya karena SMS tidak menggunakan sinyal internet seperti pada fitur – fitur canggih ponsel pintar masa kini. SMS yang sempat menjadi primadona di awal kemunculannya pada era 2000-an ini selain cepat dalam pengirimannya, juga pada umumnya semua pengguna ponsel pintar saat ini bisa menggunakan fitur SMS tersebut. Penyalahgunaan perangkat elektronik untuk mengirimkan pesan secara berulang-ulang dan tanpa dikehendaki oleh penerimanya atau yang biasa disebut spam SMS ini cukup merugikan para pengguna ponsel pintar.
Kecenderungan seperti ini membuat masyarakat enggan membaca dan langsung menghapus apapun sms yang masuk ke ponsel mereka, padahal bisa jadi ada informasi penting dari kerabat, saudara atau kolega yang masih menggunakan sms sebagai metode pertukaran informasi mereka.
Oleh karena itu, proses filter sms masuk dan pelabelan spam menjadi suatu hal yang cukup krusial kebutuhannya saat ini. Pada dokumentasi ini, kita akan melihat data sample beberapa sms yang sudah dilabeli spam terhadap sms-sms yang tidak diinginkan. Dari data tersebut kita akan melakukan beberapa eksplorasi data, lalu melakukan beberapa tahap pre-processing data/data cleansing. Setelah data cleansing selesai, tahap selanjutnya adalah prediksi sms berkategori spam menggunakan perbandingan beberapa metode machine learning. Metode terbaik akan digunakan untuk pembuatan model prediksi sms berupa spam.
Data Preprocessing yang akan saya lakukan adalah melakukan input data, menyesuaikan tipe data, eksplorasi data, text cleanseing, pembuatan data corpus,visualisasi wordcloud.
library(dplyr)
sms <- read.csv("data/data-train.csv", stringsAsFactors = F, encoding = "UTF-8",sep=",")
sms_test<-read.csv("data/data-test.csv", stringsAsFactors = F, encoding = "UTF-8",sep=",")
head(sms)
Data tersebut mengandung 3 variabel berikut :
Berdasarkan tabel diatas , data-data tersebut masih memiliki tipe data yang belum sesuai dengan tipe data yang seharusnya. Kemudian saya lakukan penyesuaian tipe datanya untuk masing-masing variabel.
library(lubridate)
sms<-sms %>%
mutate(status = as.factor(status),
datetime = ymd_hms(datetime,tz = "Asia/Jakarta"))
sms_test<-sms_test %>%
mutate(status = as.factor(status),
datetime = ymd_hms(datetime,tz = "Asia/Jakarta"))
head(sms,100)
library(ggplot2)
a <- ggplot(sms[1:1751,], aes(x = datetime))
a + geom_density(aes(fill = status), alpha = 0.4) +
scale_fill_manual(values = c("#06967e", "#660a02"))+
labs(title = "Perbandingan Densitas SMS ham vs spam")+theme(panel.background = element_rect(fill = "white"),
plot.title = element_text(size = 16, colour = "#5c0202"),
plot.background = element_rect(fill = "transparent"))
Plot di atas menunjukkan distribusi ham dan spam sepanjang waktu, terlihat antara perbandingan kedua label sms tersebut, pola persebaran sms ham vs spam tidak saling memisah. Sehingga date pada data tersebut saya keluarkan.
sms <- sms %>%
select(-datetime)
sms_test <- sms_test %>%
select(-datetime)
glimpse(sms)
#> Rows: 2,004
#> Columns: 2
#> $ text <chr> "Telegram code 53784", "Rezeki Nomplok Dompetku Pengiriman U...
#> $ status <fct> ham, spam, ham, ham, ham, ham, ham, spam, spam, spam, spam, ...
library(wordcloud)
spam <- subset(sms, status == "spam")
wordcloud(spam$text, max.words = 60, colors = brewer.pal(5, "Dark2"), random.order = FALSE)
Kata-kata yang ditemukan sebagai spam adalah pulsa, anda, kuota, kamu, paket, sms dan info dimana kata - kata tersebut lebih banyak ditemukan.
Saya akan coba mengambil beberapa sample dari text sms yang ada pada data tersebut untuk melihat perubahan sebelum dan sesudah dilakukan text cleansing.
head(sms$text[1:5])
#> [1] "Telegram code 53784"
#> [2] "Rezeki Nomplok Dompetku Pengiriman Uang! Kirim uang di Alfamart & dptkan hadiah jutaan rupiah setiap hari.Periode s.d. 28Feb17.Info: http://bit.ly/dmpurna MFI1"
#> [3] "WhatsApp code 123-994.\n\nYou can also tap on this link to verify your phone: v.whatsapp.com/123994"
#> [4] "Transaksi travel online pakai CIMB Clicks gratis perlindungan kecelakaan & tiket nonton di Pasarpolis.com. Ayo transaksi & nikmati manfaatnya! Info S&K 14041."
#> [5] "Apakah Anda mencoba mengakses akun Anda dari perangkat lain? Jika ya, mohon klik tautan ini https://api.gojek.co.id/customers/device?token=f192293e-3117-46e9-bac3-1d1473c23113 dalam 72 jam ke depan. Jika tidak, mohon abaikan pesan ini"
Proses pertama yang akan saya lakukan adalah text subbing. Fungsi sub () (kependekan dari substitusi) di R mencari pola dalam teks dan menggantikan pola ini dengan teks pengganti. Saya menggunakan sub () untuk mengganti teks dengan teks, dan saya menggunakan gsub () untuk mengganti semua kemunculan pola. (G dalam gsub () berarti global.)
sms$text <- gsub( "\n"," ",sms$text)
sms_test$text <- gsub( "\n"," ",sms_test$text)
head(sms$text[1:5])
#> [1] "Telegram code 53784"
#> [2] "Rezeki Nomplok Dompetku Pengiriman Uang! Kirim uang di Alfamart & dptkan hadiah jutaan rupiah setiap hari.Periode s.d. 28Feb17.Info: http://bit.ly/dmpurna MFI1"
#> [3] "WhatsApp code 123-994. You can also tap on this link to verify your phone: v.whatsapp.com/123994"
#> [4] "Transaksi travel online pakai CIMB Clicks gratis perlindungan kecelakaan & tiket nonton di Pasarpolis.com. Ayo transaksi & nikmati manfaatnya! Info S&K 14041."
#> [5] "Apakah Anda mencoba mengakses akun Anda dari perangkat lain? Jika ya, mohon klik tautan ini https://api.gojek.co.id/customers/device?token=f192293e-3117-46e9-bac3-1d1473c23113 dalam 72 jam ke depan. Jika tidak, mohon abaikan pesan ini"
Kemudian saya akan menggunakan replace_url() dan replace_html() untuk menggantikan html dan url menjadi blank.
sms$text <- sms$text %>%
textclean::replace_url() %>%
textclean::replace_html()
sms_test$text <- sms_test$text %>%
textclean::replace_url() %>%
textclean::replace_html()
sms$text[1:5]
#> [1] "Telegram code 53784"
#> [2] "Rezeki Nomplok Dompetku Pengiriman Uang! Kirim uang di Alfamart & dptkan hadiah jutaan rupiah setiap hari.Periode s.d. 28Feb17.Info: MFI1"
#> [3] "WhatsApp code 123-994. You can also tap on this link to verify your phone: v.whatsapp.com/123994"
#> [4] "Transaksi travel online pakai CIMB Clicks gratis perlindungan kecelakaan & tiket nonton di Pasarpolis.com. Ayo transaksi & nikmati manfaatnya! Info S&K 14041."
#> [5] "Apakah Anda mencoba mengakses akun Anda dari perangkat lain? Jika ya, mohon klik tautan ini dalam 72 jam ke depan. Jika tidak, mohon abaikan pesan ini"
Selanjutnya, saya akan menggunakan fungsi replace_emoji() dan replace_html () kembali karena replace_emoji akan menghasilkan format html.
sms$text <- sms$text%>%
textclean::replace_emoji() %>%
textclean::replace_html()
sms_test$text <- sms_test$text%>%
textclean::replace_emoji() %>%
textclean::replace_html()
sms$text[1:5]
#> [1] "Telegram code 53784"
#> [2] "Rezeki Nomplok Dompetku Pengiriman Uang! Kirim uang di Alfamart & dptkan hadiah jutaan rupiah setiap hari.Periode s.d. 28Feb17.Info: MFI1"
#> [3] "WhatsApp code 123-994. You can also tap on this link to verify your phone: v.whatsapp.com/123994"
#> [4] "Transaksi travel online pakai CIMB Clicks gratis perlindungan kecelakaan & tiket nonton di Pasarpolis.com. Ayo transaksi & nikmati manfaatnya! Info S&K 14041."
#> [5] "Apakah Anda mencoba mengakses akun Anda dari perangkat lain? Jika ya, mohon klik tautan ini dalam 72 jam ke depan. Jika tidak, mohon abaikan pesan ini"
sms$text <- sms$text%>%
textclean::replace_tag(sms$text, pattern = "@([A-Za-z0-9_]+)",replacement="") %>%
textclean::replace_tag(sms$text, pattern = "#([A-Za-z0-9_]+)",replacement="")
sms_test$text <- sms_test$text%>%
textclean::replace_tag(sms_test$text, pattern = "@([A-Za-z0-9_]+)",replacement="") %>%
textclean::replace_tag(sms_test$text, pattern = "#([A-Za-z0-9_]+)",replacement="")
sms$text[1:5]
#> [1] "Telegram code 53784"
#> [2] "Rezeki Nomplok Dompetku Pengiriman Uang! Kirim uang di Alfamart & dptkan hadiah jutaan rupiah setiap hari.Periode s.d. 28Feb17.Info: MFI1"
#> [3] "WhatsApp code 123-994. You can also tap on this link to verify your phone: v.whatsapp.com/123994"
#> [4] "Transaksi travel online pakai CIMB Clicks gratis perlindungan kecelakaan & tiket nonton di Pasarpolis.com. Ayo transaksi & nikmati manfaatnya! Info S&K 14041."
#> [5] "Apakah Anda mencoba mengakses akun Anda dari perangkat lain? Jika ya, mohon klik tautan ini dalam 72 jam ke depan. Jika tidak, mohon abaikan pesan ini"
Membuat data corpus dari teks di dataset. Sebelum memisahkan corpus menjadi kata-kata individual, corpus harus dibersihkan dan distandarisasi dari huruf besar, angka, dan karakter simbol. Fungsi yang digunakan adalah tm_map.
library(tm)
sms.corpus <- VCorpus(VectorSource(sms$text))
sms.corpus_test <- VCorpus(VectorSource(sms_test$text))
sms.corpus
#> <<VCorpus>>
#> Metadata: corpus specific: 0, document level (indexed): 0
#> Content: documents: 2004
Kemudian melakukan modifikasi huruf menjadi kecil
sms.corpus.clean <- tm_map(sms.corpus, content_transformer(tolower))
sms.corpus.clean_test <- tm_map(sms.corpus_test, content_transformer(tolower))
sms.corpus.clean[[4]]$content
#> [1] "transaksi travel online pakai cimb clicks gratis perlindungan kecelakaan & tiket nonton di pasarpolis.com. ayo transaksi & nikmati manfaatnya! info s&k 14041."
sms.corpus.clean <- tm_map(sms.corpus.clean, removeNumbers)
sms.corpus.clean_test <- tm_map(sms.corpus.clean_test, removeNumbers)
sms.corpus.clean[[4]]$content
#> [1] "transaksi travel online pakai cimb clicks gratis perlindungan kecelakaan & tiket nonton di pasarpolis.com. ayo transaksi & nikmati manfaatnya! info s&k ."
Kemudian menghapus kata dasar bahasa indonesia dengan meload file yang berisikan list kata dasar indonesia.
stopwords_id <- readLines("stopwords-id.txt", warn=FALSE)
sms.corpus.clean <- tm_map(sms.corpus.clean, removeWords, c(stopwords("english"),stopwords_id))
sms.corpus.clean_test <- tm_map(sms.corpus.clean_test, removeWords, c(stopwords("english"),stopwords_id))
sms.corpus.clean[[26]]$content
#> [1] "pelanggan , ngajak chatting. hubungi **# baca. pesan dihapus menit. silakan hubungi **# ."
sms.corpus.clean <- tm_map(sms.corpus.clean, removePunctuation)
sms.corpus.clean_test <- tm_map(sms.corpus.clean_test, removePunctuation)
sms.corpus.clean[[26]]$content
#> [1] "pelanggan ngajak chatting hubungi baca pesan dihapus menit silakan hubungi "
Seteleah menghilangkan simbol-simbol, terakhir menghilangkan spasi berlebih.
sms.corpus.clean <- tm_map(sms.corpus.clean, stripWhitespace)
sms.corpus.clean_test <- tm_map(sms.corpus.clean_test, stripWhitespace)
sms.corpus.clean[[26]]$content
#> [1] "pelanggan ngajak chatting hubungi baca pesan dihapus menit silakan hubungi "
Setelah kita mendapatkan teks yang sudah bersih, pertanyaan berikutnya adalah bagaimana cara kita membuat model jika prediktor-nya masih berupa text?
Dalam text mining, biasanya teks diubah menjadi Document-Term Matrix (DTM) melalui proses yang bernama tokenization. Tokenization berfungsi memecah 1 kalimat menjadi beberapa term. term dapat berupa 1 kata, pasangan 2 kata, dan seterusnya. Dalam DTM, 1 kata akan menjadi 1 prediktor, dengan nilainya berupa frekuensi kemunculan kata tersebut pada dokumen (dalam hal ini 1 sms).
sms.dtm <- DocumentTermMatrix(sms.corpus.clean)
sms.dtm_test <- DocumentTermMatrix(sms.corpus.clean_test)
inspect(sms.dtm)
#> <<DocumentTermMatrix (documents: 2004, terms: 2746)>>
#> Non-/sparse entries: 16735/5486249
#> Sparsity : 100%
#> Maximal term length: 40
#> Weighting : term frequency (tf)
#> Sample :
#> Terms
#> Docs beli bonus dgn info internet kuota paket pulsa sms utk
#> 1929 0 0 0 0 0 0 0 0 0 0
#> 193 0 0 0 0 0 0 0 0 0 0
#> 197 0 0 0 0 0 0 0 0 1 0
#> 225 0 0 0 0 1 0 0 0 0 0
#> 29 0 0 0 0 0 0 0 0 0 0
#> 378 0 0 0 0 0 0 0 0 0 0
#> 409 0 0 0 0 0 0 0 0 0 0
#> 410 0 1 1 2 0 0 2 2 0 0
#> 903 0 0 0 0 0 0 0 0 0 0
#> 955 0 0 0 0 2 0 3 2 0 0
smsFreq <- findFreqTerms(sms.dtm, lowfreq = 250)
smsFreq
#> [1] "info" "kuota" "pulsa"
Sebelum pembuatan model, split data menjadi data_train dan data_test dengan komposisi 75% sebagai data training.
RNGkind(sample.kind = "Rounding")
set.seed(100)
index <- sample(nrow(sms.dtm), nrow(sms.dtm)*0.75)
data_train <- sms.dtm[index,]
data_test <- sms.dtm[-index,]
label_train <- sms[index,"status"]
label_test <- sms[-index,"status"]
prop.table(table(label_train))
#> label_train
#> ham spam
#> 0.584165 0.415835
inspect(data_train)
#> <<DocumentTermMatrix (documents: 1503, terms: 2746)>>
#> Non-/sparse entries: 12516/4114722
#> Sparsity : 100%
#> Maximal term length: 40
#> Weighting : term frequency (tf)
#> Sample :
#> Terms
#> Docs beli bonus dgn info internet kuota paket pulsa sms utk
#> 1281 0 0 2 1 1 1 0 0 0 0
#> 1929 0 0 0 0 0 0 0 0 0 0
#> 197 0 0 0 0 0 0 0 0 1 0
#> 225 0 0 0 0 1 0 0 0 0 0
#> 29 0 0 0 0 0 0 0 0 0 0
#> 378 0 0 0 0 0 0 0 0 0 0
#> 409 0 0 0 0 0 0 0 0 0 0
#> 410 0 1 1 2 0 0 2 2 0 0
#> 650 1 0 1 0 1 0 0 0 0 1
#> 903 0 0 0 0 0 0 0 0 0 0
berdasarkan hasil inspect data trainnya, terdapat 2782 variabel , variabel tersebut yang sangat banyak sehingga saya mencoba memfilternya dengan mengambil variabel yang minimal terdapat 5 data, untuk itu saya menggunakan fungsi findFreqTerms dari library tm . Kemudian saya implementasikan ke data test juga.
sms_freq <- findFreqTerms(sms.dtm, lowfreq = 5)
# Aplikasikan ke data train dan test
data_train <- data_train[,sms_freq]
data_test <- data_test[,sms_freq]
inspect(data_train)
#> <<DocumentTermMatrix (documents: 1503, terms: 630)>>
#> Non-/sparse entries: 10037/936853
#> Sparsity : 99%
#> Maximal term length: 20
#> Weighting : term frequency (tf)
#> Sample :
#> Terms
#> Docs beli bonus dgn info internet kuota paket pulsa sms utk
#> 1068 1 0 0 1 0 1 0 0 0 0
#> 1072 1 1 0 1 1 2 0 0 0 0
#> 1124 0 0 2 1 1 1 0 0 0 0
#> 1177 0 0 2 1 1 1 0 0 0 0
#> 1189 0 0 0 0 0 2 1 1 1 1
#> 1235 0 0 2 1 1 1 0 0 0 0
#> 1281 0 0 2 1 1 1 0 0 0 0
#> 1400 0 0 0 0 0 2 1 1 1 1
#> 1409 0 0 2 1 1 1 0 0 0 0
#> 410 0 1 1 2 0 0 2 2 0 0
Nilai pada matrix masih berupa nilai frekuensi. Untuk perhitungan peluang, frekuensi akan diubah menjadi hanya kondisi muncul (1) atau tidak (0). Salah satu caranya dengan menggunakan Bernoulli Converter.
bernoulli_conv <- function(x){
x <- as.factor(ifelse(x > 0, 1, 0))
}
data_train_bn <- apply(data_train, MARGIN = 2, bernoulli_conv)
data_test_bn <- apply(data_test, MARGIN = 2, bernoulli_conv)
Proses selanjutnya adalah membentuk data dalam format yang siap dimasukkan ke dalam model.
Saya buat model Naive Bayes berdasarkan data yang sudah diproses dan coba prediksi nilai target pada data test.
library(e1071)
spam_model1 <- naiveBayes(data_train_bn, label_train,laplace=0)
sms_prediction <- predict(spam_model1, data_test_bn, type = "class")
library(caret)
naive_model<-confusionMatrix(sms_prediction, label_test, positive = "spam")
eval_naive <- data.frame(Accuracy = naive_model$overall[1],
Recall = naive_model$byClass[1],
Specificity = naive_model$byClass[2],
Precision = naive_model$byClass[3])
round(eval_naive,2)
Berdasarkan model diatas didapatkan hasil bahwa accuracy sebesar 95%, Recall 96%, Sepcificity sebesar 94% dan Precision sebesar 92%.
data_train_bn = as.data.frame(as.matrix(data_train_bn))
data_train_bn<-data_train_bn %>% mutate_all(as.factor)
data_test_bn = as.data.frame(as.matrix(data_test_bn))
data_test_bn<-data_test_bn %>% mutate_all(as.factor)
library(lime)
class(spam_model1)
#> [1] "naiveBayes"
model_type.naiveBayes <- function(x){
return("classification")
}
predict_model.naiveBayes <- function(x, newdata, type = "raw") {
# return classification probabilities only
res <- predict(x, newdata, type = "raw") %>% as.data.frame()
return(res)
}
set.seed(123)
explainer <- lime(data_train_bn , spam_model1)
explanation <- explain(data_test_bn %>% head(4),
n_labels = 1,
explainer = explainer,
n_features = 3,
n_permutations = 5,
feature_select = "none")
plot_features(explanation)
Nilai tersebut menunjukkan bahwa model naiveBayes memberikan probabilitas sekitar 100%, dan Explanation Fit memiliki nilai sekitar 0,98 - 0,99 (98% - 99%), yang dapat diartikan bahwa LIME dapat menjelaskan sekitar 98% - 99 % dari model ini. Dalam kasus 1 - 4, terlihat adda beberapa kata yang mendukung sms tersebut spam seperti promo, cashback, prabayar, terdekat, free.
library(partykit)
sms_tree <- ctree(formula = label_train ~ ., data = data_train_bn)
pred_sms_test <- predict(sms_tree, newdata = data_test_bn,
type = "response") # untuk probability; type = "prob"
# confusion matrix data test
decision_model<-confusionMatrix(pred_sms_test, reference = label_test, positive = "spam")
eval_tree <- data.frame(Accuracy = decision_model$overall[1],
Recall = decision_model$byClass[1],
Specificity = decision_model$byClass[2],
Precision = decision_model$byClass[3])
round(eval_tree,2)
Berdasarkan model diatas didapatkan hasil bahwa accuracy sebesar 90%, Recall 89%, Sepcificity sebesar 90% dan Precision sebesar 88%.
model_type.party <- function(x){
return("classification")
}
predict_model.party <- function(x, newdata, type = "prob") {
# return classification probabilities only
res <- predict(x, newdata, type = "prob") %>% as.data.frame()
return(res)
}
set.seed(123)
explainer2 <- lime(data_train_bn, sms_tree)
explanation2 <- explain(data_test_bn %>% head(4),
n_labels = 1,
explainer = explainer2,
n_features = 5,
n_permutations = 5,
feature_select = "none")
plot_features(explanation2)
Nilai tersebut menunjukkan bahwa model naiveBayes memberikan probabilitas sekitar 86%-92%, dan Explanation Fit memiliki nilai sekitar 0,98 - 0,99 (98% - 99%), yang dapat diartikan bahwa LIME dapat menjelaskan sekitar 97% - 99 % dari model ini. Dalam kasus 1 - 4, terlihat beberapa kata juga sama mendukung sms tersebut spam seperti promo, cashback, prabayar, terdekat, free.
Jika saya bandingkan model naive bayes dan decision tree pada data sms spam/ham menunjukan hasil lebih baik menggunakan model naive bayes, sehingga model yang akan saya pilih adalah model naive bayes.
Model yang saya pilih berdasarkan percobaan diatas, kemudian saya lakukan prediksi ke data test yang telah disediakan.
RNGkind(sample.kind = "Rounding")
set.seed(100)
sms_freq <- findFreqTerms(sms.dtm, lowfreq = 5)
sms_freq_test <- findFreqTerms(sms.dtm_test, lowfreq = 5)
data_train_full <- sms.dtm[,sms_freq]
label_train_full <- sms[,"status"]
data_test_full <- sms.dtm_test[,sms_freq_test]
bernoulli_conv <- function(x){
x <- as.factor(ifelse(x > 0, 1, 0))
}
data_train_bn_full <- apply(data_train_full, MARGIN = 2, bernoulli_conv)
data_test_bn_full <- apply(data_test_full, MARGIN = 2, bernoulli_conv)
spam_model_full <- naiveBayes(data_train_bn_full, label_train_full,laplace=0)
data_test_bn_full = as.data.frame(as.matrix(data_test_bn_full))
Hasil prediksi saya simpan kedalam file submission.csv dan didapatkan hasil sebagai berikut :
sms_test<-read.csv("data/data-test.csv", stringsAsFactors = F, encoding = "UTF-8",sep=",")
sms_test<-sms_test %>% mutate(status=predict(spam_model_full, data_test_bn_full, type = "class")) %>%
select(datetime,status)
write.csv(sms_test,file = "submission.csv",row.names = FALSE)
Performance
Berdasarkan percobaan yang telah saya lakukan untuk memprediksi data sms spam atau ham menggunakan machine learning naive bayes dan decision tree menghasilkan ketepatan prediksi yang sangat baik dan diantara kedua model yang dicobakan model naive bayes yang memiliki ketepatan yang lebih baik dengan tingkat akurasi, recall, prescision dan speficity yang telah dituliskan diatas. Model machine learning tersebut dapat bermanfaat bagi pemberi layanan penyedia sms untuk dapat meningkatkan kepuasan dan experienced dari pelanggan , karena machine learning dapat membedakan sms yang termasuk spam dan ham, sama halnya dengan email terdapat inbox dan spam.
A work by Briandamar Kencana
damarbrian@gmail.com