İçeriğe geç
← Blog

Finans başlıklarında duygu analizi: kıyaslama seti neden yanıltır?

Burak Berk Şama · · 6 dk okuma · Yapay Zekâ
Finans başlıklarında duygu analizi: kıyaslama seti neden yanıltır?

Finans haberlerinden duygu çıkaran bir model eğittim ve kıyaslama setinde 0.79 macro-F1 aldım. Gayet iyi bir sayı. Sonra modeli gerçek, günlük Türkçe haber başlıklarında denedim ve skor 0.53'e düştü.

Bu yazı, o farkın nereden geldiğini ve onu nasıl kısmen kapattığımı anlatıyor.

Kurulum

Hedef basitti: bir başlık ver, pozitif / negatif / nötr etiketi al. Eğitim için iki kaynak kullandım:

  • Financial PhraseBank — İngilizce finans cümleleri, uzmanlarca etiketlenmiş.
  • ITU'nun KAP başlıkları ve PhraseBank'in Türkçe çevirisi — Türkçe taraf için.

Önce en basit modeli kurdum: TF-IDF + lojistik regresyon, İngilizce testte 0.69 macro-F1. Ardından xlm-roberta-base'i iki dilin karışımıyla ince ayara soktum: karışık test setinde 0.79 (İngilizce 0.85, Türkçe 0.78).

Veriyi birleştirirken baştan kapattığım bir sızıntı vardı: bir İngilizce PhraseBank cümlesi ile Türkçe çevirisi aynı gruba atanıyor. Aksi hâlde biri eğitimde, öbürü testte kalır ve model aslında ezberlediği bir cümleyi "bilmiş" gibi görünür.

Gerçek başlıklarla tanışma

Kıyaslama setleri temiz, dengeli ve tutarlıdır. Gerçek haber akışı öyle değil. Canlı RSS kaynaklarından topladığım başlıklardan 129 tanesini elle etiketleyip modeli bunlarla sınadım:

Ölçüm macro-F1
XLM-R, karışık kıyaslama testi 0.79
XLM-R, gerçek TR başlıklar 0.53

Hata matrisine bakınca sorun netleşti: model neredeyse hiç "nötr" demiyordu.

Sebep bir domain shift. Türkçe eğitim verisinin büyük kısmı KAP açıklamalarından geliyor; bunlar "net kâr yüzde X arttı", "sözleşme imzalandı" gibi somut olaylar anlatıyor. Gerçek başlıkların çoğu ise yön belirtmiyor: "Gözler Merkez Bankası'nın faiz kararında", "Piyasalarda haftanın ajandası". Model, her başlıkta bir yön görmeye alışmıştı.

Bir eşik, büyük bir fark

İlk çözüm yeni veri değil, bir karar kuralıydı: model duygulu bir sınıfı seçiyor ama o sınıfa yeterince emin değilse, tahmini nötre düşür.

def apply_margin(probs, margin):
    """argmax duygulu ve olasılığı < margin ise nötr der."""
    out = []
    for p in probs:
        i = int(p.argmax())
        out.append(LABELS[NEU] if i != NEU and p[i] < margin else LABELS[i])
    return out

Eşiği tahminle değil, elle etiketli başlıklar üzerinde çapraz doğrulamayla seçtim; iki katlamada çıkan değerlerin ortalaması varsayılan oldu. Sonuç:

Ölçüm macro-F1
Gerçek TR başlıklar, eşiksiz 0.53
Gerçek TR başlıklar, nötr eşikli 0.72

Bunun bir yama olduğunu saklamıyorum. Model yanlış şeyi öğrenmiş; eşik yalnızca bu yanlışın etkisini azaltıyor. Kalıcı çözüm, gerçek başlıklarla yeniden eğitim.

Sınıf ağırlığında ince bir ayar

Eğitimde sınıflar dengesizdi ve ilk refleksim scikit-learn'deki "balanced" ağırlıkları kullanmaktı. Bu, nötr sınıfı fazla ezip modeli duygulu tahminlere daha da itti; yani tam da gerçek dünyada yaşadığım soruna. Ağırlıkların karekökünü almak daha yumuşak bir denge sağladı.

Finans dışını ayıklamak

Canlı akışta bir sorun daha vardı: magazin, spor, sağlık haberleri. Duygu modeli bunlara da güvenle etiket basıyordu. Önlerine ikili bir "finans / konu dışı" filtresi koydum.

Elimde yalnızca 46 konu dışı örnek vardı. TF-IDF bu kadar az veriyle tutunamadı (macro-F1 0.69, konu dışı geri çağırma 0.43). Aynı veride XLM-R gömmeleri üzerine lojistik regresyon 0.82 verdi. Önceden eğitilmiş bir dil modelinin gömmeleri, az örnekle öğrenmeyi mümkün kılıyor. Bir dil modeliyle etiketlediğim 294 Türkçe başlığı ekleyince skor 0.84'e çıktı.

Öğrendiklerim

Kıyaslama setindeki skor, modelin ne kadar iyi olduğunu değil, kıyaslama setine ne kadar benzediğini ölçer.

  • Küçük de olsa gerçek veriyle doğrula. 129 elle etiketli başlık, binlerce satırlık kıyaslama setinin gizlediği sorunu bir öğleden sonrada ortaya çıkardı.
  • Hata matrisine bak. Tek bir skor "kötü" der; hata matrisi "neden"ini söyler.
  • Az veride gömme kullan. Sıfırdan öğrenen bir model yerine önceden eğitilmiş temsiller, birkaç düzine örnekle bile işe yarıyor.

Sıradaki adım belli: gerçek başlıkları büyütüp modeli onlarla yeniden eğitmek ve eşiğin artık gerekmediği noktaya gelmek.

Python Yapay Zekâ Makine Öğrenmesi