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

647 lines
26 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Naloga razvrščanja besedila\n",
"\n",
"V tem modulu bomo začeli s preprosto nalogo razvrščanja besedila na podlagi nabora podatkov **[AG_NEWS](http://www.di.unipi.it/~gulli/AG_corpus_of_news_articles.html)**: razvrstili bomo naslove novic v eno od 4 kategorij: Svet, Šport, Posel in Znanost/Tehnologija.\n",
"\n",
"## Nabor podatkov\n",
"\n",
"Za nalaganje nabora podatkov bomo uporabili API **[TensorFlow Datasets](https://www.tensorflow.org/datasets)**.\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": [
"Zdaj lahko dostopamo do učnih in testnih delov nabora podatkov z uporabo `dataset['train']` in `dataset['test']` oziroma:\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": [
"Natisnimo prvih 10 novih naslovov iz našega nabora podatkov:\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": [
"## Vektorizacija besedila\n",
"\n",
"Zdaj moramo besedilo pretvoriti v **številke**, ki jih lahko predstavimo kot tenzorje. Če želimo predstavitev na ravni besed, moramo narediti dve stvari:\n",
"\n",
"* Uporabiti **tokenizator**, da razdelimo besedilo na **tokene**.\n",
"* Zgraditi **besedišče** teh tokenov.\n",
"\n",
"### Omejevanje velikosti besedišča\n",
"\n",
"V primeru podatkovnega nabora AG News je velikost besedišča precej velika, več kot 100.000 besed. Na splošno ne potrebujemo besed, ki se redko pojavljajo v besedilu — le nekaj stavkov jih bo vsebovalo, in model se iz njih ne bo učil. Zato je smiselno omejiti velikost besedišča na manjše število z dodajanjem argumenta konstruktorju vektorizatorja:\n",
"\n",
"Oba koraka lahko izvedemo z uporabo sloja **TextVectorization**. Ustvarimo objekt vektorizatorja in nato pokličimo metodo `adapt`, da preletimo vse besedilo in zgradimo besedišče:\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": [
"> **Opomba** uporabljamo le podmnožico celotnega nabora podatkov za gradnjo besedišča. To počnemo, da pospešimo čas izvajanja in vam ni treba čakati. Vendar pa s tem tvegamo, da nekaterih besed iz celotnega nabora podatkov ne bo vključenih v besedišče in bodo med usposabljanjem prezrte. Zato bi uporaba celotne velikosti besedišča in obdelava celotnega nabora podatkov med `adapt` lahko povečala končno natančnost, vendar ne bistveno.\n",
"\n",
"Zdaj lahko dostopamo do dejanskega besedišča:\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": [
"Z uporabo vektorizatorja lahko enostavno kodiramo katero koli besedilo v niz številk:\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": [
"## Predstavitev besedila z metodo vreče besed\n",
"\n",
"Ker besede predstavljajo pomen, lahko včasih ugotovimo pomen določenega besedila že samo z opazovanjem posameznih besed, ne glede na njihov vrstni red v stavku. Na primer, pri razvrščanju novic besede, kot sta *vreme* in *sneg*, verjetno nakazujejo na *vremensko napoved*, medtem ko bi besede, kot sta *delnice* in *dolar*, kazale na *finančne novice*.\n",
"\n",
"**Predstavitev z metodo vreče besed** (BoW) je najpreprostejša za razumevanje med tradicionalnimi vektorskimi predstavitvami. Vsaka beseda je povezana z indeksom vektorja, element vektorja pa vsebuje število pojavitev posamezne besede v določenem dokumentu.\n",
"\n",
"![Slika, ki prikazuje, kako je predstavitev z metodo vreče besed predstavljena v pomnilniku.](../../../../../translated_images/sl/bag-of-words-example.606fc1738f1d7ba9.webp) \n",
"\n",
"> **Opomba**: Na metodo BoW lahko gledate tudi kot na vsoto vseh eno-vroče kodiranih vektorjev za posamezne besede v besedilu.\n",
"\n",
"Spodaj je primer, kako ustvariti predstavitev z metodo vreče besed z uporabo knjižnice Scikit Learn v Pythonu:\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": [
"Prav tako lahko uporabimo Kerasov vektorizator, ki smo ga definirali zgoraj, vsako številko besede pretvorimo v eno-vroče kodiranje in vse te vektorje seštejemo:\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": [
"> **Opomba**: Morda vas bo presenetilo, da se rezultat razlikuje od prejšnjega primera. Razlog za to je, da v primeru s Keras dolžina vektorja ustreza velikosti besedišča, ki je bilo ustvarjeno iz celotnega nabora podatkov AG News, medtem ko smo v primeru s Scikit Learn besedišče ustvarili sproti iz vzorčnega besedila.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Učenje klasifikatorja BoW\n",
"\n",
"Zdaj, ko smo se naučili, kako zgraditi predstavitev besedne vreče za našo besedilo, lahko začnemo z učenjem klasifikatorja, ki jo uporablja. Najprej moramo naš nabor podatkov pretvoriti v predstavitev besedne vreče. To lahko dosežemo z uporabo funkcije `map` na naslednji način:\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": [
"Zdaj definirajmo preprosto nevronsko mrežo za klasifikacijo, ki vsebuje eno linearno plast. Velikost vhodnega sloja je `vocab_size`, velikost izhodnega sloja pa ustreza številu razredov (4). Ker rešujemo nalogo klasifikacije, je končna aktivacijska funkcija **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": [
"Ker imamo 4 razrede, je natančnost nad 80 % dober rezultat.\n",
"\n",
"## Učenje klasifikatorja kot ene mreže\n",
"\n",
"Ker je vektorizator prav tako Kerasov sloj, lahko definiramo mrežo, ki ga vključuje, in jo učimo od začetka do konca. Na ta način nam ni treba vektorizirati nabora podatkov z uporabo `map`, temveč lahko prvotni nabor podatkov preprosto posredujemo vhodu mreže.\n",
"\n",
"> **Opomba**: Še vedno bi morali uporabiti `map` na našem naboru podatkov, da bi polja iz slovarjev (kot so `title`, `description` in `label`) pretvorili v torke. Vendar pa lahko ob nalaganju podatkov z diska že na začetku ustvarimo nabor podatkov z zahtevano strukturo.\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": [
"## Bigrami, trigrami in n-grami\n",
"\n",
"Ena od omejitev pristopa vreče besed je, da so nekatere besede del večbesednih izrazov. Na primer, beseda 'hot dog' ima popolnoma drugačen pomen kot besedi 'hot' in 'dog' v drugih kontekstih. Če besedi 'hot' in 'dog' vedno predstavljamo z istimi vektorji, lahko to zmede naš model.\n",
"\n",
"Da bi to rešili, se pogosto uporabljajo **n-gramske reprezentacije** pri metodah klasifikacije dokumentov, kjer je frekvenca vsake besede, dvobesedne ali tribesedne kombinacije koristna značilnost za učenje klasifikatorjev. Pri bigramskih reprezentacijah, na primer, dodamo vse pare besed v besedišče, poleg originalnih besed.\n",
"\n",
"Spodaj je primer, kako ustvariti bigramsko vrečo besed z uporabo 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": [
"Glavna pomanjkljivost pristopa n-gramov je, da se velikost besedišča začne izjemno hitro povečevati. V praksi moramo združiti predstavitev n-gramov s tehniko zmanjševanja dimenzionalnosti, kot so *vgnezditve* (embeddings), o katerih bomo govorili v naslednji enoti.\n",
"\n",
"Da uporabimo predstavitev n-gramov v našem **AG News** podatkovnem naboru, moramo parameter `ngrams` posredovati konstruktorju `TextVectorization`. Dolžina besedišča bigramov je **znatno večja**, v našem primeru več kot 1,3 milijona tokenov! Zato je smiselno omejiti tudi število bigramov na neko razumno vrednost.\n",
"\n",
"Lahko bi uporabili isto kodo kot zgoraj za treniranje klasifikatorja, vendar bi bila to zelo neučinkovita uporaba pomnilnika. V naslednji enoti bomo trenirali klasifikator bigramov z uporabo vgnezditve. Medtem pa lahko eksperimentirate s treniranjem klasifikatorja bigramov v tej beležnici in preverite, ali lahko dosežete višjo natančnost.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Samodejno izračunavanje BoW vektorjev\n",
"\n",
"V zgornjem primeru smo BoW vektorje izračunali ročno, tako da smo sešteli enovrstne kodiranja posameznih besed. Vendar pa nam najnovejša različica TensorFlow omogoča samodejno izračunavanje BoW vektorjev, če parameter `output_mode='count` posredujemo konstruktorju vektorizatorja. To bistveno poenostavi definiranje in treniranje našega modela:\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": [
"## Frekvenca izraza - obratna frekvenca dokumenta (TF-IDF)\n",
"\n",
"V predstavitvi BoW so pojavitve besed utežene z enako tehniko, ne glede na samo besedo. Vendar je jasno, da so pogoste besede, kot sta *a* in *in*, veliko manj pomembne za klasifikacijo kot specializirani izrazi. Pri večini nalog obdelave naravnega jezika (NLP) so nekatere besede bolj relevantne kot druge.\n",
"\n",
"**TF-IDF** pomeni **frekvenca izraza - obratna frekvenca dokumenta**. Gre za različico metode bag-of-words, kjer namesto binarne vrednosti 0/1, ki označuje pojav besede v dokumentu, uporabimo številsko vrednost s plavajočo vejico, ki je povezana s frekvenco pojavljanja besede v korpusu.\n",
"\n",
"Bolj formalno je utež $w_{ij}$ besede $i$ v dokumentu $j$ definirana kot:\n",
"$$\n",
"w_{ij} = tf_{ij}\\times\\log({N\\over df_i})\n",
"$$\n",
"kjer\n",
"* $tf_{ij}$ predstavlja število pojavitev $i$ v $j$, torej vrednost BoW, ki smo jo videli prej\n",
"* $N$ je število dokumentov v zbirki\n",
"* $df_i$ je število dokumentov, ki vsebujejo besedo $i$ v celotni zbirki\n",
"\n",
"Vrednost TF-IDF $w_{ij}$ se povečuje sorazmerno s številom pojavitev besede v dokumentu in se zmanjša glede na število dokumentov v korpusu, ki vsebujejo to besedo. To pomaga prilagoditi dejstvo, da se nekatere besede pojavljajo pogosteje kot druge. Na primer, če se beseda pojavi v *vsakem* dokumentu v zbirki, potem velja $df_i=N$, in $w_{ij}=0$, kar pomeni, da so ti izrazi popolnoma zanemarjeni.\n",
"\n",
"TF-IDF vektorizacijo besedila lahko preprosto ustvarite s pomočjo 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": [
"V Kerasu lahko plast `TextVectorization` samodejno izračuna TF-IDF frekvence z uporabo parametra `output_mode='tf-idf'`. Ponovimo kodo, ki smo jo uporabili zgoraj, da vidimo, ali uporaba TF-IDF poveča natančnost:\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": [
"## Zaključek\n",
"\n",
"Čeprav TF-IDF predstavitve dodeljujejo uteži pogostosti različnim besedam, ne morejo predstaviti pomena ali vrstnega reda. Kot je slavni jezikoslovec J. R. Firth leta 1935 dejal: \"Popoln pomen besede je vedno kontekstualen, in nobena študija pomena brez konteksta ne more biti resna.\" Kasneje v tečaju se bomo naučili, kako zajeti kontekstualne informacije iz besedila z uporabo jezikovnega modeliranja.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Omejitev odgovornosti**: \nTa dokument je bil preveden z uporabo storitve za strojno prevajanje [Co-op Translator](https://github.com/Azure/co-op-translator). Čeprav si prizadevamo za natančnost, vas prosimo, da se zavedate, da lahko avtomatizirani prevodi vsebujejo napake ali netočnosti. Izvirni dokument v njegovem izvirnem jeziku je treba obravnavati kot avtoritativni vir. Za ključne informacije priporočamo strokovno človeško prevajanje. Ne prevzemamo odgovornosti za morebitna nesporazumevanja ali napačne razlage, ki izhajajo iz uporabe tega prevoda.\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-30T08:19:50+00:00",
"source_file": "lessons/5-NLP/13-TextRep/TextRepresentationTF.ipynb",
"language_code": "sl"
}
},
"nbformat": 4,
"nbformat_minor": 4
}