Pemrosesan Bahasa Alami (NLP) klasik berfokus pada cara mengubah teks menjadi angka lalu dilatih dengan model sederhana yang kuat. Kita mulai dari pembersihan teks, membangun fitur BoW & TF‑IDF, dan melatih Multinomial Naive Bayes serta Logistic Regression. Dengan pipeline, seluruh alur menjadi rapi dan mudah dituning.
Tujuan: paham representasi teks, menjalankan baseline NB/LR, dan membaca metrik evaluasiSesi 15 – NLP Dasar (Klasik)
Ulasan Materi: Definisi, Intuisi, dan Contoh
Mengapa Pembersihan Teks?
Teks mentah berisi variasi huruf, tanda baca, tautan, dan kata umum. Membersihkan dan menormalkan membantu model fokus pada sinyal, bukan noise. Pada bahasa Indonesia, stopwords seperti dan, yang, di, ke kerap dibuang.
BoW vs TF‑IDF
BoW menghitung frekuensi kata; TF‑IDF menurunkan bobot kata sangat umum dan menaikkan kata spesifik/topikal. N‑gram menambah konteks frasa (mis. “tidak bagus”).
Ringkasan Intuisi & Konsep:
1) Pra-pemrosesan Teks
• Normalisasi: lowercasing, hapus tanda baca/angka, strip spasi, opsional: stemming/lemmatization.
• Stopwords: kata sangat umum ("dan, yang, di, ke") yang sering dibuang agar sinyal topik lebih kuat.
2) Representasi Fitur
• Bag-of-Words (BoW): fitur = frekuensi token (unigram/bigram). Sederhana namun efektif.
• TF‑IDF: menimbang kata jarang/khusus lebih tinggi; TF=term frequency, IDF=log(N/df).
• N‑gram: memperkaya konteks (mis. "tidak bagus" → bigram).
3) Model Klasik untuk Teks
• Multinomial Naive Bayes (MNB): mengasumsikan kemandirian fitur, cepat & baseline kuat.
• Logistic Regression (LR): linear classifier dengan regularisasi (C). Sering unggul pada TF‑IDF.
4) Evaluasi
• Gunakan train/test split; metrik: akurasi, presisi, recall, F1; confusion matrix; untuk data tak seimbang: macro‑F1.
5) Pipeline
• vectorizer → classifier dibungkus dalam Pipeline; mudah untuk grid search & re‑use.
Studi Kasus
- Sentimen Ulasan: positif/negatif untuk umpan balik layanan.
- Klasifikasi Email: promo vs kantor (LR + TF‑IDF).
- Topik Berita: 20 Newsgroups subset dua kategori.
Lab: Cleaning, BoW/TF‑IDF, NB, LR, Pipeline, Confusion Heatmap
# ====== A. Pembersihan Teks Ringan (Python) ======
import re
def clean_text(s: str):
s = s.lower()
s = re.sub(r"http\S+|www\S+", " ", s)
s = re.sub(r"[^a-zA-Z\s]", " ", s) # contoh: huruf latin saja
s = re.sub(r"\s+", " ", s).strip()
return s
sample = "Produk ini BAGUS bgt!!! Cek di https://toko.example/123 😊"
print(clean_text(sample))
# ====== B. BoW & TF‑IDF (contoh cepat) ======
# Jika perlu: !pip install scikit-learn
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
corpus = [
"makan nasi di warung padang enak",
"warung padang ramai sekali",
"saya makan mie ayam enak",
"mie ayam dan bakso enak",
]
cv = CountVectorizer(ngram_range=(1,1))
x_bow = cv.fit_transform(corpus)
print('Vocab BoW:', cv.get_feature_names_out())
print('Shape BoW:', x_bow.shape)
tfidf = TfidfVectorizer(ngram_range=(1,2), min_df=1)
x_tfidf = tfidf.fit_transform(corpus)
print('Vocab TF‑IDF (dengan bigram):', tfidf.get_feature_names_out()[:12])
print('Shape TF‑IDF:', x_tfidf.shape)
# ====== C. Baseline Multinomial Naive Bayes (sentimen mini) ======
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import classification_report, confusion_matrix, accuracy_score
# Dataset mini (positif/negatif) — ganti/augment sesuai kebutuhan
texts = [
'bagus sekali pelayanannya', 'sangat memuaskan', 'luar biasa',
'buruk dan lambat', 'mengecewakan', 'tidak rekomendasi',
'produk bagus kualitas oke', 'harga tidak sesuai', 'kualitas jelek',
'pengiriman cepat', 'layanan ramah', 'salah kirim barang',
'mantap enak', 'parah rusak', 'top banget',
]
labels = [1,1,1,0,0,0,1,0,0,1,1,0,1,0,1] # 1=positif, 0=negatif
Xtr, Xte, ytr, yte = train_test_split(texts, labels, test_size=0.3, random_state=42, stratify=labels)
vec = TfidfVectorizer(ngram_range=(1,2), min_df=1)
Xtrv = vec.fit_transform(Xtr)
Xtev = vec.transform(Xte)
clf = MultinomialNB()
clf.fit(Xtrv, ytr)
yp = clf.predict(Xtev)
print('Akurasi:', accuracy_score(yte, yp))
print('Confusion Matrix:\n', confusion_matrix(yte, yp))
print(classification_report(yte, yp, digits=3))
# ====== D. Logistic Regression + Pipeline + GridSearch ======
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report
# Contoh kategorisasi 2 kelas (ganti dengan data Anda)
texts = [
'jadwal rapat proyek senin pagi', 'rapat ditunda minggu depan', 'proposal pendanaan inovasi',
'diskon besar belanja akhir pekan', 'voucher promo belanja hemat', 'flash sale tengah malam'
]
labels = [0,0,0,1,1,1] # 0=office, 1=promo
Xtr, Xte, ytr, yte = train_test_split(texts, labels, test_size=0.34, random_state=0, stratify=labels)
pipe = Pipeline([
('tfidf', TfidfVectorizer(ngram_range=(1,2), min_df=1)),
('clf', LogisticRegression(max_iter=1000))
])
param = {
'tfidf__ngram_range': [(1,1),(1,2)],
'clf__C': [0.1, 1, 5],
'clf__penalty': ['l2']
}
cv = GridSearchCV(pipe, param, cv=3, n_jobs=-1)
cv.fit(Xtr, ytr)
print('Best params:', cv.best_params_)
print(classification_report(yte, cv.best_estimator_.predict(Xte)))
# ====== E. Dataset Lebih Besar: 20 Newsgroups (opsional) ======
# Jalankan di Colab (perlu download data). Pastikan koneksi internet tersedia di runtime Colab.
from sklearn.datasets import fetch_20newsgroups
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report
cats = ['sci.space','rec.sport.baseball'] # contoh dua kategori
news = fetch_20newsgroups(subset='all', categories=cats, remove=('headers','footers','quotes'))
Xtr, Xte, ytr, yte = train_test_split(news.data, news.target, test_size=0.25, random_state=42, stratify=news.target)
pipe = Pipeline([
('tfidf', TfidfVectorizer(ngram_range=(1,2), min_df=2, max_df=0.9)),
('clf', LogisticRegression(max_iter=2000))
])
pipe.fit(Xtr, ytr)
print(classification_report(yte, pipe.predict(Xte)))
# ====== F. Heatmap Confusion Matrix ======
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import confusion_matrix
true = [1,1,1,0,0,0,1,0,1,0]
pred = [1,1,0,0,0,1,1,0,1,0]
cm = confusion_matrix(true, pred)
plt.figure(figsize=(4,3))
plt.imshow(cm)
for (i,j),v in np.ndenumerate(cm):
plt.text(j, i, str(v), ha='center', va='center')
plt.title('Confusion Matrix')
plt.xlabel('Prediksi'); plt.ylabel('Benar')
plt.colorbar(); plt.show()
# ====== G. Kuis 15 (cek mandiri) ======
qs=[
("Apa keunggulan TF‑IDF dibanding BoW murni?",
{"a":"Meningkatkan bobot kata umum","b":"Menurunkan bobot kata umum & menaikkan kata spesifik","c":"Menghapus semua stopwords","d":"Selalu lebih cepat"},"b"),
("Model baseline cepat untuk teks adalah...",
{"a":"KNN","b":"Decision Tree","c":"Multinomial Naive Bayes","d":"K‑Means"},"c"),
("Metrik yang cocok untuk data tak seimbang:",
{"a":"Akurasi saja","b":"Macro‑F1/Recall","c":"MSE","d":"Silhouette"},"b"),
("Dalam LR, parameter C mengatur...",
{"a":"Jumlah n‑gram","b":"Kekuatan regularisasi (kebalikan) ","c":"Jumlah epoch","d":"Stopwords"},"b"),
]
print('Kunci jawaban:')
for i,(_,__,ans) in enumerate(qs,1):
print(f'Q{i}: {ans}')
Penugasan & Referensi
Tugas Koding 11: Bangun pipeline teks untuk tugas pilihan (sentimen/klasifikasi dokumen). Wajib: pembersihan ringan, TF‑IDF (1–2 gram), model NB vs LR, evaluasi dengan akurasi + macro‑F1 + confusion matrix. Sertakan analisis kata penting (fitur teratas) untuk setiap kelas. Ringkasan ≤ 1 halaman.
- Manning, Raghavan, Schütze — Introduction to Information Retrieval (vector space & IR).
- Bird, Klein, Loper — Natural Language Processing with Python (NLTK Book).