N-gram nedir? N-gram ile bir sonraki kelimeyi nasıl tahmin ederiz?
n-gram belirli bir metnin n kadar ardışık ögelerden oluşan bir koleksiyondur. Bu ögeler n kadar olan kelimelerden ve harflerden oluşabilirler. Doğal dil işleme (NLP) alanında kullanılan bir tekniktir.
Hangi alanlarda kullanılır?
- Otomatik kelime tamamlamaları
- Dil modeli oluşturmaları
- Yazım Düzeltmeleri
- Cümle tahminleri
- Spam analizi duygu analizi gibi sınıflandırmaları
Bu gibi alanlarda kullanılıyor.
n-gram çalışma mantığı nedir?
| n-gram Türü | Açıklama | Çıktı (Örnek) |
|---|---|---|
| Unigram | Her kelime tek başına | ["Ben", "bugün", "sinemaya", "gittim"] |
| Bigram | İkili kelime grupları | [("Ben", "bugün"), ("bugün", "sinemaya"), ("sinemaya", "gittim")] |
| Trigram | Üçlü kelime grupları | [("Ben", "bugün", "sinemaya"), ("bugün", "sinemaya", "gittim")] |
| n-gram (n=4) | Dörtlü kelime grupları (örnek: 4-gram) | [("Ben", "bugün", "sinemaya", "gittim")] |
Unigram: Kelimeleri tek tek inceler. Genelde sıklık analizi için kullanılır.
Bigram: Her kelimenin ardından hangi kelimenin geldiğini analiz eder.
Trigram: İki kelimeye bakar üçüncü kelimeyi tahmin etmeye çalışır.
Python ile bir sonraki kelimeyi tahmin etme
İlk önce elimizde bulunan belge olabilir veya yazı olabilir onu n-gram ile koleksiyon haline getirmemiz gerekecek. Koleksiyon haline getirmeden önce büyük küçük harf ve noktalama iaretlerinden kurtulmamız gerekecek. Bir sonraki kelimeyi tahmin ederken bigram kullanabiliriz.
import re
text = "Burak markete gitti. 2 adet gazoz aldı ve marketden çıktı."
def bigramParse(text:str):
words = re.sub(r'[^\w\s]','',text.lower()).split()
bigram = []
for i,word in enumerate(words):
if i != words.__len__() - 1:
bigram.append([word,words[i+1]])
return bigram
result = bigramParse(text)
print(result)[kadir@nixos:~/Masaüstü/projects/n-gram]$ python app.py
[['burak', 'markete'], ['markete', 'gitti'], ['gitti', '2'], ['2', 'adet'], ['adet', 'gazoz'], ['gazoz', 'aldı'], ['aldı', 've'], ['ve', 'marketden'], ['marketden', 'çıktı']]Yazımızı bigram haline çevirdik. Şimdi tahmin etme fonksiyonumuzu oluşturup kodumuzu test edelim.
import re
text = "Burak markete gitti. 2 adet gazoz aldı ve marketden çıktı."
def bigramParse(text:str):
words = re.sub(r'[^\w\s]','',text.lower()).split()
bigram = []
for i,word in enumerate(words):
if i != words.__len__() - 1:
bigram.append([word,words[i+1]])
return bigram
def guess(text:str, bigram:list):
for firstWord, lastWord in bigram:
if text == firstWord:
return lastWord
bigram = bigramParse(text)
print(guess("markete",bigram))[kadir@nixos:~/Masaüstü/projects/n-gram]$ python app.py
gittiBu çok basit bir tahmin etme fonskiyonu oldu. Bunu daha da geliştirebiliriz.
- Aynı kelimeler birden fazla tekrar edebilir ve bir sonraki kelimenin ne olacak sadece aratılan kelimenin ilk bulunan sonraki kelimesi olacaktır. Bu sorunu çözmek için birden fazla sonuç verebiliriz.
- Birden fazla sonuç verdiğimizde ise en sık kullanılan bir sonraki kelimeye göre tahminler sıralanması gerekiyor.
- Sonuçların yüzdesel değerler taşıması gerekiyor.
Şimdi sırayla bu geliştirmeleri yapalım. İlk önce birden fazla sonuç vermemiz gerekiyor. guess fonksiyonunu düzeltelim.
def guess(text:str, bigram:list):
result = []
for firstWord, lastWord in bigram:
if text == firstWord:
result.append(lastWord)
return resultŞimdi guess fonksiyonunda birden fazla sonuç verebilecek. Burda en fazla tekrar eden sonuçları bulup onlara yüzdesel oranlar verip bu oranlara göre sıralamalıyız.
from collections import Counter
def rateAndSort(bigramResultList: list):
counter = Counter(bigramResultList)
total = sum(counter.values())
sortedResults = sorted(
[(word, count, round(count / total * 100, 2)) for word, count in counter.items()],
key=lambda x: x[1],
reverse=True
)
return sortedResultsŞimdi tüm kodu test edelim.
import re
from collections import Counter
text = "Burak markete gitti. 2 adet gazoz aldı ve marketden çıktı. Gazozu eline aldı. Aldığı bu gazozun tarihi geçmişti geri iade etmek için markete geri döndü."
def bigramParse(text:str):
words = re.sub(r'[^\w\s]','',text.lower()).split()
bigram = []
for i,word in enumerate(words):
if i != words.__len__() - 1:
bigram.append([word,words[i+1]])
return bigram
def guess(text:str, bigram:list):
result = []
for firstWord, lastWord in bigram:
if text == firstWord:
result.append(lastWord)
return result
def rateAndSort(bigramResultList: list):
counter = Counter(bigramResultList)
total = sum(counter.values())
sortedResults = sorted(
[(word, count, round(count / total * 100, 2)) for word, count in counter.items()],
key=lambda x: x[1],
reverse=True
)
return sortedResults
bigram = bigramParse(text)
guessedWords = guess("markete", bigram)
ranked = rateAndSort(guessedWords)
print(ranked)[kadir@nixos:~/Masaüstü/projects/n-gram]$ python app.py
[('gitti', 1, 50.0), ('geri', 1, 50.0)]Şuanda istediğimiz gibi çalışıyor.
Burda büyük bir örnek yapmasak da iyi bir başlangıç olduğunu umuyorum. Bir sonraki yazımızda görüşmek üzere.