Oefening: een neuraal netwerk maken en trainen

Voltooid

In deze eenheid gebruikt u Keras om een neuraal netwerk te maken en trainen waarmee tekst wordt geanalyseerd voor gevoel. Als u een neuraal netwerk wilt trainen, hebt u gegevens nodig waarmee het kan worden getraind. In plaats van dat u een externe gegevensset downloadt, gebruikt u de gegevensset IMDB movie reviews sentiment classification (IMDB-gevoelsclassificatie voor filmbeoordelingen) van Keras. De IMDB-gegevensset bevat 50.000 filmbeoordelingen die afzonderlijk als positief (1) of negatief (0) zijn beoordeeld. De gegevensset is onderverdeeld in 25.000 beoordelingen voor trainen en 25.000 beoordelingen voor testen. Het gevoel dat in deze beoordelingen wordt uitgedrukt, is voor het neurale netwerk de basis voor het analyseren van de aangeboden tekst en het beoordelen van het gevoel.

De IMDB-gegevensset is een van verschillende nuttige gegevenssets van Keras. Zie https://keras.io/datasets/. voor een volledige lijst met ingebouwde gegevenssets

  1. Typ of plak de volgende code in de eerste cel van de notebook en klik op de knop Uitvoeren (of druk op Shift+Enter) om de code uit te voeren en eronder een nieuwe cel toe te voegen:

    from keras.datasets import imdb
    top_words = 10000
    (x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=top_words)
    

    Met deze code wordt de IMDB-gegevensset van Keras geladen en maakt u een woordenlijst waarin de woorden in alle 50.000 beoordelingen worden toegewezen aan gehele getallen om de relatieve frequentie van het aantal gevallen aan te duiden. Aan elk woord wordt een uniek geheel getal toegewezen. Aan het meest voorkomende woord wordt het getal 1 toegewezen, aan het woord dat daarna het meest voorkomt het getal 2, enzovoort. Met load_data wordt ook een tweetal tuples geretourneerd met de filmbeoordelingen (in dit voorbeeld x_train en x_test) en de 1's en 0's waarmee die beoordelingen als positief of negatief worden geclassificeerd (y_train en y_test).

  2. Controleer of u het bericht Using TensorFlow backend (TensorFlow-back-end gebruiken) ziet waarmee wordt aangegeven dat Keras TensorFlow als back-end gebruikt.

    Loading the IMDB dataset.

    De IMDB-gegevensset laden

    Als Keras de Microsoft Cognitive Toolkit, ook wel bekend als CNTK, als back-end moet gebruiken, voegt u een paar regels code aan het begin van de notebook toe. Zie CNTK en Keras in Azure Notebooks voor een voorbeeld.

  3. Wat wordt er nu precies geladen met de load_data-functie? De variabele met de naam x_train is een lijst met 25.000 lijsten die allemaal een filmbeoordeling vertegenwoordigen. (x_test is ook een lijst van 25.000 lijsten die 25.000 beoordelingen vertegenwoordigen. x_train wordt gebruikt voor training, terwijl x_test deze wordt gebruikt voor het testen.) Maar de binnenste lijsten , de lijsten die filmrecensies vertegenwoordigen , bevatten geen woorden; ze bevatten gehele getallen. Dit wordt in de Keras-documentatie als volgt beschreven:

    Keras documentation.

    De reden dat de binnenste lijsten getallen in plaats van tekst bevatten, is dat u een neuraal netwerk niet met tekst traint maar met getallen. Om precies te zijn: u traint het met tensoren. In dit geval is elke beoordeling een 1-dimensionale tensor (vergelijkbaar met een 1-dimensionale matrix) die gehele getallen bevat waarmee de woorden in de beoordeling worden geïdentificeerd. U kunt zien hoe dit werkt door de volgende Python-instructie in een lege cel te typen en deze uit te voeren. U ziet de gehele getallen die de eerste beoordeling in de trainingsset vertegenwoordigen:

    x_train[0]
    

    Integers comprising the first review in the IMDB training set.

    Gehele getallen voor de eerste beoordeling in de IMDB-trainingsset

    Het eerste getal in de lijst (1) vertegenwoordigt geen woord. Met dit getal wordt het begin van de beoordeling gemarkeerd. Dit getal is hetzelfde voor elke beoordeling in de gegevensset. De getallen 0 en 2 zijn ook gereserveerd en u trekt 3 af van de andere getallen om een geheel getal in een beoordeling toe te wijzen aan het bijbehorende gehele getal in de woordenlijst. Het tweede getal (14) verwijst naar het woord dat overeenkomt met getal 11 in de woordenlijst, het derde getal vertegenwoordigt het woord waaraan het getal 19 in de woordenlijst is toegewezen, enzovoort.

  4. Bent u benieuwd hoe de woordenlijst eruitziet? Voer de volgende instructie uit in een nieuwe notebookcel:

    imdb.get_word_index()
    

    Er wordt alleen een subset van de woordenlijstgegevens weergegeven. De woordenlijst bevat in totaal meer dan 88.000 woorden en de bijbehorende gehele getallen. De uitvoer die u ziet, komt waarschijnlijk niet overeen met de uitvoer in de schermopname omdat de woordenlijst elke keer dat load_data wordt aangeroepen opnieuw wordt gegenereerd.

    Dictionary mapping words to integers.

    Woordenlijst waarin woorden aan gehele getallen zijn toegewezen

  5. Zoals u ziet, wordt elke beoordeling in de gegevensset gecodeerd als een verzameling van gehele getallen in plaats van woorden. Is het mogelijk de codering van een beoordeling terug te draaien zodat u de oorspronkelijke tekst kunt zien? Voer in een nieuwe cel de volgende instructies in en voer de instructies uit om de eerste beoordeling in x_train in tekstindeling weer te geven:

    word_dict = imdb.get_word_index()
    word_dict = { key:(value + 3) for key, value in word_dict.items() }
    word_dict[''] = 0  # Padding
    word_dict['>'] = 1 # Start
    word_dict['?'] = 2 # Unknown word
    reverse_word_dict = { value:key for key, value in word_dict.items() }
    print(' '.join(reverse_word_dict[id] for id in x_train[0]))
    

    In de uitvoer markeert '>' het begin van de beoordeling, terwijl '?' woorden markeert die niet tot de meest voorkomende 10.000 woorden in de gegevensset behoren. Deze 'onbekende' woorden worden vertegenwoordigd door 2's in de lijst met gehele getallen die een beoordeling vertegenwoordigen. Weet u nog dat er een num_words-parameter aan load_data werd doorgegeven? Deze parameter komt nu aan de orde. Hiermee wordt niet de grootte van de woordenlijst beperkt, maar het bereik van gehele getallen die worden gebruikt om de beoordelingen te coderen.

    The first review in textual format.

    De eerste beoordeling in tekstindeling

  6. De beoordelingen zijn 'schoon' in de zin dat letters zijn geconverteerd naar kleine letters en leestekens zijn verwijderd. Maar ze zijn nog niet klaar om een neuraal netwerk te trainen voor het analyseren van gevoel van tekst. Wanneer u een neuraal netwerk met een verzameling tensoren traint, moet elke tensor even lang zijn. Momenteel hebben de lijsten die beoordelingen in x_train en x_test vertegenwoordigen, verschillende lengten.

    Gelukkig bevat Keras een functie waarbij een lijst met lijsten als invoer wordt gebruikt en de binnenste lijsten worden geconverteerd naar een opgegeven lengte door ze zo nodig af te kappen of op te vullen met 0's. Voer de volgende code in de notebook in en voer deze uit om ervoor te zorgen dat alle lijsten die filmbeoordelingen vertegenwoordigen in x_train en x_test een lengte van 500 gehele getallen hebben:

    from keras.preprocessing import sequence
    max_review_length = 500
    x_train = sequence.pad_sequences(x_train, maxlen=max_review_length)
    x_test = sequence.pad_sequences(x_test, maxlen=max_review_length)
    
  7. Nu de gegevens voor het trainen en testen zijn voorbereid, is het tijd om het model te maken. Voer de volgende code in de notebook in om een neuraal netwerk te maken waarmee gevoel wordt geanalyseerd:

    from keras.models import Sequential
    from keras.layers import Dense
    from keras.layers.embeddings import Embedding
    from keras.layers import Flatten
    
    embedding_vector_length = 32
    model = Sequential()
    model.add(Embedding(top_words, embedding_vector_length, input_length=max_review_length))
    model.add(Flatten())
    model.add(Dense(16, activation='relu'))
    model.add(Dense(16, activation='relu'))
    model.add(Dense(1, activation='sigmoid'))
    model.compile(loss='binary_crossentropy',optimizer='adam', metrics=['accuracy'])
    print(model.summary())
    

    Controleer of de uitvoer er als volgt uitziet:

    Creating a neural network with Keras.

    Een neuraal netwerk maken met Keras

    Deze code is de kern van hoe u met Keras een neuraal netwerk maakt. Eerst wordt met de code een Sequential-object gemaakt dat een 'sequentieel' model vertegenwoordigt. Dit is een model dat bestaat uit een end-to-end-stack van lagen waarin de uitvoer van de ene laag invoer voor de volgende biedt.

    Met de volgende instructies worden lagen aan het model toegevoegd. De eerste is een insluitingslaag die essentieel is voor neurale netwerken waarmee woorden worden verwerkt. De insluitingslaag wijst in essentie veel-dimensionale matrices met woordindexen van gehele getallen toe aan zwevendekommamatrices die minder dimensies bevatten. Daarnaast is het hiermee mogelijk dat woorden met een vergelijkbare betekenis gelijk worden behandeld. Een volledige behandeling van woordinsluitingen zou in dit lab te ver voeren, maar u kunt hier meer over lezen in Waarom u met het gebruik van insluitingslagen zou moeten beginnen. Als u liever een meer wetenschappelijke uitleg wilt, raadpleegt u Efficiënte schatting van woordvoorstellingen in een vectorruimte. Met de aanroep om af te vlakken die volgt op het toevoegen van de insluitingslaag, wordt de uitvoer opnieuw vormgegeven voor de invoer voor de volgende laag.

    De volgende drie lagen die aan het model worden toegevoegd, zijn compacte lagen, ook wel bekend als volledig verbonden lagen. Dit zijn de traditionele lagen die veel in neurale netwerken worden gebruikt. Elke laag bevat n knooppunten of neuronen en elke neuron ontvangt invoer van elke neuron in de vorige laag, vandaar de term 'volledig verbonden'. Het zijn deze lagen die een neuraal netwerk toestaan om 'te leren' van invoergegevens door iteratief naar de uitvoer te raden, de resultaten te controleren en de verbindingen af te stemmen om betere resultaten te produceren. De eerste twee dichte lagen in dit netwerk bevatten elk 16 neurons. Dit getal is willekeurig gekozen; u kunt de nauwkeurigheid van het model mogelijk verder verbeteren door te experimenteren met verschillende groottes. De laatste dichte laag bevat slechts één neuron omdat het uiteindelijke doel van het netwerk is om één uitvoer te voorspellen; namelijk een gevoelsscore van 0,0 tot6 1,0.

    Het resultaat is het neurale netwerk dat hieronder wordt weergegeven. Het netwerk bevat een invoerlaag, een uitvoerlaag en twee verborgen lagen (de dichte lagen bevatten elk 16 neurons). Ter vergelijking: sommige van de meer geavanceerde neurale netwerken van tegenwoordig bevatten meer dan 100 lagen. Een voorbeeld is ResNet-152 van Microsoft Research, waarvan de nauwkeurigheid bij het identificeren van objecten in foto's soms beter is dan die van een mens. U kunt ResNet-152 bouwen met Keras, maar u hebt een cluster met GPU-computers nodig om deze te kunnen trainen.

    Visualizing the neural network.

    Het neurale netwerk visualiseren

    De aanroep aan de functie compile compileert het model door belangrijke parameters op te geven zoals welke optimizer moet worden gebruikt en welke metrische gegevens moeten worden gebruikt om de nauwkeurigheid van het model in elke trainingsstap te beoordelen. De training begint pas wanneer u de functie fit van het model aanroept, dus de compile-aanroep wordt meestal snel uitgevoerd.

  8. Roep nu de functie fit aan om het neurale netwerk te trainen:

    hist = model.fit(x_train, y_train, validation_data=(x_test, y_test), epochs=5, batch_size=128)
    

    Een training moet ongeveer zes minuten duren of iets meer dan één minuut per tijdvak. epochs=5 geeft aan Keras door dat er vijf voorwaartse en achterwaartse bewerkingen via het model moeten worden gemaakt. Met elke bewerking leert het model van de trainingsgegevens en meet (valideert) het hoe goed het heeft geleerd met behulp van de testgegevens. Vervolgens worden er aanpassingen uitgevoerd en wordt er een volgende doorvoerbewerking of tijdvak uitgevoerd. Dit is zichtbaar in de uitvoer van de functie fit, waarin de nauwkeurigheid van de training (acc) en de nauwkeurigheid van de validatie (val_acc) voor elk tijdvak wordt weergegeven.

    batch_size=128 geeft aan Keras door dat er 128 trainingsvoorbeelden tegelijk moeten worden gebruikt om het netwerk te trainen. Grotere batches versnellen de trainingstijd (minder doorvoerbewerkingen zijn vereist in elk tijdvak om alle trainingsgegevens op te nemen), maar soms wordt de nauwkeurigheid vergroot door kleinere batches. Nadat u dit lab hebt voltooid, kunt u teruggaan en het model opnieuw trainen met een batchgrootte van 32 om te zien welk effect dit heeft op de nauwkeurigheid van het model. Hiermee wordt de trainingstijd ongeveer verdubbeld.

    Training the model.

    Het model trainen

  9. Dit model is ongebruikelijk omdat het goed leert met slechts een paar tijdvakken. De nauwkeurigheid van de training zoomt snel in op bijna 100%, terwijl de validatienauwkeurigheid toeneemt voor een periode of twee en vervolgens afvlakt. Over het algemeen wilt u een model niet langer trainen dan nodig is om deze nauwkeurigheid te stabiliseren. Het risico is overfitting, wat ervoor zorgt dat het model goed presteert tegen testgegevens, maar niet zo goed met echte gegevens. Een indicatie dat er overfitting optreedt voor een model is een groeiend verschil tussen de nauwkeurigheid van de training en de nauwkeurigheid van de validatie. Zie Overfitting in Machine Learning voor een geweldige inleiding tot overfitting : What It Is and How to Prevent It.

    Als u de wijzigingen in de nauwkeurigheid van de training en validatie wilt visualiseren, voert u de volgende instructies uit in een nieuwe notebookcel:

    import seaborn as sns
    import matplotlib.pyplot as plt
    %matplotlib inline
    
    sns.set()
    acc = hist.history['acc']
    val = hist.history['val_acc']
    epochs = range(1, len(acc) + 1)
    
    plt.plot(epochs, acc, '-', label='Training accuracy')
    plt.plot(epochs, val, ':', label='Validation accuracy')
    plt.title('Training and Validation Accuracy')
    plt.xlabel('Epoch')
    plt.ylabel('Accuracy')
    plt.legend(loc='upper left')
    plt.plot()
    

    De nauwkeurigheid van de gegevens is afkomstig uit het history-object dat wordt geretourneerd door de functie fit van het model. Zou u op basis van de weergegeven grafiek aanbevelen om het aantal trainingstijdvakken te verhogen, verlagen of gelijk te houden?

  10. Een andere manier om te controleren op overfitting, is om trainingsverlies te vergelijken met validatieverlies terwijl de training wordt voortgezet. Optimalisatieproblemen zoals deze zijn bedoeld om verlies van een functie te minimaliseren. Lees hier meer informatie. Als voor een bepaald tijdvak het trainingsverlies veel groter is dan het validatieverlies, kan dit wijzen op overfitting. U hebt in de vorige stap de eigenschappen acc en val_acc van de eigenschap history van het object history gebruikt om de nauwkeurigheid van de training en validatie vast te leggen. Dezelfde eigenschap bevat ook waarden genaamd loss en val_loss die respectievelijk het trainingsverlies en validatieverlies weergeven. Als u deze waarden wilt weergeven om een grafiek te maken zoals de onderstaande, hoe zou u de code aanpassen om dit te doen?

    Training and validation loss.

    Trainings- en validatieverlies

    Gezien het feit dat de kloof tussen trainings- en validatieverlies begint toe te nemen in het derde tijdvak, wat zou u zeggen als iemand zou aanbevelen dat u het aantal tijdvakken verhoogt naar 10 of 20?

  11. Voltooi de bewerking door de evaluate-methode van het model aan te roepen om te bepalen hoe nauwkeurig het model het gevoel kan kwantificeren, uitgedrukt in tekst die is gebaseerd op de testgegevens in x_test (beoordelen) en y_test (0s en 1s of 'labels', waarmee wordt aangegeven welke beoordelingen positief zijn en welke negatief):

    scores = model.evaluate(x_test, y_test, verbose=0)
    print("Accuracy: %.2f%%" % (scores[1] * 100))
    

    Wat is de berekende nauwkeurigheid van uw model?

U hebt waarschijnlijk een nauwkeurigheid in het bereik 85% tot 90% bereikt. Dat is acceptabel aangezien u het model helemaal nieuw (in tegenstelling tot het gebruiken van een vooraf getraind neuraal neuraal netwerk) hebt gemaakt en de trainingstijd kort was zelfs zonder een GPU. Het is mogelijk om een nauwkeurigheid van 95% of hoger te bereiken met alternatieve neurale netwerkarchitecturen, met name met terugkerende neurale netwerken (RNN's) die Long Short-Term Memory-lagen (LSTM) gebruiken. U kunt met Keras eenvoudig dergelijke netwerken maken, maar de trainingstijd kan exponentieel toenemen. Het model dat u hebt gebouwd heeft een redelijke balans tussen nauwkeurigheid en trainingstijd. Als u echter meer informatie wilt over het bouwen van RNN's met Keras, leest u Understanding LSTM and its Quick Implementation in Keras for Sentiment Analysis (Informatie over LSTM en de snelle implementatie in Keras voor sentimentanalyse).

Test uw kennis

1.

Zou u op basis van de eerste grafiek die u hebt gemaakt (Trainings- en validatienauwkeurigheid), aanbevelen om het aantal trainingstijdvakken te verhogen, verlagen of gelijk te houden?