AI-For-Beginners/translations/km/lessons/5-NLP/13-TextRep/TextRepresentationPyTorch.i...

571 lines
31 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# មុខងារបែងចែកអត្ថបទ\n",
"\n",
"ដូចដែលយើងបានរំលឹក អេភាសីយើងនឹងផ្តោតលើមុខងារបែងចែកអត្ថបទសាមញ្ញមួយ dựa trên **AG_NEWS** ភាពទិន្នន័យ ដែលជា​ការបែងចែកសេចក្តីដំបូន្មានព័ត៌មានទៅក្នុងមួយចំណាត់ថ្នាក់ពីរាបបួន៖ ពិភពលោក កីឡា ពាណិជ្ជកម្ម និង វិទ្យាសាស្រ្ត/បច្ចេកវិទ្យា។\n",
"\n",
"## ព្រំប្រៃទិន្នន័យ\n",
"\n",
"ព្រំប្រៃទិន្នន័យនេះត្រូវបានសាងសង់គ្នាចូលក្នុងម៉ូឌុល [`torchtext`](https://github.com/pytorch/text) ដូច្នេះ យើងអាចចូលដំណើរការយ៉ាងងាយស្រួល។\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": [
"នៅទីនេះ `train_dataset` និង `test_dataset` មានប្រមាញ់ដែលត្រឡប់វ៉ាល្យូមនៃស្លាក (ចំនួនថ្នាក់) និងអត្ថបទដោយលំដាប់ ជាឧទាហរណ៍ៈ\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": [
"ដូច្នេះ យើងចេញសារព័ត៌មានថ្មី ១០ ចំណងជើងដំបូងពីឃ្លាំងទិន្នន័យរបស់យើង៖\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": [
"ដោយសារតែទិន្នន័យជា iterator បើយើងចង់ប្រើទិន្នន័យជាច្រើនដងយើងត្រូវបម្លែងវាទៅជាបរមាណៈ list:\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": [
"## ការបំបែកពាក្យ\n",
"\n",
"ឥឡូវនេះយើងត្រូវបំលែងអត្ថបទទៅជាខ្ទង់ **លេខ** ដែលអាចត្រូវបានតំណាងជាទិន្ស័រ។ ប្រសិនបើយើងចង់តំណាងជារាយនាមអក្សរពាក្យ ត្រូវធ្វើពីរជំហាន៖\n",
"* ប្រើ **tokenizer** ដើម្បីបំបែកអត្ថបទទៅជាប្រភេទពាក្យ **tokens**\n",
"* បង្កើត **vocabulary** សម្រាប់ពាក្យទាំងនោះ។\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": [
"ប្រើវាក្យសព្ទ យើងអាចបំលែងខ្សែអក្សរដែលបានបំបែករបស់យើងទៅជាសំណុំលេខបានយ៉ាងងាយស្រួលៈ\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": [
"## ការបង្ហាញអត្ថបទជាថង់ពាក្យ\n",
"\n",
"ដោយសារពាក្យសម្គាល់អត្ថន័យ ម្តងម្កាលយើងអាចរកឃើញអត្ថន័យនៃអត្ថបទតាមរយៈការមើលតែពាក្យនីមួយៗ ដោយមិនគិតពីលំដាប់របស់ពួកវានៅក្នុងប្រយោគ។ ឧទាហរណ៍ សម្រាប់ការតែងចំណាត់ថ្នាក់ព័ត៌មាន ពាក្យដូចជា *អាកាសធាតុ*, *ហេីយគ្រាប់ទឹកកក* មានសក្តានុពលបង្ហាញពី *ការព្យាករណ៍អាកាសធាតុ* ខណៈពាក្យដូចជា *ភាគហ៊ុន*, *ដុល្លារ* នឹងចាត់ទុកថាជា *ព័ត៌មានហិរញ្ញវត្ថុ*។\n",
"\n",
"**ថង់ពាក្យ** (BoW) គឺជាការបង្ហាញវ៉ិចទ័រដែលប្រើប្រាស់ធម្មតាពិសេសច្រើនបំផុត។ ពាក្យនីមួយៗ ត្រូវបានភ្ជាប់ទៅនឹងឧSobatាយវ៉ិចទ័រ ដោយធាតុវ៉ិចទ័រមានចំនួនករណីកើតឡើងនៃពាក្យនៅក្នុងឯកសារដែលបានផ្ដល់។\n",
"\n",
"![រូបភាពបង្ហាញពីរបៀបដែលការបង្ហាញវ៉ិចទ័រថង់ពាក្យត្រូវបានផ្ទុកនៅក្នុងអង្គចងចាំ។](../../../../../translated_images/km/bag-of-words-example.606fc1738f1d7ba9.webp) \n",
"\n",
"> **សំគាល់**: អ្នកគួរតែគិតថា BoW ជា៉ការសរុបវ៉ិចទ័រ one-hot-encoded សម្រាប់ពាក្យនីមួយៗនៅក្នុងអត្ថបទ។\n",
"\n",
"​ខាង​ក្រោម​ជា​ឧទាហរណ៍​នៃ​របៀប​បង្កើត​ការ​បង្ហាញ​ថង់ពាក្យ​ប្រើ​ប្រាស់​បណ្ណាល័យ Scikit Learn ក្នុងភាសា python ៖\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": [
"ដើម្បីគណនាពុម្ពទំនុកចិត្ត bag-of-words ពីតំណាងវ៉ិកទ័រនៃឃ្លាសន្និដ្ឋាន AG_NEWS របស់យើង យើងអាចប្រើមុខងារដូចខាងក្រោម៖\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": [
"> **កំណត់សម្គាល់:** នៅទីនេះយើងកំពុងប្រើអថេរ `vocab_size` កម្រិតសកល ដើម្បីបញ្ជាក់ទំហំលំនាំដើមនៃវាក្យសព្ទ។ ពីព្រោះទំហំពាក្យសព្ទជាញែកខ្លាំងជារឿយៗ យើងអាចកំណត់ទំហំវាក្យសព្ទទៅតែពាក្យដែលមានភាពញឹកញាប់ខ្ពស់បំផុត។ សូមព្យាយាមកាត់បន្ថយតម្លៃ `vocab_size` ហើយរត់កូដខាងក្រោម ហើយមើលថាវាមានឥទ្ធិពលយ៉ាងណាលើភាពត្រឹមត្រូវ។ អ្នកគួរត្រូវរំពឹងថា ភាពត្រឹមត្រូវនឹងធ្លាក់ចុះបន្តិច ប៉ុន្តែមិនខ្លាំងទេ ដើម្បីសំរាប់ការសមត្ថភាពខ្ពស់ជាងមុន។\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ការបណ្តុះបណ្តាលអ្នកចាត់ថ្នាក់ BoW\n",
"\n",
"ឥឡូវនេះដែលយើងបានរៀនថាតើធ្វើដូចម្តេចដើម្បីបង្កើតតំណាងបង្គោលពាក្យ Bag-of-Words នៃអត្ថបទរបស់យើងហើយ យើងចង់បណ្តុះបណ្តាលអ្នកចាត់ថ្នាក់សម្រាប់វា។ ជាមួយនេះ ដំបូង យើងត្រូវបម្លែងទិន្នន័យសម្រាប់ការបណ្តុះបណ្តាលដោយរបៀបគឺ ដំណាក់កាលតំណាងពាក្យតាមទីតាំងទាំងអស់ត្រូវបានបម្លែងទៅជាតំណាង Bag-of-Words។ នេះអាចសម្រេចបានដោយផ្ទេរអនុគមន៍ `bowify` ជាព៉ារ៉ាម៉ែត្រ `collate_fn` ទៅឲ្យ `DataLoader` នៃ 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": [
"ឥឡូវនេះចូរអនុស្សាណារៀបចំបណ្តាញសរសេរមួយសម្រាប់ចំណាត់ថ្នាក់សាមញ្ញ ដែលមានស្រទាប់ខាងស្រទាប់តែមួយ។ ទំហំវ៉ិចទ័រចូលមានទំហំស្មើនឹង `vocab_size` ហើយទំហំចេញឆបគ្នានឹងចំនួនថ្នាក់ (4)។ ពីព្រោះយើងកំពុងដោះស្រាយបញ្ហាចំណាត់ថ្នាក់ ការជំរុញចុងក្រោយគឺជា `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": [
"ឥឡូវនេះយើងនឹងកំណត់រង្វិលបណ្តុះបណ្តាល PyTorch ស្តង់ដារ។ ព្រោះតែកំណត់ទិន្នន័យរបស់យើងមានទំហំធំជាងមធ្យម សម្រាប់គោលបំណងបង្រៀនយើងនឹងបណ្តុះបណ្តាលគ្រាន់តែកំណត់មួយទេ ហើយខ្លះពេលម្យ៉ាងទៀតក៏អាចបណ្តុះបណ្តាលតិចជាងមួយកំណត់ផង (ការ​បញ្ជាក់​ពាក្យបញ្ជា `epoch_size` អនុញ្ញាតឲ្យយើងកំណត់ដែនកំណត់ការបណ្តុះបណ្តាល)។ យើងក៏នឹងរាយការណ៍ភាពត្រឹមត្រូវបណ្តុះបណ្តាលដែលបានសង្ស័យក្នុងអំឡុងពេលបណ្តុះបណ្តាលផងដែរ; ភាគរយនៃការរាយការណ៍ត្រូវបានកំណត់ដោយការបញ្ជាក់ពាក្យបញ្ជា `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 និង N-Grams\n",
"\n",
"ការកំណត់មួយនៃវិធីសាស្រ្តថតពាក្យ (bag of words) គឺពាក្យខ្លះជាផ្នែកមួយនៃការបង្កើតអត្ថាធិប្បាយពាក្យច្រើនពាក្យ ដូចជាឧទាហរណ៍ ពាក្យ 'hot dog' មានន័យខុសពីពាក្យ 'hot' និង 'dog' ក្នុងបរិបទផ្សេងៗ។ ប្រសិនបើយើងបង្ហាញពាក្យ 'hot' និង 'dog' ជានិរន្តរភាពដោយវ៉ិចទ័រដូចគ្នា វាអាចបង្កការជ្រុះច្រឡំចំពោះម៉ូដែលរបស់យើង។\n",
"\n",
"ដើម្បីដោះស្រាយបញ្ហានេះ, **ការតំណាង N-gram** ត្រូវបានប្រើជាញឹកញាប់ក្នុងវិធីសាស្រ្តចាត់ថ្នាក់ឯកសារ, ដែលប្រេកង់នៃពាក្យរាល់ខ្ទង់ពាក្យពីរឬបីពាក្យគឺជាលក្ខណៈសំខាន់សំរាប់ការបណ្តុះបណ្តាលម៉ាស៊ីនចាត់ថ្នាក់។ ក្នុងការតំណាង bigram, ឧទាហរណ៍យើងនឹងបន្ថែមដំណាក់កាលពាក្យទាំងអស់ទៅក្នុងវ៉ុកាប្យូលារី ខៀវបន្ថែមពីពាក្យដើម។\n",
"\n",
"ខាងក្រោមជាឧទាហរណ៍ពីរបៀបបង្កើតការតំណាង bigram bag of word ដោយប្រើ 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": [
"ចំណុចខ្វះខាតសំខាន់នៃវិធីសាស្រ្ត N-gram គឺទំហំវេយ្យាករណ៍ចាប់ផ្តើមរីកចម្រើនយ៉ាងឆាប់រហ័ស ។ ក្នុងការអនុវត្តន៍ ពួកយើងត្រូវការចងក្រងការ​តំណាង N-gram ជាមួយបច្ចេកទេស​ការកាត់បន្ថយ​រាងវេកទិសខ្លះៗ ដូចជា *embeddings* ដែលយើងនឹងពិភាក្សានៅឯកតាចុងក្រោយ។\n",
"\n",
"ដើម្បីប្រើប្រាស់ការតំណាង N-gram នៅក្នុងទិន្នន័យ **AG News** របស់យើង យើងត្រូវតែបង្កើតវេយ្យាករណ៍ ngram ពិសេស ៖\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": [
"យើងអាចប្រើកូដដូចខាងលើដើម្បីបណ្តុះម៉ាស៊ីនចាត់ថ្នាក់ ប៉ុន្តែវានឹងប្រើអង្គចងចាំខ្លាំងណាស់។ នៅឯកត្តាបន្ទាប់ យើងនឹងបណ្តុះម៉ាស៊ីនចាត់ថ្នាក់ bigram ដោយប្រើ embeddings។\n",
"\n",
"> **សម្គាល់:** អ្នកអាចទុកតែ ngrams ដែលបញ្ចេញឡើងក្នុងអត្ថបទច្រើនជាងចំនួនដែលបានបញ្ជាក់។ វានឹងធានាថា bigrams ដែលមានកំណត់នឹងត្រូវដកចេញ ហើយនឹងបន្ថយវិមាត្រជាប្រសើរណាស់។ ដើម្បីធ្វើដូចនេះ សូមកំណត់ប៉ារ៉ាម៉ែត្រ `min_freq` ទៅតម្លៃខ្ពស់ជាងនេះ ហើយមើលការផ្លាស់ប្តូរវែងនៃវចនានុក្រម។\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Term Frequency Inverse Document Frequency TF-IDF\n",
"\n",
"ក្នុងការតំណាង BoW, ការបង្ហាញពាក្យត្រូវបានគិតសោយាក់កម្រ, មិនគិតថាពាក្យនោះជាពាក្យអ្វីនោះទេ។ ទោះជាយ៉ាងណា, គឺច្បាស់ថាពាក្យដែលមានប្រេកង់ច្រើន ដូចជា *a*, *in* ល។ មានសារៈសំខាន់តិចជាងបច្ចេកទេសពិសេស។ ជាការពិត, ក្នុងភារកិច្ច NLP ភាគច្រើនពាក្យខ្លះមានទំនាក់ទំនងសំខាន់ជាងពាក្យផ្សេងទៀត។\n",
"\n",
"**TF-IDF** មានន័យថា **term frequencyinverse document frequency**។ វាជាបម្លែងពីបាវពាក្យដែលជំនួសដោយតម្លៃពីរបៀប 0/1 ដែលបង្ហាញពីការបង្ហាញរបស់ពាក្យមួយក្នុងឯកសារ ដែលមានតម្លៃជាចំនួនទសភាគ ដែលទាក់ទងនឹងប្រេកង់នៃការបង្ហាញពាក្យនៅក្នុងក្រុមឯកសារ។\n",
"\n",
"យ៉ាងជាក់លាក់, ទម្ងន់ $w_{ij}$ នៃពាក្យ $i$ នៅក្នុងឯកសារ $j$ ត្រូវបានកំណត់ដូចជា៖\n",
"$$\n",
"w_{ij} = tf_{ij}\\times\\log({N\\over df_i})\n",
"$$\n",
"ដែល\n",
"* $tf_{ij}$ គឺជាចំនួនការបង្ហាញនៃ $i$ នៅក្នុង $j$, គឺតម្លៃ BoW ដែលយើងបានឃើញមុន\n",
"* $N$ គឺជាចំនួនឯកសារ​នៅក្នុងប្រមូលផ្តុំ\n",
"* $df_i$ គឺជាចំនួនឯកសារដែលមានពាក្យ $i$ នៅក្នុងប្រមូលផ្តុំទាំងមូល\n",
"\n",
"តម្លៃ TF-IDF $w_{ij}$ បន្ថែមឡើងជាផ្តាច់មុខទៅនឹងចំនួនដងដែលពាក្យមួយប្រែប្រួលក្នុងឯកសារ ហើយត្រូវបានពន្លាក់ដោយចំនួនឯកសារនៅក្នុងក្រុមឯកសារដែលមានពាក្យនោះ ដែលជួយកែសម្រួលសម្រាប់ការពិតថាពាក្យខ្លះបង្ហាញញឹកញាប់ជាងពាក្យផ្សេងៗ។ ឧទាហរណ៍ ប្រសិនបើពាក្យបង្ហាញនៅក្នុង *គ្រប់* ឯកសារនៅក្នុងប្រមូលផ្តុំ, $df_i=N$, ហើយ $w_{ij}=0$, ហើយពាក្យទាំងនោះនឹងត្រូវបានមិនគិតទេ។\n",
"\n",
"អ្នកអាចបង្កើតបច្ចេកទេសវ៉េកទ័រ TF-IDF របស់អត្ថបទដោយងាយស្រួលជាមួយ 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": [
"## និទស្សន៏\n",
"\n",
"ទោះបីជាការបង្ហាញ TF-IDF ផ្តល់ទំងន់ប្រេកង់ចំពោះពាក្យផ្សេងៗក៏ដោយ វាមិនអាចបង្ហាញអត្ថន័យឬលំដាប់បានទេ។ ដូចដែលវចនករល្បី J. R. Firth បាននិយាយនៅឆ្នាំ ១៩៣៥ ថា “អត្ថន័យពេញលេញនៃពាក្យមួយគឺជានិរិច្ឆេទតែប៉ុណ្ណោះ ហើយការសិក្សាអត្ថន័យដោយមិនពាក់ព័ន្ធនឹងបរិបទមិនអាចយកត្រឹមត្រូវបានទេ។”។ យើងនឹងរៀនបន្ថែមនៅពេលក្រោយក្នុងវគ្គថ្នាក់របៀបចាប់យកព័ត៌មានបរិបទពីអត្ថបទដោយប្រើគំរូភាសា។\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n\n<!-- CO-OP TRANSLATOR DISCLAIMER START -->\n**ការពិបាក**៖\nឯកសារនេះត្រូវបានបកប្រែដោយប្រើសេវាកម្មបកប្រែ AI [Co-op Translator](https://github.com/Azure/co-op-translator)។ ខណៈពេលដែលយើងខិតខំសម្រាប់ភាពត្រឹមត្រូវ សូមយកចិត្តទុកដាក់ថាបកប្រែដោយស្វ័យប្រវត្តិក្នុងខ្លះអាចមានកំហុសឬភាពមិនត្រឹមត្រូវ។ ឯកសារដែលមានភាសាមូលដ្ឋានគួរត្រូវបានគេចាត់ទុកជាផ្លូវការមួយ។ សម្រាប់ព័ត៌មានសំខាន់ៗ ការបកប្រែដោយអ្នកជំនាញមនុស្សគឺមានការផ្តល់អនុសាសន៍។ យើងមិនទទួលខុសត្រូវចំពោះការយល់ច្រឡំឬការបកស្រាយខុសឆ្គងដែលកើតឡើងពីការប្រើប្រាស់បកប្រែនេះឡើយ។\n<!-- CO-OP TRANSLATOR DISCLAIMER END -->\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"
}
},
"nbformat": 4,
"nbformat_minor": 2
}