577 lines
26 KiB
Plaintext
577 lines
26 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"# وظیفه طبقهبندی متن\n",
|
||
"\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": [
|
||
"چون مجموعه دادهها تکرارگر هستند، اگر بخواهیم دادهها را چندین بار استفاده کنیم باید آن را به لیست تبدیل کنیم:\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",
|
||
"* استفاده از **توکنایزر** برای تقسیم متن به **توکنها**\n",
|
||
"* ساخت یک **واژگان** از این توکنها.\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",
|
||
"از آنجا که کلمات معنا را منتقل میکنند، گاهی میتوانیم با نگاه کردن به کلمات جداگانه، بدون توجه به ترتیب آنها در جمله، معنای یک متن را درک کنیم. برای مثال، هنگام دستهبندی اخبار، کلماتی مانند *هواشناسی*، *برف* احتمالاً به *پیشبینی هوا* اشاره دارند، در حالی که کلماتی مانند *سهام*، *دلار* به احتمال زیاد به *اخبار مالی* مربوط میشوند.\n",
|
||
"\n",
|
||
"نمایش برداری **Bag of Words** (BoW) یکی از رایجترین روشهای سنتی نمایش برداری است. در این روش، هر کلمه به یک شاخص بردار مرتبط میشود و عنصر بردار تعداد دفعات وقوع یک کلمه در یک سند مشخص را نشان میدهد.\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"> **Note**: میتوانید به BoW به عنوان مجموع تمام بردارهای یکداغ (one-hot-encoded) برای کلمات جداگانه در متن نیز فکر کنید.\n",
|
||
"\n",
|
||
"در زیر مثالی از نحوه تولید نمایش Bag of Words با استفاده از کتابخانه 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": [
|
||
"برای محاسبه بردار کیسه کلمات از نمایش برداری مجموعه داده 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) را برای متن خود بسازیم، بیایید یک طبقهبند را بر اساس آن آموزش دهیم. ابتدا باید دادههای خود را برای آموزش به گونهای تبدیل کنیم که تمام نمایشهای برداری موقعیتی به نمایه کیسه کلمات تبدیل شوند. این کار با استفاده از تابع `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` است و اندازه خروجی مربوط به تعداد کلاسها (۴) میباشد. چون ما در حال حل یک وظیفه طبقهبندی هستیم، تابع فعالسازی نهایی `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": [
|
||
"## بیگرامها، تریگرامها و اِنگرامها\n",
|
||
"\n",
|
||
"یکی از محدودیتهای روش کیسه کلمات این است که برخی کلمات بخشی از عبارات چندکلمهای هستند. برای مثال، کلمه «هاتداگ» معنای کاملاً متفاوتی نسبت به کلمات «هات» و «داگ» در سایر زمینهها دارد. اگر همیشه کلمات «هات» و «داگ» را با همان بردارها نمایش دهیم، ممکن است مدل ما را دچار سردرگمی کند.\n",
|
||
"\n",
|
||
"برای رفع این مشکل، از **نمایش اِنگرامها** در روشهای طبقهبندی اسناد استفاده میشود. در این روش، فراوانی هر کلمه، دوکلمهای یا سهکلمهای بهعنوان ویژگی مفیدی برای آموزش طبقهبندها در نظر گرفته میشود. برای مثال، در نمایش بیگرام، علاوه بر کلمات اصلی، تمام جفت کلمات نیز به واژگان اضافه میشوند.\n",
|
||
"\n",
|
||
"در زیر مثالی از نحوه تولید نمایش کیسه کلمات بیگرام با استفاده از 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 را با برخی تکنیکهای کاهش ابعاد، مانند *embeddingها*، ترکیب کنیم که در واحد بعدی درباره آنها صحبت خواهیم کرد.\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": [
|
||
"ما میتوانیم از همان کدی که در بالا استفاده کردیم برای آموزش دستهبند استفاده کنیم، اما این روش از نظر حافظه بسیار ناکارآمد خواهد بود. در واحد بعدی، دستهبند بیگرام را با استفاده از تعبیهها آموزش خواهیم داد.\n",
|
||
"\n",
|
||
"> **توجه:** شما فقط میتوانید آن انگرامهایی را نگه دارید که بیش از تعداد مشخصی در متن ظاهر میشوند. این کار باعث میشود بیگرامهای کمتکرار حذف شوند و به طور قابل توجهی ابعاد کاهش یابد. برای انجام این کار، پارامتر `min_freq` را به مقدار بالاتری تنظیم کنید و تغییر طول واژگان را مشاهده کنید.\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## فراوانی اصطلاح و فراوانی معکوس سند (TF-IDF)\n",
|
||
"\n",
|
||
"در نمایش BoW، وقوع کلمات به طور مساوی وزندهی میشود، بدون توجه به خود کلمه. با این حال، واضح است که کلمات پرتکرار مانند *a*، *in* و غیره برای دستهبندی اهمیت کمتری نسبت به اصطلاحات تخصصی دارند. در واقع، در بیشتر وظایف پردازش زبان طبیعی (NLP)، برخی کلمات نسبت به دیگران مرتبطتر هستند.\n",
|
||
"\n",
|
||
"**TF-IDF** مخفف **فراوانی اصطلاح–فراوانی معکوس سند** است. این یک تغییر در روش کیسه کلمات (BoW) است که به جای مقدار دودویی 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 وزن فرکانسی به کلمات مختلف اختصاص میدهند، اما قادر به نمایش معنا یا ترتیب نیستند. همانطور که زبانشناس مشهور جی. آر. فرث در سال ۱۹۳۵ گفت: «معنای کامل یک کلمه همیشه وابسته به متن است و هیچ مطالعهای درباره معنا بدون در نظر گرفتن متن نمیتواند جدی گرفته شود.» در ادامه دوره یاد خواهیم گرفت که چگونه اطلاعات متنی را با استفاده از مدلسازی زبان استخراج کنیم.\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-31T17:17:45+00:00",
|
||
"source_file": "lessons/5-NLP/13-TextRep/TextRepresentationPyTorch.ipynb",
|
||
"language_code": "fa"
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 2
|
||
} |