English· Español· Deutsch· Nederlands· Français· 日本語· ქართული· 繁體中文· 简体中文· Português· Русский· العربية· हिन्दी· Italiano· 한국어· Polski· Svenska· Türkçe· Українська· Tiếng Việt· Bahasa Indonesia

un

konuk
1 / ?
derslere geri dön

Hoş Geldiniz

Uygulamalı bir NLP dersine hoş geldiniz.

Sıfırdan çalışan bir İngilizce stemmer inşa edeceksiniz: kelimeleri kök biçimlerine indiren bir algoritma.

Sonunda, runningrun, happinesshappi & organizationalorgan gibi kelimeleri dönüştüren gerçek, test edilmiş bir algoritmanız olacak.

Ayrıca stemmeriniz için birim testleri, entegrasyon testleri ve fonksiyonel testleri yazacaksınız: çünkü test edilmemiş bir algoritma sadece bir tahadir.

Stemming Nedir?

Sorun

Arama motorları temel bir sorunla karşı karşıyadır: bir kullanıcı "running" kelimesini arar ama belge "run" veya "runs" veya "runner" içerir. Bunların hepsi aynı kavramdır: ama farklı dizgilerdir.


Stemming, çekimli kelimeleri ortak bir taban biçimine indirger (kök / stem). Gerçek bir kelime olması gerekmez: sadece tutarlı olması gerekir.


KelimeKök
runningrun
runsrun
runnerrunner
happinesshappi
happilyhappi
happyhappi

happi gerçek bir İngilizce kelime değildir. Sorun yok. Stemming anlamlandırma değil, gruplandırma hakkındadır. happiness, happily & happy hepsi aynı kök haline geldiği sürece, arama & erişim iyileşir.

Stemming: Birçok Biçim Bir Köke Dayanır, Arama Sonuçlarını İyileştirir

Kendi sözcüklerinizle, tam dize eşleştirmesi yapan bir arama motorundan daha iyi sonuçlar döndürmek için stemming kullanan bir arama motorunun neden daha iyi sonuçlar döndüreceğini açıklayın. Somut bir örnek verin.

Zellig Harris ve Dağılımsal Analiz

Hesaplamalı stemming'in kökeni

1955'te, dilbilimci Zellig Harris, kelimelerdeki anlamlı birimlerin (biçimbirimlerin) sınırlarını bulma yöntemini açıklayan From Phoneme to Morpheme yayınladı.


Onun anlayışı dağılımsal idi: geniş bir İngilizce sözcük derlemine bakarsanız, bir kök ile sonek arasındaki sınır istatistiksel bir sinyal olarak ortaya çıkar.


Halef çeşitliliği yöntemi

Bir kelimenin herhangi bir ön eki için, derlemde ondan sonra kaç farklı karakter geleceğini sayın. Harris buna halef çeşitliliği adını verdi.


Şunları içeren bir derlemde "work" ön ekini düşünün: worked, worker, working, works, workshop.


Ön EkNe GelirHalef Çeşitliliği
wo1
wor1
work1
worke, i, s, sh4
worked, r2

"work" dan sonra dört farklı karakter gelebilir: çeşitlilikte bir yükselme. Bu yükselme biçimbirim sınırını işaretler. Kök work ve ondan sonra gelen her şey sonektir.


Bu 1955'te çılgınca idi. Hiç dilbilimsel kural yok, hiç sözlük yok: sadece sayma. Harris, dil yapısının dağılım yoluyla kendini ortaya çıkardığını gösterdi.

Harris Halef Çeşitliliği: 'work' konumunda Yükselme Biçimbirim Sınırını İşaretler

Halef Çeşitliliğini Anlamak

Harris'in yöntemi herhangi bir dilde çalışır. Dil bilginizi bilmek gerekmez: istatistikler biçimbirim sınırlarını ortaya çıkarır.


Pratikte, saf halef çeşitliliği büyük bir derlem ve dikkatli tepe tespiti gerektirir. Daha sonraki araştırmacılar: Lovins (1968), Porter (1980): yaklaşımı kural tabanlı sonek çıkarmaya basitleştirdi: derlemden halef çeşitliliğini hesaplamak yerine, sonek kurallarını doğrudan kodladılar.


Bugün, Harris'in anlayışından ilham alan kural tabanlı bir sonek sökücü inşa edeceksiniz. Sonekleri açıkça tanımlayacak ve sonra kelimelerden çıkaracaksınız. Çoğu ürün stemmer'ı bu şekilde çalışır.

Harris'in halef çeşitliliği yönteminin temel anlayışı nedir? Başka bir deyişle, biçimbirim sınırının nerede olduğunu söyleyen istatistiksel sinyal nedir?

İlk Sonek Sökücünüz

Kod yazalım

Basit başlayın. stem adında bir fonksiyon yazın ve bu sonekleri çıkartsın (bu sırayla):


1. -ing (running → runn)

2. -ed (walked → walk)

3. -ly (quickly → quick)

4. -s (cats → cat)


Kurallar:

- Kelimeyi önce küçük harfe dönüştürün

- Sadece bir soneki çıkarın (yukarıdaki sıradaki ilk eşleşme)

- Sadece kalan kök en az 3 karakter uzunluğundaysa çıkarın

- Kökü döndürün


Örnek:

def stem(word):
    word = word.lower()
    # sonek çıkarma mantığınız burada
    return word
Bir `stem` fonksiyonu yazın. -ing, -ed, -ly veya -s (ilk eşleşme, sırayla) soneklerini kelimeden çıkarmalı, ancak yalnızca kalan kök 3 veya daha fazla karakter uzunluğundaysa. stem('running'), stem('walked'), stem('quickly'), & stem('cats') yazdırarak test edin.

Kenar Durumlarını Ele Almak

Stemmer'ı daha akıllı yapma

Temel sökücünüzün bir sorunu vardır: runningrunn & hopinghop. İki iyileştirmeye ihtiyacımız var:


1. Çift ünsüz temizliği: -ing veya -ed çıkarmak sonunda çift ünsüzü bırakırsa (runn gibi), son harfi çıkarın → run

2. Sessiz-e restorasyonu: -ing çıkarmak sonra sessiz harfle biten bir kök bırakırsa (ünlü değil), orijinal sessiz e olabilir (hop from hoping gibi), e geri ekleyin → hope


Sessiz-e kuralı için, basit tutun: -ing çıkardıktan sonra, kök 3+ kar, ünsüzle biterse & ikinci karakter ünlüyse (bir desen hop, mak, tak gibi), e geri ekleyin.


Ayrıca bu yeni sonekleri ekleyin (-ing, -ed, -ly, -s'den önce kontrol edin):

5. -tion (organization → organiza)

6. -ness (happiness → happi)

7. -ment (movement → move)

8. -able (readable → read)

9. -ible (sensible → sens)


Güncellenmiş sonek önceliği: -tion, -ness, -ment, -able, -ible, -ing, -ed, -ly, -s


Minimum kök uzunluğu kuralını tutun: sadece kalan kök 3+ karakterse çıkarın.

Yeni sonekler, çift ünsüz temizliği & sessiz-e restorasyonu ile `stem` fonksiyonunuzu güncelleyin. Şunlar için sonuçlar yazdırın: stem('running'), stem('hoping'), stem('happiness'), stem('organization'), stem('readable').

-ies & -ier Kuralları

Daha fazla biçimbilim

İngilizce, infleksiyon yapıldığında -y ile biten başka bir yaygın desen vardır: -ies, -ied veya -ier'a değişirler.


KelimeKökü Almalı
babiesbabi
carriedcarri
earlierearli
fliesfli
studiedstudi

-s & -ed kontrolleri öncesinde bu kuralları ekleyin:

- -ies → çıkarın & i ekleyin (babies → babi)

- -ied → çıkarın & i ekleyin (carried → carri)

- -ier → çıkarın & i ekleyin (earlier → earli)


Aynı minimum kök uzunluğu kuralı: sadece sonuç 3+ karakterse dönüştürün.

Stem fonksiyonunuza -ies, -ied, & -ier kurallarını ekleyin. Şunlar için sonuçlar yazdırın: stem('babies'), stem('carried'), stem('earlier'), stem('happiness'), stem('running').

Neden Test?

Test isteğe bağlı değildir

Çalışan bir stemmer'ınız var. Gerçekten çalıştığını nereden biliyorsunuz? Şu anda birkaç örneği el ile çalıştırıyorsunuz. Bu ölçeklenmiyor.


Profesyonel yazılım üç düzey test kullanır:


Birim testleri: bilinen girdiler ve beklenen çıktılar ile izolasyonda bir fonksiyonu test edin. Hızlı, çok sayıda, spesifik.


Entegrasyon testleri: birden çok bileşenin birlikte çalıştığını test edin. Bir stemmer için, bu kelime gruplarını test etmek ve sonuçların tutarlı olduğunu doğrulamak anlamına gelir.


Fonksiyonel testler: sistemi dışarıdan, bir kullanıcının yapacağı şekilde test edin. Bir stemmer için, bu gerçek metni beslemek ve çıktının arama gibi gerçek bir kullanım durumu için mantıklı olduğunu doğrulamak anlamına gelir.


Üçünü de yazacaksınız.

Üç Düzey Test: Birim, Entegrasyon ve Fonksiyonel Test Piramidi

Birim Testleri Yazın

Birim testleri

En az 15 test durumu ile run_unit_tests adında bir fonksiyon yazın:


1. Temel sonek çıkarma: -ing, -ed, -ly, -s ile biten kelimeler

2. Karmaşık sonekler: -tion, -ness, -ment, -able, -ible

3. Y-çekim: -ies, -ied, -ier

4. Kenar durumları: çıkarılmaması gereken kısa kelimeler, soneksiz kelimeler, zaten köklenmiş kelimeler

5. Çift ünsüz temizliği: running → run, sitting → sit

6. Sessiz-e restorasyonu: hoping → hope

7. Büyük/küçük harf duyarsızlığı: büyük harf girişi küçük harfe dönüştürülmelidir


Testlerinizi şöyle yapılandırın:

def run_unit_tests():
    tests = [
        ('running', 'run'),
        ('cats', 'cat'),
        # ... en az 15 test durumu
    ]
    passed = 0
    failed = 0
    for word, expected in tests:
        result = stem(word)
        if result == expected:
            passed += 1
        else:
            failed += 1
            print(f'FAIL: stem({word}) = {result}, expected {expected}')
    print(f'{passed}/{passed + failed} unit tests passed')
    return failed == 0
Tam `stem` fonksiyonunuzu VE en az 15 test durumu ile `run_unit_tests`'i yazın, yukarıdaki 7 kategorinin hepsiyle. Sonunda `run_unit_tests()`'i çağırın.

Entegrasyon Testleri Yazın

Entegrasyon testleri

Birim testleri bireysel girdileri doğrular. Entegrasyon testleri bileşenlerin birlikte doğru çalıştığını doğrular.


Bir stemmer için, temel entegrasyon özelliği tutarlılıktır: aynı kelimeyi iki kez kökleştirirseniz, aynı kökü alırsınız. Ve birlikte gruplandırılması gereken kelimeler aynı kökü üretmelidir.


run_integration_tests adında bir fonksiyon yazın:


1. İdemliylik: zaten köklenmiş bir kelimeyi kökleştirmek aynı kökü döndürmelidir. stem(stem(word)) == stem(word) tüm kelimeler için.

2. Gruplandırma: kök paylaşması gereken kelimeler gerçekten de paylaşıyor. En az 3 kelime ailesini test edin (örneğin, run/runs/running/runner hepsi bir kökü paylaşmalı).

3. Toplu işleme: 20+ kelime listesini işleyin ve çökmeme, boş dize yok, None değeri yok olduğunu doğrulayın.


def run_integration_tests():
    # Test 1: İdemliylik
    # Test 2: kelime ailesi gruplandırma
    # Test 3: toplu durum istikrarı
    ...
Tam `stem` fonksiyonunuzu VE tüm üç test kategorisi ile `run_integration_tests`'i yazın. Sonunda çağırın.

Fonksiyonel Testler Yazın

Fonksiyonel testler

Fonksiyonel testler, sistem amaçlanan kullanım durumları için çalıştığını doğrular. Stemmer'ınız aramayı iyileştirmek için var: bu yüzden test edin.


run_functional_tests adında bir fonksiyon yazın:


1. Arama simülasyonu: belge dizeleri listesi ve bir sorgu kelimesi verildiğinde, hem belgeleri hem de sorguyu kökleştirin, ardından köklenmiş sorgu terimlerinin köklenmiş belgelerde göründüğünü kontrol edin. 'running' araması 'run' ve 'runner' içeren bir belgeyi bulacağını test edin.

2. Kesinlik kontrolü: stemming, alakasız kelimeleri yanlışlıkla gruplandırmadığını doğrulayın. 'university' ve 'universe' bir kökü paylaşabilir: stemmer'ınız bunu ele alırsa kontrol edin (bunları gruplandırması tamam; davranışı belgeyin).

3. Gerçek metni işleme: bir paragrafın her kelimesini kökleştirin. Çıktı makul olduğunu doğrulayın: boş dize yok, çökme yok, çıktı girişle aynı kelime sayısına sahip.


def run_functional_tests():
    # Test 1: arama ilgili belgeleri bulur
    # Test 2: kesinlik: aşırı-stemming kontrol edin
    # Test 3: gerçek paragraf işleme
    ...
Tam `stem` fonksiyonunuzu VE tüm üç test kategorisi ile `run_functional_tests`'i yazın. Sonunda çağırın.

İnşa Ettikleri

İnşa ettikleri

Şunlarla çalışan bir İngilizce stemmer uyguladınız:

- 12 sonek kuralı (-tion, -ness, -ment, -able, -ible, -ies, -ied, -ier, -ing, -ed, -ly, -s)

- Çift ünsüz temizliği

- Sessiz-e restorasyonu

- Birim testleri, entegrasyon testleri & fonksiyonel testler


Soy ağacı

Stemmer'ınız, 1955'te Zellig Harris ile başlayan bir çalışma hattından doğmaktadır:


- Harris (1955): Biçimbirim sınırlarının istatistiksel sinyaller olarak göründüğünü keşfetti (halef çeşitliliği)

- Lovins (1968): İlk yayınlanan stemming algoritması, 294 sonek kuralı

- Porter (1980): 5 adımda ~60 kurala sadeleştirildi, onlarca yıl için standart haline geldi

- Snowball (2001): Porter'ın çerçevesi birden çok dile genelleştirildi

- Senin stemmer'ın (bugün): 12 kural, aynı temel ilke


Sonra ne yapabilirsiniz

- Tam Porter algoritmasını uygulayın (iyi belgelenmiş & harika bir alıştırma)

- Stemmer'ınızı C'ye aktarın 100x hız iyileştirmesi için

- Stemmer'ınızı metin dosyalarını indekslemek & sorgulamak için kullanan basit bir arama motoru inşa edin

- Doğruluğu ölçmek için stemmer'ınızın çıktısını NLTK'nin PorterStemmer'ıyla karşılaştırın


Bugün yazdığınız kod, bu gezegende her arama motorunun içinde çalışan aynı temel işlemdir. Bir günün çalışması için fena değil.

Stemmer Soy Ağacı: Harris 1955'ten Snowball 2001'e

İnşa ettikleriniz hakkında yansıtın. En şaşırtıcı şey ne öğrendiniz? Stemmer'ınızı iyileştirecek olsaydınız, ne eklerdiniz veya değiştireceksiniz?