AI-For-Beginners/translations/ms/lessons/5-NLP/13-TextRep/TextRepresentationTF.ipynb

647 lines
26 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Tugas pengelasan teks\n",
"\n",
"Dalam modul ini, kita akan memulakan dengan tugas pengelasan teks yang mudah berdasarkan dataset **[AG_NEWS](http://www.di.unipi.it/~gulli/AG_corpus_of_news_articles.html)**: kita akan mengelaskan tajuk berita kepada salah satu daripada 4 kategori: Dunia, Sukan, Perniagaan dan Sains/Teknologi.\n",
"\n",
"## Dataset\n",
"\n",
"Untuk memuatkan dataset, kita akan menggunakan API **[TensorFlow Datasets](https://www.tensorflow.org/datasets)**.\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import tensorflow as tf\n",
"from tensorflow import keras\n",
"import tensorflow_datasets as tfds\n",
"\n",
"# In this tutorial, we will be training a lot of models. In order to use GPU memory cautiously,\n",
"# we will set tensorflow option to grow GPU memory allocation when required.\n",
"physical_devices = tf.config.list_physical_devices('GPU') \n",
"if len(physical_devices)>0:\n",
" tf.config.experimental.set_memory_growth(physical_devices[0], True)\n",
"\n",
"dataset = tfds.load('ag_news_subset')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Kita kini boleh mengakses bahagian latihan dan ujian dataset dengan menggunakan `dataset['train']` dan `dataset['test']` masing-masing:\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Length of train dataset = 120000\n",
"Length of test dataset = 7600\n"
]
}
],
"source": [
"ds_train = dataset['train']\n",
"ds_test = dataset['test']\n",
"\n",
"print(f\"Length of train dataset = {len(ds_train)}\")\n",
"print(f\"Length of test dataset = {len(ds_test)}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Mari cetak 10 tajuk berita baru pertama dari set data kita:\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3 (Sci/Tech) -> b'AMD Debuts Dual-Core Opteron Processor' b'AMD #39;s new dual-core Opteron chip is designed mainly for corporate computing applications, including databases, Web services, and financial transactions.'\n",
"1 (Sports) -> b\"Wood's Suspension Upheld (Reuters)\" b'Reuters - Major League Baseball\\\\Monday announced a decision on the appeal filed by Chicago Cubs\\\\pitcher Kerry Wood regarding a suspension stemming from an\\\\incident earlier this season.'\n",
"2 (Business) -> b'Bush reform may have blue states seeing red' b'President Bush #39;s quot;revenue-neutral quot; tax reform needs losers to balance its winners, and people claiming the federal deduction for state and local taxes may be in administration planners #39; sights, news reports say.'\n",
"3 (Sci/Tech) -> b\"'Halt science decline in schools'\" b'Britain will run out of leading scientists unless science education is improved, says Professor Colin Pillinger.'\n",
"1 (Sports) -> b'Gerrard leaves practice' b'London, England (Sports Network) - England midfielder Steven Gerrard injured his groin late in Thursday #39;s training session, but is hopeful he will be ready for Saturday #39;s World Cup qualifier against Austria.'\n"
]
}
],
"source": [
"classes = ['World', 'Sports', 'Business', 'Sci/Tech']\n",
"\n",
"for i,x in zip(range(5),ds_train):\n",
" print(f\"{x['label']} ({classes[x['label']]}) -> {x['title']} {x['description']}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Pemvektoran Teks\n",
"\n",
"Sekarang kita perlu menukar teks kepada **nombor** yang boleh diwakili sebagai tensor. Jika kita mahukan perwakilan pada peringkat perkataan, kita perlu melakukan dua perkara:\n",
"\n",
"* Gunakan **tokenizer** untuk memecahkan teks kepada **token**.\n",
"* Bina **vokabulari** daripada token-token tersebut.\n",
"\n",
"### Mengehadkan Saiz Vokabulari\n",
"\n",
"Dalam contoh dataset AG News, saiz vokabulari agak besar, melebihi 100k perkataan. Secara amnya, kita tidak memerlukan perkataan yang jarang muncul dalam teks — hanya beberapa ayat sahaja yang akan mengandungi perkataan tersebut, dan model tidak akan belajar daripadanya. Oleh itu, adalah masuk akal untuk mengehadkan saiz vokabulari kepada jumlah yang lebih kecil dengan memberikan argumen kepada pembina vektorisasi:\n",
"\n",
"Kedua-dua langkah ini boleh dikendalikan menggunakan lapisan **TextVectorization**. Mari kita wujudkan objek vektorisasi, dan kemudian panggil kaedah `adapt` untuk melalui semua teks dan membina vokabulari:\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"vocab_size = 50000\n",
"vectorizer = keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size)\n",
"vectorizer.adapt(ds_train.take(500).map(lambda x: x['title']+' '+x['description']))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> **Nota** bahawa kami hanya menggunakan sebahagian kecil daripada keseluruhan set data untuk membina kosa kata. Kami melakukannya untuk mempercepatkan masa pelaksanaan dan supaya anda tidak perlu menunggu lama. Walau bagaimanapun, kami mengambil risiko bahawa beberapa perkataan daripada keseluruhan set data mungkin tidak dimasukkan ke dalam kosa kata, dan akan diabaikan semasa latihan. Oleh itu, menggunakan saiz kosa kata penuh dan menjalankan keseluruhan set data semasa `adapt` seharusnya meningkatkan ketepatan akhir, tetapi tidak secara signifikan.\n",
"\n",
"Sekarang kita boleh mengakses kosa kata sebenar:\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['', '[UNK]', 'the', 'to', 'a', 'in', 'of', 'and', 'on', 'for']\n",
"Length of vocabulary: 5335\n"
]
}
],
"source": [
"vocab = vectorizer.get_vocabulary()\n",
"vocab_size = len(vocab)\n",
"print(vocab[:10])\n",
"print(f\"Length of vocabulary: {vocab_size}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Dengan menggunakan penvektor, kita boleh dengan mudah mengekod sebarang teks ke dalam satu set nombor:\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<tf.Tensor: shape=(7,), dtype=int64, numpy=array([ 112, 3695, 3, 304, 11, 1041, 1], dtype=int64)>"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"vectorizer('I love to play with my words')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Representasi teks Bag-of-words\n",
"\n",
"Oleh kerana perkataan mewakili makna, kadangkala kita boleh memahami maksud sesuatu teks hanya dengan melihat perkataan individu, tanpa menghiraukan susunan mereka dalam ayat. Sebagai contoh, apabila mengklasifikasikan berita, perkataan seperti *cuaca* dan *salji* mungkin menunjukkan *ramalan cuaca*, manakala perkataan seperti *saham* dan *dolar* akan merujuk kepada *berita kewangan*.\n",
"\n",
"**Bag-of-words** (BoW) adalah representasi vektor tradisional yang paling mudah difahami. Setiap perkataan dihubungkan dengan indeks vektor, dan elemen vektor mengandungi bilangan kemunculan setiap perkataan dalam dokumen tertentu.\n",
"\n",
"![Imej menunjukkan bagaimana representasi vektor bag-of-words diwakili dalam memori.](../../../../../translated_images/ms/bag-of-words-example.606fc1738f1d7ba9.webp) \n",
"\n",
"> **Note**: Anda juga boleh menganggap BoW sebagai jumlah semua vektor satu-hot-encoded untuk setiap perkataan dalam teks.\n",
"\n",
"Di bawah adalah contoh bagaimana untuk menghasilkan representasi bag-of-words menggunakan pustaka python Scikit Learn:\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[1, 1, 0, 2, 0, 0, 0, 0, 0]], dtype=int64)"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from sklearn.feature_extraction.text import CountVectorizer\n",
"sc_vectorizer = CountVectorizer()\n",
"corpus = [\n",
" 'I like hot dogs.',\n",
" 'The dog ran fast.',\n",
" 'Its hot outside.',\n",
" ]\n",
"sc_vectorizer.fit_transform(corpus)\n",
"sc_vectorizer.transform(['My dog likes hot dogs on a hot day.']).toarray()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Kita juga boleh menggunakan penvektor Keras yang telah kita definisikan di atas, menukar setiap nombor perkataan kepada pengekodan satu-hot dan menambahkan semua vektor tersebut:\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([0., 5., 0., ..., 0., 0., 0.], dtype=float32)"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def to_bow(text):\n",
" return tf.reduce_sum(tf.one_hot(vectorizer(text),vocab_size),axis=0)\n",
"\n",
"to_bow('My dog likes hot dogs on a hot day.').numpy()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> **Nota**: Anda mungkin terkejut bahawa hasilnya berbeza daripada contoh sebelumnya. Sebabnya ialah dalam contoh Keras, panjang vektor sepadan dengan saiz perbendaharaan kata, yang dibina daripada keseluruhan dataset AG News, manakala dalam contoh Scikit Learn, kita membina perbendaharaan kata daripada teks sampel secara langsung.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Melatih Pengklasifikasi BoW\n",
"\n",
"Sekarang kita telah mempelajari cara membina representasi bag-of-words untuk teks kita, mari kita latih pengklasifikasi yang menggunakannya. Pertama, kita perlu menukar dataset kita kepada representasi bag-of-words. Ini boleh dilakukan dengan menggunakan fungsi `map` seperti berikut:\n"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"batch_size = 128\n",
"\n",
"ds_train_bow = ds_train.map(lambda x: (to_bow(x['title']+x['description']),x['label'])).batch(batch_size)\n",
"ds_test_bow = ds_test.map(lambda x: (to_bow(x['title']+x['description']),x['label'])).batch(batch_size)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Sekarang mari kita tentukan rangkaian neural pengklasifikasi mudah yang mengandungi satu lapisan linear. Saiz input ialah `vocab_size`, dan saiz output sepadan dengan bilangan kelas (4). Oleh kerana kita sedang menyelesaikan tugas pengklasifikasian, fungsi pengaktifan terakhir ialah **softmax**:\n"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"938/938 [==============================] - 66s 70ms/step - loss: 0.6144 - acc: 0.8427 - val_loss: 0.4416 - val_acc: 0.8697\n"
]
},
{
"data": {
"text/plain": [
"<keras.callbacks.History at 0x20c70a947f0>"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model = keras.models.Sequential([\n",
" keras.layers.Dense(4,activation='softmax',input_shape=(vocab_size,))\n",
"])\n",
"model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])\n",
"model.fit(ds_train_bow,validation_data=ds_test_bow)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Memandangkan kita mempunyai 4 kelas, ketepatan melebihi 80% adalah hasil yang baik.\n",
"\n",
"## Melatih pengklasifikasi sebagai satu rangkaian\n",
"\n",
"Oleh kerana penvektor juga merupakan lapisan Keras, kita boleh mentakrifkan satu rangkaian yang merangkuminya, dan melatihnya secara end-to-end. Dengan cara ini, kita tidak perlu memvektor dataset menggunakan `map`, kita hanya boleh menghantar dataset asal ke input rangkaian.\n",
"\n",
"> **Nota**: Kita masih perlu menggunakan `map` pada dataset kita untuk menukar medan daripada kamus (seperti `title`, `description` dan `label`) kepada tuple. Walau bagaimanapun, apabila memuatkan data daripada cakera, kita boleh membina dataset dengan struktur yang diperlukan sejak awal.\n"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"model\"\n",
"_________________________________________________________________\n",
" Layer (type) Output Shape Param # \n",
"=================================================================\n",
" input_1 (InputLayer) [(None, 1)] 0 \n",
" \n",
" text_vectorization (TextVec (None, None) 0 \n",
" torization) \n",
" \n",
" tf.one_hot (TFOpLambda) (None, None, 5335) 0 \n",
" \n",
" tf.math.reduce_sum (TFOpLam (None, 5335) 0 \n",
" bda) \n",
" \n",
" dense_2 (Dense) (None, 4) 21344 \n",
" \n",
"=================================================================\n",
"Total params: 21,344\n",
"Trainable params: 21,344\n",
"Non-trainable params: 0\n",
"_________________________________________________________________\n",
"938/938 [==============================] - 73s 77ms/step - loss: 0.6057 - acc: 0.8414 - val_loss: 0.4202 - val_acc: 0.8736\n"
]
},
{
"data": {
"text/plain": [
"<keras.callbacks.History at 0x20c721521f0>"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def extract_text(x):\n",
" return x['title']+' '+x['description']\n",
"\n",
"def tupelize(x):\n",
" return (extract_text(x),x['label'])\n",
"\n",
"inp = keras.Input(shape=(1,),dtype=tf.string)\n",
"x = vectorizer(inp)\n",
"x = tf.reduce_sum(tf.one_hot(x,vocab_size),axis=1)\n",
"out = keras.layers.Dense(4,activation='softmax')(x)\n",
"model = keras.models.Model(inp,out)\n",
"model.summary()\n",
"\n",
"model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])\n",
"model.fit(ds_train.map(tupelize).batch(batch_size),validation_data=ds_test.map(tupelize).batch(batch_size))\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Bigram, trigram dan n-gram\n",
"\n",
"Satu kekurangan pendekatan bag-of-words ialah beberapa perkataan adalah sebahagian daripada ungkapan berbilang perkataan. Sebagai contoh, perkataan 'hot dog' mempunyai makna yang berbeza sama sekali daripada perkataan 'hot' dan 'dog' dalam konteks lain. Jika kita sentiasa mewakili perkataan 'hot' dan 'dog' menggunakan vektor yang sama, ia boleh mengelirukan model kita.\n",
"\n",
"Untuk menangani isu ini, **representasi n-gram** sering digunakan dalam kaedah pengelasan dokumen, di mana kekerapan setiap perkataan, dua perkataan atau tiga perkataan adalah ciri yang berguna untuk melatih pengelas. Dalam representasi bigram, sebagai contoh, kita akan menambah semua pasangan perkataan ke dalam perbendaharaan kata, selain daripada perkataan asal.\n",
"\n",
"Di bawah adalah contoh bagaimana untuk menjana representasi bag-of-words bigram menggunakan Scikit Learn:\n"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Vocabulary:\n",
" {'i': 7, 'like': 11, 'hot': 4, 'dogs': 2, 'i like': 8, 'like hot': 12, 'hot dogs': 5, 'the': 16, 'dog': 0, 'ran': 14, 'fast': 3, 'the dog': 17, 'dog ran': 1, 'ran fast': 15, 'its': 9, 'outside': 13, 'its hot': 10, 'hot outside': 6}\n"
]
},
{
"data": {
"text/plain": [
"array([[1, 0, 1, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],\n",
" dtype=int64)"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"bigram_vectorizer = CountVectorizer(ngram_range=(1, 2), token_pattern=r'\\b\\w+\\b', min_df=1)\n",
"corpus = [\n",
" 'I like hot dogs.',\n",
" 'The dog ran fast.',\n",
" 'Its hot outside.',\n",
" ]\n",
"bigram_vectorizer.fit_transform(corpus)\n",
"print(\"Vocabulary:\\n\",bigram_vectorizer.vocabulary_)\n",
"bigram_vectorizer.transform(['My dog likes hot dogs on a hot day.']).toarray()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Kelemahan utama pendekatan n-gram adalah saiz perbendaharaan kata mula berkembang dengan sangat pantas. Dalam praktiknya, kita perlu menggabungkan representasi n-gram dengan teknik pengurangan dimensi, seperti *embeddings*, yang akan kita bincangkan dalam unit seterusnya.\n",
"\n",
"Untuk menggunakan representasi n-gram dalam dataset **AG News** kita, kita perlu memberikan parameter `ngrams` kepada pembina `TextVectorization` kita. Panjang perbendaharaan kata bigram adalah **jauh lebih besar**, dalam kes kita ia melebihi 1.3 juta token! Oleh itu, adalah masuk akal untuk menghadkan token bigram kepada jumlah yang munasabah.\n",
"\n",
"Kita boleh menggunakan kod yang sama seperti di atas untuk melatih pengklasifikasi, namun, ia akan menjadi sangat tidak efisien dari segi memori. Dalam unit seterusnya, kita akan melatih pengklasifikasi bigram menggunakan embeddings. Sementara itu, anda boleh mencuba latihan pengklasifikasi bigram dalam notebook ini dan lihat jika anda boleh mendapatkan ketepatan yang lebih tinggi.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Mengira Vektor BoW Secara Automatik\n",
"\n",
"Dalam contoh di atas, kita mengira vektor BoW secara manual dengan menjumlahkan pengekodan satu-haba bagi setiap perkataan. Walau bagaimanapun, versi terkini TensorFlow membolehkan kita mengira vektor BoW secara automatik dengan memberikan parameter `output_mode='count` kepada pembina penvektor. Ini menjadikan proses mendefinisikan dan melatih model kita jauh lebih mudah:\n"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Training vectorizer\n",
"938/938 [==============================] - 7s 7ms/step - loss: 0.5929 - acc: 0.8486 - val_loss: 0.4168 - val_acc: 0.8772\n"
]
},
{
"data": {
"text/plain": [
"<keras.callbacks.History at 0x20c725217c0>"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model = keras.models.Sequential([\n",
" keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size,output_mode='count'),\n",
" keras.layers.Dense(4,input_shape=(vocab_size,), activation='softmax')\n",
"])\n",
"print(\"Training vectorizer\")\n",
"model.layers[0].adapt(ds_train.take(500).map(extract_text))\n",
"model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])\n",
"model.fit(ds_train.map(tupelize).batch(batch_size),validation_data=ds_test.map(tupelize).batch(batch_size))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Kekerapan istilah - kekerapan dokumen songsang (TF-IDF)\n",
"\n",
"Dalam representasi BoW, kejadian perkataan diberi berat menggunakan teknik yang sama tanpa mengira perkataan itu sendiri. Walau bagaimanapun, jelas bahawa perkataan yang kerap muncul seperti *a* dan *in* adalah jauh kurang penting untuk pengelasan berbanding istilah khusus. Dalam kebanyakan tugas NLP, sesetengah perkataan lebih relevan daripada yang lain.\n",
"\n",
"**TF-IDF** bermaksud **kekerapan istilah - kekerapan dokumen songsang**. Ia adalah variasi daripada bag-of-words, di mana nilai binari 0/1 yang menunjukkan kemunculan perkataan dalam dokumen digantikan dengan nilai titik terapung, yang berkaitan dengan kekerapan kemunculan perkataan dalam korpus.\n",
"\n",
"Secara lebih formal, berat $w_{ij}$ bagi perkataan $i$ dalam dokumen $j$ ditakrifkan sebagai:\n",
"$$\n",
"w_{ij} = tf_{ij}\\times\\log({N\\over df_i})\n",
"$$\n",
"di mana\n",
"* $tf_{ij}$ ialah bilangan kemunculan $i$ dalam $j$, iaitu nilai BoW yang telah kita lihat sebelum ini\n",
"* $N$ ialah bilangan dokumen dalam koleksi\n",
"* $df_i$ ialah bilangan dokumen yang mengandungi perkataan $i$ dalam keseluruhan koleksi\n",
"\n",
"Nilai TF-IDF $w_{ij}$ meningkat secara berkadar dengan bilangan kali perkataan muncul dalam dokumen dan diselaraskan dengan bilangan dokumen dalam korpus yang mengandungi perkataan tersebut, yang membantu menyesuaikan fakta bahawa sesetengah perkataan muncul lebih kerap daripada yang lain. Sebagai contoh, jika perkataan muncul dalam *setiap* dokumen dalam koleksi, $df_i=N$, dan $w_{ij}=0$, dan istilah tersebut akan diabaikan sepenuhnya.\n",
"\n",
"Anda boleh dengan mudah mencipta vektorisasi TF-IDF teks menggunakan Scikit Learn:\n"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[0.43381609, 0. , 0.43381609, 0. , 0.65985664,\n",
" 0.43381609, 0. , 0. , 0. , 0. ,\n",
" 0. , 0. , 0. , 0. , 0. ,\n",
" 0. ]])"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from sklearn.feature_extraction.text import TfidfVectorizer\n",
"vectorizer = TfidfVectorizer(ngram_range=(1,2))\n",
"vectorizer.fit_transform(corpus)\n",
"vectorizer.transform(['My dog likes hot dogs on a hot day.']).toarray()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Dalam Keras, lapisan `TextVectorization` boleh secara automatik mengira frekuensi TF-IDF dengan memberikan parameter `output_mode='tf-idf'`. Mari ulangi kod yang kita gunakan di atas untuk melihat sama ada penggunaan TF-IDF meningkatkan ketepatan:\n"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Training vectorizer\n",
"938/938 [==============================] - 12s 12ms/step - loss: 0.4197 - acc: 0.8662 - val_loss: 0.3432 - val_acc: 0.8849\n"
]
},
{
"data": {
"text/plain": [
"<keras.callbacks.History at 0x20c729dfd30>"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model = keras.models.Sequential([\n",
" keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size,output_mode='tf-idf'),\n",
" keras.layers.Dense(4,input_shape=(vocab_size,), activation='softmax')\n",
"])\n",
"print(\"Training vectorizer\")\n",
"model.layers[0].adapt(ds_train.take(500).map(extract_text))\n",
"model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])\n",
"model.fit(ds_train.map(tupelize).batch(batch_size),validation_data=ds_test.map(tupelize).batch(batch_size))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Kesimpulan\n",
"\n",
"Walaupun representasi TF-IDF memberikan berat kekerapan kepada pelbagai perkataan, ia tidak mampu mewakili makna atau susunan. Seperti yang dikatakan oleh ahli bahasa terkenal J. R. Firth pada tahun 1935, \"Makna lengkap sesuatu perkataan sentiasa bersifat kontekstual, dan tiada kajian tentang makna yang terpisah daripada konteks boleh dianggap serius.\" Kita akan belajar bagaimana menangkap maklumat kontekstual daripada teks menggunakan pemodelan bahasa dalam kursus ini nanti.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Penafian**: \nDokumen ini telah diterjemahkan menggunakan perkhidmatan terjemahan AI [Co-op Translator](https://github.com/Azure/co-op-translator). Walaupun kami berusaha untuk memastikan ketepatan, sila ambil perhatian bahawa terjemahan automatik mungkin mengandungi kesilapan atau ketidaktepatan. Dokumen asal dalam bahasa asalnya harus dianggap sebagai sumber yang berwibawa. Untuk maklumat yang kritikal, terjemahan manusia profesional adalah disyorkan. Kami tidak bertanggungjawab atas sebarang salah faham atau salah tafsir yang timbul daripada penggunaan terjemahan ini.\n"
]
}
],
"metadata": {
"interpreter": {
"hash": "0cb620c6d4b9f7a635928804c26cf22403d89d98d79684e4529119355ee6d5a5"
},
"kernel_info": {
"name": "conda-env-py37_tensorflow-py"
},
"kernelspec": {
"display_name": "py37_tensorflow",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.12"
},
"nteract": {
"version": "nteract-front-end@1.0.0"
},
"coopTranslator": {
"original_hash": "19b43951d55b377a76209c24c1f017e4",
"translation_date": "2025-08-29T16:43:51+00:00",
"source_file": "lessons/5-NLP/13-TextRep/TextRepresentationTF.ipynb",
"language_code": "ms"
}
},
"nbformat": 4,
"nbformat_minor": 4
}