Diziden Tek Çıktıya: LSTM ile Duygu Analizi
Baştan sona bir duygu sınıflandırıcısı oluşturacaksınız: yorumları belirteçlere ayıracak, nn.Embedding ile sözcükleri gömecek, LSTM'den geçirecek ve son gizli durumu sınıflandıracaksınız.
Diziden Tek Çıktıya: LSTM ile Duygu Analizi, CoddyKit'te ücretsiz bir Machine Learning Academy dersidir. Bu, 4 dersinin 4. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, Machine Learning Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Machine Learning Academy kursu toplamda 4 dersten oluşur.
Diziden Teke Sınıflandırma Açıklaması
Diziden teke görevlerinde model, dizinin tamamını okur ve tek bir çıktı etiketi üretir. Duygu analizi bunun klasik örneğidir: tam bir film incelemesi ('Bu filmin her dakikasına bayıldım') verildiğinde, olumlu veya olumsuz olmak üzere tek bir etiket tahmin edilir.
Bu, diziden diziye (çeviri; her girdi belirteci bir çıktı belirteci üretir) ve tekten diziye (görüntü açıklaması oluşturma) görevlerinden farklıdır. Diziden teke görevinde ara LSTM çıktılarını atar ve yalnızca teorik olarak tüm girdi dizisinin anlamını kodlayan son gizli durumu h_T kullanırız.
Veri Kümesi: IMDB Film İncelemeleri
IMDB veri kümesi, olumlu veya olumsuz olarak etiketlenmiş 50.000 film incelemesi (25.000 eğitim, 25.000 sınama) içerir. Her inceleme, uzunluğu değişebilen bir metin dizisidir. Bir LSTM'ye vermeden önce üç ön işleme adımına ihtiyacımız vardır: belirteçlere ayırma (metni sözcüklere bölme), sözlük oluşturma (sözcükleri tamsayı indislerine eşleme) ve dolgu (tüm dizileri aynı uzunluğa getirme).
Ayrıca çok uzun incelemeleri ele almamız gerekir — LSTM eğitimi dizi uzunluğuyla karesel olarak yavaşladığından, doğruluğu önemli ölçüde düşürmeden 256 veya 512 belirtece kısaltmak yaygın bir uygulamadır.
from torchtext.datasets import IMDB
from torchtext.data.utils import get_tokenizer
from torchtext.vocab import build_vocab_from_iterator
tokenizer = get_tokenizer('basic_english')
def yield_tokens(data_iter):
for _, text in data_iter:
yield tokenizer(text)
train_iter = IMDB(split='train')
vocab = build_vocab_from_iterator(yield_tokens(train_iter),
specials=['<unk>', '<pad>'])
vocab.set_default_index(vocab['<unk>'])
print('Vocabulary size:', len(vocab))Dizileri Belirteçlere Ayırma ve Doldurma
Dolgu gereklidir; çünkü PyTorch DataLoaders bir parti içindeki tensörlerin aynı biçimde olmasını gerektirir. Kısa dizileri özel bir <pad> belirteciyle (genellikle 0 indisi) doldurur, uzun dizileri ise en fazla uzunluğa kısaltırız.
Temel nokta, LSTM'nin dolgu belirteçlerini yok sayması gerektiğidir. PyTorch'un pack_padded_sequence ve pad_packed_sequence yardımcı araçları, LSTM hesaplaması sırasında dolguyu verimli biçimde atlamanızı sağlar. Bu, doğruluk açısından önemlidir; aksi hâlde model, anlamsız dolguyu temel alarak gizli durumunu günceller ve son h_T değerini bozar.
import torch
from torch.nn.utils.rnn import pad_sequence
def text_pipeline(text):
return vocab(tokenizer(text))[:256] # Truncate to 256 tokens
def label_pipeline(label):
return 1 if label == 'pos' else 0
def collate_batch(batch):
labels, texts, lengths = [], [], []
for label, text in batch:
labels.append(label_pipeline(label))
processed = torch.tensor(text_pipeline(text), dtype=torch.long)
texts.append(processed)
lengths.append(len(processed))
texts = pad_sequence(texts, batch_first=True, padding_value=1) # 1 = <pad>
return torch.tensor(labels), texts, torch.tensor(lengths)Gömme Katmanı: Sözcüklerden Yoğun Vektörlere
Tamsayı biçimindeki sözcük indisleri doğrudan bir LSTM'ye verilemez; bunları sürekli vektörlere dönüştürmemiz gerekir. Gömme katmanı nn.Embedding(vocab_size, embedding_dim), her sözcük indisini kayan noktalı sayılardan oluşan yoğun bir vektöre eşleyen bir arama tablosudur.
Yaygın gömme boyutları 100, 200 veya 300'dür. Gömme değerleri, LSTM ağırlıklarıyla birlikte eğitim sırasında güncellenen öğrenilebilir parametrelerdir. Alternatif olarak bunları, sözcükler arasındaki önceden öğrenilmiş anlamsal ilişkileri sağlayarak küçük veri kümelerinde eğitimi büyük ölçüde hızlandıran önceden eğitilmiş sözcük vektörlerinden, örneğin GloVe'dan başlatabilirsiniz.
import torch.nn as nn
vocab_size = 25000
embedding_dim = 100
hidden_size = 128
output_dim = 1 # Binary classification: positive/negative
embedding = nn.Embedding(vocab_size, embedding_dim, padding_idx=1)
# Optional: load pre-trained GloVe vectors
# from torchtext.vocab import GloVe
# glove = GloVe(name='6B', dim=100)
# embedding.weight.data.copy_(glove.vectors)
print('Embedding weight shape:', embedding.weight.shape) # (25000, 100)SentimentLSTM Modelini Oluşturma
Tam model mimarisi üç bölümden oluşur: bir gömme katmanı, bir LSTM ve bir tam bağlı başlık. Gömme katmanı belirteç indislerini vektörlere dönüştürür, LSTM diziyi işler ve doğrusal katman son gizli durumu tek bir logite eşler.
Modeli düzenlileştirmek için gömme katmanından sonra ve doğrusal katmandan önce dropout ekleriz. Çıktı için 0 ile 1 arasında bir olasılık elde etmek üzere sigmoid uygularız. Bu ikili sınıflandırma olduğundan eğitimde İkili Çapraz Entropi kaybı kullanılır.
import torch
import torch.nn as nn
class SentimentLSTM(nn.Module):
def __init__(self, vocab_size, embed_dim, hidden_size, num_layers, dropout):
super().__init__()
self.embedding = nn.Embedding(vocab_size, embed_dim, padding_idx=1)
self.lstm = nn.LSTM(embed_dim, hidden_size, num_layers,
batch_first=True, dropout=dropout)
self.dropout = nn.Dropout(dropout)
self.fc = nn.Linear(hidden_size, 1)
def forward(self, text):
embedded = self.dropout(self.embedding(text)) # (B, T, embed_dim)
output, (h_n, c_n) = self.lstm(embedded)
last_hidden = self.dropout(h_n[-1]) # Final layer hidden state
return self.fc(last_hidden).squeeze(1) # (B,) logitsEğitim Kurulumu: Kayıp ve İyileştirici
İkili sınıflandırma için sigmoid etkinleştirmesini ve ikili çapraz entropi kaybını sayısal olarak kararlı tek bir işlemde birleştiren nn.BCEWithLogitsLoss kullanırız. Bu, sigmoid'i elle uygulayıp ardından nn.BCELoss kullanmaya kıyasla tercih edilir.
Öğrenme oranı 1e-3 olan Adam iyileştiricisini kullanırız. Adam, her parametre için öğrenme oranını uyarlar; bu da gömmelerden kaynaklanan seyrek gradyanlar için onu uygun kılar (yalnızca partide görünen sözcüklerin gömmeleri gradyan güncellemeleri alır). RNN eğitiminde yaygın bir sorun olan gradyanların patlamasını önlemek için torch.nn.utils.clip_grad_norm_ ile gradyan kırpma kullanın.
import torch
import torch.nn as nn
import torch.optim as optim
model = SentimentLSTM(
vocab_size=25000, embed_dim=100,
hidden_size=128, num_layers=2, dropout=0.3
)
optimizer = optim.Adam(model.parameters(), lr=1e-3)
criterion = nn.BCEWithLogitsLoss()
# Gradient clipping prevents exploding gradients in RNNs
MAX_GRAD_NORM = 1.0
print('Model parameters:', sum(p.numel() for p in model.parameters()))Sentiment LSTM için Eğitim Döngüsü
Diziden teke sınıflandırma için eğitim döngüsü standart PyTorch düzenini izler: ileri geçiş, kaybı hesaplama, geri yayılım, gradyanları kırpma ve parametreleri güncelleme. Ayrıca tahmin edilen sınıfı (sigmoid çıktısı > 0.5) gerçek etiketlerle karşılaştırarak doğruluğu hesaplarız.
Önemli bir nokta, hem modelin hem de parti tensörlerinin aynı cihaza (CPU veya GPU) taşınmasıdır. model.to(device) ve tensor.to(device) kullanmak hesaplamaların tutarlı olmasını sağlar. GPU üzerinde IMDB ile iki katmanlı bir LSTM'yi eğitmek genellikle dönem başına 2-5 dakika sürer.
def train_epoch(model, loader, optimizer, criterion, device):
model.train()
total_loss, correct = 0.0, 0
for labels, texts, lengths in loader:
labels, texts = labels.float().to(device), texts.to(device)
optimizer.zero_grad()
predictions = model(texts) # Forward pass
loss = criterion(predictions, labels) # Compute loss
loss.backward() # Backprop
torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0) # Clip
optimizer.step() # Update weights
total_loss += loss.item()
preds = (torch.sigmoid(predictions) > 0.5).float()
correct += (preds == labels).sum().item()
return total_loss / len(loader), correct / len(loader.dataset)Değerlendirme ve İlerlemeyi İzleme
Değerlendirme sırasında model.eval() çağrısı yapar ve dropout'u ve gradyan izlemeyi devre dışı bırakmak için ileri geçişleri torch.no_grad() içine alırız. Böylece genelleme başarısına ilişkin tarafsız bir görünüm elde ederiz.
Dönemler boyunca dört sayıyı izleriz: eğitim kaybı, doğrulama kaybı, eğitim doğruluğu ve doğrulama doğruluğu. Eğitim doğruluğu artarken doğrulama doğruluğu sabit kalıyorsa model aşırı öğreniyordur — dropout'u artırın veya model boyutunu küçültün. İkisi de düşükse model yetersiz öğreniyordur — LSTM katmanları ekleyin veya gizli boyutu artırın.
def evaluate(model, loader, criterion, device):
model.eval()
total_loss, correct = 0.0, 0
with torch.no_grad():
for labels, texts, lengths in loader:
labels, texts = labels.float().to(device), texts.to(device)
predictions = model(texts)
loss = criterion(predictions, labels)
total_loss += loss.item()
preds = (torch.sigmoid(predictions) > 0.5).float()
correct += (preds == labels).sum().item()
return total_loss / len(loader), correct / len(loader.dataset)
# Training run
for epoch in range(5):
tr_loss, tr_acc = train_epoch(model, train_loader, optimizer, criterion, device)
vl_loss, vl_acc = evaluate(model, val_loader, criterion, device)
print(f'Epoch {epoch+1}: Train Acc={tr_acc:.3f}, Val Acc={vl_acc:.3f}')Beklenen Başarım ve Yaygın Hatalar
İyi ayarlanmış bir LSTM duygu sınıflandırıcısı, IMDB üzerinde genellikle %85-90 sınama doğruluğuna ulaşır. Başarımı düşüren yaygın hatalar arasında değerlendirme sırasında model.eval() ayarını yapmamak (dropout etkin kalır), geri yayılımdan önce gradyanları sıfırlamamak ve gömmeler yakınsaymadan önce çok az dönem boyunca eğitim yapmak bulunur.
Bir başka sorun, bilinmeyen sözcükler ve dolgu için aynı sözlük indisini kullanmaktır. Bilinmeyen sözcükler için <unk> (0 indisi), dolgu için <pad> (1 indisi) belirteçlerini ayırın ve dolgu gömmelerinin her zaman sıfır olması, gradyanlarının da eğitim sırasında bastırılması için gömme katmanına padding_idx=1 geçirin.
# Common mistakes checklist:
# 1. Missing model.eval() before evaluation
# 2. Missing optimizer.zero_grad() before backward
# 3. Applying sigmoid twice (using BCELoss instead of BCEWithLogitsLoss)
# 4. Not handling unknown words (<unk> token)
# 5. Padding and unknown sharing the same index
# Correct: separate special tokens
vocab = build_vocab_from_iterator(
yield_tokens(train_iter),
specials=['<unk>', '<pad>'], # 0 and 1
min_freq=2 # Discard rare words
)Yeni Metinler Üzerinde Tahmin Yapma
Yeni incelemeleri çıkarım sırasında sınıflandırmak için eğitimde kullanılan ön işleme akışının aynısını uygularız: belirteçlere ayırma, indislerine dönüştürme, kısaltma ve bir parti boyutu ekleme. Model bir logit döndürür; sigmoid uygulamak bunu bir olasılığa dönüştürür.
0.5'in üzerindeki bir tahmin puanı olumlu duyguyu gösterir. Bu eşiği ayarlayabilirsiniz: eşiği 0.3'e düşürmek, kesinlik pahasına olumlu incelemeler için duyarlılığı artırır. Dropout'u devre dışı bırakmak ve gereksiz gradyan hesaplamasını önlemek için çıkarım sırasında her zaman model.eval() ve torch.no_grad() kullanın.
def predict_sentiment(model, text, vocab, tokenizer, device, max_len=256):
model.eval()
tokens = vocab(tokenizer(text))[:max_len]
tensor = torch.tensor(tokens, dtype=torch.long).unsqueeze(0).to(device)
with torch.no_grad():
logit = model(tensor)
prob = torch.sigmoid(logit).item()
return 'positive' if prob > 0.5 else 'negative', prob
label, score = predict_sentiment(
model,
'This film was absolutely brilliant. Loved every scene!',
vocab, tokenizer, device
)
print(f'Sentiment: {label} ({score:.3f})')Duygu Analizi için LSTM ve BERT Karşılaştırması
LSTM'ler yaklaşık 2018'e kadar doğal dil işleme alanında en ileri teknoloji olsa da, günümüzde BERT gibi dönüştürücü tabanlı modeller doğal dil işleme başarı ölçütlerinin çoğunda öne çıkmaktadır. BERT, IMDB'de LSTM'nin yaklaşık %87-90'lık sonucuna kıyasla yaklaşık %93-95 başarı elde eder.
Bununla birlikte, LSTM'ler çeşitli nedenlerle hâlâ önemini korumaktadır: çok uzun dizilerde hesaplama açısından çok daha verimlidir (dönüştürücüler dizi uzunluğuyla karesel olarak ölçeklenir), sıralı yapının doğasında bulunduğu zaman serisi verilerinde iyi çalışır ve bellek kullanımı çok daha düşüktür. LSTM'leri anlamak, dikkat mekanizmalarının onları nasıl geliştirdiğini kavramak için gereken temel anlayışı da sağlar.
Hızlı Kontrol
Bu derste LSTM tabanlı dizi sınıflandırmasını ne kadar anladığınızı test edin.
Ders Özeti
Bu derste şunları öğrendiniz: birden-bire mimarisi, bir giriş dizisinin tamamını okur ve son LSTM gizli durumunu kullanarak bunu tek bir etikete eşler; metin ön işleme işlem hattı, veriler modele girmeden önce belirteçlere ayırma, sözlük oluşturma ve dolgu işlemlerini gerektirir; gömme katmanları ise ayrık kelime indislerini anlamsal anlamı yakalayan yoğun, öğrenilebilir vektörlere dönüştürür. Sırada, sıfırdan eğitim yapmak yerine önceden eğitilmiş model ağırlıklarının kullanıldığı aktarım öğrenmesini inceleyeceğiz.
Yapay zeka eğitmeniyle Python öğren — ücretsiz
Tarayıcında gerçek kod yaz ve çalıştır, 7/24 yapay zeka eğitmeninden anında yardım al; web'de ya da uygulamada kaldığın yerden devam et.
- Kurslar
- 30
- Dersler
- 120
Sıkça Sorulan Sorular
“Diziden Tek Çıktıya: LSTM ile Duygu Analizi” dersi ücretsiz mi?
Evet — “Diziden Tek Çıktıya: LSTM ile Duygu Analizi” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve Machine Learning Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Machine Learning Academy kursu toplamda 4 dersten oluşur.
“Diziden Tek Çıktıya: LSTM ile Duygu Analizi” dersinde ne öğreneceğim?
Baştan sona bir duygu sınıflandırıcısı oluşturacaksınız: yorumları belirteçlere ayıracak, nn.Embedding ile sözcükleri gömecek, LSTM'den geçirecek ve son gizli durumu sınıflandıracaksınız. Machine Learning Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
Machine Learning Academy öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te Machine Learning Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 4. dersidir.
“Diziden Tek Çıktıya: LSTM ile Duygu Analizi” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu Machine Learning Academy dersinde kod yazıp çalıştırabilir miyim?
Evet. Her Machine Learning Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- Temel RNN'ler: Gizli Durum ve Dizi Açılımı
- Derin Zaman Adımlarında Kaybolan Gradyan Sorunu
- LSTM Hücresi: Girdi, Unutma ve Çıktı Kapıları
- Diziden Tek Çıktıya: LSTM ile Duygu Analizi