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

577 lines
30 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",
"ตามที่เราได้กล่าวไว้ เราจะมุ่งเน้นไปที่งานการจัดประเภทข้อความแบบง่าย โดยใช้ชุดข้อมูล **AG_NEWS** ซึ่งเป็นการจัดประเภทหัวข้อข่าวให้อยู่ในหนึ่งใน 4 หมวดหมู่ ได้แก่ World, Sports, Business และ Sci/Tech\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": [
"ดังนั้น มาพิมพ์พาดหัวข่าวใหม่ 10 หัวข้อแรกจากชุดข้อมูลของเรากัน:\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": [
"เนื่องจากชุดข้อมูลเป็นตัววนซ้ำ หากเราต้องการใช้ข้อมูลหลายครั้ง เราจำเป็นต้องแปลงมันเป็นรายการ:\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** เพื่อแบ่งข้อความออกเป็น **โทเค็น**\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": [
"## การแสดงข้อความแบบ Bag of Words\n",
"\n",
"เนื่องจากคำมีความหมายในตัวเอง บางครั้งเราสามารถเข้าใจความหมายของข้อความได้เพียงแค่มองที่คำแต่ละคำ โดยไม่ต้องสนใจลำดับของคำในประโยค ตัวอย่างเช่น เมื่อเราจำแนกข่าว คำอย่าง *weather* และ *snow* มักจะบ่งบอกถึง *พยากรณ์อากาศ* ในขณะที่คำอย่าง *stocks* และ *dollar* จะเกี่ยวข้องกับ *ข่าวการเงิน*\n",
"\n",
"**Bag of Words** (BoW) เป็นการแสดงข้อความในรูปแบบเวกเตอร์ที่ใช้กันอย่างแพร่หลายที่สุดในวิธีการแบบดั้งเดิม โดยแต่ละคำจะถูกเชื่อมโยงกับดัชนีในเวกเตอร์ และแต่ละองค์ประกอบในเวกเตอร์จะแสดงจำนวนครั้งที่คำปรากฏในเอกสารที่กำหนด\n",
"\n",
"![ภาพแสดงการแสดงข้อความแบบ Bag of Words ในหน่วยความจำ](../../../../../translated_images/th/bag-of-words-example.606fc1738f1d7ba9.webp) \n",
"\n",
"> **Note**: คุณสามารถมองว่า BoW เป็นผลรวมของเวกเตอร์แบบ one-hot-encoded ของคำแต่ละคำในข้อความได้เช่นกัน\n",
"\n",
"ด้านล่างนี้คือตัวอย่างวิธีการสร้างการแสดงข้อความแบบ Bag of Words โดยใช้ไลบรารี 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": [
"ในการคำนวณเวกเตอร์แบบถุงคำจากการแสดงเวกเตอร์ของชุดข้อมูล 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 classifier\n",
"\n",
"ตอนนี้เราได้เรียนรู้วิธีสร้างตัวแทน Bag-of-Words สำหรับข้อความของเราแล้ว มาฝึกโมเดล classifier บนพื้นฐานนี้กัน ก่อนอื่น เราจำเป็นต้องแปลงชุดข้อมูลของเราให้เหมาะสมสำหรับการฝึก โดยที่ตัวแทนเวกเตอร์เชิงตำแหน่งทั้งหมดจะถูกแปลงเป็นตัวแทนแบบ 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 และบางครั้งอาจน้อยกว่าหนึ่ง epoch (การกำหนดพารามิเตอร์ `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 words โดยใช้ 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": [
"## ความถี่คำและความถี่คำผกผันเอกสาร (TF-IDF)\n",
"\n",
"ในรูปแบบการแทนคำแบบ BoW (Bag of Words) การปรากฏของคำจะถูกให้น้ำหนักเท่ากัน โดยไม่คำนึงถึงตัวคำเอง อย่างไรก็ตาม เป็นที่ชัดเจนว่าคำที่ปรากฏบ่อย เช่น *a*, *in* เป็นต้น มีความสำคัญน้อยกว่าคำเฉพาะทางสำหรับการจัดประเภท ในความเป็นจริง ในงานประมวลผลภาษาธรรมชาติ (NLP) ส่วนใหญ่ บางคำมีความเกี่ยวข้องมากกว่าคำอื่นๆ\n",
"\n",
"**TF-IDF** ย่อมาจาก **term frequencyinverse document frequency** ซึ่งเป็นการปรับปรุงจากวิธี Bag of Words โดยแทนที่จะใช้ค่า 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 กล่าวไว้ในปี 1935 ว่า “ความหมายที่สมบูรณ์ของคำจะขึ้นอยู่กับบริบทเสมอ และการศึกษาความหมายที่แยกออกจากบริบทนั้นไม่สามารถถือว่าเป็นเรื่องจริงจังได้” ในบทเรียนต่อไป เราจะได้เรียนรู้วิธีการดึงข้อมูลเชิงบริบทจากข้อความโดยใช้การสร้างแบบจำลองภาษา\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**ข้อจำกัดความรับผิดชอบ**: \nเอกสารนี้ได้รับการแปลโดยใช้บริการแปลภาษาอัตโนมัติ [Co-op Translator](https://github.com/Azure/co-op-translator) แม้ว่าเราจะพยายามให้การแปลมีความถูกต้อง แต่โปรดทราบว่าการแปลอัตโนมัติอาจมีข้อผิดพลาดหรือความไม่แม่นยำ เอกสารต้นฉบับในภาษาต้นทางควรถือเป็นแหล่งข้อมูลที่เชื่อถือได้ สำหรับข้อมูลที่สำคัญ ขอแนะนำให้ใช้บริการแปลภาษาจากผู้เชี่ยวชาญ เราไม่รับผิดชอบต่อความเข้าใจผิดหรือการตีความที่ผิดพลาดซึ่งเกิดจากการใช้การแปลนี้\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-29T11:01:27+00:00",
"source_file": "lessons/5-NLP/13-TextRep/TextRepresentationPyTorch.ipynb",
"language_code": "th"
}
},
"nbformat": 4,
"nbformat_minor": 2
}