Bloga geri dön
Günümüzde dijital iletişim araçlarının hızla yaygınlaşmasıyla birlikte mesajlaşma sistemleri üzerinden spam mesajların sayısında da ciddi artış görüyoruz. Telefonlara gelen "Tebrikler! Hediye kazandınız hemen tıklayın” gibi mesajlar sadece kullanıcı deneyimini olumsuz etkilemekle kalmaz aynı zamanda siber güvenlik açısından da önemli riskler oluşturur.
Bu spam mesajlar kimlik avı ( phishing olarak da bilinir) kötü amaçlı yazılımları yayma, dolandırıcılık ya da istenmeyen reklamlar gibi birçok kötü niyetli amaca hizmet edebiliyor. Kullanıcıların bu tarz içeriklerden korunabilmesi için çeşitli filtreleme sistemlerine ihtiyaç duyulur. Bu yazımda yapay zeka ve metin madenciliği tekniklerini kullanarak doğal dil işleme ile kendi sms spam tespit uygulamamızı geliştireceğiz.
Makine öğrenmesi ve derin öğrenme sınıflandırma problemlerinde kullanılan oldukça etkili yöntemlerdir. Gerçek sms verisi üzerinden hem geleneksel yöntemler (örneğin TF-IDF ve Naive Bayes vb) hem de derin öğrenme modelleri (LSTM gibi) ile spam tespiti gerçekleştireceğiz. Burada amacımız her iki yaklaşımın da nasıl çalıştığını uygulamalı olarak göstermek ve elde edilen sonuçları karşılaştırarak güçlü yönlerini analiz etmek.
Projenin sonunda gelen mesajları "spam" ve "ham" olarak sınıflandırılan ve gerçek dünyada da kullanabileceğimiz bir sistem elde etmiş olacağız. Bu sistemi komut üzerinde de çalıştırarak bir uygulama formatında sunabilir ve aynı zamanda geliştirilebilir bir alt yapı da sağlamış olacağız.
Öncelikle veri setini inceleyelim: SMS Spam Collection
Sınıflandırma problemlerinde elimizde anlamlı ve yeterli sayıda örnek veri olması gerçekten çok önemlidir. Ben bu projede sıkça kullanılan ve bu alanda referans gösterilen güvenilen veri setlerinden biri olan Sms Spam Collection veri setini kullanmak istedim.
Veri setini aşağıdaki sayfadan indirebilirsiniz;
https://www.kaggle.com/datasets/uciml/sms-spam-collection-dataset
Veri setine genel olarak bakacak olursak; 5.574 adet gerçek SMS mesajı içeriyor ve bu veriler UCI Machine Learning Repository üzerinden temin edilmiş ve mesajlar temelde iki kategoriye ayrılmakta;
ham: kullanıcının görmek istediği, yani spam sayılmayan normal mesajlar
spam: içerisinde kötü niyetli yazılım, reklam, dolandırıcılık veya phishing içeren ve kullanıcı tarafından istenmeyen mesajlardır
Bu veri setinde her satırda bir etiket (ham ya da spam) ve bu etikete karşılık gelen bir metin mesajı bulunmakta.
Örneğin;
Bu mesajlar kullanıcı gizliliği korunarak anonimleştirilerek modelin daha iyi öğrenebilmesi için kullanılıyor, bu şekilde veri seti gerçek dünyadaki örneklerle şekillenerek daha kapsamlı bir şekilde eğitilmiş oluyor.
Verileri yüklemek için pandas kütüphanesini kullanıyoruz.
Bu adımda yalnızca işimize yarayan iki sütunu aldık: label ve text (v1 ve v2) diğer sütunlar analizle ilgili pek bir anlam ifade etmediği için onları dışarıda bıraktık.
Makine öğrenmesinde modeller doğrudan metin şeklindeki string ifadelerle çalışamaz bu yüzden öncelikle label sütununda yer alan 'ham' ve 'spam' gibi ifadeleri sayısal hale çevirerek modele uygun hale getirmemiz gerekiyor. sayısal hale getirmemiz gerekiyor:
bu dönüşüm sayesinde artık elimizde şöyle bir yapı var:
0: ham mesaj
1: spam mesaj
Yani verimizi modelin anlayabileceği şekilde sadeleştirmiş ve etiketlemiş olduk, artık bu verilerle daha rahat çalışabiliriz.
Metin madenciliğinde en önemli adımlardan birisi veri temizleme işlemidir çünkü makine öğrenmesi modelleri kelimeler üzerinde çalışır ve bu kelimelerin düzgün işlenmesi modelin başarısını etkiler
Bu aşamada bazı temel adımları uyguladık;
- tüm metni küçük harfe çevirdik
-metindeki sayılar temizlendi
-noktalama işaretleri kaldırıldı
-ve eğer gerekiyorsa, fazla boşlukları da sadeleştirmiş olduk.
Bu sayede daha net ve modelin anlaması için daha kolay bir metin yapısı elde etmiş olduk.
Bu işlemler sonrası örnek bir mesaj şuna dönüşür:
Orijinal hali;
"Congratulations! You have won £1000. Call 09061701461 now."
Temizlenmiş mesaj;
"congratulations you have won call now"
İlk 5 mesaj için uygulama ekran çıktısı:
Bu sadeleştirme sayesinde model, gereksiz ve herhangi bir anlam taşımayan karakterlerden etkilenmeden mesajın asıl yapısına odaklanabiliyor.
Veri setinin genel dağılımına baktığımızda spam ve ham mesaj sayısında belirgin bir fark olduğunu gözlemliyoruz. Spam mesajların daha az olması ya da tam tersi oldukça fazla olması model eğitiminde dikkat etmemiz gereken bir nokta çünkü bu durum modelin bir sınıfa daha fazla ağırlık vermesine yol açabilir.
Ekran çıktısı:
Yani verilerin yaklaşık olarak %87’si ham, %13’ü ise spam mesajlardan oluşuyor diyebiliriz. Model eğitimlerinde bu tip dağılımların göz önünde bulundurulması gerekir, çünkü sadece doğruluk (accuracy) tek başına yeterli bir değerlendirme ölçütü olmayabilir, bu sebeple precision, recall ve f1-score gibi metriklere de bakmak önemli hale geliyor.
Sonuç olarak bu bölümde;
-verileri sorunsuz bir şekilde yükledik,
-etiketleri sayısal hale dönüştürdük,
-metinleri temizledik,
-verideki dengesiz sınıf dağılımını gözlemledik.
Artık elimizde spam tespiti için hazır, temiz ve işlenebilir bir veri seti var. Bir sonraki adımda bu veriyi kullanarak Native Bayes ve TF-IDF uygulama tabanlı makine öğrenimi modelleriyle ilk sonuçlarımızı elde etmeye başlayacağız.
Spam tespiti gibi metin sınıflandırma problemlerinde makine öğrenmesi, uzun zamandır etkili ve pratik çözümler sunan bir yaklaşım. Özellikle düşük donanım ihtiyacı ve yüksek doğruluk oranları sayesinde birçok gerçek dünya uygulamasında ilk tercih olarak karşımıza çıkıyor. Bu bölümde biz de klasik ama güçlü bir yöntem olan Naive Bayes algoritmasını TF-IDF vektörleştirme yöntemiyle birlikte kullanacağız.
Modelin ne kadar iyi çalıştığını anlayabilmek için elimizdeki veriyi iki gruba ayırmamız gerekiyor: eğitim ve test
Genellikle verinin %80’i modeli eğitmek için, kalan %20’si ise modelin perforformansını test etmek için kullanılır, bu sayede model hiç görmediği verilerle test edildiğinde gerçek dünyadaki başarısı hakkında bize net bir fikir vermiş olur.
Metin verileri doğrudan sayılarla ifade edilemediği için bu verileri modele çevirebilmek adına bir şekilde sayısallaştırmak gerekir. TF-IDF (Term Frequency – Inverse Document Frequency) yöntemiyle kelimelerin belgelerdeki önem derecelerine göre bir ağırlık atanır.
TF (Terim Frekansı): bir kelimenin belgede kaç kez geçtiğini gösterir
IDF (Ters Belge Frekansı): kelimenin tüm belgeler içinde ne kadar nadir geçtiğini gösterir
Bu sayede mesajlarda sıkça geçen ama anlam açısından ayırt edici olmayan kelimeler (the, you gibi) düşük skor alırken, sadece spam mesajlarda sıkça geçen kelimeler (örneğin; win, free) daha yüksek skor alır. Böylece model hangi kelimenin daha anlamlı olduğunu daha iyi öğrenebilir.
Naive Bayes, özellikle metin sınıflandırma gibi problemler söz konusu olduğunda hem hızlı hem de oldukça etkili çalışan bir yöntemdir. Bu modelin temel varsayımına göre her kelime diğerlerinden bağımsız olarak mesajın hangi sınıfa ait olduğunu etkiler, ancak gerçek hayatta kelimeler tamamen bağımsız değildir bu varsayıma rağmen Naive Bayes birçok durumda gayet pratik bir yöntem olmuş ve başarılı sonuçlar vermiştir. Bu yüzden başlangıç aşamasında sıkça tercih edilen yöntemlerden biridir.
Eğitilen modeli şimdi test verisi üzerinde inceleyelim.
Modelin başarı oranını doğruluk(accuracy), hassasiyet (precision), duyarlılık (recall) ve f1 skoru gibi birden fazla ölçüm kriteri kullanarak detaylı şekilde analiz edeceğiz.
Precision (kesinlik): Model “spam” dediğinde gerçekten spam olma ihtimali.
Recall (duyarlılık): Gerçek spam mesajlardan kaç tanesini model doğru tahmin edebildi bunu ölçer.
F1-Score: Precision ve recall arasındaki dengeyi sağlar, özellikle dengesiz veri setlerindeki önemli bir değerlendirme kriteridir.
Şimdi modeli eğitim sırasında hiç görmediği bir örnekle test edelim:
Model mesajı spam olarak doğru bir şekilde sınıflandırdı.
-Hızlı çalışır
-Az miktarda veriyle bile iyi sonuçlar verebilir
-Yorumlanması ve uygulanması daha kolaydır
-Dilin karmaşık yapısı karşısında duyarsız kalabilir
-Bağlamı anlayamaz özellikle ironi ve alay gibi ifadelerde yanılma payı yüksektir
-Alışılmışın dışında beklenmedik mesajları tespit etmekte zorlanabilir.
Bu bölümde klasik bir makine öğrenmesi modeli olan TF-IDF ile Naive Bayes yöntemini uyguladık ve oldukça başarılı sonuçlar elde ettik. Ancak bu yöntem kelimeler arasındaki sıralama ya da bağlam gibi ilişkileri tam olarak anlayamaz. bu nedenle bir sonraki adımda derin öğrenme tekniklerine geçiyoruz.
LSTM (Long Short-Term Memory) gibi modeller cümle içerisindeki kelimeler arasındaki ilişkileri öğrenerek çok daha güçlü ve anlamlı sonuçlar verebilir.
Makine öğrenmesi modelleri, spam mesajları genel olarak başarılı bir şekilde sınıflandırabilir ancak daha karmaşık yapı ve bağlamlarda, kelimeler arası ilişkilerde bu yöntemler yetersiz kalabiliyor. Bu gibi durumlarda bağlamı ve kelime sırasını da anlayabilen derin öğrenme modelleri devreye giriyor.
Bu aşamada metin sınıflandırma problemleri için oldukça etkili olan LSTM (Long Short-Term Memory) mimarisi ile spam mesaj tespiti gerçekleştireceğiz.
LSTM, klasik RNN (Recurrent Neural Network) modellerinin daha gelişmiş bir versiyonudur. RNN yapıları kelimelerin sırasını göz önünde bulundurur, fakat uzun cümlelerde önceki bilgileri hatırlamakta zorlanabilirler, yani zaman içinde bilgi kaybı yaşanır.
LSTM bu sorunu aşmak için özel olarak tasarlanmış giriş (input gate), çıkış (output gate) ve unutma kapısı (forget gates) kullanır. Bu kapılar sayesinde model geçmişteki önemli bilgileri hatırlayarak çok daha anlamlı ve tutarlı tahminlerde bulunabilir.
Bu sayede LSTM sadece hangi kelimenin geçtiğine değil, aynı zamanda o kelimenin cümledeki sırasına ve bağlamına da dikkat eder, model mesajın yapısını çok daha iyi kavrayabilir.
İlk olarak her kelimeye bir sayısal ID (kimlik) atayacağız, bu işlem için Tokenizer sınıfı kullanılır. Tokenizer metindeki her kelimeyi temsil eden sayılar oluşturarak veriyi modelin anlayabileceği formata dönüştürmemizi sağlar.
oov_token="<OOV>": Model eğitimi sırasında görülmemiş kelimeler için bir yer sembol (placeholder) belirlenir.
vocab_size: kelime haznesindeli toplam kelime sayısı
Artık her kelimenin sayısal bir ID’si olduğuna göre mesajların tamamını bu ID’lerden oluşan bir sayı dizisine (sequence) çevirebiliriz.
Bu dönüşüm sonrası örnek bir mesaj şöyle görünür:
LSTM modelleri değişken uzunlukta cümlelerle çalışmakta zorlandığı için genellikle sabit uzunlukta girişleri tercih eder. Bu nedenle, elimizdeki tüm mesajları aynı uzunluğa getiriyoruz (örneğin 100 kelime)
Mesaj 100 kelimeden kısa ise, eksik kalan kısmını 0 ile dolduruyoruz (padding), eğer mesaj çok uzunsa sadece ilk 100 kelimeyi alıyoruz ve fazlasını kesiyoruz (truncating) Bu sayede modelin alacağı veriler hem düzgün hem de karşılaştırılabilir bir hale geliyor.
Modelimizi TensorFlow/Keras kütüphanesi aracılığıyla oluşturacağız. Aşağıda sırayla modet katmanlarını inceleyebilirsiniz:
Embedding: Her kelimeye karşılık gelen sayısal ID’yi anlamlı bir vektöre çevirir.
Bidirectional LSTM: Cümleyi sadece soldan sağa değil, aynı zamanda sağdan sola doğru da okur. Böylece model kelimeler arasındaki bağlamı daha iyi yakalar.
Dropout: Aşırı öğrenmenin (overfitting) önüne geçmek için bazı nöronları rastgele devre dışı bırakır. Burada %50 oranında nöron geçici olarak kapatılır.
Dense: Modelin son katmanıdır, tek bir nörondan oluşur ve sigmoid aktivasyon fonksiyonu kullanılarak 0 ile 1 arasında bir çıktı üretir bu da mesajın spam olma ihtimalini gösterir.
Modeli çalıştırmadan önce derlememiz ve ardından eğitim verisiyle eğitmemiz (fit) gerekir
loss='binary_crossentropy': ikili sınıflandırma problemleri için en yaygın kullanılan kayıp fonksiyonudur
optimizer='adam': Öğrenme sürecinde ağırlıkları güncelleyen algoritmadır
epochs=10: Model tüm veri seti üzerinde 10 kez eğitilir
Modeli ve birlikte kullandığımız tokenizer'ı daha sonra tekrar kullanabilmek için kaydediyoruz, böylece eğitimi yeniden yapmak zorunda kalmadan doğrudan tahmin işlemleri gerçekleştirebiliriz.
Bu dosyalar, ilerleyen aşamalarda gerçek zamanlı tahminler yapabilmek için (örneğin dl-predict.py dosyasında) kullanılacak.
Modelin doğruluk oranının eğitim süreci boyunca nasıl değiştiğini aşağıdaki gibi görselleştirebiliriz:
Grafiğe baktığımızda modelin eğitim sürecini genel hatlarıyla başarılı şekilde tamamladığını söyleyebiliriz. Eğitim doğruluğu oldukça yüksek neredeyse 1.00’e kadar çıkmış. Bu da modelin eğitim verisini çok iyi öğrendiğini gösteriyor ancak bu kadar yüksek doğruluk bazen overfitting (ezberleme) belirtisi olabilir.
Genel olarak model öğrenmiş ve doğrulama skoru da gayet iyi ama fazla epoch yapılırsa overfitting riski artabilir.
Bu adımda makine öğrenmesi ve derin öğrenme yaklaşımlarını başarı oranı, esneklik ve yorumlanabilirlik gibi kriterler üzerinden değerlendirerek hangi durumlarda hangi yöntemin daha uygun olduğunu inceleyeceğiz.
Aşağıda Naive Bayes ve TF-IDF kullanan makine öğrenmesi yöntemi ile LSTM ile Embedding kullanan derin öğrenme yaklaşımlarının performans karşılaştırması:
Modelin doğruluk oranı ile birlikte modelin aynı zamanda hangi hataları yaptığına da bakmamız gerekir.
Bu noktada devreye confusion matrix yani karmaşıklık matrisi girer. Bu matris sayesinde doğru şekilde tespit edilen spam’ler (true positive), yanlışlıkla spam sanılan mesajlar (false positive), doğru şekilde ham olarak sınıflandırılan mesajlar (true negative) ve gözden kaçan spam’ler (false negative) gibi ayrıntılar net biçimde incelebilir.
Bu confusion matrix, modelin test verisinde ne kadar doğru tahmin yaptığını özetliyor.
-Model, 965 adet ham mesajı doğru şekilde “ham” olarak sınıflandırmış.
-96 spam mesajını da doğru şekilde “spam” olarak tanımış.
-Ancak, 54 spam mesajını yanlışlıkla “ham” olarak algılamış fakat model, hiçbir ham mesajı spam sanmamış, yani yanlış alarm vermemiş.
Bu tabloya göre modelin ham mesajları tanıma konusunda oldukça başarılı olduğunu ancak bazı spam mesajları kaçırdığını söyleyebiliriz. Spam tespiti için bu durum iyileştirilebilir ama modelimiz genel olarak dengeli ve kabul edilebilir bir performans sergiliyor.
LSTM için:
LSTM modeline ait olan bu son confusion matrix, modelin test verilerindeki başarısını ortaya koymaktadır. Tablodan gördüğümüz kadarıyla model, 960 ham mesajı doğru şekilde ham olarak sınıflandırmış ve 133 spam mesajını da başarılı bir şekilde spam olarak tespit etmiş bu da modelin genel doğruluk açısından oldukça sağlam bir performans sergilediğini gösteriyor.
Ancak tamamen hatasız da değil. Model, 5 adet ham mesajı yanlışlıkla spam olarak algılamış (bu durum "yanlış alarm" olarak değerlendirilir) ve 17 spam mesajını gözden kaçırıp ham olarak sınıflandırmış, bu tür hatalar (False Negative),özellikle güvenlik açısından kritik sistemlerde istenmeyen sonuçlar doğurabilir.
Yine de önceki modelle kıyasladığımızda False Negative (FN) oranının belirgin şekilde düştüğü görülüyor. Yani LSTM modeli spam mesajlarını kaçırma konusunda daha dikkatli ve başarılı. Bu yönüyle model, hem daha dengeli bir tahmin performansı sunuyor hem de güvenlik hassasiyeti yüksek alanlarda kullanıma daha uygun hale geliyor.
LSTM modeli yalnızca yüksek doğruluk değil aynı zamanda hata türleri açısından da bize dengeli ve güvenilir bir yapı sunuyor.
ROC eğrisi, modelin ne kadar doğru şekilde pozitifleri yakaladığını ve yanlış pozitif oranıyla nasıl başa çıktığını gösterir. bu eğri grafik üzerinde sol üst köşeye ne kadar yakınsa, modelin performansı da o kadar iyi demektir.
Bu örnekte hem klasik bir makine öğrenmesi modeli (Naive Bayes) hem de derin öğrenme modelini (LSTM) kullanarak bu iki modelin ROC eğrilerini çizerek karşılaştırmaya çalıştım. ROC eğrisi altında kalan alan (AUC - Area Under Curve) genellikle LSTM modeli daha yüksek AUC değeri vererek daha güçlü bir performans sergilemiştir.
ROC eğrisi karşılaştırmasına göre her iki model de yüksek performans göstermekte ancak LSTM modelinin AUC değeri 0.98 ile Naive Bayes modeline (0.97) göre biraz daha yüksek görünüyor , bu da LSTM’in pozitif sınıfları ayırt etme konusunda biraz daha başarılı olduğunu bize gösterir.
Makine öğrenmesi ve derin öğrenme yöntemlerinin her biri bize farklı senaryolarda avantaj sağlar.
Örneğin;
-Eğer veri az ve eğitim süresi önemliyse, hızı ve hafif yapısı nedeniyle Naive Bayes gibi klasik makine öğrenmesi yöntemlerini tercih edebiliriz.
-Ancak yüksek doğruluk, karmaşık cümle yapıları ya da büyük veriyle uzun vadeli çözümler söz konusu olduğunda LSTM gibi derin öğrenme tabanlı modeller daha başarılı sonuçlar vermektedir.
-Gerçek zamanlı uygulamalarda ise hem ML hem de hafifletilmiş (quantized) DL modelleri kullanılabilir
Makine öğrenmesi modelleri daha sade ve hızlıdır ancak daha sınırlı yapıdadır.
LSTM gibi derin öğrenme modelleri ise attention, önceden eğitilmiş embedding’ler veya GRU/Transformer gibi yapılarla geliştirilebilir ve daha güçlü hale getirilebililer.
Örnek Uygulama Yapalım: Gerçek Zamanlı Tahmin Aracı (CLI) ve Uygulama Senaryoları
Eğittiğimiz LSTM modelini komut satırı arayüzü (CLI) ile entegre ederek, kullanıcıdan alınan SMS mesajının anlık olarak “spam” mi “ham” mı olduğunu tahmin eden basit bir uygulama geliştireceğiz.
Uygulama Akışı (dl-predict.py):
-sms_model.h5 ve tokenizer.pkl dosyalarını yükler
- kullanıcıdan bir SMS alır
- mesajı temizler, tokenize eder, pad’ler
- LSTM modeline verir ve sonucu yazdırır
(dl-predict.py dosyası):
$ python dl-predict.py
Bir SMS giriniz (çıkmak için 'q'): You have been selected! Click here to win a gift card!
Tahmin Oranı: 0.9724
Sonuç: SPAM
Bir SMS giriniz (çıkmak için 'q'): Can you send me the meeting notes from today?
Tahmin Oranı: 0.0812
Sonuç: HAM
-E-posta Filtreleme: Spam maillerin otomatik tespitinde kullanılır
-SMS Güvenliği: Bankalar gelen mesajları analiz ederek kimlik avı riskini azaltabilir,
-Müşteri Hizmeti: Chatbot’lar mesajları sınıflandırarak önceliklendirme yapabilir.
-Sosyal Medya Moderasyonu: Uygunsuz içerikler önceden tespit edilerek engellenebilir.
Modelimiz şu anda kelimelere rastgele vektörler atıyor ancak GloVe gibi önceden eğitilmiş kelime vektörleri kullanılırsa model benzer anlamlı kelimeleri daha iyi tanıyabilir ve böylece spam tespitinde daha güçlü hale gelir.
embedding_matrix = np.zeros((vocab_size, embedding_dim))
for word, i in tokenizer.word_index.items():
embedding_vector = pretrained_vectors.get(word)
if embedding_vector is not None:
embedding_matrix[i] = embedding_vector
bu sayede eğitim süresi azalır, modelin başlangıç seviyesi bilgisi artar ve genelleme gücü gelişir
Modelin performansını artırmak için izleyebileceğimiz bazı yollar:
-Önemli kelimelere odaklanma (Attention):
LSTM modelleri sıralı çalışır ama bu modelde her kelime aynı önemde değildir. “FREE” gibi spam işaretleri taşıyan kelimelere ağırlık verilerek daha doğru sonuçlar elde edebiliriz
-Mobil uyumluluk (Model Küçültme):
Başarılı ama büyük modeller mobil cihazlarda çalışmaz, Quantization veya pruning gibi tekniklerle daha hafif hale getirilebilir
-Geri bildirimle kendini geliştirme:
Kullanıcılardan gelen doğru/yanlış geri dönüşler toplanarak model güncellemesi yapılabilir
-Web arayüzü:
Daha kullanıcı dostu bir arayüz için Flask veya Streamlit kullanılarak bir web arayüzü sunulabilir.
-Çoklu dil desteği:
Model şu an yalnızca İngilizceyi anlıyor ancak Türkçe veya başka diller için veri genişletilerek dil uyumu sağlanabilir.
-Düzenli yeniden eğitim:
Spam içerikler zamanla değiştiği için model belirli aralıklarla yeniden eğitilmelidir.