zondag 27 december 2020

Installatie perikelen.

Vermoedelijk na wat updates die ik heb moeten / willen draaien voor de Toonify / deepfake experimenten, werkt mijn gpu niet meer bij het trainen van deel learning netwerken. Vanuit de blog van mijn broer haal ik een werkbare configuratie.


  • Cuda 10.0
  • Tensorflow-GPU==1.14.0
  • Python 3.6.5
  • Keras 2.2.4

Ik installeer deze en verifieer de versies:
 

>>> keras.__version__   

'2.2.4-tf'

>>> keras.__version__

'2.2.4'

Python 3.6.5

>>> import tensorflow as tf

>>> tf.__version__

'1.14.0'


PS C:\Users\DirkW> nvcc --version

nvcc: NVIDIA (R) Cuda compiler driver

Copyright (c) 2005-2018 NVIDIA Corporation

Built on Sat_Aug_25_21:08:04_Central_Daylight_Time_2018

Cuda compilation tools, release 10.0, V10.0.130

De versies kloppen en lijken op het eerste gezicht ook een werkbare installatie op te leveren. Hiermee test je snel of de gpu ook inderdaad gevonden wordt:

>>>tf.test.is_gpu_available(cuda_only=False, min_cuda_compute_capability=None)

De installatie geeft wel al snel veel memory-tekort-errors. Ik denk dat ik toch ga proberen een eerdere versie te installeren.  


Ik begin met het deinstalleren van keras en tensorflow-gpu

>pip uninstall keras

 Successfully uninstalled Keras-2.2.4

>pip uninstall tensorflow-gpu

 Successfully uninstalled tensorflow-gpu-1.14.0


Via Windows 'Apps and Feautures deinstalleer ik alle CUDA software / versies. 

Ik haal versie 8 hier op met ook een patch:

https://developer.nvidia.com/cuda-80-ga2-download-archive

Cuda 8 herkent de grafische kaart nog niet. Ik schakel nu naar 9.2

Nsight moet blijkbaar ook worden gedeinstalleerd. Dus ik laat opnieuw de installatie lopen en daarna de patch. Dit lijkt aallemaal goed te gaan tot nu toe.


Nu nog CuDNN : 

en download deze



Deze moeten weer naar de betreffende Cuda direcories worden gekopieerd.
(C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.2)
Ook moest ergens het pad worden opgenomen in de systeem variabelen.
Met Control X en daarna advanced system settings kom ik hier:


Ik zie dat ze al zijn toegevoegd:




Ok, verder met de juiste tensorflow en keras versies:
Ik lees dat deze versie met Cuda 9.2 zou ,oeten werken:

> pip install tensorflow-gpu==1.8.0

Bij geeft aan dat de installatie succesvol is maar tocj ook een error m.b.t. tensorboard. (Hoewel hij net 2.4.0 heeft gedeinstalleerd)
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
-ensorflow 1.12.0 requires tensorboard<1.13.0,>=1.12.0, but you have tensorboard 1.8.0 which is incompatible.
tensorflow 1.14.0 requires tensorboard<1.15.0,>=1.14.0, but you have tensorboard 1.8.0 which is incompatible.

Ik ben benieuwd of keras nu ook is geinstalleerd

 >>> from tensorflow import keras
ImportError: Could not find 'cudart64_90.dll'. TensorFlow requires that this DLL be installed in a directory that is named in your %PATH% environment variable. Download and install CUDA 9.0 from this URL: https://developer.nvidia.com/cuda-toolkit


Vreemd, misschien eerst even rebooten.

Ook dat werkt niet. Ik besluit op basis van wat adviezen om Cuda 9.0 t installeren. Dit lijkt prima te werken. Ik hoef ook geen nieuwe CuDNN te downloaden. Na reboot komt hij gelijk met de juiste bevestiging: 

>>> tf.test.is_gpu_available(cuda_only=False, min_cuda_compute_capability=None)
2020-12-27 20:12:56.087941: I T:\src\github\tensorflow\tensorflow\core\common_runtime\gpu\gpu_device.cc:1435] Adding visible gpu devices: 0
2020-12-27 20:12:56.089254: I T:\src\github\tensorflow\tensorflow\core\common_runtime\gpu\gpu_device.cc:923] Device interconnect StreamExecutor with strength 1 edge matrix:
2020-12-27 20:12:56.089831: I T:\src\github\tensorflow\tensorflow\core\common_runtime\gpu\gpu_device.cc:929]      0
2020-12-27 20:12:56.090446: I T:\src\github\tensorflow\tensorflow\core\common_runtime\gpu\gpu_device.cc:942] 0:   N
2020-12-27 20:12:56.091079: I T:\src\github\tensorflow\tensorflow\core\common_runtime\gpu\gpu_device.cc:1053] Created TensorFlow device (/device:GPU:0 with 9647 MB memory) -> physical GPU (device: 0, name: GeForce GTX 1080 Ti, pci bus id: 0000:05:00.0, compute capability: 6.1)
True

Alleen dit vind ik een beetje vreemd:


>>> from tensorflow import keras

>>> keras.__version__

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

AttributeError: module 'tensorflow.tools.api.generator.api.keras' has no attribute '__version__'

 Dit doet het wel:

tf.__version__

'1.8.0'

Ik heb dus nu 

- Tensorflow - GPU 1.8.0

- Keras - ?

- Cuda - 9.0

- CuDNN v7.6.5

Ik ga nog de Cuda 9.0 patches downloaden. Hoop dat dat geen roet in het eten gooit. 

Dat is gelukt maar er is nog een probleempje met keras zelf. Ondanks dat een import van keras uit tensorflow geen fout geeft lijken er geen modules te kunnen worden geladen.  Ik moet Keras blijkbaar zelf ook nog installeren. Versie 2.1.6 lijkt hierbij te passen:

pip install keras==2.1.6

Dit lijkt nu weer helemaal goed te werken. Ook Keras werkt met de GPU

Nu nog een juist deep learning programma :-)



donderdag 10 december 2020

NLP nieuwe experimenten 01

Het is alweer even geleden dat ik met nlp heb geexperimenteerd. Nog wel wat zaken voor incident classificatie gedaan op basis van Bert maar eigen testjes hebben even stil gelegen. Toch borrelen er af en toe wat gedachten op die dan ook soms tot nieuwe programmeer experimentjes leiden. 


Een van die gedachten / overwegingen is de keuze bij Bert om woorden op te splitsen in woorddelen. In het char2word2vev verhaal ben ik ervan uitgegaan dat je , door van de karakters uit te gaan, in elk geval geen informatie verloren laat gaan van gelijkvormige woorden zoals 'school' en 'schoollokaal', 'schoolbank' etc . Uit deze woorden kan je afleiden, zelfs als je niet zou kunnen leen, dat er veel meer overeenkomst is tussen de woorden dan bijvoorbeeld 3 willekeurige andere. Zoals aangegeven hoopte ik deze betekenis te kunnen vasthouden tijdens de omzetting naar getallen (creatie van een vocabulary met indices). Dit leidt in pincipe tot een zeer beperkte / kleine 'vocab' van, zeg maar, 28 letters (eventueel het dubbele bij hoofdletters) , 10 cijfers en een setje symbolen. 

Dit kleine setje zou het gevoelsmatig makkelijker moeten maken om uit een reeks informatie te extraheren.  


Bij Bert is de vocab echter zo'n 30K groot en blijkbaar geeft dat heel goede resultaten. Neurale netwerken hebben dus niet heel veel moeite om met dergelijke grotere vocabulares om te gaan. De opdeling van woorden in woorddelen lijkt bij Bert echter wat willekeurig. Een goede tussen mogelijkheid is wellicht om woorden op te splitsen in lettergrepen. Daarbij blijft veel 'woordinformatie' behouden. Bijvoorbeeld 'school' uit bovenstaand voorbeeld wordt in alle drie de gevallen op dezelfde wijze gecodeerd. 

Ik vind al snel een aardige python lettergreep omzetter:

from hyphenate import hyphenate_word

Ik pak weer het 'movie sentiment bestand' en doe wat testen. Dit bestand bevat 100.000 reviews. Ik kijk hoe lang (aantal karakters) de reviews gemiddeld zijn (voor de aardigheid opgesplitst naar sentiment):

sentiment

negative    1294.0

neutral     1329.9

positive    1324.8

Het omzetten naar lettergrepen gaat niet allemaal zoals ik zou verwachten maar we komen een heel eind. Ik krijg 65.626 verschillende 'lettergrepen'. Hier een voorbeeld van de 10 meest voorkomende lettergrepen en de frequentie:

[('ing', 5072), ('i', 3462), ('ly', 3082), ('er', 2944), ('in', 2266), ('re', 1914), ('ed', 1766), ('tion', 1753), ('un', 1693), ('ter', 1495)]

Maar als ik de lettergrepen verwijder die maar 1x voorkomen hou ik er maar 14.543 over. De overige 'lettergrepen' moeten maar, net als bij Bert, met de letters zelf worden gecodeerd. Die moet ik dan, denk ik, nog wel toevoegen, voor zover ze nog niet in de huidige vocabulary beschikbaar zijn.  

Nu maar eens even een lettergreep codeer functie schrijven die woorden omzet in arrays met de indexen uit deze volledige vocabulary.

   

     

zondag 14 juni 2020

Bert testen met incident beschrijvingen 2 (vervolg)

Eindelijk heb ik ook mensen op het werk geinteresseerd gekregen voor een AI experiment :-)
We gaan testen of het bijsturen van de priority van GCS incidenten zinvol kan zijn. Omdat het maart is geweest dat ik hier het laatst mee bezig ben geweest (en tussendoor vooral met chars2word2vec) moet ik alles even weerophalen.
Ik maak een nieuwe dataset aan van 55.448 records. Nu met alleen GCS incidenten. Ik neem ook de langere omschrijving mee om te zien of ik de validation accuracy daarmee wellicht omhoog kan brengen. 

De eerste test lijkt wat raar te verlopen:

Zeker de loss schiet in epoch 4 en 5 naar een rare hoogte en blijft dan fixed. Ook de accuracy waarden blijven constant. Maar goed, dit is een eerste test.
Ik ga eerst de descriptions wat opschonen. Dit is zonder de 'tags'.

 
Niet heel erg veel verschil. Dan nu maar eens helemaal goed opschonen. Leestekens verwijderen en linefeeds.

Lijkt alleen maar te verslechteren. Hmmm
Dan maar eens weer terug naar alleen korte omschrijvingen:
De loss en de accuracy vertonen nu iig een mooi verloop.  Maar ook hier gaan de validatie waarden omslaan bij de 3e epoch. Ik verlaag de learning rate:


Dat geeft een iets vertraagd maar verder vergelijkbaar resultaat.
Terugkijkend lijkt de training met langere omschrijving feitelijk de beste resulaten te geven. In de 2e grafiek van boven komt de validation accuracy bij de 4e epoch zo rond de 90%. Dat die daarna raar gaat doen maakt het resultaat denk ik niet minder. Toch eens opnieuw proberen te trainen met deze situatie. Ik bouw nu een 'callback' in waardoor die stopt na een keer mindere validation loss en ook steeds het beste model opslaat.
Het lukt mij eerst niet om het opgeslagen model weer op te laden. Heeft te maken met 'customer definities'. Uiteindelijk lukt het mij om alleen de weights weer op te laden. 


  Met maar 2 epochs zit ik aan bijna de 90% validation accuracy. De F1 blijft echter steeds erg laag. Ik kijk naar de sklearn definities en zie dat een imbalanced dataset daar een oorzaak van kan zijn. 
Even kijken:

>>> Counter(val_y)
Counter({3: 46634, 2: 8364, 1: 383, 0: 44})

of

>>> Counter (test_y)
Counter({3: 9351, 2: 1642, 1: 78, 0: 4})

Ja dat is verwacht. Dat kan je wel imbalanced noemen. 

Ook even kijken hoe de predicions zijn:

>>> Counter(predicts)
Counter({3: 9785, 2: 1290})

Uiteraard ook uit balans. Wellicht moet ik meet high en critical incidenten meenemen uit andere services om het een beetje in balans te brengen.

De F1 kan ik iig ergens op laten lijken. Dat 'micro' doet wonderen:
(micro : Calculate metrics globally by counting the total true positives, false negatives and false positives.)

>>> [f1_score(test_y, predicts, average='micro')]
[0.8924604966139955]

Sluit in ieder geval beter aan bij het gevoel. 






 

zondag 24 mei 2020

Leren met letters 13 - Nieuwe insteek

Met een eigen getraind chars2vec model kom ik niet niet veel verder dan (ruim) 80% validation accuracy. Ik test eens wat het effect van mijn training is. Een setje woorden moet meer inzicht geven. Ik kies, in lijn met de meest voorkomende AI tests, voor o.a. katten en honden:

words = ['cat', 'catfish', 'catering','catt', 'kat','dog', 'dogfood',
        'hounddog','computer', 'computation', 'compiling',
        'mouse','mousetrap', 'mousewire','random']

Met het standaard model 50 doet hij dit:

 Standaard 100 vectoren:

Ik zie niet veel verschil. Maar nu mijn eigen getrainde model:

Hmmm. Dat ziet er zo op het eerste gezicht niet zo best uit.  Als we inzoomen is er gelukkig wel verschil:
Bijzonder dat ik uiteindelijk toch die 80% valacc haal hiermee. Ik test of het aan mijn hoofdletter toevoeging ligt met alternatieve charset of wellicht aan de gebruikte dataselectie.
Hmmm. Beide zo te zien. Weliswaar liggen de woorden nu iets beter uit elkaar maar de schaal is nog steeds klein vergeleken met de originele modellen. 

Een ander probleem blijft de de grote datasets en meerdere tussenstappen die ik moet maken om tot het gewenste resultaat te komen. 
Even ter herinnnering: Ik wil karakter input laten meespelen om woorden met een vergelijkbare stam een vergelijkbare betekenis mee te geven. Daarnaast moet ook de betekenis van woorden uit hun omgeving mee gaan tellen (word2vec). 

Wellicht is de training te combineren. Door een karakter woord als input te geven en de omliggende woorden als te voorspellen krijg ik wellicht gecombineerde woordvectoren. Zeker als ik ook mutaties op de woorden mee ga trainen. Ik maak dus voor de input een onehot op basis van de karakters en voor de output een onehot op basis van de (omliggende) woorden.

Uitdaging!!!



  


   

zondag 17 mei 2020

Leren met letters 12 - Op herhaling

Ja, dat is alweer even geleden dat ik mij met deze matererie heb bezig gehouden. (Zo te zien iets meer dan een maand). Tussendoor wat bezig geweest met een opleiding voor AI in healthcare.  Wel wat van opgestoken (sensitivity / specificity / true - false - positives - negatives / ROC / F1  etc) maar geen nieuwe experimenten mee gedaan. (en alweer een beetje vergeten :-( )



Na het laatste succes in het char2word2vec model wil ik dit toch ook eens proberen met hoofdletter gevoelige zinnen. 
Daarvoor moet ik de volgende stappen doen:
  1. De karakterset in het chars2vec model aanvullen met hoofdletters.
  2. Het chars2vec model aanpassen zodat woorden niet naar lowercase worden omgezet.
  3. Het chars2vec model trainen met een eigen woorden corpus dat ook de begin-hoofdletter mee traint.
  4. Op basis van het nieuwe chars2vec model een dataset genereren voor het trainen van 'word - embeddings'.
  5. Het movie-sentiment model trainen op basis van het eigen word2vec model en het neiuwe embeddings model.
Deel 1 en 2 lijken weinig problemen te geven. 

Bij deel 3 (train_chars2vec_eng_caps.py) loop ik tegen memory errors aan. Ik selecteer 70.000 van de aangemaakte woordparen om in 6 epochs het model te trainen. Ik vergeet de vectorgrootte in te stellen dus hij pakt de default van 50 per woord. Misschien wel voor nu even groot genoeg.

In deel 4  (new_model_for_text_evaluation_chars2vec_train_embeddings.py) maak ik bij elk woord uit de movie review corpus, de 4 omliggende woordvectoren aan. Dit om een wordembedding-model te trainen op basis van de 50 vectoren per woord. Dit geeft ook al snel memory errors. De grootte van de input (train_x) is 40.000 x 300 x 50 (zinnen x woorden x vector). Het formaat van de output (train_y) is nog eens 4 x zo groot. Voor deze training neem ik een (willekeurige) selectie van 20.000. Dit blijkt voldoende om de memory errors te ontlopen. Ik bewaar het nieuwe embedding model in 'model-best-c2w2v_v100.h5' waarbij de v100 dus feitelijk niet correct is maar goed, whats in a name?.

Deel 5 (new_model_for_text_evaluation_chars2word2vec2.py) is de 'proof of the pudding'. Ik heb daar een maand geleden met de model vormgeving zitten experimenteren en ik merk dat het begrip over de gebruikte methodiek behoorlijk is weggezakt. Ik loop dan ook al snel tegen meerdere nu onbegrijpelijke fouten aan. Maar eens kijken wat het oorspronkelijke idee is.

  1. Eerst worden de reviews weer omgezet naar v50 vectoren per woord met de functie "conv_text_ch2v". Deze verwijdert de 'tags', splitst de woorden op in zinnen, bewerkt de bijzondere tekens en vertaald vervolgens woorden naar v50 vectoren met de functie "c2v_model.vectorize_words(list of words)". Uiteraard is eerst hiervoor mijn eigen, op hoofdletters getrainde c2v model geladen.  
  2. Deze data wordt opgesplitst in een train en test deel en opgeslagen voor verder gebruik.
  3. De v50 zinnen worden als input in het te trainen eindmodel meegegeven. Daarvoor moet eerst een layer aan het model worden toegevoegd met de getrainde wordembeddings. We maken hiervoor gebruik van een 'hulpmodel':
    • c2w2v_model = load_model(path + 'model-best-c2w2v_v100.h5')
    • get_1st_layer_output = K.function([c2w2v_model.layers[0].input],
    •                                   [c2w2v_model.layers[0].output])
    • hmodel = Model(c2w2v_model.inputs, c2w2v_model.layers[0].output)
  4. Dit 'hmodel' wordt als eerste laag in het te trainen model gebruikt:
    • def Model_attention_conv_api():
    •     input_shape = Input(shape = (max_sent * max_words, max_vec))
    •     x = hmodel (input_shape)
    •     x = Dense(512) (x)
    •     x = Conv1D(512, 2, activation='relu') (x)
    •     x = AveragePooling1D() (x)
    •     x = SeqSelfAttention(attention_activation='relu') (x)
    •     x = Flatten() (x)
    •     x = Dense(128) (x)
    •     x = Dense(label_size-1, activation='sigmoid') (x)
    •     model = Model(inputs = input_shape,outputs=x)
    •     return model
Ik zie nu waarom ik een aantal fouten krijg die ik niet snap. Ik heb blijkbaar nog een poging gedaan om ook de v50 vertaling direkt in het model op te nemen. (Ben dus uitgegaan van de verkeerde code :-( ) 
Dat heb je als je er teveel tijd tussen laat zitten.  

Maar nu doet hij het:

Training met hoofdletters (F1 =  0.80)

Ok, nog geen topprestatie maar wel een aanwijzing dat de methodiek werkt.   


  
          


dinsdag 14 april 2020

Leren met letters 11 - En dus nu ook met woorden !!! (84%)

Het was even lastig maar het is nu gelukt! Het trainen met zowel karakters naar vectoren en vervolgens deze vectoren naar 'word2vec' vectoren. En dan toepassen in het 'vertrouwde' film sentiment model.

De eerste stap was het trainen van de 'word-embeddings'. Ook daarvoor heb ik alle woorden uit de filmsentiment data genomen en ze getraind op 'omliggende woorden':

Train on 12000000 samples, validate on 3000000 samples
Epoch 1/60
12000000/12000000 [==============================] - 1828s 152us/step - loss: 0.2814 - accuracy: 0.0412 - val_loss: 0.2790 - val_accuracy: 0.0398
Epoch 2/60
12000000/12000000 [==============================] - 1716s 143us/step - loss: 0.2790 - accuracy: 0.0415 - val_loss: 0.2790 - val_accuracy: 0.0386
Epoch 3/60
12000000/12000000 [==============================] - 1496s 125us/step - loss: 0.2790 - accuracy: 0.0416 - val_loss: 0.2790 - val_accuracy: 0.0458
Epoch 4/60
12000000/12000000 [==============================] - 1346s 112us/step - loss: 0.2790 - accuracy: 0.0414 - val_loss: 0.2790 - val_accuracy: 0.0425
Epoch 5/60
12000000/12000000 [==============================] - 1290s 107us/step - loss: 0.2790 - accuracy: 0.0416 - val_loss: 0.2790 - val_accuracy: 0.0456 

Met 12 miljoen woorden leek me 6 epochs wel genoeg. Je ziet de validation loss nauwelijks bewegen.

Eerst heb ik de c2w2v vectoren apart willen converteren maar dat gaf memory errors. Gek genoeg niet bij de conversie zelf maar pas bij de poging om de data (met numpy) op te slaan. Blijkbaar heeft die dan tijdelijk meer memory nodig.

Het lukt mij nu echter om de 2e conversie als 'layer' op te nemen.

Eerst maak ik een 'hulpmodel' van de getrainde woord embeddings.

c2w2v_model = load_model(path + 'model-best-c2w2v.h5')
get_1st_layer_output = K.function([c2w2v_model.layers[0].input],
                                  [c2w2v_model.layers[0].output])
hmodel = Model(c2w2v_model.inputs,c2w2v_model.layers[0].output)

En dan kan ik dat hulpmodel als layer opnemen in de Keras 'api - versie' van mijn eerdere model:

def Model_attention_conv_api():
    input_shape = Input(shape = (max_sent * max_words, max_vec))
    x = hmodel (input_shape)
    x = Dense(512) (x)
    x = Conv1D(512, 2, activation='relu') (x)
    x = AveragePooling1D() (x)
    x = SeqSelfAttention(attention_activation='relu') (x)
    x = Flatten() (x)
    x = Dense(128) (x)
    x = Dense(label_size-1, activation='sigmoid') (x)
    model = Model(inputs = input_shape,outputs=x)
    return model

Wow, daar ben ik best wel trots op. Nu eens kijken wat het resultaat gaat zijn. Misschien lukt het zo ook nog wel om ook de chars2vec zo op te nemen zodat data conversie niet nodig is.


Dat is heel niet slecht, lijkt mij. Welliswaar nog niet bij de 85% val acc die ik zou willen maar voor een eerste test ben ik verre van ontevreden.

En na even door trainen bijna 83% !!!



Een, iets hogere trainings rate (van 0.00001 to .0001) geeft een score van meer dan 84% in 16 epochs! We naderen de beoogde 85%!!!


This is the result with chars2vec size 100 (instead of 50)  



maandag 6 april 2020

Leren met letters 10 -chars2words2vec ?

Hoewel het 'leren met letters' al behoorlijke resultaten heeft gegeven geeft het chars2vec vooral 'kennis' over gelijksoortige woorden zoasl hier:

De kennis van een word2vec lijkt meer (onderlinge) betekenis vast te leggen.

En is daarmee dus een krachtige opstap voor elk NLP algoritme.  Nadeel van word2vec is, zoals eerder beschreven, van elk woord in principe door een getal wordt vertegenwoordigd en dus, stam,  hoofdletter en spelfout ongevoelig is. Zie hier voor meer informatie.

Wellicht is een combinatie van die 2 een goede oplossing. Word2vec wordt in principe getraind door voor elk woord de meest waarschijnlijke omliggende woorden te voorspellen. Dat moet, denk ik, ook te doen zijn voor de chars2vec vectoren. Neem bijvoorbeeld een woord dat met chars2vec in 50 'features' wordt beschreven. Er moet een NN te trainen zijn dat de meest waarschijnlijke, omliggende 6 * 50 woordfeatures kan voorspellen. (of meer/minder). De vectoren die hierbij ontstaan zijn dan, denk ik, de chars2word2vec vectoren. Met hopelijk de voordelen van beide ineen verpakt.
Wel zullen deze vrij groot uitpakken, neem ik aan. Als in een normale word2vec vaak minimaal zo'n 100 vectoren worden getraind en we voor chars2vec uitgaan van het huidige kleinste model zijn dat al 5000 vectoren per woord. (Bert base heeft er bijvoorbeeld 768).

Voor de test eerst maar eens uitgaan van bijvoorbeeld 30 woordvectoren dus een totaal van 50*30. Het gaat er tenslotte eerst om om aan te tonen of 'chars2words2vec' kan werken. Ik denk dat ik maar eens terug ga naar mijn filmrecentie experimenten.


 


donderdag 2 april 2020

Leren met letters 09 - Zelf een NL chars2vec netwerk trainen.

Nee, deze keer nog geen nieuwe resultaten in het verder optimaliseren van het deeplearning met chars2vec. Maar wel een start met iets nieuws: Kijken of ik ook zelf een chars2vec embedding network kan trainen. Met name ook met Nederlandse woorden. En wellicht later een keer met hoofd- en kleine letters. (Daar was het tenslotte allemaal (ondermeer) om te doen. Om de 'betekenis' in een zin van hoofdletters mee te kunnen nemen zonder daarbij een volledig nieuw 'woord' te hoeven maken. Zie toelichting hier.

Ik heb al eens eerder Nederlandse wiki artikelen gedownload en die staan nog 'braaf' te wachten om verder van nut te zijn. Dat komt nu goed uit.

Ik moet blijkbaar trainingsdata maken in deze vorm:

X_train = [('mecbanizing', 'mechanizing'), # similar words, target is equal 0
           ('dicovery', 'dis7overy'), # similar words, target is equal 0
           ('prot$oplasmatic', 'prtoplasmatic'), # similar words, target is equal 0
           ('copulateng', 'lzateful'), # not similar words, target is equal 1
           ('estry', 'evadin6'), # not similar words, target is equal 1
           ('cirrfosis', 'afear') # not similar words, target is equal 1
          ]

y_train = [0, 0, 0, 1, 1, 1]

Dat zou moeten lukken. De NL wiki beval genoeg woorden zou ik zeggen om een stevige hoeveelheid materiaal aan te maken.

Het gaat om 211.674 wiki artikelen en dat blijkt al snel veel te veel voor mijn (computers) geheugen. Ik neem de eerste 5.000 en kom daarmee op 222948 verschillende woorden als uitganspunt. Dat is best veul!



Van deze woorden maak ik 1 x een paar met random letter vervanging, 1 x met letter verwisseling en 2 x met een random ander woord. Na 'schudden' selecteer ik de eerste 100.000 paren om de training mee te doen. Hier een voorbeeld:

[('Engelsche', 'Engelscje'), ('visual', 'Lichenology'), ('Inhoudsopgave', 'Ministre'), ('Dandelion', 'Dandeilon'), ('tombe', 'tobme'), ('woningcrisis', 'tollenaar'), ('gallicisme', 'gallicisem'), ('Boekhoorn', 'Boekhoorn'), ('bouwster', 'richtinggetrouw'), ('Reu', 'eRu')]

Grappig dat het eerste woord van deze NL selectie 'Engelsche' is.

Standaard traint het model 200 epochs met 10 'patience' d.w.z. dat er maximaal 10x geen verbetring in de costfunctie te zien mag zijn. Ik ben ongeduldig en verander dat laatste naar 3x.
Hij draait nu in ongeveer 316 seconden 1 epoch en ik moet er 17 wachten tot hij vanzelf stopt.

Epoch 17/200
95000/95000 [==============================] - 281s 3ms/step - loss: 4.2194e-04 - val_loss: 0.0023

Een nette validatie loss, lijkt mij, en hij saved netjes he model in de door mij opgegevn directory.
Nu gaat het erom spannen of ik er ook redelijke resultaten mee ga halen. Wordt vervolgd!












dinsdag 24 maart 2020

NLP Document / semantic text similarity - module test

Na het avontuur met letter - leren, waar ik vast nog eens op terug kom, nu even weer iets anders. Ik heb al eens eerder geexperimenteerd met documentvergelijking. Dat lijkt mij een zinvolle toepassing, Ook bijvoorbeeld in het checken in een 'incident registratie systeem' of een bepaald probleem al eens eerder is gemeld. Ik zoek of er al eens iets met Bert is gedaan (uiteraard) en vind deze site.

Het installeren met pip van "semantic-text-similarity" gaat goed. Evenals de import. Maar het 'activeren' van het model geeft, na het initieel juist downloaden dan de model-date, een error. Op een of andere manier zijn er onvoldoende rechten op de plek waar het model 'ge-unzipped' moet worden. Met wat aanpassingen in de code weet ik dat te omzeilen. Hierdoor krijg ik gelijk de mogelijkheid, denk ik, om andere Bert modellen uit te proberen. Maar eerst maar eens deze.  




Ik gebruik een selectie van incident teksten uit ServiceNow. Ik wil nu ook de uitgebreidere omschrijvingen meenemen maar zie tot mijn verbazing dat het Snow rapport ze wel selecteerd maar dat ze in de download niet worden meegenomen in de huidige Snow versie. Eerder was dat geen probleem. Ik kijk naar de verschillende 'download-opties' (xlxs / csv / pdf / json) en zie dat alleen json ze wel meeneemt. Het rare is dat daar helemaal niet naar de kolomselecties wordt gekeken en ik krijg dus nu alle mogelijke velden mee. Maar goed, dat is beter dan te weinig.

Het lukt mij vrij snel om en programma te maken dat de teksten uit de verschillende incidenten met elkaar vergelijkt en er een 'similarity score' van 0 tot 5 aan geeft.
Hier een paar voorbeelden:

89 *****************************************************************************************************   4
Not able to login into skype, error could not login  not able to login into skype, error could not login
935 ====================================================================================================
Skype is not able to login  skype is not able to login


85 ****************************************************************************************************   3
WO-01368223 no PA available  kindly,i couldnot find a pa for the work order wo-01368223 ,please,fyka
3195 ====================================================================================================
kindly your support is highly appreciated as I didn’t found the PA for the work order WO-01396592 after making Many Synchronization.


73 ****************************************************************************************************   2
TS: Time Statement missing/wrong since 9th of february, timestatement is missing entries
348 ====================================================================================================
TS: do not receive Time Statements even with today's time accounting my reported times were not counted. my time-writing is since the beginning of february. 

Valt mij niet tegen. Het gaat natuurlijk hier om kortere teksten maar er lijkt aardig wat 'logica' gebruikt te worden.

Nadeel is wel dat het (relatief) enorm lang duurt om teksten met elkaar te vergelijken. Hij heeft er ongeveer 10 uur voor nodig gehad om 153 documenten met 3598 te vergelijken. Even rekenen ... zijn dus 917 vergelijkingen per minuut. hmmmm  15 per seconde. Is op zich niet slecht maar eigelijk wil je misschien ongeveer 3598 * 3598 documenten vergelijken. Dan duurt het 235 uur.  Tja...



Eens kijken of het ook nog sneller kan.
  
   

zondag 22 maart 2020

Leren met letters 08 (83%) - Een eigen Keras layer

Vandaag heb ik mij verdiept in het maken van een echte eigen Keras layer. door de gekozen vaste structuur van mijn data heeft het model met chars2vec veel ruimte nodig om de data op te slaan. De v50 versie gaat prima, de v100 ook nog wel maar de v200 lijkt wel de limiet te zijn. Ik zou zo graag ook nog eens de V300 versie testen. Bert werkt tenslotte met 768 vectoren dus waarom ik niet met minstens 300 😀 ?



De oplossing zou mogelijk zijn om de chars2vec conversie als eerste layer in het model op te nemen. Dan bied ik gewoon de teksten aan als list en de eerste layer maakt er de mooie vector van gebaseerd op chars2vec.

Ik probeer deze eenvoudige 'class' toe te voegen:

class C2v(Layer):

  def __init__(self, units=batchsize, input=[]):
    super(C2v, self).__init__()

  def call(self, inputs):
    return conv_texts_c2v(inputs) 

De conv_texts_c2v splitst de input op in losse teksten en laat ze in conv_text_ch2v per tekt eerst wat opschonen rond tags en punctuaties en roept vervolgens het c2v_model.vectorize_words aan om alles om te zetten naar passende vectoren.
Na wat experimenteren lijkt de syntax in ieder geval goed. Helaas komt er een foutmelding dat dit zo niet is toegestaan:

tensorflow.python.framework.errors_impl.OperatorNotAllowedInGraphError: iterating over `tf.Tensor` is not allowed in Graph execution. Use Eager execution or decorate this function with @tf.function.

Ik probeer uiteraard de 'decorating optie' maar dat geeft helaas nog geen verbeteringen. Ook 'eager excecution', waar eerder naar verwezen wordt lijkt hier helaas niets te doen.
Het is mij nog niet duidelijk wat er nu precies fout gaat maar het lijkt te maken te hebben met de tensorflow graph-methode die bepaalde zaken niet toestaat.

Bij de keras embedding layer is het toch ook mogelijk om bijvoorbeeld pretrained word2vec te gebruiken. De code daarvan geeft mij helaas niet veel houvast. 


zaterdag 21 maart 2020

Leren met letters 07 (83%) - Door naar vectorsize 100

Na het laatste succes door enerzijds de stride in de conv layer terug naar 2 te brengen en anderzijds ipv een maxpooling een avarage pooling layer te nemen (ik heb ook nog de sigmoid activatie bij de selfattention layer door een relu vervangen maar dat leverde alleen iets tijdswinst), probeer ik nu weer even of de 100 vector ons naar 83% kan brengen.
En inderdaad we komen voorbij de 83! Met ook een F1 van ruim 83%.

Wellicht is dit model nog door te trainen.


vrijdag 20 maart 2020

Leren met letters 06 (82%) - Aangepaste stride conv-layer

Soms kunnen wat kleine aanpassingen weer voor verbetering zorgen. Ik heb de stride van de conv layer van 5 naar 3 teruggebracht. (conv naar 7 maakte het veel slechter)  Hoewel ik, voor de snelheid van het proberen van verschillende varianten weer teruggegaan ben naar de 50 vector kom
ik in de nieuwe test uit op een kleine 82%! Grappig is wel dat nu ook de train accuracy lager blijft uitkomen. Mogelijk duidt dat op minder overfitting. (Meer generalisatie)


En met een stride van 2 nog beter. Nu ook boven de 82:

F1           =  [0.817]

donderdag 19 maart 2020

Leren met letters 05 (81%) - Grotere char-vector sizes

Dit is het resultaat van 'doorleren' met een dropout van 30%


Zoals aangegeven volgt de validation accuracy nu mooi de training accuracy, zoals te verwachten op een iets lager niveau. Helaas breekt die af bij de 71 epochs door de early stopping van 10 x geen val_loss verbetering. Dus erg veel hoger komt die helaas niet.

Ik besluit de nacht te gebruiken om 100 in plaats van 50 features voor chars2vec te testen. De dataset is nu opnieuw te groot (8.94 GB) voor mijn pc-geheugen en het programma blijkt te zijn afgebroken. Gelukkig gaat de conversie (gek genoeg) pas fout bij het proberen op te slaan van de data. Door wat overbodige variabelen weg te gooien lukt het toch om de save uit te voeren en het programma verder te laten trainen.

We komen nu boven de 81% val acc met een F1 van 81%. Niet slecht! (Maar nog niet bij de gewenste 85% 😒). Wellicht dat wat dropout nu wel kan gaan helpen?

Helaas, de dropout trekt alleen de train acc omlaag maar neemt de test/val acc niet mee omhoog. Wel grappig overigens dat de val acc voornamelijk boven de train acc blijft.

Ook een test met dubbele layers, met vectorvergroting naar 200 (max_sent   =  10, max_words  =  20, max_chars  =  15) en een correctie omdat er nog een deling door max uitgevoerd werd, toch geen hogere vall_acc score helaas.
 

woensdag 18 maart 2020

Leren met letters 04 (79%) - Tests dropout/double layers/normalisaties

Oke, na het succes van de chars2vec conversie nu eens kijken of we de resultaten nog verder kunnen verbeteren. Huidige score is een test accuracy van bijna 80%. Met een F1 van ook bijna 80: (0.7999). 

De accuracy loopt nog omhoog na 60 epochs maar de test acc lijkt wat af te vlakken. Doortrainen heeft dus vermoedelijk maar beperkt zin. 

Ik test wat zaken achter elkaar:

  • dropout layers om overfitting te voorkomen. Eerst maar eens 20% bij elke layer.
  • dropout 50%
  • dropout 10%
  • dubbele layerset. Ik zie echter te laat dat ik ook de normalisatie layer actief heb gemaakt en de 'input layer' heb gekopieerd.
  • dubbele layerset met correcties (normalisatie + inputlayer weg)
  • verschillende locaties van de normalisatie layer. (na dense, na conv)
  • normalisatie tussen conv en aparte activation layer
Geen enkele aanpassing leidt tot een verbetering tot nu toe. Met name de normalisatie layer geeft (weer) instabiliteit en zorgt ervoor dat de 'early stopping' van 5 pogingen om de 'validation loss' te verminderen, de zaak af laat breken.

Mislukken, zoveel leuker dan nooit proberen :-)


Dit is een voorbeeld van het 'dropout 10%' resultaat:

Door de early stopping op '10' te zetten kan ik een dropout van 30% doortrainen naar 60 epochs met dit resultaat:

Het aardige is dat, hoewel de accuracy minder hard klimt dan oorsponkelijk, de validation accuracy nu 'meegroeid'. Tussen de 40 en 60 komt er ongeveer 3% bij. Dat zou kunnen betekenen dat we met 100 epochs in de buurt van de gezochte 85% validation accuracy kunnen komen. (2x3% minus de afvlakking). Proberen maar!

Ondertussen eens kijken of ik een keras layer van de words2vec zou kunnen maken zodat ik de data niet in zijn geheel van tevoren hoef te converteren en dus ook mogelijk de '300 feature-variant' in mijn computers geheugen past.


      

Leren met letters 03 (80%) - Introductie chars2vec module

Met deze exercitie hoop ik de ingebouwde (semantische?) betekenis van de woorden te behouden door uit te gaan van codering van letters in plaats van de gangbare codering van woorden, Dat is enigzins succesvol maar haalt het nog bij lange na niet bij de resultaten die met woordcoding worden gehaald. Een belangrijke missende factor is de embedding ofwel word2vec methodiek. Hierbij wordt dus de betekenis van woorden in hun onderlinge relatie in de zinnen geleerd.

Ik had stiekum gehoopt dat dit, door de manier van aanbieden van de data, 'meegeleerd' zou worden. Omdat ik nog niet precies snap hoe het algoritme zelf in detail in elkaar steekt is het versterken van het model met een eigengebouwde 'char2vec' oplossing nog geen optie. Gelukkig vind ik anderen die zich met dezelfde problematiek hebben bezig gehouden.



Met een eenvoudige import van de python 'chars2vec' module (en wat gepruts aan het programma) kan ik de eerder gebruikte documenten omzetten naar voorgetrainde vectoren. Er is keuze uit verschillende voorgetrainde formaten dus uiteraard 😁kies ik eerst de grootste (300). Dat leidt tot een memory error dus ik besluit de nacht te gebruiken voor een hertraining met het (kleinste) 50 vectoren formaat.

En succes!

We schieten omhoog van 66% test accuracy naar ruim 80%. Wow!!
Met een F1 van ook bijna 80: (0.7999).

Dat is nog eens vooruitgang! Nog niet de streefwaarde van 85 testacc of meer maar we komen in ieder geval behoorlijk in de buurt.


maandag 16 maart 2020

Leren met letters 02 (66%) - Normbepaling (85%) - data cleansing - layer volgorde

Op deze site wordt dezelfde sentiment analyse uitgevoerd met de movie database en dan met het gebruik van woorden als tokens. De resultaten daar lijken een aardige 'streefnorm' te geven.

Met dit eenvoudige embed / lstm model komt men daar tot een test accuracy van 85%

_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
embedding_3 (Embedding)      (None, 100, 100)          9254700
_________________________________________________________________
lstm_1 (LSTM)                (None, 128)               117248
_________________________________________________________________
dense_3 (Dense)              (None, 1)                 129
=================================================================
Total params: 9,372,077
Trainable params: 117,377
Non-trainable params: 9,254,700

Het laatste testmodel komt ongeveer tot 64% dus nog een stevige weg te gaan. Eerst even kijken of ik iets mis in de data-voorbehandeling. Tags, punctuaties, enkelvoudige karakters en dubbele spaties worden verwijderd. Ik neem de "tag-verwijderfunctie" over. Die geeft inderdaad mogelijk onnodige onzin. De andere laat ik voorlopg in mijn model intact. Punctuatie heeft m.i. betekenis. Ik kan hier wellicht later nogeens op terugkomen.

Dit is het resultaat zonder de tags:

Die lijkt wel heel erg op de laatste met tags. Dat heeft dus niet veel uitgehaald. Wel is de F1 van 63 naar bijna 64% gegaan. Maar dat kan een random effect zijn.

Ik test of de volgorde van de nu gebruikte layers veel uitmaakt.

  1. uitgangspunt: dense/conv/maxp/atten (+flatten + dens)
  2. dense/atten/conv/maxp
  3. dense/conv/atten/maxp
Maar de oorspronkelijke volgorde lijkt tot nu toe toch de beste resultaten te geven.
De bedoeling is om een serie layers te gaan herhalen analoog aan de opbouw van Bert. Ik test een eerst een verdubbeling'. Ik zie zojuist dat model 2 en 3 hierboven een stevige tijdsverlenging met zich mee brachten. Van 38 naar 72 sec per epoch. Bij de verdubbeling van de lagen gaat de tijd naar zo'n 49 seconden.


Dat is interessant. Een verdubbeling van de layers lijkt voor een iets betere training accuracy te zorgen maar laat de validatie acc een beetje weglopen. Dat lijkt op overfitting te duiden.

Ik ga even terug naar de oorspronkelijke kearning rate (0.00001) en laat het model nu een keertje doortrainen naar 60 epochs.

Dat lijkt toch wel interesant, Naar de 66% test accuracy met een mooie F1 =  0.659. Wel lopen de curves wat uiteen en de verhoging gaat maar langaam. Ik scan eens of er andere karakter gebaseerde modellen te vinden zijn en kom op chars2vec. Die moet ik maar eens bestuderen.