14.9. BERT Ön Eğitimi için Veri Kümesi
Open the notebook in Colab
Open the notebook in Colab
Open the notebook in Colab
Open the notebook in SageMaker Studio Lab

BERT modelini Section 14.8 içinde uygulandığı şekilde ön eğitirken, iki ön eğitim görevini kolaylaştırmak için veri kümesini ideal formatta oluşturmamız gerekir: Maskeli dil modelleme ve sonraki cümle tahmini. Bir yandan, orijinal BERT modeli, bu kitabın en okuyucuları için koşmayı zorlaştıran iki büyük külliyatın, BookCorpus ve İngilizce Wikipedia’nın (bkz. Section 14.8.5), bitiştirilmesinde ön eğitilmiştir. Öte yandan, kullanıma hazır önceden eğitilmiş BERT modeli tıp gibi belirli alanlardan gelen uygulamalar için uygun olmayabilir. Bu nedenden, BERT’i özelleştirilmiş bir veri kümesi üzerinde ön eğitmek popüler hale gelmektedir. BERT ön eğitiminin gösterilmesini kolaylaştırmak için daha küçük bir külliyat, WikiText-2 (Merity et al., 2016) kullanıyoruz.

Section 14.3 içinde word2vec ön eğitimi için kullanılan PTB veri kümesiyle karşılaştırıldığında, WikiText-2 (i) orijinal noktalama işaretlerini korur ve bir sonraki cümle tahmini için uygun hale getirir; (ii) orijinal harf büyüklüğünü (büyük-küçük) ve sayıları korur; (iii) iki kat daha büyüktür.

import os
import random
from d2l import mxnet as d2l
from mxnet import gluon, np, npx

npx.set_np()
import os
import random
import torch
from d2l import torch as d2l

WikiText-2 veri kümesinde, her satır herhangi bir noktalama işareti ile önceki belirteci arasına boşluk eklenen bir paragrafı temsil eder. En az iki cümle içeren paragraflar korunur. Cümleleri bölerken, noktayı sadece basitlik için sınırlayıcı olarak kullanıyoruz. Daha karmaşık cümle bölme teknikleriyle ilgili tartışmaları bu bölümün sonundaki alıştırmalara bırakıyoruz.

#@save
d2l.DATA_HUB['wikitext-2'] = (
    'https://s3.amazonaws.com/research.metamind.io/wikitext/'
    'wikitext-2-v1.zip', '3c914d17d80b1459be871a5039ac23e752a53cbe')

#@save
def _read_wiki(data_dir):
    file_name = os.path.join(data_dir, 'wiki.train.tokens')
    with open(file_name, 'r') as f:
        lines = f.readlines()
    # Büyük harfler küçük harflere dönüştürülür.
    paragraphs = [line.strip().lower().split(' . ')
                  for line in lines if len(line.split(' . ')) >= 2]
    random.shuffle(paragraphs)
    return paragraphs
#@save
d2l.DATA_HUB['wikitext-2'] = (
    'https://s3.amazonaws.com/research.metamind.io/wikitext/'
    'wikitext-2-v1.zip', '3c914d17d80b1459be871a5039ac23e752a53cbe')

#@save
def _read_wiki(data_dir):
    file_name = os.path.join(data_dir, 'wiki.train.tokens')
    with open(file_name, 'r') as f:
        lines = f.readlines()
    # Büyük harfler küçük harflere dönüştürülür.
    paragraphs = [line.strip().lower().split(' . ')
                  for line in lines if len(line.split(' . ')) >= 2]
    random.shuffle(paragraphs)
    return paragraphs

14.9.1. Ön Eğitim Görevleri için Yardımcı İşlevleri Tanımlama

Aşağıda, iki BERT ön eğitim görevi için yardımcı fonksiyonları uygulayarak başlıyoruz: Sonraki cümle tahmini ve maskeli dil modelleme. Bu yardımcı işlevler, daha sonra, bu ham metin külliyatı, BERT ön eğitimi için ideal biçimli veri kümesine dönüştürülürken çağrılacaktır.

14.9.1.1. Sonraki Cümle Tahmini Görevi Oluşturma

Section 14.8.5.2 açıklamalarına göre, _get_next_sentence işlevi ikili sınıflandırma görevi için bir eğitim örneği oluşturur.

#@save
def _get_next_sentence(sentence, next_sentence, paragraphs):
    if random.random() < 0.5:
        is_next = True
    else:
        # `paragraphs` bir listelerin listelerinin listesidir
        next_sentence = random.choice(random.choice(paragraphs))
        is_next = False
    return sentence, next_sentence, is_next
#@save
def _get_next_sentence(sentence, next_sentence, paragraphs):
    if random.random() < 0.5:
        is_next = True
    else:
        # `paragraphs` bir listelerin listelerinin listesidir
        next_sentence = random.choice(random.choice(paragraphs))
        is_next = False
    return sentence, next_sentence, is_next

Aşağıdaki işlev _get_next_sentence işlevini çağırarak paragraph girdisinden sonraki cümle tahmini için eğitim örnekleri oluşturur. Burada paragraph, her cümlenin bir belirteç listesi olduğu bir cümleler listesidir. max_len bağımsız değişkeni, ön eğitim sırasında BERT girdi dizisinin maksimum uzunluğunu belirtir.

#@save
def _get_nsp_data_from_paragraph(paragraph, paragraphs, vocab, max_len):
    nsp_data_from_paragraph = []
    for i in range(len(paragraph) - 1):
        tokens_a, tokens_b, is_next = _get_next_sentence(
            paragraph[i], paragraph[i + 1], paragraphs)
        # 1 tane '<cls>' belirteci ve 2 tane '<sep>' belirteci düşünün
        if len(tokens_a) + len(tokens_b) + 3 > max_len:
            continue
        tokens, segments = d2l.get_tokens_and_segments(tokens_a, tokens_b)
        nsp_data_from_paragraph.append((tokens, segments, is_next))
    return nsp_data_from_paragraph
#@save
def _get_nsp_data_from_paragraph(paragraph, paragraphs, vocab, max_len):
    nsp_data_from_paragraph = []
    for i in range(len(paragraph) - 1):
        tokens_a, tokens_b, is_next = _get_next_sentence(
            paragraph[i], paragraph[i + 1], paragraphs)
        # 1 tane '<cls>' belirteci ve 2 tane '<sep>' belirteci düşünün
        if len(tokens_a) + len(tokens_b) + 3 > max_len:
            continue
        tokens, segments = d2l.get_tokens_and_segments(tokens_a, tokens_b)
        nsp_data_from_paragraph.append((tokens, segments, is_next))
    return nsp_data_from_paragraph

14.9.1.2. Maskeli Dil Modelleme Görevi Oluşturma

BERT girdi dizisinden maskelenmiş dil modelleme görevi için eğitim örnekleri oluşturmak için aşağıdaki _replace_mlm_tokens işlevini tanımlıyoruz. Girdilerinde, tokens, BERT girdi dizisini temsil eden belirteçlerin bir listesidir, candidate_pred_positions, özel belirteçler hariç BERT girdi dizisinin belirteç indekslerinin bir listesidir (maskeli dil modelleme görevinde özel belirteçler tahmin edilmez) ve num_mlm_preds tahminlerin sayısını gösterir (tahmin etmek için %15 rastgele belirteci geri çağırın). Section 14.8.5.1 içindeki maskelenmiş dil modelleme görevinin tanımını takiben, her tahmin konumunda, girdi özel bir “<mask>” belirteci veya rastgele bir belirteç ile değiştirilebilir veya değişmeden kalabilir. Sonunda, işlev olası değiştirmeden sonra girdi belirteçlerini, tahminlerin gerçekleştiği belirteç endekslerini ve bu tahminler için etiketleri döndürür.

#@save
def _replace_mlm_tokens(tokens, candidate_pred_positions, num_mlm_preds,
                        vocab):
    # Girdinin değiştirilmiş '<mask>' veya rastgele belirteçler içerebileceği
    # maskelenmiş bir dil modelinin girdisi için belirteçlerin
    # yeni bir kopyasını oluşturun
    mlm_input_tokens = [token for token in tokens]
    pred_positions_and_labels = []
    # Maskeli dil modelleme görevinde tahmin için %15 rastgele
    # belirteç almak için karıştır
    random.shuffle(candidate_pred_positions)
    for mlm_pred_position in candidate_pred_positions:
        if len(pred_positions_and_labels) >= num_mlm_preds:
            break
        masked_token = None
        # Zamanın %80'inde sözcüğü '<mask>' simgesiyle değiştirin
        if random.random() < 0.8:
            masked_token = '<mask>'
        else:
            # Zamanın %10'unda kelimeyi değiştirmeden bırakın
            if random.random() < 0.5:
                masked_token = tokens[mlm_pred_position]
            # Zamanın %10'unda kelimeyi rastgele bir kelimeyle değiştirin
            else:
                masked_token = random.choice(vocab.idx_to_token)
        mlm_input_tokens[mlm_pred_position] = masked_token
        pred_positions_and_labels.append(
            (mlm_pred_position, tokens[mlm_pred_position]))
    return mlm_input_tokens, pred_positions_and_labels
#@save
def _replace_mlm_tokens(tokens, candidate_pred_positions, num_mlm_preds,
                        vocab):
    # Girdinin değiştirilmiş '<mask>' veya rastgele belirteçler içerebileceği
    # maskelenmiş bir dil modelinin girdisi için belirteçlerin
    # yeni bir kopyasını oluşturun
    mlm_input_tokens = [token for token in tokens]
    pred_positions_and_labels = []
    # Maskeli dil modelleme görevinde tahmin için %15 rastgele
    # belirteç almak için karıştır
    random.shuffle(candidate_pred_positions)
    for mlm_pred_position in candidate_pred_positions:
        if len(pred_positions_and_labels) >= num_mlm_preds:
            break
        masked_token = None
        # Zamanın %80'inde sözcüğü '<mask>' simgesiyle değiştirin
        if random.random() < 0.8:
            masked_token = '<mask>'
        else:
            # Zamanın %10'unda kelimeyi değiştirmeden bırakın
            if random.random() < 0.5:
                masked_token = tokens[mlm_pred_position]
            # Zamanın %10'unda kelimeyi rastgele bir kelimeyle değiştirin
            else:
                masked_token = random.choice(vocab.idx_to_token)
        mlm_input_tokens[mlm_pred_position] = masked_token
        pred_positions_and_labels.append(
            (mlm_pred_position, tokens[mlm_pred_position]))
    return mlm_input_tokens, pred_positions_and_labels

Yukarıda bahsedilen _replace_mlm_tokens işlevini çağırarak, aşağıdaki işlev bir BERT girdi dizisini (tokens) girdi olarak alır ve girdi belirteçlerinin dizinlerini (Section 14.8.5.1 içinde açıklandığı gibi olası belirteç değişiminden sonra), belirteç tahminlerin gerçekleştiği indeksleri ve bu tahminler için etiket indekslerini döndürür.

#@save
def _get_mlm_data_from_tokens(tokens, vocab):
    candidate_pred_positions = []
    # `tokens` bir dizgiler listesidir
    for i, token in enumerate(tokens):
        # Maskeli dil modelleme görevinde özel belirteçler tahmin edilmez
        if token in ['<cls>', '<sep>']:
            continue
        candidate_pred_positions.append(i)
    # Rastgele belirteçlerin %15'i maskelenmiş dil modelleme görevinde tahmin edilir
    num_mlm_preds = max(1, round(len(tokens) * 0.15))
    mlm_input_tokens, pred_positions_and_labels = _replace_mlm_tokens(
        tokens, candidate_pred_positions, num_mlm_preds, vocab)
    pred_positions_and_labels = sorted(pred_positions_and_labels,
                                       key=lambda x: x[0])
    pred_positions = [v[0] for v in pred_positions_and_labels]
    mlm_pred_labels = [v[1] for v in pred_positions_and_labels]
    return vocab[mlm_input_tokens], pred_positions, vocab[mlm_pred_labels]
#@save
def _get_mlm_data_from_tokens(tokens, vocab):
    candidate_pred_positions = []
    # `tokens` bir dizgiler listesidir
    for i, token in enumerate(tokens):
        # Maskeli dil modelleme görevinde özel belirteçler tahmin edilmez
        if token in ['<cls>', '<sep>']:
            continue
        candidate_pred_positions.append(i)
    # Rastgele belirteçlerin %15'i maskelenmiş dil modelleme görevinde tahmin edilir
    num_mlm_preds = max(1, round(len(tokens) * 0.15))
    mlm_input_tokens, pred_positions_and_labels = _replace_mlm_tokens(
        tokens, candidate_pred_positions, num_mlm_preds, vocab)
    pred_positions_and_labels = sorted(pred_positions_and_labels,
                                       key=lambda x: x[0])
    pred_positions = [v[0] for v in pred_positions_and_labels]
    mlm_pred_labels = [v[1] for v in pred_positions_and_labels]
    return vocab[mlm_input_tokens], pred_positions, vocab[mlm_pred_labels]

14.9.2. Metni Ön Eğitim Veri Kümesine Dönüştürme

Şimdi BERT ön eğitimi için bir Dataset sınıfını özelleştirmeye neredeyse hazırız. Bundan önce, girdilere özel “<mask>” belirteçlerini eklemek için _pad_bert_inputs bir yardımcı işlevi tanımlamamız gerekiyor. Onun argümanı examples, iki ön eğitim görevi için yardımcı işlevlerden _get_nsp_data_from_paragraph ve _get_mlm_data_from_tokens çıktılarını içerir.

#@save
def _pad_bert_inputs(examples, max_len, vocab):
    max_num_mlm_preds = round(max_len * 0.15)
    all_token_ids, all_segments, valid_lens,  = [], [], []
    all_pred_positions, all_mlm_weights, all_mlm_labels = [], [], []
    nsp_labels = []
    for (token_ids, pred_positions, mlm_pred_label_ids, segments,
         is_next) in examples:
        all_token_ids.append(np.array(token_ids + [vocab['<pad>']] * (
            max_len - len(token_ids)), dtype='int32'))
        all_segments.append(np.array(segments + [0] * (
            max_len - len(segments)), dtype='int32'))
        # `valid_lens`, '<pad>' belirteçlerinin sayısını hariç tutar
        valid_lens.append(np.array(len(token_ids), dtype='float32'))
        all_pred_positions.append(np.array(pred_positions + [0] * (
            max_num_mlm_preds - len(pred_positions)), dtype='int32'))
        # Dolgulu belirteçlerin tahminleri, 0 ağırlıklar çarpımı
        # yoluyla kayıpta filtrelenecektir.
        all_mlm_weights.append(
            np.array([1.0] * len(mlm_pred_label_ids) + [0.0] * (
                max_num_mlm_preds - len(pred_positions)), dtype='float32'))
        all_mlm_labels.append(np.array(mlm_pred_label_ids + [0] * (
            max_num_mlm_preds - len(mlm_pred_label_ids)), dtype='int32'))
        nsp_labels.append(np.array(is_next))
    return (all_token_ids, all_segments, valid_lens, all_pred_positions,
            all_mlm_weights, all_mlm_labels, nsp_labels)
#@save
def _pad_bert_inputs(examples, max_len, vocab):
    max_num_mlm_preds = round(max_len * 0.15)
    all_token_ids, all_segments, valid_lens,  = [], [], []
    all_pred_positions, all_mlm_weights, all_mlm_labels = [], [], []
    nsp_labels = []
    for (token_ids, pred_positions, mlm_pred_label_ids, segments,
         is_next) in examples:
        all_token_ids.append(torch.tensor(token_ids + [vocab['<pad>']] * (
            max_len - len(token_ids)), dtype=torch.long))
        all_segments.append(torch.tensor(segments + [0] * (
            max_len - len(segments)), dtype=torch.long))
        # `valid_lens`, '<pad>' belirteçlerinin sayısını hariç tutar
        valid_lens.append(torch.tensor(len(token_ids), dtype=torch.float32))
        all_pred_positions.append(torch.tensor(pred_positions + [0] * (
            max_num_mlm_preds - len(pred_positions)), dtype=torch.long))
        # Dolgulu belirteçlerin tahminleri, 0 ağırlıklar çarpımı
        # yoluyla kayıpta filtrelenecektir.
        all_mlm_weights.append(
            torch.tensor([1.0] * len(mlm_pred_label_ids) + [0.0] * (
                max_num_mlm_preds - len(pred_positions)),
                dtype=torch.float32))
        all_mlm_labels.append(torch.tensor(mlm_pred_label_ids + [0] * (
            max_num_mlm_preds - len(mlm_pred_label_ids)), dtype=torch.long))
        nsp_labels.append(torch.tensor(is_next, dtype=torch.long))
    return (all_token_ids, all_segments, valid_lens, all_pred_positions,
            all_mlm_weights, all_mlm_labels, nsp_labels)

İki ön eğitim görevinin eğitim örneklerini üretmek için yardımcı fonksiyonları ve girdi dolgulama için yardımcı işlevini bir araya getirerek, BERT ön eğitimi için WikiText-2 veri kümesi olarak aşağıdaki _WikiTextDataset sınıfını özelleştiriyoruz. __getitem__ işlevini uygulayarak, WikiText-2 külliyatından bir çift cümleden oluşturulan ön eğitim (maskeli dil modelleme ve sonraki cümle tahmini) örneklerine keyfi olarak erişebiliriz.

Orijinal BERT modeli kelime boyutu 30000 (Wu et al., 2016) olan WordPiece gömmeleri kullanır. WordPiece’nin belirteçlere ayırma yöntemi, Section 14.6.2 içinde orijinal sekizli çifti kodlama algoritmasının hafif bir değişiğidir. Basitlik için, belirteçlere ayırmak için d2l.tokenize işlevini kullanıyoruz. Beş kereden az görünen seyrek belirteçler filtrelenir.

#@save
class _WikiTextDataset(gluon.data.Dataset):
    def __init__(self, paragraphs, max_len):
        # Girdi `paragraphs[i]`, bir paragrafı temsil eden cümle dizilerinin
        # bir listesidir; çıktı `paragraphs[i]` bir paragrafı temsil eden
        # cümlelerin bir listesidir, burada her cümle bir belirteç listesidir
        paragraphs = [d2l.tokenize(
            paragraph, token='word') for paragraph in paragraphs]
        sentences = [sentence for paragraph in paragraphs
                     for sentence in paragraph]
        self.vocab = d2l.Vocab(sentences, min_freq=5, reserved_tokens=[
            '<pad>', '<mask>', '<cls>', '<sep>'])
        # Bir sonraki cümle tahmini görevi için veri alın
        examples = []
        for paragraph in paragraphs:
            examples.extend(_get_nsp_data_from_paragraph(
                paragraph, paragraphs, self.vocab, max_len))
        # Maskeli dil modeli görevi için veri alın
        examples = [(_get_mlm_data_from_tokens(tokens, self.vocab)
                      + (segments, is_next))
                     for tokens, segments, is_next in examples]
        # Girdiyi dolgula
        (self.all_token_ids, self.all_segments, self.valid_lens,
         self.all_pred_positions, self.all_mlm_weights,
         self.all_mlm_labels, self.nsp_labels) = _pad_bert_inputs(
            examples, max_len, self.vocab)

    def __getitem__(self, idx):
        return (self.all_token_ids[idx], self.all_segments[idx],
                self.valid_lens[idx], self.all_pred_positions[idx],
                self.all_mlm_weights[idx], self.all_mlm_labels[idx],
                self.nsp_labels[idx])

    def __len__(self):
        return len(self.all_token_ids)
#@save
class _WikiTextDataset(torch.utils.data.Dataset):
    def __init__(self, paragraphs, max_len):
        # Girdi `paragraphs[i]`, bir paragrafı temsil eden cümle dizilerinin
        # bir listesidir; çıktı `paragraphs[i]` bir paragrafı temsil eden
        # cümlelerin bir listesidir, burada her cümle bir belirteç listesidir
        paragraphs = [d2l.tokenize(
            paragraph, token='word') for paragraph in paragraphs]
        sentences = [sentence for paragraph in paragraphs
                     for sentence in paragraph]
        self.vocab = d2l.Vocab(sentences, min_freq=5, reserved_tokens=[
            '<pad>', '<mask>', '<cls>', '<sep>'])
        # Bir sonraki cümle tahmini görevi için veri alın
        examples = []
        for paragraph in paragraphs:
            examples.extend(_get_nsp_data_from_paragraph(
                paragraph, paragraphs, self.vocab, max_len))
        # Maskeli dil modeli görevi için veri alın
        examples = [(_get_mlm_data_from_tokens(tokens, self.vocab)
                      + (segments, is_next))
                     for tokens, segments, is_next in examples]
        # Girdiyi dolgula
        (self.all_token_ids, self.all_segments, self.valid_lens,
         self.all_pred_positions, self.all_mlm_weights,
         self.all_mlm_labels, self.nsp_labels) = _pad_bert_inputs(
            examples, max_len, self.vocab)

    def __getitem__(self, idx):
        return (self.all_token_ids[idx], self.all_segments[idx],
                self.valid_lens[idx], self.all_pred_positions[idx],
                self.all_mlm_weights[idx], self.all_mlm_labels[idx],
                self.nsp_labels[idx])

    def __len__(self):
        return len(self.all_token_ids)

_read_wiki işlevini ve _WikiTextDataset sınıfını kullanarak, WikiText-2 veri kümesini indirmek ve ondan ön eğitim örnekleri oluşturmak için aşağıdaki load_data_wiki’yı tanımlıyoruz.

#@save
def load_data_wiki(batch_size, max_len):
    """WikiText-2 veri kümesini yükleyin."""
    num_workers = d2l.get_dataloader_workers()
    data_dir = d2l.download_extract('wikitext-2', 'wikitext-2')
    paragraphs = _read_wiki(data_dir)
    train_set = _WikiTextDataset(paragraphs, max_len)
    train_iter = gluon.data.DataLoader(train_set, batch_size, shuffle=True,
                                       num_workers=num_workers)
    return train_iter, train_set.vocab
#@save
def load_data_wiki(batch_size, max_len):
    """WikiText-2 veri kümesini yükleyin."""
    num_workers = d2l.get_dataloader_workers()
    data_dir = d2l.download_extract('wikitext-2', 'wikitext-2')
    paragraphs = _read_wiki(data_dir)
    train_set = _WikiTextDataset(paragraphs, max_len)
    train_iter = torch.utils.data.DataLoader(train_set, batch_size,
                                        shuffle=True, num_workers=num_workers)
    return train_iter, train_set.vocab

Toplu iş boyutunu 512 olarak ve BERT girdi dizisinin maksimum uzunluğunu 64 olarak ayarlayarak, BERT ön eğitim örneklerinden oluşan bir minigrubun şekillerini yazdırıyoruz. Her BERT girdi dizisinde, maskelenmiş dil modelleme görevi için \(10\) (\(64 \times 0.15\)) konumun tahmin edildiğini unutmayın.

batch_size, max_len = 512, 64
train_iter, vocab = load_data_wiki(batch_size, max_len)

for (tokens_X, segments_X, valid_lens_x, pred_positions_X, mlm_weights_X,
     mlm_Y, nsp_y) in train_iter:
    print(tokens_X.shape, segments_X.shape, valid_lens_x.shape,
          pred_positions_X.shape, mlm_weights_X.shape, mlm_Y.shape,
          nsp_y.shape)
    break
(512, 64) (512, 64) (512,) (512, 10) (512, 10) (512, 10) (512,)
batch_size, max_len = 512, 64
train_iter, vocab = load_data_wiki(batch_size, max_len)

for (tokens_X, segments_X, valid_lens_x, pred_positions_X, mlm_weights_X,
     mlm_Y, nsp_y) in train_iter:
    print(tokens_X.shape, segments_X.shape, valid_lens_x.shape,
          pred_positions_X.shape, mlm_weights_X.shape, mlm_Y.shape,
          nsp_y.shape)
    break
torch.Size([512, 64]) torch.Size([512, 64]) torch.Size([512]) torch.Size([512, 10]) torch.Size([512, 10]) torch.Size([512, 10]) torch.Size([512])

Sonunda, kelime dağarcığına bir göz atalım. Sık görülen belirteçleri filtreledikten sonra bile, PTB veri kümesinden iki kat daha büyüktür.

len(vocab)
20256
len(vocab)
20256

14.9.3. Özet

  • PTB veri kümesiyle karşılaştırıldığında, WikiText-2 veri kümesi orijinal noktalama işaretlerini, büyük/küçük harf ve sayıları korur ve iki kat daha büyüktür.

  • WikiText-2 külliyatındaki bir çift cümleden oluşturulan ön eğitim (maskeli dil modellemesi ve sonraki cümle tahmini) örneklerine keyfi olarak erişebiliriz.

14.9.4. Alıştırmalar

  1. Basitlik açısından, nokta cümleleri bölmede tek sınırlayıcı olarak kullanılır. SpaCy ve NLTK gibi diğer cümle ayırma tekniklerini deneyin. Örnek olarak NLTK’yi ele alalım. Önce NLTK’yi kurmanız gerekiyor: pip install nltk. Kodda, ilk import nltk çağırın. Daha sonra Punkt cümle belirteci ayıklayıcıyı indirin: nltk.download('punkt'). sentences = 'This is great ! Why not ?' gibi cümleleri ayırmak için nltk.tokenize.sent_tokenize(sentences) çağırmak iki cümlelik bir liste döndürür: ['This is great !', 'Why not ?']

  2. Seyrek belirteçleri filtrelemezsek kelime dağarcığı boyutu ne olur?