Pernahkah Anda bertanya-tanya bagaimana Gmail tahu bahwa email yang menjanjikan $10 juta adalah spam? Atau bagaimana cara Gmail menangkap pesan "Anda memenangkan iPhone gratis!" sebelum mencapai inbox Anda?
Dalam tutorial ini, Anda akan membangun classifier email spam sendiri dari awal menggunakan algoritma Naive Bayes. Di akhir tutorial, Anda akan memiliki model yang berfungsi dengan akurasi lebih dari 97%—dan Anda akan memahami dengan tepat bagaimana cara kerjanya.
Daftar Isi
- Prasyarat
- Mengapa Naive Bayes untuk Deteksi Spam?
- Cara Mengatur Lingkungan Pengembangan
- Cara Memuat dan Mengeksplorasi Dataset
- Cara Memvisualisasikan Distribusi Data
- Menganalisis Pola Kata dengan Word Clouds
- Preprocessing Data Teks
- Cara Mengubah Teks menjadi Fitur Numerik
- Cara Melatih Naive Bayes Classifier
- Cara Mengevaluasi Performa Model
- Menguji pada Email Individual
- Kesimpulan Utama
Prasyarat
Anda harus memiliki pemahaman dasar tentang Python dan beberapa pemahaman tentang konsep machine learning fundamental. Jangan khawatir jika Anda masih belajar—saya akan menjelaskan semuanya selama kita berjalan.
Mengapa Naive Bayes untuk Deteksi Spam?
Sebelum kita mulai coding, mari pahami mengapa Naive Bayes sangat cocok untuk tugas ini.
Bayangkan Anda menerima email yang berisi kata-kata seperti "gratis," "pemenang," "klik di sini," dan "penawaran waktu terbatas." Otak Anda segera menandai ini sebagai mencurigakan. Algoritma Naive Bayes melakukan sesuatu yang serupa—ia menghitung probabilitas bahwa sebuah email adalah spam berdasarkan kata-kata yang dikandungnya.
Algoritma ini disebut "naive" karena membuat asumsi yang menyederhanakan: ia memperlakukan setiap kata sebagai independen dari setiap kata lainnya. Pada kenyataannya, kombinasi kata penting (pikirkan "uji coba gratis" vs. "uang gratis"), tetapi penyederhanaan ini bekerja sangat baik dalam praktik.
Mengapa Memilih Naive Bayes?
- Kecepatan: Melatih sangat cepat, bahkan pada dataset besar
- Efisiensi: Membutuhkan data pelatihan minimal untuk menghasilkan hasil yang andal
- Kesederhanaan: Mudah diimplementasikan dan diinterpretasikan
- Performa: Terlepas dari kesederhanaannya, sering mengungguli algoritma yang lebih kompleks untuk klasifikasi teks
Keterbatasan yang Perlu Diingat:
- Asumsi independensi berarti tidak dapat menangkap hubungan antar kata
- Jika sebuah kata muncul dalam data pengujian tetapi tidak pernah muncul dalam pelatihan, algoritma memberinya probabilitas nol (meskipun ada cara untuk menangani ini)
Sekarang mari kita bangun detektor spam kita.
Cara Mengatur Lingkungan Pengembangan
Pertama, instal library yang diperlukan. Buka terminal Anda atau jalankan ini di sel Jupyter notebook:
%pip install regex wordcloud numpy pandas seaborn matplotlib scikit-learn
Berikut ringkasan cepat tentang apa yang dilakukan setiap library:
- regex / re — untuk membersihkan teks menggunakan pencocokan pola
- wordcloud — untuk memvisualisasikan kata-kata yang paling sering muncul
- numpy dan pandas — untuk pemuatan dan manipulasi data
- seaborn dan matplotlib — untuk bagan dan visualisasi
- scikit-learn — menyediakan classifier Naive Bayes, vectorizer, dan alat evaluasi
Setelah instalasi selesai, impor semuanya di bagian atas skrip atau notebook Anda. Mengelompokkan semua impor di bagian atas adalah praktik terbaik Python—ini membuat dependensi mudah dilihat dengan cepat.
# Data manipulation and analysis
import pandas as pd
import numpy as np
# Data visualization
import seaborn as sns
import matplotlib.pyplot as plt
# Natural language processing
import nltk
import re
from nltk.corpus import stopwords
# Machine learning
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics import classification_report, confusion_matrix, accuracy_score
# Word cloud visualization
from wordcloud import WordCloud
Cara Memuat dan Mengeksplorasi Dataset
Kita akan menggunakan dataset email yang sudah diberi label. Anda dapat mengunduhnya dari Kaggle atau menggunakan dataset email serupa dengan kolom teks dan spam.
Gunakan fungsi read_csv() pandas untuk memuat dataset dari file CSV ke dalam DataFrame—struktur seperti tabel yang memudahkan inspeksi dan manipulasi data. Metode head() kemudian menampilkan 5 baris pertama sehingga Anda dapat mengonfirmasi data dimuat dengan benar dan memahami strukturnya.
message_dataset = pd.read_csv('emails.csv')
message_dataset.head()
Selanjutnya, panggil shape pada DataFrame untuk memeriksa dimensinya—ini mengembalikan tuple (baris, kolom) dan merupakan cara cepat untuk mengonfirmasi Anda memuat dataset lengkap tanpa pemotongan.
# Get the dimensions of our dataset (rows, columns)
message_dataset.shape
Dataset berisi 5.728 email dengan dua kolom: text (konten email) dan spam (1 untuk spam, 0 untuk email yang sah).
Cara Memvisualisasikan Distribusi Data
Sebelum melatih model apa pun, penting untuk memahami data Anda. Mari kita lihat bagaimana spam dan email yang sah didistribusikan.

value_counts() menghitung berapa banyak email yang termasuk dalam setiap kelas (spam vs. sah). Rantai .plot(kind="pie") pada hasil mengubah hitungan tersebut langsung menjadi diagram pai. Argumen autopct="%1.0f%%" memberitahu matplotlib untuk memberi label setiap irisan dengan persentasenya, dibulatkan ke bilangan bulat terdekat.
plt.rcParams["figure.figsize"] = [8, 10]
message_dataset.spam.value_counts().plot(kind="pie", autopct="%1.0f%%")
Anda akan melihat bahwa sekitar 24% email dalam dataset adalah spam, sementara 76% adalah sah. Ini adalah dataset yang cukup tidak seimbang, yang akan kita ingat saat mengevaluasi model kita.
Menganalisis Pola Kata dengan Word Clouds
Word clouds memberikan visualisasi intuitif dari kata-kata yang paling sering dalam korpus teks. Kata-kata yang muncul lebih sering dirender lebih besar. Mari kita buat word clouds terpisah untuk spam dan email yang sah untuk mengidentifikasi pola yang membedakan.
Pertama, kita perlu menghapus stop words—kata-kata umum seperti "the," "is," dan "at" yang muncul di mana-mana dan tidak membawa sinyal yang bermakna untuk klasifikasi. stopwords.words("english") NLTK mengembalikan daftar yang sudah dibuat sebelumnya dari kata-kata ini. Metode apply() menjalankan fungsi di setiap baris dalam kolom, dan lambda di dalamnya membagi setiap email menjadi kata-kata individual, memfilter kata-kata stop, kemudian menggabungkan kembali kata-kata yang tersisa menjadi string yang bersih.
stop = stopwords.words("english")
message_dataset["text_without_sw"] = message_dataset["text"].apply(
lambda x: "".join([item for item in x.split() if item not in stop])
)
Sekarang mari kita visualisasikan email spam. Kita filter DataFrame ke baris di mana spam == 1, gabungkan semua teks itu menjadi satu string besar, dan kirimkan ke WordCloud().generate(). Fungsi imshow() merender gambar yang dihasilkan, dan axis("off") menyembunyikan sumbu x/y karena tidak bermakna untuk tampilan gambar.

message_dataset_spam = message_dataset[message_dataset["spam"] == 1]
plt.rcParams["figure.figsize"] = [8, 10]
text = ' '.join(message_dataset_spam['text_without_sw'])
wordcloud2 = WordCloud().generate(text)
plt.imshow(wordcloud2)
plt.axis("off")
plt.show()
Sekarang lakukan hal yang sama untuk email yang sah dengan memfilter ke baris di mana spam == 0:

message_dataset_ham = message_dataset[message_dataset["spam"] == 0]
plt.rcParams["figure.figsize"] = [8, 10]
text = ' '.join(message_dataset_ham['text_without_sw'])
wordcloud2 = WordCloud().generate(text)
plt.imshow(wordcloud2)
plt.axis("off")
plt.show()
Observasi Utama:
- Email spam sering mengandung bahasa promosi: "free," "money," "offer," "click," "please"
- Email yang sah mengandung lebih banyak istilah percakapan dan terkait pekerjaan: "company," "time," "thanks"
Anda juga akan melihat kata "enron" muncul menonjol dalam cloud email yang sah. Ini karena email non-spam dalam dataset ini diambil dari korpus email Enron yang tersedia secara publik—koleksi besar email internal nyata dari Enron Corporation yang dirilis selama investigasi penipuan mereka pada tahun 2001. Sejak saat itu menjadi salah satu dataset benchmark yang paling banyak digunakan dalam penelitian NLP, itulah sebabnya "enron" muncul begitu sering sebagai kata dalam konten email yang sah.
Pola-pola ini memberi kita keyakinan bahwa klasifikasi berbasis kata akan bekerja dengan baik.
Preprocessing Data Teks
Teks mentah perlu dibersihkan sebelum algoritma machine learning dapat memprosesnya secara efektif. Mari kita pertama-tama pisahkan fitur kita dari label kita. Dalam terminologi ML, X menyimpan input (teks email yang kita gunakan untuk membuat prediksi) dan y menyimpan label target (1 untuk spam, 0 untuk sah).
X = message_dataset["text"]
y = message_dataset["spam"]
Sekarang kita akan mendefinisikan fungsi untuk membersihkan teks. Fungsi re.sub() dari modul re bawaan Python melakukan substitusi berbasis pola menggunakan regular expression. Kita memanggilnya tiga kali secara berurutan:
re.sub('[^a-zA-Z]', ' ', doc)— mengganti apa pun yang bukan huruf (angka, tanda baca, simbol) dengan spasi. Ini menghilangkan noise yang tidak membantu klasifikasi.re.sub(r'\s+[a-zA-Z]\s+', ' ', document)— menghapus karakter tunggal yang terisolasi (seperti "I" atau "a" yang tertinggal setelah menghapus tanda baca) dengan mencocokkan huruf tunggal yang dikelilingi spasi.re.sub(r'\s+', ' ', document)— menggabungkan beberapa spasi berturut-turut menjadi satu spasi, merapikan celah tambahan yang dibuat oleh dua langkah sebelumnya.
def clean_text(doc):
document = re.sub('[^a-zA-Z]', ' ', doc)
document = re.sub(r'\s+[a-zA-Z]\s+', ' ', document)
document = re.sub(r'\s+', ' ', document)
return document
Terapkan fungsi pembersihan ini ke setiap email dalam dataset. Kita pertama-tama mengonversi Series pandas ke daftar Python biasa menggunakan list(), kemudian loop melalui setiap email, membersihkannya, dan mengumpulkan hasilnya dalam X_sentences.
# Create an empty list to store cleaned emails
X_sentences = []
# Convert the pandas Series to a list for iteration
reviews = list(X)
# Clean each email and add it to our list
for rev in reviews:
X_sentences.append(clean_text(rev))
Cara Mengubah Teks menjadi Fitur Numerik
Algoritma machine learning bekerja dengan angka, bukan teks. Kita perlu mengubah teks yang sudah dibersihkan menjadi representasi numerik.
TF-IDF (Term Frequency-Inverse Document Frequency) adalah pilihan yang sangat baik untuk ini. Ini memberikan setiap kata skor yang mencerminkan seberapa penting kata tersebut untuk dokumen tertentu relatif terhadap seluruh dataset. Kata yang sering muncul dalam satu email tetapi jarang di semua email mendapat skor tinggi—artinya kata itu khas dan kemungkinan bermakna. Kata-kata umum yang muncul di mana-mana mendapat skor lebih rendah.
TfidfVectorizer dari scikit-learn menangani transformasi ini. Parameter yang kita tetapkan mengontrol apa yang disertakan:
- max_features=2500 — hanya menyimpan 2.500 kata yang paling sering, membuang kata-kata jarang yang tidak menggeneralisasi dengan baik
- min_df=5 — mengabaikan kata-kata yang muncul dalam kurang dari 5 email (terlalu jarang untuk berguna)
- max_df=0.7 — mengabaikan kata-kata yang muncul dalam lebih dari 70% dari semua email (terlalu umum untuk menjadi khas)
- stop_words=stopwords.words('english') — menghapus kata-kata umum bahasa Inggris seperti "the" dan "is"
fit_transform() melakukan dua hal dalam satu langkah: ia mempelajari kosakata dari teks kita (fit), kemudian mengonversi setiap email menjadi vektor numerik berdasarkan kosakata itu (transform). Memanggil .toarray() pada hasil mengonversi output matriks sparse—yang hanya menyimpan nilai non-nol untuk efisiensi—menjadi array NumPy dense biasa yang diharapkan classifier scikit-learn.
vectorizer = TfidfVectorizer(
max_features=2500,
min_df=5,
max_df=0.7,
stop_words=stopwords.words('english')
)
X = vectorizer.fit_transform(X_sentences).toarray()
Setiap email sekarang direpresentasikan sebagai vektor 2.500 angka, di mana setiap angka adalah skor TF-IDF untuk kata tertentu.
Cara Melatih Naive Bayes Classifier
Sekarang bagian yang menarik—melatih model kita! Pertama, bagi data menjadi set pelatihan dan pengujian menggunakan train_test_split(). Fungsi ini secara acak mengocok dan membagi X dan y secara bersamaan, menjaga label tetap selaras dengan email yang sesuai. Mengatur test_size=0.20 memesan 20% data untuk pengujian. Mengatur random_state=42 menentukan seed generator angka acak sehingga Anda mendapatkan pembagian yang sama setiap kali Anda menjalankan kode, membuat hasil Anda dapat direproduksi.
X_train, X_test, y_train, y_test = train_test_split(
X, y,
test_size=0.20,
random_state=42
)
Sekarang latih classifier Multinomial Naive Bayes. Kita menggunakan MultinomialNB secara khusus karena dirancang untuk fitur yang merepresentasikan hitungan atau frekuensi—persis seperti apa skor TF-IDF. Memanggil fit(X_train, y_train) melatih model dengan membuatnya menghitung probabilitas setiap kata muncul dalam spam versus email yang sah di seluruh set pelatihan. Tabel probabilitas itu adalah yang digunakan model nanti untuk mengklasifikasikan email baru.
spam_detector = MultinomialNB()
spam_detector.fit(X_train, y_train)
Itu saja! Algoritma Naive Bayes sangat cepat—pelatihan selesai dalam milidetik bahkan dengan ribuan email.
Cara Mengevaluasi Performa Model
Mari kita lihat seberapa baik detektor spam kita bekerja pada email yang belum pernah dilihat sebelumnya. Metode predict() mengambil fitur set pengujian dan mengembalikan label yang diprediksi (0 atau 1) untuk setiap email, berdasarkan tabel probabilitas yang dipelajari model selama pelatihan.
y_pred = spam_detector.predict(X_test)
Sekarang evaluasi prediksi menggunakan tiga alat berbeda dari modul metrics scikit-learn:
- confusion_matrix() — menghasilkan grid 2×2 yang membandingkan label aktual vs. yang diprediksi, menunjukkan dengan tepat di mana model melakukan dengan benar dan salah
- classification_report() — mencetak presisi, recall, dan F1-score untuk setiap kelas, memberikan gambaran yang lebih lengkap daripada akurasi saja
- accuracy_score() — mengembalikan persentase keseluruhan prediksi yang benar
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred))
print(accuracy_score(y_test, y_pred))
Output:
[[849 7]
[ 18 272]]
precision recall f1-score support
0 0.98 0.99 0.99 856
1 0.97 0.94 0.96 290
accuracy 0.98 1146
macro avg 0.98 0.96 0.97 1146
weighted avg 0.98 0.98 0.98 1146
0.9781849912739965
Model kita mencapai akurasi 97,82%! Mari kita uraikan apa yang diberitahu confusion matrix kepada kita:
- 849: Email yang sah diidentifikasi dengan benar sebagai sah (True Negatives)
- 7: Email yang salah ditandai sebagai spam (False Positives)
- 18: Email spam yang lolos sebagai email yang sah (False Negatives)
- 272: Email spam yang tertangkap dengan benar (True Positives)
Laporan klasifikasi menunjukkan:
- Untuk email yang sah (kelas 0): 98% presisi, 99% recall
- Untuk email spam (kelas 1): 97% presisi, 94% recall
Angka-angka ini mengesankan, terutama mempertimbangkan kesederhanaan pendekatan kita.
Menguji pada Email Individual
Mari kita verifikasi model kita bekerja dengan mengujinya pada email tertentu. Kita pertama-tama akan mencetak teks yang sudah dibersihkan pada indeks 56 dan label aktualnya untuk melihat apa yang kita kerjakan. Kemudian kita akan meminta model untuk memprediksinya.
print(X_sentences[56])
print(y[56])
Output:
Subject localized software all languages available hello we would like to offer localized software versions german french spanish uk and many others aii iisted software is available for immediate downioad no need to wait week for cd deiivery just few exampies norton lnternet security pro windows xp professionai with sp fuil version corei draw graphics suite dreamweaver mx homesite inciudinq macromedia studio mx just browse our site and find any software you need in your native ianguaqe best reqards kayieen
1
Ini jelas adalah email spam yang mencoba menjual perangkat lunak bajakan. Label aktualnya adalah 1 (spam). Sekarang kirimkan email tunggal ini melalui pipeline yang sama—pertama mengubahnya menjadi vektor TF-IDF menggunakan vectorizer yang sudah di-fit, kemudian memanggil predict() pada hasilnya. Penting untuk menggunakan vectorizer yang sama yang di-fit pada data pelatihan, sehingga pemetaan kata-ke-indeks konsisten.
print(spam_detector.predict(vectorizer.transform([X_sentences[56]])))
Output:
[1]
Model dengan benar mengidentifikasi email promosi ini sebagai spam.
Kesimpulan Utama
- Naive Bayes sangat kuat untuk klasifikasi teks terlepas dari asumsi penyederhanaannya. Untuk deteksi spam, ia mencapai akurasi yang sangat baik dengan biaya komputasi minimal.
- Preprocessing teks penting. Menghilangkan noise (karakter khusus, angka, spasi ekstra) membantu algoritma fokus pada pola yang bermakna.
- TF-IDF menangkap pentingnya kata secara efektif. Ini memberikan bobot lebih tinggi pada kata-kata khas yang membantu membedakan spam dari email yang sah.
- Selalu evaluasi dengan beberapa metrik. Akurasi saja bisa menyesatkan, terutama dengan dataset yang tidak seimbang. Presisi, recall, dan F1-score memberikan gambaran lengkap.
- Mulailah dari yang sederhana. Sebelum beralih ke model deep learning yang kompleks, coba algoritma klasik seperti Naïve Bayes. Mereka dapat diinterpretasikan, cepat, dan sering kali mengejutkan efektifnya.
Langkah Selanjutnya
Ingin meningkatkan detektor spam ini lebih lanjut? Berikut beberapa ide:
- Bereksperimen dengan vectorizer berbeda: Coba CountVectorizer atau word embeddings (Word2Vec, GloVe)
- Tangani ketidakseimbangan kelas: Gunakan teknik seperti SMOTE atau sesuaikan bobot kelas
- Feature engineering: Tambahkan fitur seperti panjang email, jumlah tautan, atau domain pengirim
- Coba algoritma lain: Bandingkan dengan SVM, Random Forest, atau gradient boosting
- Deploy model: Bangun API sederhana menggunakan Flask atau FastAPI
Kesimpulan
Anda telah membangun classifier email spam yang mencapai lebih dari 97% akurasi menggunakan algoritma Naïve Bayes. Di sepanjang jalan, Anda belajar tentang preprocessing teks, ekstraksi fitur dengan TF-IDF, dan teknik evaluasi model.
Keindahan pendekatan ini adalah kesederhanaannya. Dengan hanya beberapa lusin baris kode, Anda telah menciptakan sesuatu yang benar-benar berfungsi—dan sekarang Anda memahami prinsip-prinsip di balik filter spam komersial.
Jangan ragu untuk bereksperimen dengan kode, coba parameter berbeda, dan lihat bagaimana hasilnya berubah. Itu adalah cara terbaik untuk memperdalam pemahaman Anda.
Referensi
- Python Machine Learning Workbook for Beginners: 10 Machine Learning Projects Explained from Scratch by AI Publishing
Sumber: freeCodeCamp
0 Comments
Terima kasih atas komentarnya
Emoji