577 lines
22 KiB
Plaintext
577 lines
22 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"# Tugas pengelasan teks\n",
|
||
"\n",
|
||
"Seperti yang telah kami nyatakan, kami akan memberi tumpuan kepada tugas pengelasan teks yang mudah berdasarkan dataset **AG_NEWS**, iaitu untuk mengelaskan tajuk berita kepada salah satu daripada 4 kategori: Dunia, Sukan, Perniagaan dan Sains/Teknologi.\n",
|
||
"\n",
|
||
"## Dataset\n",
|
||
"\n",
|
||
"Dataset ini telah tersedia dalam modul [`torchtext`](https://github.com/pytorch/text), jadi kita boleh mengaksesnya dengan mudah.\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 1,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"import torch\n",
|
||
"import torchtext\n",
|
||
"import os\n",
|
||
"import collections\n",
|
||
"os.makedirs('./data',exist_ok=True)\n",
|
||
"train_dataset, test_dataset = torchtext.datasets.AG_NEWS(root='./data')\n",
|
||
"classes = ['World', 'Sports', 'Business', 'Sci/Tech']"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Di sini, `train_dataset` dan `test_dataset` mengandungi koleksi yang mengembalikan pasangan label (nombor kelas) dan teks masing-masing, sebagai contoh:\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 2,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"(3,\n",
|
||
" \"Wall St. Bears Claw Back Into the Black (Reuters) Reuters - Short-sellers, Wall Street's dwindling\\\\band of ultra-cynics, are seeing green again.\")"
|
||
]
|
||
},
|
||
"execution_count": 2,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"list(train_dataset)[0]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Jadi, mari cetak 10 tajuk berita baru pertama daripada set data kita:\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 5,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"**Sci/Tech** -> Wall St. Bears Claw Back Into the Black (Reuters) Reuters - Short-sellers, Wall Street's dwindling\\band of ultra-cynics, are seeing green again.\n",
|
||
"**Sci/Tech** -> Carlyle Looks Toward Commercial Aerospace (Reuters) Reuters - Private investment firm Carlyle Group,\\which has a reputation for making well-timed and occasionally\\controversial plays in the defense industry, has quietly placed\\its bets on another part of the market.\n",
|
||
"**Sci/Tech** -> Oil and Economy Cloud Stocks' Outlook (Reuters) Reuters - Soaring crude prices plus worries\\about the economy and the outlook for earnings are expected to\\hang over the stock market next week during the depth of the\\summer doldrums.\n",
|
||
"**Sci/Tech** -> Iraq Halts Oil Exports from Main Southern Pipeline (Reuters) Reuters - Authorities have halted oil export\\flows from the main pipeline in southern Iraq after\\intelligence showed a rebel militia could strike\\infrastructure, an oil official said on Saturday.\n",
|
||
"**Sci/Tech** -> Oil prices soar to all-time record, posing new menace to US economy (AFP) AFP - Tearaway world oil prices, toppling records and straining wallets, present a new economic menace barely three months before the US presidential elections.\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"for i,x in zip(range(5),train_dataset):\n",
|
||
" print(f\"**{classes[x[0]]}** -> {x[1]}\")\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Oleh kerana set data adalah pengulang, jika kita ingin menggunakan data beberapa kali kita perlu menukarkannya kepada senarai:\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 3,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"train_dataset, test_dataset = torchtext.datasets.AG_NEWS(root='./data')\n",
|
||
"train_dataset = list(train_dataset)\n",
|
||
"test_dataset = list(test_dataset)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Penjanaan Token\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",
|
||
"* gunakan **penjana token** untuk memecahkan teks kepada **token**\n",
|
||
"* bina **perbendaharaan kata** daripada token-token tersebut.\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 4,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"['he', 'said', 'hello']"
|
||
]
|
||
},
|
||
"execution_count": 4,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"tokenizer = torchtext.data.utils.get_tokenizer('basic_english')\n",
|
||
"tokenizer('He said: hello')"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 5,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"counter = collections.Counter()\n",
|
||
"for (label, line) in train_dataset:\n",
|
||
" counter.update(tokenizer(line))\n",
|
||
"vocab = torchtext.vocab.vocab(counter, min_freq=1)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Dengan menggunakan perbendaharaan kata, kita boleh dengan mudah mengekodkan rentetan token yang telah ditokenkan ke dalam satu set nombor:\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 19,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Vocab size if 95810\n"
|
||
]
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"[599, 3279, 97, 1220, 329, 225, 7368]"
|
||
]
|
||
},
|
||
"execution_count": 19,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"vocab_size = len(vocab)\n",
|
||
"print(f\"Vocab size if {vocab_size}\")\n",
|
||
"\n",
|
||
"stoi = vocab.get_stoi() # dict to convert tokens to indices\n",
|
||
"\n",
|
||
"def encode(x):\n",
|
||
" return [stoi[s] for s in tokenizer(x)]\n",
|
||
"\n",
|
||
"encode('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*, *salji* mungkin menunjukkan *ramalan cuaca*, manakala perkataan seperti *saham*, *dolar* mungkin merujuk kepada *berita kewangan*.\n",
|
||
"\n",
|
||
"**Bag of Words** (BoW) adalah representasi vektor yang paling biasa digunakan dalam kaedah tradisional. Setiap perkataan dikaitkan dengan indeks vektor, dan elemen vektor mengandungi bilangan kemunculan sesuatu perkataan dalam dokumen tertentu.\n",
|
||
"\n",
|
||
" \n",
|
||
"\n",
|
||
"> **Note**: Anda juga boleh menganggap BoW sebagai jumlah semua vektor satu-hot-encoded untuk setiap perkataan individu 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": 7,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"array([[1, 1, 0, 2, 0, 0, 0, 0, 0]], dtype=int64)"
|
||
]
|
||
},
|
||
"execution_count": 7,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"from sklearn.feature_extraction.text import CountVectorizer\n",
|
||
"vectorizer = CountVectorizer()\n",
|
||
"corpus = [\n",
|
||
" 'I like hot dogs.',\n",
|
||
" 'The dog ran fast.',\n",
|
||
" 'Its hot outside.',\n",
|
||
" ]\n",
|
||
"vectorizer.fit_transform(corpus)\n",
|
||
"vectorizer.transform(['My dog likes hot dogs on a hot day.']).toarray()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Untuk mengira vektor bag-of-words daripada representasi vektor dataset AG_NEWS kita, kita boleh menggunakan fungsi berikut:\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 20,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"tensor([2., 1., 2., ..., 0., 0., 0.])\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"vocab_size = len(vocab)\n",
|
||
"\n",
|
||
"def to_bow(text,bow_vocab_size=vocab_size):\n",
|
||
" res = torch.zeros(bow_vocab_size,dtype=torch.float32)\n",
|
||
" for i in encode(text):\n",
|
||
" if i<bow_vocab_size:\n",
|
||
" res[i] += 1\n",
|
||
" return res\n",
|
||
"\n",
|
||
"print(to_bow(train_dataset[0][1]))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"> **Nota:** Di sini kita menggunakan pembolehubah global `vocab_size` untuk menentukan saiz lalai perbendaharaan kata. Oleh kerana saiz perbendaharaan kata sering kali sangat besar, kita boleh mengehadkan saiz perbendaharaan kata kepada perkataan yang paling kerap digunakan. Cuba kurangkan nilai `vocab_size` dan jalankan kod di bawah, dan lihat bagaimana ia mempengaruhi ketepatan. Anda sepatutnya menjangkakan sedikit penurunan ketepatan, tetapi tidak secara dramatik, sebagai ganti prestasi yang lebih tinggi.\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Melatih Pengelas BoW\n",
|
||
"\n",
|
||
"Sekarang setelah kita mempelajari cara membina representasi Bag-of-Words untuk teks kita, mari kita latih sebuah pengelas di atasnya. Pertama, kita perlu menukar dataset kita untuk latihan dengan cara di mana semua representasi vektor posisi ditukar kepada representasi bag-of-words. Ini boleh dicapai dengan menghantar fungsi `bowify` sebagai parameter `collate_fn` kepada `DataLoader` standard torch:\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 21,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"from torch.utils.data import DataLoader\n",
|
||
"import numpy as np \n",
|
||
"\n",
|
||
"# this collate function gets list of batch_size tuples, and needs to \n",
|
||
"# return a pair of label-feature tensors for the whole minibatch\n",
|
||
"def bowify(b):\n",
|
||
" return (\n",
|
||
" torch.LongTensor([t[0]-1 for t in b]),\n",
|
||
" torch.stack([to_bow(t[1]) for t in b])\n",
|
||
" )\n",
|
||
"\n",
|
||
"train_loader = DataLoader(train_dataset, batch_size=16, collate_fn=bowify, shuffle=True)\n",
|
||
"test_loader = DataLoader(test_dataset, batch_size=16, collate_fn=bowify, shuffle=True)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Sekarang mari kita definisikan rangkaian neural pengklasifikasi mudah yang mengandungi satu lapisan linear. Saiz vektor input adalah sama dengan `vocab_size`, dan saiz output sepadan dengan bilangan kelas (4). Oleh kerana kita sedang menyelesaikan tugas pengklasifikasian, fungsi pengaktifan akhir adalah `LogSoftmax()`.\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 22,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"net = torch.nn.Sequential(torch.nn.Linear(vocab_size,4),torch.nn.LogSoftmax(dim=1))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Sekarang kita akan mendefinisikan gelung latihan standard PyTorch. Oleh kerana dataset kita agak besar, untuk tujuan pengajaran kita akan melatih hanya untuk satu epoch, dan kadang-kadang kurang daripada satu epoch (menentukan parameter `epoch_size` membolehkan kita menghadkan latihan). Kita juga akan melaporkan ketepatan latihan terkumpul semasa latihan; kekerapan pelaporan ditentukan menggunakan parameter `report_freq`.\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 24,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"def train_epoch(net,dataloader,lr=0.01,optimizer=None,loss_fn = torch.nn.NLLLoss(),epoch_size=None, report_freq=200):\n",
|
||
" optimizer = optimizer or torch.optim.Adam(net.parameters(),lr=lr)\n",
|
||
" net.train()\n",
|
||
" total_loss,acc,count,i = 0,0,0,0\n",
|
||
" for labels,features in dataloader:\n",
|
||
" optimizer.zero_grad()\n",
|
||
" out = net(features)\n",
|
||
" loss = loss_fn(out,labels) #cross_entropy(out,labels)\n",
|
||
" loss.backward()\n",
|
||
" optimizer.step()\n",
|
||
" total_loss+=loss\n",
|
||
" _,predicted = torch.max(out,1)\n",
|
||
" acc+=(predicted==labels).sum()\n",
|
||
" count+=len(labels)\n",
|
||
" i+=1\n",
|
||
" if i%report_freq==0:\n",
|
||
" print(f\"{count}: acc={acc.item()/count}\")\n",
|
||
" if epoch_size and count>epoch_size:\n",
|
||
" break\n",
|
||
" return total_loss.item()/count, acc.item()/count"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 25,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"3200: acc=0.8028125\n",
|
||
"6400: acc=0.8371875\n",
|
||
"9600: acc=0.8534375\n",
|
||
"12800: acc=0.85765625\n"
|
||
]
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"(0.026090790722161722, 0.8620069296375267)"
|
||
]
|
||
},
|
||
"execution_count": 25,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"train_epoch(net,train_loader,epoch_size=15000)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## BiGrams, TriGrams dan N-Grams\n",
|
||
"\n",
|
||
"Satu kelemahan pendekatan bag of words ialah beberapa perkataan merupakan sebahagian daripada ungkapan berbilang perkataan, contohnya, perkataan 'hot dog' mempunyai makna yang sangat berbeza daripada perkataan 'hot' dan 'dog' dalam konteks lain. Jika kita sentiasa mewakili perkataan 'hot' dan 'dog' dengan vektor yang sama, ia boleh mengelirukan model kita.\n",
|
||
"\n",
|
||
"Untuk mengatasi masalah ini, **representasi N-gram** sering digunakan dalam kaedah pengelasan dokumen, di mana kekerapan setiap perkataan, bi-perkataan atau tri-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 menghasilkan representasi bigram bag of words menggunakan Scikit Learn:\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 26,
|
||
"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": 26,
|
||
"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 ialah saiz perbendaharaan kata mula berkembang dengan sangat pantas. Dalam praktiknya, kita perlu menggabungkan representasi N-gram dengan beberapa 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 membina perbendaharaan kata ngram khas:\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 27,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Bigram vocabulary length = 1308842\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"counter = collections.Counter()\n",
|
||
"for (label, line) in train_dataset:\n",
|
||
" l = tokenizer(line)\n",
|
||
" counter.update(torchtext.data.utils.ngrams_iterator(l,ngrams=2))\n",
|
||
" \n",
|
||
"bi_vocab = torchtext.vocab.vocab(counter, min_freq=1)\n",
|
||
"\n",
|
||
"print(\"Bigram vocabulary length = \",len(bi_vocab))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Kita boleh menggunakan kod yang sama seperti di atas untuk melatih pengklasifikasi, namun, ia akan menjadi sangat tidak cekap dari segi memori. Dalam unit seterusnya, kita akan melatih pengklasifikasi bigram menggunakan embeddings.\n",
|
||
"\n",
|
||
"> **Nota:** Anda hanya boleh meninggalkan ngram yang muncul dalam teks lebih daripada jumlah yang ditentukan. Ini akan memastikan bigram yang jarang berlaku akan diabaikan, dan akan mengurangkan dimensi dengan ketara. Untuk melakukan ini, tetapkan parameter `min_freq` kepada nilai yang lebih tinggi, dan perhatikan perubahan panjang perbendaharaan kata.\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Kekerapan Istilah dan Frekuensi Dokumen Songsang TF-IDF\n",
|
||
"\n",
|
||
"Dalam representasi BoW, kemunculan perkataan diberi berat yang sama, tanpa mengira perkataan itu sendiri. Walau bagaimanapun, jelas bahawa perkataan yang kerap muncul, seperti *a*, *in*, dan sebagainya, adalah jauh kurang penting untuk pengelasan berbanding istilah khusus. Malah, dalam kebanyakan tugas NLP, sesetengah perkataan lebih relevan daripada yang lain.\n",
|
||
"\n",
|
||
"**TF-IDF** adalah singkatan kepada **kekerapan istilah–frekuensi 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}$ adalah bilangan kemunculan $i$ dalam $j$, iaitu nilai BoW yang telah kita lihat sebelum ini\n",
|
||
"* $N$ adalah bilangan dokumen dalam koleksi\n",
|
||
"* $df_i$ adalah 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": 28,
|
||
"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": 28,
|
||
"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": [
|
||
"## 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 kemudian dalam kursus ini bagaimana untuk menangkap maklumat kontekstual daripada teks menggunakan pemodelan bahasa.\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 penting, 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": "16af2a8bbb083ea23e5e41c7f5787656b2ce26968575d8763f2c4b17f9cd711f"
|
||
},
|
||
"kernelspec": {
|
||
"display_name": "Python 3.8.12 ('py38')",
|
||
"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"
|
||
},
|
||
"coopTranslator": {
|
||
"original_hash": "7b9040985e748e4e2d4c689892456ad7",
|
||
"translation_date": "2025-08-29T16:38:21+00:00",
|
||
"source_file": "lessons/5-NLP/13-TextRep/TextRepresentationPyTorch.ipynb",
|
||
"language_code": "ms"
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 2
|
||
} |