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

647 lines
26 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Tekstklassifiseringsoppgave\n",
"\n",
"I denne modulen skal vi starte med en enkel tekstklassifiseringsoppgave basert på **[AG_NEWS](http://www.di.unipi.it/~gulli/AG_corpus_of_news_articles.html)**-datasettet: vi skal klassifisere nyhetsoverskrifter i en av 4 kategorier: Verden, Sport, Næringsliv og Vitenskap/Teknologi.\n",
"\n",
"## Datasettet\n",
"\n",
"For å laste inn datasettet, skal vi bruke **[TensorFlow Datasets](https://www.tensorflow.org/datasets)**-APIet.\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": [
"Vi kan nå få tilgang til trenings- og testdelene av datasettet ved å bruke `dataset['train']` og `dataset['test']` henholdsvis:\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": [
"La oss skrive ut de første 10 nye overskriftene fra datasettet vårt:\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": [
"## Tekstvektorisering\n",
"\n",
"Nå må vi konvertere tekst til **tall** som kan representeres som tensorer. Hvis vi ønsker representasjon på ordnivå, må vi gjøre to ting:\n",
"\n",
"* Bruke en **tokenizer** for å dele opp teksten i **tokens**.\n",
"* Bygge et **vokabular** av disse tokens.\n",
"\n",
"### Begrense vokabularstørrelsen\n",
"\n",
"I eksempelet med AG News-datasettet er vokabularstørrelsen ganske stor, mer enn 100 000 ord. Generelt sett trenger vi ikke ord som sjelden forekommer i teksten — bare noen få setninger vil inneholde dem, og modellen vil ikke lære noe av dem. Derfor gir det mening å begrense vokabularstørrelsen til et mindre antall ved å sende et argument til vektorisatorens konstruktør:\n",
"\n",
"Begge disse trinnene kan håndteres ved hjelp av **TextVectorization**-laget. La oss opprette vektorisatorobjektet og deretter kalle `adapt`-metoden for å gå gjennom all tekst og bygge et vokabular:\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": [
"> **Merk** at vi kun bruker en delmengde av hele datasettet for å bygge et ordforråd. Vi gjør dette for å redusere kjøretiden og unngå at du må vente. Imidlertid tar vi risikoen for at noen av ordene fra hele datasettet ikke blir inkludert i ordforrådet og dermed blir ignorert under trening. Derfor bør bruk av hele ordforrådet og gjennomgang av hele datasettet under `adapt` øke den endelige nøyaktigheten, men ikke vesentlig.\n",
"\n",
"Nå kan vi få tilgang til det faktiske ordforrådet:\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": [
"Ved å bruke vektorisatoren kan vi enkelt kode enhver tekst til et sett med tall:\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": [
"## Bag-of-words tekstrepresentasjon\n",
"\n",
"Fordi ord representerer mening, kan vi noen ganger forstå betydningen av en tekst ved bare å se på de individuelle ordene, uavhengig av rekkefølgen i setningen. For eksempel, når vi klassifiserer nyheter, vil ord som *vær* og *snø* sannsynligvis indikere *værmelding*, mens ord som *aksjer* og *dollar* vil peke mot *finansnyheter*.\n",
"\n",
"**Bag-of-words** (BoW) vektorrepresentasjon er den enkleste tradisjonelle vektorrepresentasjonen å forstå. Hvert ord er knyttet til en vektorindeks, og et vektorelement inneholder antall forekomster av hvert ord i et gitt dokument.\n",
"\n",
"![Bilde som viser hvordan en bag-of-words vektorrepresentasjon lagres i minnet.](../../../../../translated_images/no/bag-of-words-example.606fc1738f1d7ba9.webp) \n",
"\n",
"> **Note**: Du kan også tenke på BoW som en sum av alle én-hot-kodede vektorer for individuelle ord i teksten.\n",
"\n",
"Nedenfor er et eksempel på hvordan man kan generere en bag-of-words representasjon ved hjelp av Scikit Learn python-biblioteket:\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": [
"Vi kan også bruke Keras-vektoriseringen som vi definerte ovenfor, konvertere hvert ordnummer til en one-hot-koding og legge sammen alle disse vektorene:\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": [
"> **Merk**: Du kan bli overrasket over at resultatet skiller seg fra det forrige eksempelet. Årsaken er at i Keras-eksempelet tilsvarer lengden på vektoren vokabularstørrelsen, som ble bygget fra hele AG News-datasettet, mens vi i Scikit Learn-eksempelet bygde vokabularet fra eksempelteksten underveis.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Trene BoW-klassifikatoren\n",
"\n",
"Nå som vi har lært hvordan vi bygger bag-of-words-representasjonen av teksten vår, la oss trene en klassifikator som bruker den. Først må vi konvertere datasettet vårt til en bag-of-words-representasjon. Dette kan gjøres ved å bruke `map`-funksjonen på følgende måte:\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": [
"La oss nå definere et enkelt klassifiserings-nevralt nettverk som inneholder ett lineært lag. Inngangsstørrelsen er `vocab_size`, og utgangsstørrelsen tilsvarer antall klasser (4). Fordi vi løser en klassifiseringsoppgave, er den endelige aktiveringsfunksjonen **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": [
"Siden vi har 4 klasser, er en nøyaktighet på over 80% et godt resultat.\n",
"\n",
"## Trene en klassifiserer som ett nettverk\n",
"\n",
"Siden vektoriseringen også er et Keras-lag, kan vi definere et nettverk som inkluderer det, og trene det fra start til slutt. På denne måten trenger vi ikke å vektorisere datasettet ved hjelp av `map`, vi kan bare sende det originale datasettet til inngangen av nettverket.\n",
"\n",
"> **Note**: Vi må fortsatt bruke `map` på datasettet vårt for å konvertere felt fra ordbøker (som `title`, `description` og `label`) til tupler. Men når vi laster inn data fra disk, kan vi bygge et datasett med den nødvendige strukturen fra starten av.\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": [
"## Bigrammer, trigrammer og n-grammer\n",
"\n",
"En begrensning med bag-of-words-tilnærmingen er at noen ord er en del av flerordsuttrykk. For eksempel har ordet 'hot dog' en helt annen betydning enn ordene 'hot' og 'dog' i andre sammenhenger. Hvis vi alltid representerer ordene 'hot' og 'dog' med de samme vektorene, kan det forvirre modellen vår.\n",
"\n",
"For å løse dette brukes ofte **n-gram-representasjoner** i metoder for dokumentklassifisering, der frekvensen av hvert ord, to-ordsuttrykk eller tre-ordsuttrykk er en nyttig funksjon for å trene klassifikatorer. I bigram-representasjoner, for eksempel, legger vi til alle ordpar i vokabularet, i tillegg til de opprinnelige ordene.\n",
"\n",
"Nedenfor er et eksempel på hvordan man kan generere en bigram bag-of-words-representasjon ved hjelp av 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": [
"Den største ulempen med n-gram-tilnærmingen er at vokabularstørrelsen begynner å vokse ekstremt raskt. I praksis må vi kombinere n-gram-representasjonen med en teknikk for dimensjonsreduksjon, slik som *embeddings*, som vi skal diskutere i neste enhet.\n",
"\n",
"For å bruke en n-gram-representasjon i vårt **AG News**-datasett, må vi sende `ngrams`-parameteren til vår `TextVectorization`-konstruktør. Lengden på et bigram-vokabular er **betydelig større**, i vårt tilfelle er det mer enn 1,3 millioner tokens! Derfor gir det mening å begrense bigram-tokens til et rimelig antall.\n",
"\n",
"Vi kunne brukt den samme koden som ovenfor for å trene klassifisereren, men det ville vært svært minne-ineffektivt. I neste enhet skal vi trene bigram-klassifisereren ved hjelp av embeddings. I mellomtiden kan du eksperimentere med bigram-klassifiseringstrening i denne notatboken og se om du kan oppnå høyere nøyaktighet.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Automatisk beregning av BoW-vektorer\n",
"\n",
"I eksempelet ovenfor beregnet vi BoW-vektorer manuelt ved å summere one-hot-enkodingene av individuelle ord. Men den nyeste versjonen av TensorFlow lar oss beregne BoW-vektorer automatisk ved å sende parameteren `output_mode='count'` til vektorisatorens konstruktør. Dette gjør det betydelig enklere å definere og trene modellen vår:\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": [
"## Termfrekvens - invers dokumentfrekvens (TF-IDF)\n",
"\n",
"I BoW-representasjon vektes ordforekomster ved hjelp av samme teknikk uavhengig av selve ordet. Det er imidlertid tydelig at hyppige ord som *en* og *i* er langt mindre viktige for klassifisering enn spesialiserte termer. I de fleste NLP-oppgaver er noen ord mer relevante enn andre.\n",
"\n",
"**TF-IDF** står for **termfrekvens - invers dokumentfrekvens**. Det er en variant av bag-of-words, der man i stedet for en binær 0/1-verdi som indikerer tilstedeværelsen av et ord i et dokument, bruker en flyttallsverdi som er relatert til hvor ofte ordet forekommer i korpuset.\n",
"\n",
"Mer formelt er vekten $w_{ij}$ til et ord $i$ i dokumentet $j$ definert som:\n",
"$$\n",
"w_{ij} = tf_{ij}\\times\\log({N\\over df_i})\n",
"$$\n",
"hvor\n",
"* $tf_{ij}$ er antall forekomster av $i$ i $j$, altså BoW-verdien vi har sett tidligere\n",
"* $N$ er antall dokumenter i samlingen\n",
"* $df_i$ er antall dokumenter som inneholder ordet $i$ i hele samlingen\n",
"\n",
"TF-IDF-verdien $w_{ij}$ øker proporsjonalt med antall ganger et ord vises i et dokument og justeres ned basert på antall dokumenter i korpuset som inneholder ordet. Dette bidrar til å kompensere for det faktum at noen ord forekommer oftere enn andre. For eksempel, hvis ordet vises i *alle* dokumentene i samlingen, er $df_i=N$, og $w_{ij}=0$, og disse termene vil bli fullstendig ignorert.\n",
"\n",
"Du kan enkelt lage TF-IDF-vektorisering av tekst ved hjelp av 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": [
"I Keras kan `TextVectorization`-laget automatisk beregne TF-IDF-frekvenser ved å sende parameteren `output_mode='tf-idf'`. La oss gjenta koden vi brukte ovenfor for å se om bruk av TF-IDF øker nøyaktigheten:\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": [
"## Konklusjon\n",
"\n",
"Selv om TF-IDF-representasjoner gir frekvensvekter til ulike ord, er de ikke i stand til å representere mening eller rekkefølge. Som den kjente lingvisten J. R. Firth sa i 1935: \"Den fullstendige betydningen av et ord er alltid kontekstuell, og ingen studie av betydning utenfor kontekst kan tas seriøst.\" Senere i kurset vil vi lære hvordan vi kan fange opp kontekstuell informasjon fra tekst ved hjelp av språklig modellering.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Ansvarsfraskrivelse**: \nDette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vær oppmerksom på at automatiske oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på sitt opprinnelige språk bør anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.\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-28T17:57:09+00:00",
"source_file": "lessons/5-NLP/13-TextRep/TextRepresentationTF.ipynb",
"language_code": "no"
}
},
"nbformat": 4,
"nbformat_minor": 4
}