Python ile Doğal Dil İşleme: NLP Projesi Adım Adım
NLP Nedir ve Neden Önemlidir?
Doğal Dil İşleme (Natural Language Processing - NLP), bilgisayarların insan dilini anlama, yorumlama ve üretme yeteneğini kazandıran yapay zeka alt dalıdır. Günlük hayatımızda kullandığımız sanal asistanlar, spam filtreleri, otomatik çeviri sistemleri ve duygu analizi araçlarının tamamı NLP teknolojileri üzerine inşa edilmiştir.
Python, zengin kütüphane ekosistemi sayesinde NLP projeleri için en popüler programlama dilidir. Bu yazıda, sıfırdan bir NLP projesi oluşturacak ve her adımı detaylı şekilde inceleyeceğiz.
Geliştirme Ortamının Hazırlanması
Öncelikle projemiz için gerekli kütüphaneleri kuralım:
pip install nltk spacy transformers scikit-learn pandas numpy
python -m spacy download tr_core_news_trf
Projemizde kullanacağımız temel kütüphaneler şunlardır:
- NLTK — Klasik NLP işlemleri için temel kütüphane
- spaCy — Endüstriyel düzeyde hızlı NLP işlemleri
- Transformers (Hugging Face) — Önceden eğitilmiş dil modelleri
- scikit-learn — Makine öğrenmesi algoritmaları ve metin sınıflandırma
Adım 1: Veri Toplama ve Yükleme
Her NLP projesinin temeli veridir. Örnek projemizde müşteri yorumlarını analiz ederek duygu sınıflandırması yapacağız. Veri setimizi bir CSV dosyasından yükleyelim:
import pandas as pd
df = pd.read_csv("musteri_yorumlari.csv")
print(df.head())
print(f"Toplam yorum sayısı: {len(df)}")
print(f"Sınıf dağılımı:\n{df['etiket'].value_counts()}")
Veri setinizde dengesizlik varsa (örneğin pozitif yorumlar negatiflerden çok fazlaysa), modelin yanlı öğrenmesini önlemek için oversampling veya undersampling tekniklerini uygulamayı düşünmelisiniz.
Adım 2: Metin Ön İşleme (Preprocessing)
Ham metin verisi doğrudan modele beslenemez. Metin ön işleme adımları, NLP projelerinin en kritik aşamasıdır ve model performansını doğrudan etkiler.
Temel Ön İşleme Fonksiyonu
import re
import nltk
from nltk.corpus import stopwords
from nltk.stem import SnowballStemmer
nltk.download('stopwords')
nltk.download('punkt')
turkish_stopwords = stopwords.words('turkish')
stemmer = SnowballStemmer('turkish')
def metin_temizle(metin):
# Küçük harfe çevir
metin = metin.lower()
# URL'leri kaldır
metin = re.sub(r'http\S+|www\S+', '', metin)
# HTML etiketlerini kaldır
metin = re.sub(r'<.*?>', '', metin)
# Özel karakterleri ve sayıları kaldır
metin = re.sub(r'[^a-zçğıöşü\s]', '', metin)
# Fazla boşlukları temizle
metin = re.sub(r'\s+', ' ', metin).strip()
# Stopword'leri kaldır
kelimeler = metin.split()
kelimeler = [k for k in kelimeler if k not in turkish_stopwords]
# Stemming uygula
kelimeler = [stemmer.stem(k) for k in kelimeler]
return ' '.join(kelimeler)
df['temiz_metin'] = df['yorum'].apply(metin_temizle)
Ön İşleme Adımlarının Açıklaması
- Küçük harfe çevirme: "Güzel" ve "güzel" kelimelerinin aynı token olarak değerlendirilmesini sağlar
- URL ve HTML temizliği: Anlamsız gürültüyü ortadan kaldırır
- Özel karakter temizliği: Noktalama işaretleri ve sayılar çoğu NLP görevinde gereksizdir
- Stopword kaldırma: "bir", "ve", "ama" gibi anlam taşımayan bağlaçları çıkarır
- Stemming: Kelimeleri köklerine indirgeyerek kelime dağarcığını küçültür
Adım 3: Özellik Çıkarımı (Feature Extraction)
Temizlenmiş metni sayısal vektörlere dönüştürmemiz gerekir. En yaygın iki yöntem şunlardır:
TF-IDF Vektörizasyonu
from sklearn.feature_extraction.text import TfidfVectorizer
tfidf = TfidfVectorizer(
max_features=5000,
ngram_range=(1, 2), # unigram ve bigram
min_df=2, # en az 2 belgede geçen kelimeler
max_df=0.95 # çok yaygın kelimeleri ele
)
X = tfidf.fit_transform(df['temiz_metin'])
y = df['etiket']
print(f"Özellik matrisi boyutu: {X.shape}")
TF-IDF (Term Frequency - Inverse Document Frequency), bir kelimenin belge içindeki önemini ölçer. Belgede sık geçen ama tüm belgelerde nadir olan kelimeler daha yüksek ağırlık alır. ngram_range=(1, 2) parametresi ile hem tekli kelimeler hem de ikili kelime grupları (örneğin "çok güzel", "hiç beğenmedim") özellik olarak kullanılır.
Adım 4: Model Eğitimi ve Değerlendirme
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.svm import LinearSVC
from sklearn.metrics import classification_report, confusion_matrix
# Veriyi böl
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
# Birden fazla model dene
modeller = {
'Lojistik Regresyon': LogisticRegression(max_iter=1000),
'Destek Vektör Makinesi': LinearSVC(max_iter=2000),
}
for isim, model in modeller.items():
# Çapraz doğrulama
skorlar = cross_val_score(model, X_train, y_train, cv=5, scoring='f1_weighted')
print(f"{isim} - Ortalama F1: {skorlar.mean():.4f} (±{skorlar.std():.4f})")
# Eğit ve test et
model.fit(X_train, y_train)
tahminler = model.predict(X_test)
print(classification_report(y_test, tahminler))
stratify=y parametresi, eğitim ve test setlerinde sınıf dağılımının orantılı kalmasını sağlar. F1 skoru, özellikle dengesiz veri setlerinde doğruluk (accuracy) yerine tercih edilmesi gereken bir metriktir.
Adım 5: Transformer Tabanlı Yaklaşım
Daha yüksek doğruluk istiyorsanız, önceden eğitilmiş transformer modelleri güçlü bir alternatiftir:
from transformers import pipeline
# Türkçe destekli duygu analizi pipeline'ı
duygu_analizi = pipeline(
"sentiment-analysis",
model="savasy/bert-base-turkish-sentiment-cased"
)
ornekler = [
"Bu ürünü çok beğendim, herkese tavsiye ederim.",
"Kargo çok geç geldi ve ürün hasarlıydı.",
"Fiyatına göre idare eder, fena değil."
]
for ornek in ornekler:
sonuc = duygu_analizi(ornek)[0]
print(f"Metin: {ornek}")
print(f"Sonuç: {sonuc['label']} (Güven: {sonuc['score']:.4f})\n")
Transformer modelleri, bağlamsal kelime temsillerini öğrenebildiği için TF-IDF tabanlı yaklaşımlardan genellikle çok daha başarılıdır. Ancak daha fazla hesaplama kaynağı gerektirir; GPU erişiminiz yoksa küçük veri setlerinde klasik yöntemler daha pratik olabilir.
Adım 6: Modeli Kaydetme ve Servise Alma
import joblib
# Klasik modeli kaydet
joblib.dump(model, 'duygu_modeli.pkl')
joblib.dump(tfidf, 'tfidf_vektorizor.pkl')
# Yükleme ve tahmin
def tahmin_yap(metin):
model = joblib.load('duygu_modeli.pkl')
vektorizor = joblib.load('tfidf_vektorizor.pkl')
temiz = metin_temizle(metin)
vektor = vektorizor.transform([temiz])
return model.predict(vektor)[0]
sonuc = tahmin_yap("Harika bir deneyimdi, teşekkürler!")
print(f"Tahmin: {sonuc}")
Performans İyileştirme İpuçları
- Lemmatizasyon vs. Stemming: Türkçe gibi sondan eklemeli dillerde lemmatizasyon (Zeyrek kütüphanesi) stemming'den daha doğru sonuçlar verebilir
- Hiperparametre optimizasyonu:
GridSearchCVveyaOptunaile model parametrelerini otomatik olarak ayarlayın - Veri artırma: Eşanlamlı kelime değiştirme veya geri çeviri (back-translation) teknikleriyle eğitim verisini çoğaltın
- Ensemble yöntemler: Birden fazla modelin tahminlerini birleştirerek daha gürbüz sonuçlar elde edin
- Hata analizi: Yanlış sınıflandırılan örnekleri inceleyerek veri kalitesini ve ön işleme adımlarını iyileştirin
Sonuç
Bu yazıda, Python ile uçtan uca bir NLP projesi oluşturduk. Veri toplama, metin ön işleme, özellik çıkarımı, model eğitimi ve değerlendirme adımlarını detaylıca inceledik. Geleneksel makine öğrenmesi yöntemlerinin yanı sıra transformer tabanlı modern yaklaşımları da ele aldık.
NLP alanı hızla gelişiyor. Büyük dil modellerinin (LLM) yaygınlaşmasıyla birlikte, özellikle Türkçe gibi düşük kaynaklı dillerde fine-tuning ve transfer öğrenme teknikleri giderek daha önemli hale gelmektedir. Projenizi geliştirirken küçük başlayın, metrikleri takip edin ve iteratif olarak iyileştirin.