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

577 lines
22 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": [
"# Gawain sa Pag-uuri ng Teksto\n",
"\n",
"Tulad ng nabanggit, magtutuon tayo sa isang simpleng gawain sa pag-uuri ng teksto gamit ang **AG_NEWS** dataset, kung saan kailangang uriin ang mga headline ng balita sa isa sa 4 na kategorya: World, Sports, Business, at Sci/Tech.\n",
"\n",
"## Ang Dataset\n",
"\n",
"Ang dataset na ito ay naka-built-in sa [`torchtext`](https://github.com/pytorch/text) module, kaya madali natin itong ma-access.\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": [
"Narito, ang `train_dataset` at `test_dataset` ay naglalaman ng mga koleksyon na nagbabalik ng mga pares ng label (numero ng klase) at teksto, halimbawa:\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": [
"Kaya, i-print natin ang unang 10 bagong headline mula sa ating dataset:\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": [
"Dahil ang mga dataset ay mga iterator, kung nais nating gamitin ang data nang maraming beses kailangan natin itong i-convert sa listahan:\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": [
"## Tokenisasyon\n",
"\n",
"Ngayon, kailangan nating i-convert ang teksto sa **mga numero** na maaaring i-representa bilang mga tensor. Kung nais natin ng word-level na representasyon, kailangan nating gawin ang dalawang bagay:\n",
"* gumamit ng **tokenizer** upang hatiin ang teksto sa **mga token**\n",
"* bumuo ng isang **bokabularyo** ng mga token na iyon.\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": [
"Gamit ang bokabularyo, madali nating ma-encode ang ating tokenized na string sa isang set ng mga numero:\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 na representasyon ng teksto\n",
"\n",
"Dahil ang mga salita ay may kahulugan, minsan ay maaari nating maunawaan ang kahulugan ng isang teksto sa pamamagitan lamang ng pagtingin sa mga indibidwal na salita, kahit na hindi natin isaalang-alang ang pagkakasunod-sunod ng mga ito sa pangungusap. Halimbawa, kapag nag-uuri ng balita, ang mga salitang tulad ng *weather*, *snow* ay malamang na tumutukoy sa *weather forecast*, habang ang mga salitang tulad ng *stocks*, *dollar* ay maaaring magpahiwatig ng *financial news*.\n",
"\n",
"Ang **Bag of Words** (BoW) na representasyon ng vector ay ang pinakakaraniwang ginagamit na tradisyunal na representasyon ng vector. Ang bawat salita ay naka-link sa isang index ng vector, at ang elemento ng vector ay naglalaman ng bilang ng paglitaw ng isang salita sa isang partikular na dokumento.\n",
"\n",
"![Larawan na nagpapakita kung paano kinakatawan ang bag of words na representasyon ng vector sa memorya.](../../../../../translated_images/bag-of-words-example.606fc1738f1d7ba98a9d693e3bcd706c6e83fa7bf8221e6e90d1a206d82f2ea4.tl.png) \n",
"\n",
"> **Note**: Maaari mo ring isipin ang BoW bilang kabuuan ng lahat ng one-hot-encoded na mga vector para sa bawat indibidwal na salita sa teksto.\n",
"\n",
"Narito ang isang halimbawa kung paano bumuo ng isang bag of words na representasyon gamit ang Scikit Learn python library:\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": [
"Upang makalkula ang bag-of-words na vector mula sa vector na representasyon ng ating AG_NEWS dataset, maaari nating gamitin ang sumusunod na function:\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": [
"> **Tandaan:** Dito, ginagamit natin ang global na variable na `vocab_size` upang tukuyin ang default na laki ng bokabularyo. Dahil kadalasan ang laki ng bokabularyo ay medyo malaki, maaari nating limitahan ang laki ng bokabularyo sa mga pinakakaraniwang salita. Subukang babaan ang halaga ng `vocab_size` at patakbuhin ang code sa ibaba, at tingnan kung paano ito nakakaapekto sa katumpakan. Dapat mong asahan ang kaunting pagbaba sa katumpakan, ngunit hindi masyadong malaki, kapalit ng mas mataas na pagganap.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Pagsasanay ng BoW classifier\n",
"\n",
"Ngayon na natutunan natin kung paano bumuo ng Bag-of-Words na representasyon ng ating teksto, magtuturo tayo ng isang classifier gamit ito. Una, kailangan nating i-convert ang ating dataset para sa pagsasanay sa paraang lahat ng positional vector representations ay ma-convert sa Bag-of-Words na representasyon. Magagawa ito sa pamamagitan ng pagpasa ng `bowify` function bilang `collate_fn` parameter sa standard torch `DataLoader`:\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": [
"Ngayon, mag-define tayo ng isang simpleng classifier neural network na naglalaman ng isang linear layer. Ang laki ng input vector ay katumbas ng `vocab_size`, at ang laki ng output ay tumutugma sa bilang ng mga klase (4). Dahil ang sinusolusyonan natin ay isang classification task, ang huling activation function ay `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": [
"Ngayon ay itatakda natin ang standard na PyTorch training loop. Dahil medyo malaki ang ating dataset, para sa layunin ng pagtuturo, magte-train tayo para sa isang epoch lamang, at minsan ay mas mababa pa sa isang epoch (ang pag-specify ng parameter na `epoch_size` ay nagbibigay-daan sa atin na limitahan ang training). Iuulat din natin ang naipong training accuracy habang nagte-training; ang dalas ng pag-uulat ay tinutukoy gamit ang parameter na `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 at N-Grams\n",
"\n",
"Isang limitasyon ng bag of words na pamamaraan ay ang ilang mga salita ay bahagi ng mga multi-word na ekspresyon. Halimbawa, ang salitang 'hot dog' ay may ganap na ibang kahulugan kaysa sa mga salitang 'hot' at 'dog' sa ibang konteksto. Kung palaging ire-represent natin ang mga salitang 'hot' at 'dog' gamit ang parehong mga vector, maaaring malito ang ating modelo.\n",
"\n",
"Upang matugunan ito, madalas ginagamit ang **N-gram representations** sa mga pamamaraan ng dokumento klasipikasyon, kung saan ang dalas ng bawat salita, bi-word, o tri-word ay isang kapaki-pakinabang na tampok para sa pag-train ng mga classifier. Sa bigram representation, halimbawa, idaragdag natin ang lahat ng pares ng salita sa vocabulary, bukod pa sa mga orihinal na salita.\n",
"\n",
"Narito ang isang halimbawa kung paano gumawa ng bigram bag of word representation gamit ang 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": [
"Ang pangunahing kahinaan ng N-gram na pamamaraan ay ang mabilis na paglaki ng laki ng bokabularyo. Sa praktika, kailangan nating pagsamahin ang N-gram na representasyon sa ilang mga teknik sa pagbabawas ng dimensyon, tulad ng *embeddings*, na tatalakayin natin sa susunod na yunit.\n",
"\n",
"Upang magamit ang N-gram na representasyon sa ating **AG News** dataset, kailangan nating bumuo ng espesyal na ngram na bokabularyo:\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": [
"Maaari nating gamitin ang parehong code tulad ng nasa itaas upang sanayin ang classifier, ngunit magiging napaka-inefficient ito sa memorya. Sa susunod na unit, magsasanay tayo ng bigram classifier gamit ang embeddings.\n",
"\n",
"> **Note:** Maaari mo lamang iwan ang mga ngrams na lumalabas sa teksto nang higit sa tinukoy na bilang ng beses. Sisiguraduhin nito na ang mga bihirang bigrams ay maaalis, at mababawasan nang malaki ang dimensionality. Upang gawin ito, itakda ang parameter na `min_freq` sa mas mataas na halaga, at obserbahan ang pagbabago sa haba ng vocabulary.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Term Frequency Inverse Document Frequency TF-IDF\n",
"\n",
"Sa BoW na representasyon, pantay ang timbang ng bawat paglitaw ng salita, anuman ang mismong salita. Gayunpaman, malinaw na ang mga madalas na salita, tulad ng *a*, *in*, atbp., ay mas hindi mahalaga para sa klasipikasyon kumpara sa mga espesyalisadong termino. Sa katunayan, sa karamihan ng mga gawain sa NLP, may mga salita na mas may kaugnayan kaysa sa iba.\n",
"\n",
"Ang **TF-IDF** ay nangangahulugang **term frequencyinverse document frequency**. Isa itong bersyon ng bag of words, kung saan sa halip na binary na 0/1 na halaga na nagpapakita ng paglitaw ng isang salita sa isang dokumento, isang floating-point na halaga ang ginagamit, na may kaugnayan sa dalas ng paglitaw ng salita sa corpus.\n",
"\n",
"Mas pormal, ang timbang na $w_{ij}$ ng isang salita $i$ sa dokumento $j$ ay tinutukoy bilang:\n",
"$$\n",
"w_{ij} = tf_{ij}\\times\\log({N\\over df_i})\n",
"$$\n",
"kung saan\n",
"* $tf_{ij}$ ay ang bilang ng paglitaw ng $i$ sa $j$, ibig sabihin, ang BoW na halaga na nakita natin dati\n",
"* $N$ ay ang bilang ng mga dokumento sa koleksyon\n",
"* $df_i$ ay ang bilang ng mga dokumento na naglalaman ng salita $i$ sa buong koleksyon\n",
"\n",
"Ang halaga ng TF-IDF na $w_{ij}$ ay tumataas nang proporsyonal sa bilang ng beses na lumitaw ang isang salita sa isang dokumento at nababawasan batay sa bilang ng mga dokumento sa corpus na naglalaman ng salita, na tumutulong upang maiakma ang katotohanan na ang ilang mga salita ay mas madalas lumitaw kaysa sa iba. Halimbawa, kung ang salita ay lumitaw sa *bawat* dokumento sa koleksyon, $df_i=N$, at $w_{ij}=0$, at ang mga terminong iyon ay ganap na hindi papansinin.\n",
"\n",
"Madali kang makakagawa ng TF-IDF vectorization ng teksto gamit ang 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": [
"## Konklusyon\n",
"\n",
"Gayunpaman, kahit na nagbibigay ang mga TF-IDF na representasyon ng timbang sa dalas ng iba't ibang salita, hindi nito kayang ipakita ang kahulugan o pagkakasunod-sunod. Tulad ng sinabi ng kilalang lingguwista na si J. R. Firth noong 1935, “Ang kumpletong kahulugan ng isang salita ay palaging nakabatay sa konteksto, at walang pag-aaral ng kahulugan na hiwalay sa konteksto ang maaaring ituring na seryoso.” Matututuhan natin sa mga susunod na bahagi ng kurso kung paano makuha ang impormasyong nakabatay sa konteksto mula sa teksto gamit ang pagmomodelo ng wika.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Paunawa**: \nAng dokumentong ito ay isinalin gamit ang AI translation service na [Co-op Translator](https://github.com/Azure/co-op-translator). Bagama't sinisikap naming maging tumpak, pakitandaan na ang mga awtomatikong pagsasalin ay maaaring maglaman ng mga pagkakamali o hindi pagkakatugma. Ang orihinal na dokumento sa kanyang katutubong wika ang dapat ituring na opisyal na sanggunian. Para sa mahalagang impormasyon, inirerekomenda ang propesyonal na pagsasalin ng tao. Hindi kami mananagot sa anumang hindi pagkakaunawaan o maling interpretasyon na dulot ng paggamit ng pagsasaling ito.\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-28T04:37:26+00:00",
"source_file": "lessons/5-NLP/13-TextRep/TextRepresentationPyTorch.ipynb",
"language_code": "tl"
}
},
"nbformat": 4,
"nbformat_minor": 2
}