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

647 lines
27 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Sarcina de clasificare a textului\n",
"\n",
"În acest modul, vom începe cu o sarcină simplă de clasificare a textului bazată pe setul de date **[AG_NEWS](http://www.di.unipi.it/~gulli/AG_corpus_of_news_articles.html)**: vom clasifica titlurile știrilor în una dintre cele 4 categorii: Lume, Sport, Afaceri și Știință/Tehnologie.\n",
"\n",
"## Setul de date\n",
"\n",
"Pentru a încărca setul de date, vom folosi API-ul **[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": [
"Putem acum să accesăm părțile de antrenament și testare ale setului de date folosind `dataset['train']` și `dataset['test']` respectiv:\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": [
"Să imprimăm primele 10 titluri noi din setul nostru de date:\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": [
"## Vectorizarea textului\n",
"\n",
"Acum trebuie să convertim textul în **numere** care pot fi reprezentate ca tensori. Dacă dorim o reprezentare la nivel de cuvinte, trebuie să facem două lucruri:\n",
"\n",
"* Folosim un **tokenizator** pentru a împărți textul în **tokeni**.\n",
"* Construim un **vocabular** din acei tokeni.\n",
"\n",
"### Limitarea dimensiunii vocabularului\n",
"\n",
"În exemplul dataset-ului AG News, dimensiunea vocabularului este destul de mare, mai mult de 100k cuvinte. În general, nu avem nevoie de cuvinte care apar rar în text — doar câteva propoziții le vor conține, iar modelul nu va învăța din ele. Astfel, are sens să limităm dimensiunea vocabularului la un număr mai mic, prin transmiterea unui argument constructorului vectorizatorului:\n",
"\n",
"Ambele etape pot fi gestionate folosind stratul **TextVectorization**. Să instanțiem obiectul vectorizator și apoi să apelăm metoda `adapt` pentru a parcurge tot textul și a construi un vocabular:\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": [
"> **Notă** că folosim doar un subset al întregului set de date pentru a construi un vocabular. Facem acest lucru pentru a accelera timpul de execuție și pentru a nu te ține în așteptare. Totuși, ne asumăm riscul ca unele dintre cuvintele din întregul set de date să nu fie incluse în vocabular și să fie ignorate în timpul antrenării. Astfel, utilizarea dimensiunii întregului vocabular și parcurgerea întregului set de date în timpul `adapt` ar trebui să crească acuratețea finală, dar nu semnificativ.\n",
"\n",
"Acum putem accesa vocabularul actual:\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": [
"Folosind vectorizatorul, putem codifica cu ușurință orice text într-un set de numere:\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": [
"## Reprezentarea textului prin metoda Bag-of-words\n",
"\n",
"Deoarece cuvintele transmit semnificație, uneori putem înțelege sensul unui text doar analizând cuvintele individuale, indiferent de ordinea lor în propoziție. De exemplu, atunci când clasificăm știri, cuvinte precum *vreme* și *zăpadă* sunt susceptibile să indice *prognoza meteo*, în timp ce cuvinte precum *acțiuni* și *dolar* ar sugera *știri financiare*.\n",
"\n",
"Reprezentarea vectorială **Bag-of-words** (BoW) este cea mai simplă de înțeles dintre reprezentările vectoriale tradiționale. Fiecare cuvânt este asociat unui index vectorial, iar un element al vectorului conține numărul de apariții ale fiecărui cuvânt într-un document dat.\n",
"\n",
"![Imagine care arată cum este reprezentată în memorie o reprezentare vectorială bag-of-words.](../../../../../translated_images/ro/bag-of-words-example.606fc1738f1d7ba9.webp) \n",
"\n",
"> **Note**: Poți considera BoW și ca o sumă a tuturor vectorilor one-hot-encoded pentru cuvintele individuale din text.\n",
"\n",
"Mai jos este un exemplu despre cum să generezi o reprezentare bag-of-words folosind biblioteca python Scikit Learn:\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": [
"Putem folosi, de asemenea, vectorizatorul Keras pe care l-am definit mai sus, transformând fiecare număr de cuvânt într-o codificare one-hot și adunând toți acei vectori:\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": [
"> **Notă**: S-ar putea să fiți surprins că rezultatul diferă de exemplul anterior. Motivul este că, în exemplul Keras, lungimea vectorului corespunde dimensiunii vocabularului, care a fost construit din întregul set de date AG News, în timp ce în exemplul Scikit Learn am construit vocabularul din textul eșantion pe loc.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Antrenarea clasificatorului BoW\n",
"\n",
"Acum că am învățat cum să construim reprezentarea bag-of-words a textului nostru, să antrenăm un clasificator care o folosește. Mai întâi, trebuie să convertim setul nostru de date într-o reprezentare bag-of-words. Acest lucru poate fi realizat folosind funcția `map` în următorul mod:\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": [
"Acum să definim o rețea neuronală clasificatoare simplă care conține un singur strat liniar. Dimensiunea de intrare este `vocab_size`, iar dimensiunea de ieșire corespunde numărului de clase (4). Deoarece rezolvăm o sarcină de clasificare, funcția de activare finală este **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": [
"Deoarece avem 4 clase, o acuratețe de peste 80% este un rezultat bun.\n",
"\n",
"## Antrenarea unui clasificator ca o singură rețea\n",
"\n",
"Pentru că vectorizatorul este, de asemenea, un strat Keras, putem defini o rețea care îl include și o putem antrena cap-coadă. În acest fel, nu mai este nevoie să vectorizăm setul de date folosind `map`, ci putem pur și simplu să trecem setul de date original la intrarea rețelei.\n",
"\n",
"> **Note**: Totuși, va trebui să aplicăm mapări setului de date pentru a converti câmpurile din dicționare (cum ar fi `title`, `description` și `label`) în tupluri. Cu toate acestea, atunci când încărcăm datele de pe disc, putem construi un set de date cu structura necesară de la bun început.\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": [
"## Bigrame, trigrame și n-grame\n",
"\n",
"O limitare a abordării sacului de cuvinte este că unele cuvinte fac parte din expresii formate din mai multe cuvinte; de exemplu, cuvântul „hot dog” are un sens complet diferit față de cuvintele „hot” și „dog” în alte contexte. Dacă reprezentăm cuvintele „hot” și „dog” mereu folosind aceleași vectori, acest lucru poate deruta modelul nostru.\n",
"\n",
"Pentru a rezolva această problemă, **reprezentările n-gram** sunt adesea utilizate în metodele de clasificare a documentelor, unde frecvența fiecărui cuvânt, pereche de cuvinte sau grup de trei cuvinte este o caracteristică utilă pentru antrenarea clasificatorilor. În reprezentările bigram, de exemplu, vom adăuga toate perechile de cuvinte în vocabular, pe lângă cuvintele originale.\n",
"\n",
"Mai jos este un exemplu despre cum să generăm o reprezentare bigram a sacului de cuvinte folosind 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": [
"Principalul dezavantaj al abordării n-gram este că dimensiunea vocabularului începe să crească extrem de rapid. În practică, trebuie să combinăm reprezentarea n-gram cu o tehnică de reducere a dimensionalității, cum ar fi *embeddings*, pe care o vom discuta în unitatea următoare.\n",
"\n",
"Pentru a utiliza o reprezentare n-gram în setul nostru de date **AG News**, trebuie să transmitem parametrul `ngrams` constructorului nostru `TextVectorization`. Lungimea unui vocabular de bigram este **semnificativ mai mare**, în cazul nostru depășește 1,3 milioane de tokeni! Astfel, are sens să limităm și tokenii bigram la un număr rezonabil.\n",
"\n",
"Am putea folosi același cod ca mai sus pentru a antrena clasificatorul, însă ar fi foarte ineficient din punct de vedere al memoriei. În unitatea următoare, vom antrena clasificatorul bigram folosind embeddings. Între timp, poți experimenta cu antrenarea clasificatorului bigram în acest notebook și să vezi dacă poți obține o acuratețe mai mare.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Calcularea automată a vectorilor BoW\n",
"\n",
"În exemplul de mai sus, am calculat vectorii BoW manual, prin însumarea codificărilor one-hot ale cuvintelor individuale. Totuși, cea mai recentă versiune a TensorFlow ne permite să calculăm vectorii BoW automat, prin transmiterea parametrului `output_mode='count` constructorului vectorizatorului. Acest lucru face definirea și antrenarea modelului nostru semnificativ mai ușoare:\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": [
"## Frecvența termenilor - frecvența inversă a documentelor (TF-IDF)\n",
"\n",
"În reprezentarea BoW, aparițiile cuvintelor sunt ponderate folosind aceeași tehnică, indiferent de cuvântul în sine. Totuși, este evident că cuvinte frecvente precum *a* și *în* sunt mult mai puțin importante pentru clasificare decât termenii specializați. În majoritatea sarcinilor NLP, unele cuvinte sunt mai relevante decât altele.\n",
"\n",
"**TF-IDF** înseamnă **frecvența termenilor - frecvența inversă a documentelor**. Este o variație a modelului bag-of-words, unde, în loc de o valoare binară 0/1 care indică apariția unui cuvânt într-un document, se folosește o valoare în virgulă mobilă, care este legată de frecvența apariției cuvântului în corpus.\n",
"\n",
"Mai formal, greutatea $w_{ij}$ a unui cuvânt $i$ în documentul $j$ este definită astfel:\n",
"$$\n",
"w_{ij} = tf_{ij}\\times\\log({N\\over df_i})\n",
"$$\n",
"unde\n",
"* $tf_{ij}$ este numărul de apariții ale lui $i$ în $j$, adică valoarea BoW pe care am văzut-o anterior\n",
"* $N$ este numărul de documente din colecție\n",
"* $df_i$ este numărul de documente care conțin cuvântul $i$ în întreaga colecție\n",
"\n",
"Valoarea TF-IDF $w_{ij}$ crește proporțional cu numărul de ori în care un cuvânt apare într-un document și este ajustată în funcție de numărul de documente din corpus care conțin cuvântul, ceea ce ajută la corectarea faptului că unele cuvinte apar mai frecvent decât altele. De exemplu, dacă cuvântul apare în *fiecare* document din colecție, $df_i=N$, și $w_{ij}=0$, iar acei termeni ar fi complet ignorați.\n",
"\n",
"Poți crea cu ușurință o vectorizare TF-IDF a textului folosind 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": [
"În Keras, stratul `TextVectorization` poate calcula automat frecvențele TF-IDF prin transmiterea parametrului `output_mode='tf-idf'`. Să repetăm codul pe care l-am folosit mai sus pentru a vedea dacă utilizarea TF-IDF crește acuratețea:\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": [
"## Concluzie\n",
"\n",
"Deși reprezentările TF-IDF atribuie greutăți de frecvență diferitelor cuvinte, ele nu pot reprezenta sensul sau ordinea. Așa cum a spus faimosul lingvist J. R. Firth în 1935: „Sensul complet al unui cuvânt este întotdeauna contextual, iar niciun studiu al sensului în afara contextului nu poate fi luat în serios.” Vom învăța mai târziu în curs cum să capturăm informațiile contextuale din text folosind modelarea limbajului.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Declinare de responsabilitate**: \nAcest document a fost tradus folosind serviciul de traducere AI [Co-op Translator](https://github.com/Azure/co-op-translator). Deși ne străduim să asigurăm acuratețea, vă rugăm să fiți conștienți că traducerile automate pot conține erori sau inexactități. Documentul original în limba sa natală ar trebui considerat sursa autoritară. Pentru informații critice, se recomandă traducerea profesională realizată de un specialist uman. Nu ne asumăm responsabilitatea pentru eventualele neînțelegeri sau interpretări greșite care pot apărea din utilizarea acestei traduceri.\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-30T01:15:48+00:00",
"source_file": "lessons/5-NLP/13-TextRep/TextRepresentationTF.ipynb",
"language_code": "ro"
}
},
"nbformat": 4,
"nbformat_minor": 4
}