AI-For-Beginners/translations/lt/lessons/5-NLP/13-TextRep/TextRepresentationTF.ipynb

647 lines
26 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": [
"# Teksto klasifikavimo užduotis\n",
"\n",
"Šiame modulyje pradėsime nuo paprastos teksto klasifikavimo užduoties, remdamiesi **[AG_NEWS](http://www.di.unipi.it/~gulli/AG_corpus_of_news_articles.html)** duomenų rinkiniu: klasifikuosime naujienų antraštes į vieną iš 4 kategorijų: Pasaulis, Sportas, Verslas ir Mokslas/Technologijos.\n",
"\n",
"## Duomenų rinkinys\n",
"\n",
"Norėdami įkelti duomenų rinkinį, naudosime **[TensorFlow Datasets](https://www.tensorflow.org/datasets)** API.\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import tensorflow as tf\n",
"from tensorflow import keras\n",
"import tensorflow_datasets as tfds\n",
"\n",
"# In this tutorial, we will be training a lot of models. In order to use GPU memory cautiously,\n",
"# we will set tensorflow option to grow GPU memory allocation when required.\n",
"physical_devices = tf.config.list_physical_devices('GPU') \n",
"if len(physical_devices)>0:\n",
" tf.config.experimental.set_memory_growth(physical_devices[0], True)\n",
"\n",
"dataset = tfds.load('ag_news_subset')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Dabar galime pasiekti mokymo ir testavimo duomenų rinkinio dalis naudodami `dataset['train']` ir `dataset['test']` atitinkamai:\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Length of train dataset = 120000\n",
"Length of test dataset = 7600\n"
]
}
],
"source": [
"ds_train = dataset['train']\n",
"ds_test = dataset['test']\n",
"\n",
"print(f\"Length of train dataset = {len(ds_train)}\")\n",
"print(f\"Length of test dataset = {len(ds_test)}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Išspausdinkime pirmąsias 10 naujų antraščių iš mūsų duomenų rinkinio:\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3 (Sci/Tech) -> b'AMD Debuts Dual-Core Opteron Processor' b'AMD #39;s new dual-core Opteron chip is designed mainly for corporate computing applications, including databases, Web services, and financial transactions.'\n",
"1 (Sports) -> b\"Wood's Suspension Upheld (Reuters)\" b'Reuters - Major League Baseball\\\\Monday announced a decision on the appeal filed by Chicago Cubs\\\\pitcher Kerry Wood regarding a suspension stemming from an\\\\incident earlier this season.'\n",
"2 (Business) -> b'Bush reform may have blue states seeing red' b'President Bush #39;s quot;revenue-neutral quot; tax reform needs losers to balance its winners, and people claiming the federal deduction for state and local taxes may be in administration planners #39; sights, news reports say.'\n",
"3 (Sci/Tech) -> b\"'Halt science decline in schools'\" b'Britain will run out of leading scientists unless science education is improved, says Professor Colin Pillinger.'\n",
"1 (Sports) -> b'Gerrard leaves practice' b'London, England (Sports Network) - England midfielder Steven Gerrard injured his groin late in Thursday #39;s training session, but is hopeful he will be ready for Saturday #39;s World Cup qualifier against Austria.'\n"
]
}
],
"source": [
"classes = ['World', 'Sports', 'Business', 'Sci/Tech']\n",
"\n",
"for i,x in zip(range(5),ds_train):\n",
" print(f\"{x['label']} ({classes[x['label']]}) -> {x['title']} {x['description']}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Teksto vektorizacija\n",
"\n",
"Dabar turime konvertuoti tekstą į **skaičius**, kurie gali būti pateikti kaip tensoriai. Jei norime žodžių lygmens reprezentacijos, turime atlikti du dalykus:\n",
"\n",
"* Naudoti **tokenizatorių**, kad tekstas būtų padalintas į **tokenus**.\n",
"* Sukurti tų tokenų **žodyną**.\n",
"\n",
"### Žodyno dydžio ribojimas\n",
"\n",
"AG News duomenų rinkinio pavyzdyje žodyno dydis yra gana didelis daugiau nei 100 tūkst. žodžių. Apskritai, mums nereikia žodžių, kurie tekste pasitaiko retai — tik keliose sakiniuose jie bus, o modelis iš jų nesimokys. Todėl logiška apriboti žodyno dydį iki mažesnio skaičiaus, perduodant argumentą vektorizatoriaus konstruktoriui:\n",
"\n",
"Abu šiuos veiksmus galima atlikti naudojant **TextVectorization** sluoksnį. Sukurkime vektorizatoriaus objektą ir tada iškvieskime `adapt` metodą, kad pereitume per visą tekstą ir sukurtume žodyną:\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"vocab_size = 50000\n",
"vectorizer = keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size)\n",
"vectorizer.adapt(ds_train.take(500).map(lambda x: x['title']+' '+x['description']))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> **Pastaba**: mes naudojame tik dalį viso duomenų rinkinio, kad sukurtume žodyną. Tai darome tam, kad pagreitintume vykdymo laiką ir nereikėtų jūsų laukti. Tačiau prisiimame riziką, kad kai kurie žodžiai iš viso duomenų rinkinio nebus įtraukti į žodyną ir bus ignoruojami mokymo metu. Taigi, naudojant visą žodyno dydį ir apdorojant visą duomenų rinkinį per `adapt`, galutinis tikslumas turėtų padidėti, bet ne žymiai.\n",
"\n",
"Dabar galime pasiekti tikrąjį žodyną:\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['', '[UNK]', 'the', 'to', 'a', 'in', 'of', 'and', 'on', 'for']\n",
"Length of vocabulary: 5335\n"
]
}
],
"source": [
"vocab = vectorizer.get_vocabulary()\n",
"vocab_size = len(vocab)\n",
"print(vocab[:10])\n",
"print(f\"Length of vocabulary: {vocab_size}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Naudodami vektorizatorių, galime lengvai užkoduoti bet kokį tekstą į skaičių rinkinį:\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<tf.Tensor: shape=(7,), dtype=int64, numpy=array([ 112, 3695, 3, 304, 11, 1041, 1], dtype=int64)>"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"vectorizer('I love to play with my words')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Žodžių maišo (Bag-of-words) teksto reprezentacija\n",
"\n",
"Kadangi žodžiai perteikia prasmę, kartais galime suprasti teksto reikšmę tiesiog pažvelgę į atskirus žodžius, nepaisant jų tvarkos sakinyje. Pavyzdžiui, klasifikuojant naujienas, tokie žodžiai kaip *oras* ir *sniegas* greičiausiai nurodys į *orų prognozę*, o žodžiai kaip *akcijos* ir *doleris* bus susiję su *finansinėmis naujienomis*.\n",
"\n",
"**Žodžių maišo** (BoW) vektorinė reprezentacija yra pati paprasčiausia ir lengviausiai suprantama tradicinė vektorinė reprezentacija. Kiekvienas žodis yra susietas su vektoriaus indeksu, o vektoriaus elementas nurodo, kiek kartų tam tikras žodis pasirodo konkrečiame dokumente.\n",
"\n",
"![Paveikslėlis, rodantis, kaip žodžių maišo vektorinė reprezentacija saugoma atmintyje.](../../../../../lessons/5-NLP/13-TextRep/images/bag-of-words-example.png) \n",
"\n",
"> **Note**: Taip pat galite galvoti apie BoW kaip apie visų vieno žodžio vienetinės koduotės (one-hot-encoded) vektorių sumą tekste.\n",
"\n",
"Žemiau pateiktas pavyzdys, kaip sugeneruoti žodžių maišo reprezentaciją naudojant Scikit Learn python biblioteką:\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[1, 1, 0, 2, 0, 0, 0, 0, 0]], dtype=int64)"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from sklearn.feature_extraction.text import CountVectorizer\n",
"sc_vectorizer = CountVectorizer()\n",
"corpus = [\n",
" 'I like hot dogs.',\n",
" 'The dog ran fast.',\n",
" 'Its hot outside.',\n",
" ]\n",
"sc_vectorizer.fit_transform(corpus)\n",
"sc_vectorizer.transform(['My dog likes hot dogs on a hot day.']).toarray()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Mes taip pat galime naudoti aukščiau apibrėžtą Keras vektorizatorių, konvertuodami kiekvieną žodžio numerį į vieno karšto kodavimo formatą ir sudėdami visus tuos vektorius:\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([0., 5., 0., ..., 0., 0., 0.], dtype=float32)"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def to_bow(text):\n",
" return tf.reduce_sum(tf.one_hot(vectorizer(text),vocab_size),axis=0)\n",
"\n",
"to_bow('My dog likes hot dogs on a hot day.').numpy()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> **Pastaba**: Gali nustebinti, kad rezultatas skiriasi nuo ankstesnio pavyzdžio. Taip yra todėl, kad Keras pavyzdyje vektoriaus ilgis atitinka žodyno dydį, kuris buvo sukurtas naudojant visą AG News duomenų rinkinį, o Scikit Learn pavyzdyje žodyną sukūrėme iš pateikto teksto vietoje.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Mokymas BoW klasifikatoriaus\n",
"\n",
"Dabar, kai išmokome sukurti žodžių maišo (bag-of-words) reprezentaciją mūsų tekstui, pereikime prie klasifikatoriaus mokymo, kuris ja naudojasi. Pirmiausia, turime konvertuoti savo duomenų rinkinį į žodžių maišo reprezentaciją. Tai galima padaryti naudojant `map` funkciją tokiu būdu:\n"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"batch_size = 128\n",
"\n",
"ds_train_bow = ds_train.map(lambda x: (to_bow(x['title']+x['description']),x['label'])).batch(batch_size)\n",
"ds_test_bow = ds_test.map(lambda x: (to_bow(x['title']+x['description']),x['label'])).batch(batch_size)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Dabar apibrėžkime paprastą klasifikatoriaus neuroninį tinklą, kuris turi vieną linijinį sluoksnį. Įvesties dydis yra `vocab_size`, o išvesties dydis atitinka klasių skaičių (4). Kadangi sprendžiame klasifikavimo užduotį, galutinė aktyvacijos funkcija yra **softmax**:\n"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"938/938 [==============================] - 66s 70ms/step - loss: 0.6144 - acc: 0.8427 - val_loss: 0.4416 - val_acc: 0.8697\n"
]
},
{
"data": {
"text/plain": [
"<keras.callbacks.History at 0x20c70a947f0>"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model = keras.models.Sequential([\n",
" keras.layers.Dense(4,activation='softmax',input_shape=(vocab_size,))\n",
"])\n",
"model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])\n",
"model.fit(ds_train_bow,validation_data=ds_test_bow)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Kadangi turime 4 klases, tikslumas virš 80% yra geras rezultatas.\n",
"\n",
"## Klasifikatoriaus mokymas kaip vieno tinklo\n",
"\n",
"Kadangi vektorizatorius taip pat yra Keras sluoksnis, galime apibrėžti tinklą, kuris jį įtraukia, ir mokyti jį nuo pradžios iki pabaigos. Tokiu būdu nereikia vektorizuoti duomenų rinkinio naudojant `map`, tiesiog galime perduoti originalų duomenų rinkinį į tinklo įvestį.\n",
"\n",
"> **Pastaba**: Vis tiek reikės taikyti `map` mūsų duomenų rinkiniui, kad laukus iš žodynų (pvz., `title`, `description` ir `label`) paverstume į poras. Tačiau, kai duomenys įkeliami iš disko, galime iš karto sukurti duomenų rinkinį su reikiama struktūra.\n"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"model\"\n",
"_________________________________________________________________\n",
" Layer (type) Output Shape Param # \n",
"=================================================================\n",
" input_1 (InputLayer) [(None, 1)] 0 \n",
" \n",
" text_vectorization (TextVec (None, None) 0 \n",
" torization) \n",
" \n",
" tf.one_hot (TFOpLambda) (None, None, 5335) 0 \n",
" \n",
" tf.math.reduce_sum (TFOpLam (None, 5335) 0 \n",
" bda) \n",
" \n",
" dense_2 (Dense) (None, 4) 21344 \n",
" \n",
"=================================================================\n",
"Total params: 21,344\n",
"Trainable params: 21,344\n",
"Non-trainable params: 0\n",
"_________________________________________________________________\n",
"938/938 [==============================] - 73s 77ms/step - loss: 0.6057 - acc: 0.8414 - val_loss: 0.4202 - val_acc: 0.8736\n"
]
},
{
"data": {
"text/plain": [
"<keras.callbacks.History at 0x20c721521f0>"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def extract_text(x):\n",
" return x['title']+' '+x['description']\n",
"\n",
"def tupelize(x):\n",
" return (extract_text(x),x['label'])\n",
"\n",
"inp = keras.Input(shape=(1,),dtype=tf.string)\n",
"x = vectorizer(inp)\n",
"x = tf.reduce_sum(tf.one_hot(x,vocab_size),axis=1)\n",
"out = keras.layers.Dense(4,activation='softmax')(x)\n",
"model = keras.models.Model(inp,out)\n",
"model.summary()\n",
"\n",
"model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])\n",
"model.fit(ds_train.map(tupelize).batch(batch_size),validation_data=ds_test.map(tupelize).batch(batch_size))\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Bigramai, trigramai ir n-gramai\n",
"\n",
"Viena iš maišo žodžių metodo apribojimų yra ta, kad kai kurie žodžiai sudaro daugiakalbius posakius. Pavyzdžiui, žodis „hot dog“ turi visiškai kitokią reikšmę nei žodžiai „hot“ ir „dog“ kitame kontekste. Jei žodžius „hot“ ir „dog“ visada atvaizduosime tais pačiais vektoriais, tai gali suklaidinti mūsų modelį.\n",
"\n",
"Norint tai išspręsti, dokumentų klasifikavimo metodai dažnai naudoja **n-gramų reprezentacijas**, kur kiekvieno žodžio, dviejų žodžių ar trijų žodžių dažnis yra naudinga savybė mokant klasifikatorius. Pavyzdžiui, bigramų reprezentacijoje į žodyną pridedame visas žodžių poras, be originalių žodžių.\n",
"\n",
"Žemiau pateiktas pavyzdys, kaip sukurti bigramų maišo žodžių reprezentaciją naudojant Scikit Learn:\n"
]
},
{
"cell_type": "code",
"execution_count": 14,
"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": 14,
"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": [
"Pagrindinis n-gramų metodo trūkumas yra tas, kad žodyno dydis pradeda augti itin greitai. Praktikoje mums reikia derinti n-gramų reprezentaciją su dimensijų mažinimo technika, tokia kaip *embedding'ai*, apie kuriuos kalbėsime kitame skyriuje.\n",
"\n",
"Norėdami naudoti n-gramų reprezentaciją mūsų **AG News** duomenų rinkinyje, turime perduoti `ngrams` parametrą mūsų `TextVectorization` konstruktoriui. Bigramų žodyno ilgis yra **žymiai didesnis**, mūsų atveju jis viršija 1,3 milijono žodžių! Todėl yra prasminga apriboti bigramų žodžius iki tam tikro pagrįsto skaičiaus.\n",
"\n",
"Galėtume naudoti tą patį kodą, kaip ir aukščiau, norėdami apmokyti klasifikatorių, tačiau tai būtų labai neefektyvu atminties atžvilgiu. Kitame skyriuje apmokysime bigramų klasifikatorių naudodami embedding'us. Tuo tarpu galite eksperimentuoti su bigramų klasifikatoriaus mokymu šiame užrašų knygelėje ir pažiūrėti, ar galite pasiekti didesnį tikslumą.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Automatinis BoW vektorių skaičiavimas\n",
"\n",
"Ankstesniame pavyzdyje BoW vektorius skaičiavome rankiniu būdu, sudėdami atskirų žodžių vieno karšto kodavimo rezultatus. Tačiau naujausia TensorFlow versija leidžia automatiškai apskaičiuoti BoW vektorius, perduodant `output_mode='count` parametrą vektorizatoriaus konstruktoriui. Tai žymiai supaprastina mūsų modelio apibrėžimą ir treniravimą:\n"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Training vectorizer\n",
"938/938 [==============================] - 7s 7ms/step - loss: 0.5929 - acc: 0.8486 - val_loss: 0.4168 - val_acc: 0.8772\n"
]
},
{
"data": {
"text/plain": [
"<keras.callbacks.History at 0x20c725217c0>"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model = keras.models.Sequential([\n",
" keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size,output_mode='count'),\n",
" keras.layers.Dense(4,input_shape=(vocab_size,), activation='softmax')\n",
"])\n",
"print(\"Training vectorizer\")\n",
"model.layers[0].adapt(ds_train.take(500).map(extract_text))\n",
"model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])\n",
"model.fit(ds_train.map(tupelize).batch(batch_size),validation_data=ds_test.map(tupelize).batch(batch_size))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Termino dažnis - atvirkštinis dokumento dažnis (TF-IDF)\n",
"\n",
"BoW reprezentacijoje žodžių pasikartojimai yra vertinami naudojant tą pačią techniką, nepriklausomai nuo paties žodžio. Tačiau akivaizdu, kad dažni žodžiai, tokie kaip *a* ir *in*, yra daug mažiau svarbūs klasifikacijai nei specializuoti terminai. Daugumoje NLP užduočių kai kurie žodžiai yra reikšmingesni nei kiti.\n",
"\n",
"**TF-IDF** reiškia **termino dažnis - atvirkštinis dokumento dažnis**. Tai yra maišo su žodžiais (BoW) variacija, kur vietoj dvejetainės 0/1 reikšmės, nurodančios žodžio buvimą dokumente, naudojama slankiojo kablelio reikšmė, susijusi su žodžio pasikartojimo dažniu korpuse.\n",
"\n",
"Formaliau, žodžio $i$ svoris $w_{ij}$ dokumente $j$ apibrėžiamas taip:\n",
"$$\n",
"w_{ij} = tf_{ij}\\times\\log({N\\over df_i})\n",
"$$\n",
"kur\n",
"* $tf_{ij}$ yra žodžio $i$ pasikartojimų skaičius dokumente $j$, t. y. BoW reikšmė, kurią jau matėme\n",
"* $N$ yra dokumentų skaičius kolekcijoje\n",
"* $df_i$ yra dokumentų, kuriuose yra žodis $i$, skaičius visoje kolekcijoje\n",
"\n",
"TF-IDF reikšmė $w_{ij}$ didėja proporcingai žodžio pasikartojimų skaičiui dokumente ir yra koreguojama pagal dokumentų skaičių korpuse, kuriuose yra tas žodis. Tai padeda atsižvelgti į tai, kad kai kurie žodžiai pasikartoja dažniau nei kiti. Pavyzdžiui, jei žodis pasirodo *kiekviename* kolekcijos dokumente, $df_i=N$, ir $w_{ij}=0$, tokie terminai būtų visiškai ignoruojami.\n",
"\n",
"TF-IDF tekstų vektorizaciją galite lengvai sukurti naudodami Scikit Learn:\n"
]
},
{
"cell_type": "code",
"execution_count": 16,
"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": 16,
"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": [
"Keras bibliotekoje `TextVectorization` sluoksnis gali automatiškai apskaičiuoti TF-IDF dažnius, perduodant parametrą `output_mode='tf-idf'`. Pakartokime aukščiau naudotą kodą, kad pamatytume, ar TF-IDF naudojimas padidina tikslumą:\n"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Training vectorizer\n",
"938/938 [==============================] - 12s 12ms/step - loss: 0.4197 - acc: 0.8662 - val_loss: 0.3432 - val_acc: 0.8849\n"
]
},
{
"data": {
"text/plain": [
"<keras.callbacks.History at 0x20c729dfd30>"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model = keras.models.Sequential([\n",
" keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size,output_mode='tf-idf'),\n",
" keras.layers.Dense(4,input_shape=(vocab_size,), activation='softmax')\n",
"])\n",
"print(\"Training vectorizer\")\n",
"model.layers[0].adapt(ds_train.take(500).map(extract_text))\n",
"model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])\n",
"model.fit(ds_train.map(tupelize).batch(batch_size),validation_data=ds_test.map(tupelize).batch(batch_size))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Išvada\n",
"\n",
"Nors TF-IDF reprezentacijos suteikia skirtingiems žodžiams dažnio svorius, jos nesugeba perteikti prasmės ar tvarkos. Kaip garsus lingvistas J. R. Firth pasakė 1935 m., „Visapusiška žodžio prasmė visada yra kontekstinė, ir joks prasmės tyrimas, atskirtas nuo konteksto, negali būti laikomas rimtu.“ Vėliau kurse išmoksime, kaip iš teksto išgauti kontekstinę informaciją naudojant kalbos modeliavimą.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Atsakomybės apribojimas**: \nŠis dokumentas buvo išverstas naudojant dirbtinio intelekto vertimo paslaugą [Co-op Translator](https://github.com/Azure/co-op-translator). Nors siekiame tikslumo, atkreipkite dėmesį, kad automatiniai vertimai gali turėti klaidų ar netikslumų. Originalus dokumentas jo gimtąja kalba turėtų būti laikomas autoritetingu šaltiniu. Kritinei informacijai rekomenduojama naudoti profesionalų žmogaus vertimą. Mes neprisiimame atsakomybės už nesusipratimus ar klaidingus aiškinimus, kylančius dėl šio vertimo naudojimo.\n"
]
}
],
"metadata": {
"interpreter": {
"hash": "0cb620c6d4b9f7a635928804c26cf22403d89d98d79684e4529119355ee6d5a5"
},
"kernel_info": {
"name": "conda-env-py37_tensorflow-py"
},
"kernelspec": {
"display_name": "py37_tensorflow",
"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"
},
"nteract": {
"version": "nteract-front-end@1.0.0"
},
"coopTranslator": {
"original_hash": "19b43951d55b377a76209c24c1f017e4",
"translation_date": "2025-08-31T14:12:42+00:00",
"source_file": "lessons/5-NLP/13-TextRep/TextRepresentationTF.ipynb",
"language_code": "lt"
}
},
"nbformat": 4,
"nbformat_minor": 4
}