Langkah 3: Siapkan Data Anda

Sebelum data dapat di-feed ke model, data tersebut perlu diubah ke format yang dapat dipahami oleh model.

Pertama, sampel data yang telah kami kumpulkan mungkin berada dalam urutan tertentu. Kami tidak ingin informasi apa pun yang terkait dengan pengurutan sampel memengaruhi hubungan antara teks dan label. Misalnya, jika set data diurutkan berdasarkan class, lalu dibagi menjadi set pelatihan/validasi, set ini tidak akan merepresentasikan keseluruhan distribusi data.

Praktik terbaik yang sederhana untuk memastikan model tidak terpengaruh oleh urutan data adalah dengan selalu mengacak data sebelum melakukan hal lain. Jika data sudah dibagi menjadi set pelatihan dan validasi, pastikan Anda mengubah data validasi dengan cara yang sama seperti mengubah data pelatihan. Jika belum memiliki set pelatihan dan validasi terpisah, Anda dapat membagi sampel setelah diacak; biasanya menggunakan 80% sampel untuk pelatihan dan 20% untuk validasi.

Kedua, algoritme machine learning mengambil angka sebagai input. Ini berarti kita perlu mengonversi teks menjadi vektor numerik. Ada dua langkah untuk proses ini:

  1. Token: Membagi teks menjadi kata atau sub-teks yang lebih kecil, yang akan memungkinkan generalisasi hubungan yang baik antara teks dan label. Ini menentukan “kosakata” set data (kumpulan token unik yang ada dalam data).

  2. Vektorisasi: Menentukan ukuran numerik yang baik untuk membentuk karakteristik teks ini.

Mari kita lihat cara melakukan kedua langkah tersebut untuk vektor n-gram dan vektor urutan, serta cara mengoptimalkan representasi vektor menggunakan teknik pemilihan fitur dan normalisasi.

Vektor N-gram [Opsi A]

Dalam paragraf berikutnya, kita akan melihat cara melakukan tokenisasi dan vektorisasi untuk model n-gram. Kita juga akan membahas cara mengoptimalkan representasi n-gram menggunakan teknik pemilihan fitur dan normalisasi.

Dalam vektor n-gram, teks direpresentasikan sebagai kumpulan n-gram unik: grup n token yang berdekatan (biasanya, kata). Perhatikan teks The mouse ran up the clock. Di sini, kata unigram (n = 1) adalah ['the', 'mouse', 'ran', 'up', 'clock'], kata bigram (n = 2) adalah ['the mouse', 'mouse ran', 'ran up', 'up the', 'the clock'], dan seterusnya.

Tokenisasi

Kami mendapati bahwa dengan membuat token unigram + bigram, Anda akan memperoleh akurasi yang baik sekaligus mengurangi waktu komputasi.

Vektorisasi

Setelah membagi sampel teks menjadi n-gram, kita perlu mengubah n-gram ini menjadi vektor numerik yang dapat diproses oleh model machine learning kita. Contoh di bawah menunjukkan indeks yang ditetapkan ke unigram dan bigram yang dihasilkan untuk dua teks.

Texts: 'The mouse ran up the clock' and 'The mouse ran down'
Index assigned for every token: {'the': 7, 'mouse': 2, 'ran': 4, 'up': 10,
  'clock': 0, 'the mouse': 9, 'mouse ran': 3, 'ran up': 6, 'up the': 11, 'the
clock': 8, 'down': 1, 'ran down': 5}

Setelah indeks ditetapkan ke n-gram, biasanya kita melakukan vektor menggunakan salah satu opsi berikut.

Encoding sekali klik: Setiap contoh teks direpresentasikan sebagai vektor yang menunjukkan adanya atau tidak adanya token dalam teks.

'The mouse ran up the clock' = [1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1]

Encoding encoding: Setiap teks sampel direpresentasikan sebagai vektor yang menunjukkan jumlah token dalam teks. Perhatikan bahwa elemen yang sesuai dengan unigram 'the' (dicetak tebal di bawah) sekarang direpresentasikan sebagai 2 karena kata “the” muncul dua kali dalam teks.

'The mouse ran up the clock' = [1, 0, 1, 1, 1, 0, 1, 2, 1, 1, 1, 1]

Encoding tf-idf: Masalah dengan dua pendekatan di atas adalah bahwa kata-kata umum yang terjadi dalam frekuensi yang serupa di semua dokumen (yaitu, kata-kata yang tidak terlalu unik untuk sampel teks dalam set data) tidak dihukum. Misalnya, kata seperti “a” akan sering muncul di semua teks. Jadi, jumlah token yang lebih tinggi untuk kata "the" daripada kata lain yang lebih bermakna tidak terlalu berguna.

'The mouse ran up the clock' = [0.33, 0, 0.23, 0.23, 0.23, 0, 0.33, 0.47, 0.33,
0.23, 0.33, 0.33] (See Scikit-learn TfidfTransformer)

Ada banyak representasi vektor lain, tetapi tiga di atas adalah yang paling umum digunakan.

Kami mengamati bahwa encoding tf-idf sedikit lebih baik daripada dua encoding lainnya dalam hal akurasi (rata-rata: 0,25-15% lebih tinggi), dan sebaiknya gunakan metode ini untuk memvektorkan n-gram. Namun, perlu diingat bahwa model ini menempati lebih banyak memori (karena menggunakan representasi floating point) dan membutuhkan lebih banyak waktu untuk melakukan komputasi, terutama untuk set data yang besar (dalam beberapa kasus bisa memakan waktu dua kali lebih lama).

Pilihan fitur

Jika kami mengonversi semua teks dalam set data menjadi token kata uni+bigram, kami mungkin akan memiliki puluhan ribu token. Tidak semua token/fitur ini berkontribusi pada prediksi label. Jadi, kita dapat menghapus token tertentu, misalnya yang jarang terjadi di seluruh set data. Kita juga dapat mengukur nilai penting fitur (jumlah kontribusi setiap token terhadap prediksi label), dan hanya menyertakan token yang paling informatif.

Ada banyak fungsi statistik yang menggunakan fitur serta label yang sesuai, dan menghasilkan skor nilai penting fitur. Dua fungsi yang umum digunakan adalah f_classif dan chi2. Eksperimen kami menunjukkan bahwa kedua fungsi ini berperforma sama baiknya.

Yang lebih penting, kami melihat bahwa akurasi mencapai puncaknya pada sekitar 20.000 fitur untuk banyak set data (Lihat Gambar 6). Menambahkan lebih banyak fitur di atas ambang batas ini memberikan kontribusi sangat sedikit dan terkadang bahkan menyebabkan overfit dan menurunkan performa.

Akurasi K vs. Teratas

Gambar 6: Fitur K teratas versus Akurasi. Di seluruh set data, keakuratan mencapai sekitar 20 ribu fitur teratas.

Normalisasi

Normalisasi mengonversi semua nilai fitur/sampel menjadi nilai kecil dan nilai serupa. Hal ini menyederhanakan konvergensi penurunan gradien dalam algoritme pembelajaran. Dari apa yang telah kita lihat, normalisasi selama prapemrosesan data tampaknya tidak menambah banyak nilai dalam masalah klasifikasi teks. Sebaiknya lewati langkah ini.

Kode berikut menggabungkan semua langkah di atas:

  • Membuat token sampel teks menjadi kata uni+bigram,
  • Vektor menggunakan encoding tf-idf,
  • Pilih hanya 20.000 fitur teratas dari vektor token dengan menghapus token yang muncul kurang dari 2 kali dan gunakan f_classif untuk menghitung nilai penting fitur.
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import f_classif

# Vectorization parameters
# Range (inclusive) of n-gram sizes for tokenizing text.
NGRAM_RANGE = (1, 2)

# Limit on the number of features. We use the top 20K features.
TOP_K = 20000

# Whether text should be split into word or character n-grams.
# One of 'word', 'char'.
TOKEN_MODE = 'word'

# Minimum document/corpus frequency below which a token will be discarded.
MIN_DOCUMENT_FREQUENCY = 2

def ngram_vectorize(train_texts, train_labels, val_texts):
    """Vectorizes texts as n-gram vectors.

    1 text = 1 tf-idf vector the length of vocabulary of unigrams + bigrams.

    # Arguments
        train_texts: list, training text strings.
        train_labels: np.ndarray, training labels.
        val_texts: list, validation text strings.

    # Returns
        x_train, x_val: vectorized training and validation texts
    """
    # Create keyword arguments to pass to the 'tf-idf' vectorizer.
    kwargs = {
            'ngram_range': NGRAM_RANGE,  # Use 1-grams + 2-grams.
            'dtype': 'int32',
            'strip_accents': 'unicode',
            'decode_error': 'replace',
            'analyzer': TOKEN_MODE,  # Split text into word tokens.
            'min_df': MIN_DOCUMENT_FREQUENCY,
    }
    vectorizer = TfidfVectorizer(**kwargs)

    # Learn vocabulary from training texts and vectorize training texts.
    x_train = vectorizer.fit_transform(train_texts)

    # Vectorize validation texts.
    x_val = vectorizer.transform(val_texts)

    # Select top 'k' of the vectorized features.
    selector = SelectKBest(f_classif, k=min(TOP_K, x_train.shape[1]))
    selector.fit(x_train, train_labels)
    x_train = selector.transform(x_train).astype('float32')
    x_val = selector.transform(x_val).astype('float32')
    return x_train, x_val

Dengan representasi vektor n-gram, kami menghapus banyak informasi tentang urutan kata dan tata bahasa (terbaik, kami dapat mempertahankan beberapa informasi pengurutan saat n > 1). Hal ini disebut pendekatan tas kata-kata. Representasi ini digunakan bersama dengan model yang tidak memperhitungkan pengurutan, seperti regresi logistik, perceptron berlapis, mesin penguat gradien, mendukung mesin vektor.

Vektor Urutan [Opsi B]

Dalam paragraf berikutnya, kita akan melihat cara melakukan tokenisasi dan vektorisasi untuk model urutan. Kita juga akan membahas cara mengoptimalkan representasi urutan menggunakan teknik pemilihan fitur dan normalisasi.

Untuk beberapa contoh teks, urutan kata sangat penting untuk arti teks. Misalnya, kalimat, "Saya dulu tidak suka dengan perjalanan. Sepeda baru saya telah berubah sepenuhnya” hanya dapat dipahami jika dibaca secara berurutan. Model seperti CNN/RNN dapat menyimpulkan arti dari urutan kata dalam sampel. Untuk model ini, kami menampilkan teks sebagai urutan token, dengan mempertahankan urutan.

Tokenisasi

Teks dapat direpresentasikan sebagai urutan karakter, atau urutan kata. Kami mendapati bahwa penggunaan representasi tingkat kata memberikan performa yang lebih baik daripada token karakter. Ini juga merupakan norma umum yang diikuti oleh industri. Penggunaan token karakter hanya masuk akal jika teks mengandung banyak kesalahan ketik, yang biasanya tidak demikian.

Vektorisasi

Setelah mengonversi sampel teks menjadi rangkaian kata, kita harus mengubah urutan ini menjadi vektor numerik. Contoh di bawah ini menunjukkan indeks yang ditetapkan ke unigram yang dibuat untuk dua teks, lalu urutan indeks token yang menjadi dasar konversi teks pertama.

Texts: 'The mouse ran up the clock' and 'The mouse ran down'
Index assigned for every token: {'clock': 5, 'ran': 3, 'up': 4, 'down': 6, 'the': 1, 'mouse': 2}.
NOTE: 'the' occurs most frequently, so the index value of 1 is assigned to it.
Some libraries reserve index 0 for unknown tokens, as is the case here.
Sequence of token indexes: 'The mouse ran up the clock' = [1, 2, 3, 4, 1, 5]

Ada dua opsi yang tersedia untuk memvaksinasi urutan token:

Encoding sekali klik: Urutan direpresentasikan menggunakan vektor kata dalam ruang n dengan dimensi n = ukuran kosakata. Representasi ini sangat bagus jika kita membuat token sebagai karakter, sehingga kosakatanya menjadi kecil. Saat membuat token sebagai kata, kosakata biasanya akan memiliki puluhan ribu token, sehingga vektor satu kali menjadi sangat jarang dan tidak efisien. Contoh:

'The mouse ran up the clock' = [
  [0, 1, 0, 0, 0, 0, 0],
  [0, 0, 1, 0, 0, 0, 0],
  [0, 0, 0, 1, 0, 0, 0],
  [0, 0, 0, 0, 1, 0, 0],
  [0, 1, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 1, 0]
]

Penyematan kata: Kata memiliki arti yang terkait dengannya. Oleh karena itu, kita dapat mewakili token kata dalam ruang vektor yang padat (~sekitar beberapa ratus angka nyata), dengan lokasi dan jarak antarkata menunjukkan kemiripan secara semantik (Lihat Gambar 7). Representasi ini disebut penyematan kata.

Penyematan Kata

Gambar 7: Penyematan kata

Model urutan sering kali memiliki lapisan penyematan seperti lapisan pertamanya. Lapisan ini belajar mengubah urutan indeks kata menjadi vektor penyematan kata selama proses pelatihan, sehingga setiap indeks kata dipetakan ke vektor padat berisi nilai nyata yang mewakili lokasi kata tersebut dalam ruang semantik (Lihat Gambar 8).

Lapisan Penyematan

Gambar 8: Menyematkan lapisan

Pilihan fitur

Tidak semua kata dalam data berkontribusi pada prediksi label. Kita dapat mengoptimalkan proses pembelajaran dengan menghapus kata-kata yang langka atau tidak relevan dari kosakata kita. Faktanya, kami mengamati bahwa penggunaan 20.000 fitur yang paling sering secara umum sudah memadai. Hal ini juga berlaku untuk model n-gram (Lihat Gambar 6).

Mari kita gabungkan semua langkah di atas dalam vektorisasi urutan. Kode berikut menjalankan tugas-tugas berikut:

  • Membuat token teks menjadi kata
  • Membuat kosakata menggunakan 20.000 token teratas
  • Mengonversi token menjadi vektor urutan
  • Mem-build urutan dengan panjang urutan tetap
from tensorflow.python.keras.preprocessing import sequence
from tensorflow.python.keras.preprocessing import text

# Vectorization parameters
# Limit on the number of features. We use the top 20K features.
TOP_K = 20000

# Limit on the length of text sequences. Sequences longer than this
# will be truncated.
MAX_SEQUENCE_LENGTH = 500

def sequence_vectorize(train_texts, val_texts):
    """Vectorizes texts as sequence vectors.

    1 text = 1 sequence vector with fixed length.

    # Arguments
        train_texts: list, training text strings.
        val_texts: list, validation text strings.

    # Returns
        x_train, x_val, word_index: vectorized training and validation
            texts and word index dictionary.
    """
    # Create vocabulary with training texts.
    tokenizer = text.Tokenizer(num_words=TOP_K)
    tokenizer.fit_on_texts(train_texts)

    # Vectorize training and validation texts.
    x_train = tokenizer.texts_to_sequences(train_texts)
    x_val = tokenizer.texts_to_sequences(val_texts)

    # Get max sequence length.
    max_length = len(max(x_train, key=len))
    if max_length > MAX_SEQUENCE_LENGTH:
        max_length = MAX_SEQUENCE_LENGTH

    # Fix sequence length to max value. Sequences shorter than the length are
    # padded in the beginning and sequences longer are truncated
    # at the beginning.
    x_train = sequence.pad_sequences(x_train, maxlen=max_length)
    x_val = sequence.pad_sequences(x_val, maxlen=max_length)
    return x_train, x_val, tokenizer.word_index

Vektorisasi label

Kita telah melihat cara mengonversi data teks sampel menjadi vektor numerik. Proses yang serupa harus diterapkan ke label. Kita dapat mengonversi label menjadi nilai dalam rentang [0, num_classes - 1]. Misalnya, jika ada 3 class, kita cukup menggunakan nilai 0, 1, dan 2 untuk mewakilinya. Secara internal, jaringan akan menggunakan vektor one-hot untuk mewakili nilai ini (agar tidak ada hubungan yang salah antara label). Representasi ini bergantung pada fungsi kerugian dan fungsi aktivasi lapisan terakhir yang kita gunakan di jaringan neural. Kita akan mempelajari hal ini lebih lanjut di bagian berikutnya.