Macademia'nın robotik ve mühendislik programı · ücretsiz seviye tespiti ve kişisel öğrenme yolu

Bölüm 3 · Klasik algoritmalar · Ders 13

Naive Bayes ile spam süzgeci

Kelime saymak, +1 eklemek ve puanları toplamak: gelen kutusunu koruyan algoritma

Veri. Robot atölyesinin ortak e-posta kutusu: 400 e-posta, yarısı spam. Aralarında zor olanlar da var: iş yazışması gibi görünen spam ('yarın toplantı notları için hemen tıkla') ve üye olunan mağazanın bülteni. Süzgeç yalnızca ilk 300 e-postanın etiketini görür; kalan 100 e-postayla sınanır.

400 e-posta · yarısı spam300 eğitim (146 spam) · 100 test · eşik 0,0
1 / 20
spam_suzgeci.pypython
  1. import math
  2. from collections import Counter
  3. import numpy as np
  4. D = np.genfromtxt('spam-epostalar.csv', delimiter=',', names=True, dtype=None, encoding='utf-8') # 400 e-posta
  5. posta = [(m.split(), s == 1) for m, s in zip(D['metin'], D['spam'])] # (kelimeler, spam_mi) çiftleri
  6. egitim, test = posta[:300], posta[300:] # ilk 300 eğitim, son 100 test
  7. sayac = {True: Counter(), False: Counter()}
  8. for kelimeler, spam in egitim:
  9. sayac[spam].update(kelimeler) # her kelimeyi say
  10. sozluk = set(sayac[True]) | set(sayac[False])
  11. toplam = {s: sum(c.values()) + len(sozluk) for s, c in sayac.items()} # +1 ekleme
  12. def puan(k):
  13. return math.log((sayac[True][k] + 1) / toplam[True]) - math.log((sayac[False][k] + 1) / toplam[False]) # kelimenin spam puanı
  14. def spam_mi(kelimeler, esik=0.0):
  15. return sum(puan(k) for k in kelimeler if k in sozluk) > esik # eşiğin üstü spam
  16. dogru = sum(spam_mi(k) == s for k, s in test)
  17. print(dogru, "/", len(test))
  18. history = {'n_train': [], 'train_acc': [], 'test_acc': []} # öğrenme eğrisi: 50, 100, … 300 e-posta
  19. for n in range(50, 301, 50):
  20. sayac = {True: Counter(), False: Counter()} # yalnız ilk n e-postayla yeniden say
  21. for kelimeler, spam in egitim[:n]: sayac[spam].update(kelimeler)
  22. sozluk = set(sayac[True]) | set(sayac[False])
  23. toplam = {s: sum(c.values()) + len(sozluk) for s, c in sayac.items()}
  24. basari = lambda kume: sum(spam_mi(k) == s for k, s in kume) / len(kume)
  25. for k, v in zip(history, (n, basari(egitim[:n]), basari(test))): history[k].append(float(v)) # son turda n = 300: tam model
  26. skor = [sum(puan(k) for k in kel if k in sozluk) for kel, _ in test] # e-posta puanları (ROC için)
  27. tp = sum(p > 0 and s for p, (_, s) in zip(skor, test)); fp = sum(p > 0 and not s for p, (_, s) in zip(skor, test))
  28. fn = sum(p <= 0 and s for p, (_, s) in zip(skor, test))
  29. for k, v in [('test_acc', history['test_acc'][-1]), ('precision', tp / max(tp + fp, 1)), ('recall', tp / max(tp + fn, 1))]: # son ölçümler tablosu
  30. print(f'{k:<10}{v:>10.4f}')
  31. import csv
  32. with open('egitim_gecmisi.csv', 'w', newline='') as f: # geçmişi CSV'ye yaz
  33. csv.writer(f).writerows([list(history), *zip(*history.values())]) # satır başına bir eğitim büyüklüğü
  34. try:
  35. import matplotlib.pyplot as plt # varsa grafik çiz
  36. for k in ('train_acc', 'test_acc'): plt.plot(history['n_train'], history[k], marker='o', label=k)
  37. plt.xlabel('n_train'); plt.ylabel('accuracy'); plt.legend(); plt.show()
  38. except ImportError:
  39. print('matplotlib yok: grafik atlandı')

Eğitim paneli

Eğitim çalıştırılıyor…

Sahnedeki her sayı, aynı algoritmanın tarayıcında yapılan gerçek çalıştırmasından gelir (sabit tohum, her seferinde aynı sonuç). Python kodunu kendi bilgisayarında çalıştırırsan rastgele başlangıçlar farklı olacağı için sayılar biraz değişebilir.

Kodu tarayıcıda çalıştırPython · NumPy · matplotlib · Pyodide

Python ve NumPy bu sayfada, tarayıcında çalışır (Pyodide). Kodu değiştirip yeniden çalıştırabilirsin; dersin veri setleri çalışma klasöründe hazır. Kod matplotlib kullanırsa grafikler çıktının altında görünür, yazdığı dosyalar (ör. egitim_gecmisi.csv) indirilebilir.

spam_suzgeci.pypython

Çıktı

Çıktı burada görünecek.

Nasıl çalışır

  1. Süzgeç eğitim e-postalarındaki her kelimenin spam’de ve normal postada kaç kez geçtiğini sayar. Eğitimin tamamı budur.
  2. Her sayıya 1 eklenir (Laplace düzeltmesi): bir kelime spam’de hiç görülmediyse bile olasılığı sıfır olmaz ve tek bir kelime kararı kilitleyemez.
  3. Kelimenin puanı iki oranın logaritmasıdır: log P(kelime | spam) − log P(kelime | normal). Sıfırın üstü spam’e, altı normale işaret eder.
  4. “Naive” varsayım: kelimeler birbirinden bağımsız sayılır, bu yüzden e-postanın puanı kelime puanlarının toplamıdır. Süzgeç cümleyi anlamaz; kılık değiştirmiş spam bu yüzden bazen kaçar.
  5. Şunu dene: spam eşiğini −4’e indir. Kılık değiştirmiş spam’in çoğu yakalanır ama bu kez mağaza bültenlerinin hepsi spam kutusuna düşer. Eşiği +2’ye çıkar: bültenler kurtulur, kılık değiştirmiş spam hep kaçar. Hiçbir eşik ikisini birden çözmez; süzgeç cümleyi değil kelimeyi görür.

Neden önemli

İlk ciddi spam süzgeçleri tam olarak bu birkaç satırdı ve bugün de metin sınıflandırmada ilk denenen yöntemdir: eğitimi bir sayım, tahmini bir toplamdır, binlerce kelimeyle bile anında çalışır. Aynı kod robotun hata günlüklerini “donanım / yazılım / ağ” diye ayırmak ya da kullanıcı komutlarını sınıflandırmak için de kullanılır. Sensör verisiyle çalışan Gauss sürümü bir önceki derste.

ESOF 323, 11. hafta: robotlarda derin öğrenme →
Esc
  • PanelAna sayfaSayfa
  • ModüllerTüm modüllerSayfa
  • ParçalarParça ansiklopedisiSayfa
  • Mühendislik yoluBüyükler için robotik: 128 parça, 7 seviyeSayfa
  • Robotik dersi (ESOF 323)Üniversite robotik dersi, 14 haftaSayfa
  • Drone dersiBüyükler için: parça, simülasyon, yazılım; 10 üniteSayfa
  • Blok atölyesiSerbest blok programlamaAraç
  • Devre laboratuvarıSanal Arduino ve devreAraç
  • Robot arenasıSanal robot sürüşüAraç
  • OyunlarBloklarla 8 öğretici oyunAraç
  • Mikro Kart atölyesiSanal LED kartı bloklarla programlaAraç
  • Robot atölyesiMikro Kart'ı robota tak, bloklarla görev yapAraç