maandag 18 januari 2021

Toch weer even met mnist spelen

 Al heel lan g niets meer met de AI dataset der datasets gedaan: De Mnist geschreven nummerset met afbeeldingen van 0 t/m 9 in een 28x28 formaat.

Zoals deze:

  

De reden hiervoor is een artikeltje over het leren zoals mensen dat doen op SingularityHub. 

Er wordt vaak aangegeven dat de huidige NN's zo ontzettend veel voorbeelden moeten hebben om een beetje kennis op te doen. Dit in schijnbare tegenstelling tot mensen die aantal voorbeelden al genoeg lijken te hebben. Vaak wordt echter denk ik vergeten dat mensen als baby en kind (en volwassene) eerst een heleboel voorbeelden waarnemen voordat ze hiertoe in staat zijn.  Dagelijks neemt men elke seconde nieuwe beelden op die als ervaring gebruikt kunnen worden. 

Babies beginnen, meen ik met vage, en dus vereenvoudigede, beelden omdat ze simpleweg nog niet de goede lenzen hebben. Maar ze leggen wel al langzamerhand verbanden, Geleidelijk wordt het zicht beter en daarmee de complexiteit van de afbeeldingen groter. Het leek mij wel leuk om dat ook eens met een NN te proberen en welke is dan beter dan mnist!

Eerst draai ik een oud, ongewijzigd model om een 'baseline' te krijgen:

Een test accuracy van 0.9947 %. Aardig om mee te beginnen. 
Een blurfilter vind ik in cv2 met de toepasselijke naam 'cv2.blur'. Daat kan ik ook een blurfactor invullen als tuple (bijvoorbeeld (5,5)). Ik neem even aan dat dat vertikale en horizontale blur betreft.
Hier een voorbeeld:

Blurred (5, 5)

Blurred (7, 7)

Ik kan mij een beetje voorstellen dat een baby een dergelijk beeld 'van de wereld' zou kunnen hebben.
Eerst maar eens trainen op blurred(5, 5). Ook op de y_train waarden gebruik ik de blur functie waardoor bijvoorbeeld  
        y_train[0] = array([0., 0., 1., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)
Deze waarden krijgt: 
        y_train_blur[0] = array([0.08, 0.04, 0.04, 0.12, 0.12, 0.16, 0.16, 0.16, 0.08, 0.16], dtype=float32)

Ik weet nog niet waar ik tijdens de 'blur-training' de waarde op uit wil laten komen. (Babies zullen ook niet direct weten wat ze met een cijfer 3 aanmoeten ;-) Dus dit lijkt wel even een aardige manier om mee te beginnen.


Oke, niet een verbetering maar ook niet slecht met een testaccuracy van 0.9942. Bij pretraining met dubbel blurring (7,7) gaan we terug naar 0.9930. 

Ik probeer eens om zowel een (7,7) als een (5,5) blurring achter elkaar als pretraining uit te voeren. Ik kom dan terug op onze benchmark 0.9947. 

Het helpt blijkbaar een beetje om y_train ook te blurren want zonder dat zaken we naar 0.9942. 

Bij 'halfsize double blurring' (5,5) en (3,3) ga ik voor het eerst iets (1/100%) omhoog t.o.v. de benchmark: 0.9948 

Ik probeer of het toevoegen van wat noise kan helpen. We duiken weer omlaag naar 0.9935

Gezien het 'succes' van de 'halfsize blurring' probeer ik ook eens of ik blurring in meerdere stappen kan laten trainen. [(9,9), (7,7), (5,5), (3,3)] Helaas is dat geen goed idee : 0.9925

Goed, terug naar 'halfsize double blurring' en eens kijken of ik hier iets met de y_train waarden kan doen. Daar veel noise toevoegen is geen goed idee (0.9904)

Dat gaat al veel beter bij een kleine noisefactor van 0.01. Ik ben weer terug bij 0.9948

Misschien is het beter om te starten met waarden rond de 0,5 ipv 0,0? Nee: 0.9939

  

Zou ik ze gewoon vast naar 0 moeten laten trainen? --> Nee, helaas (0,9944)

Misschien pretrainen met niet geblurde afbeeldingen? (Dat haalt wel mijn feitelijke uitgangspunt met de slecht ziende babies een beetje onderuit) Wow, niet verwacht: 0,9914! Dat is wel heel erg omlaag. Het lijkt erop dat pre-trainen op bovengenoemde manieren nog niet veel oplevert.

 ðŸ˜’







maandag 4 januari 2021

Bert , terug van weggeweest

Om verder te kijken wat we in de (IT) bedrijfsprocessen met AI zouden kunnen doen heb ik opnieuw een setje incidenten (GCS - Global Customer Service) geladen (24.586 records) maar deze keer met de tijdsduur die het heeft genomen om het incident te behandelen. Hiermee wil ik kijken of ik kan voorspellen hoe moeilijk (tijdsintensief) het betreffende incident is. (Of dus 'gaat zijn').

Omdat de tijdsduur in seconden staat opgenomen lijkt het mij zinvol om een logaritmische schaal toe te passen. Hierdoor krijgen we uitkomsten van tussen de 0 en de 7 (6.792 om precies te zijn). 

Bij het omzetten naar logaritmische waarden krijg ik -inf waarden als de tijdsduur 0 is. Dat moet ik eerst even corrigeren om het model goed te laten werken.

Hier is een verdeling van de (naar beneden) afgeronde logaritmische waarden:

Als input gebruik ik de 'Short description', de 'Service' en de 'Assignmentgroup' en de 'Description' tot een maximum lengte van 128 tokens. De Service blijkt uitsluitend 'GCS Helpdesk' te zijn, dus die kan ik eigelijk uitsluiten. De assignmentgroup moet er ook eigelijk uit. Dat is wellicht juist iets wat later op basis van de complexiteit moet worden gestuurd.   

Normaal heb ik met het Bert model classificaties uitgevoerd. Nu gaat het om een regressie probleem: Het vinden van een getal welke de 'duur' (complexiteit) aangeeft. De loss pas ik aan naar 'mse' (mean squared error)  Al snel weet ik het model nu aan de praat te krijgen. 


Bij 4 epochs vindt die het beste resultaat. Maar hoe goed doet die het nou? Een error van, zeg maar, 0.82 is dat nu goed (genoeg) of niet?
Door ook weer hier te tellen hoeveel voorspellingen goed zouden zijn krijg je een beetje een indruk.  Dit wordt in dit geval bepaald door de 'acceptabele afwijking'. 
Bij een maximale afwijking van 1.0 krijg ik   0,79% correctheid. Dus in vrijwel 80% van de gevallen lijkt de complexiteit redelijk juist te voorspellen. 

Of dit ook in de praktijk bruikbaar kan gaan zijn moet nog blijken. 

Ik ga nu ook even kijken of ik de hierboven genoemde overbodige 'features' eruit kan halen en alleen op basis van de korte beschrijving andere resultaten krijg. 
  

 

Dat lijkt toch wat minder positief. 

 print("Percentage correct :",count / len(test_y))

Percentage correct : 0.4493877551020408


Als ik de lange omschrijving toch mee neem krijg ik dit resultaat:

Percentage correct : 0.6557142857142857


Met het toevoegen van alle initiele (door de gebruiker ingevulde) invoervelden, zoals 'Incident Type', ('Service'), 'Configuration item', 'Impact', 'Short description' en 'Description' haal ik ruim 70%

Percentage correct : 0.7157788944723618



Dat valt niet tegen.

Incident type = {'Question', 'Complaint', 'Incident'}
Configuration item verwijst meestal naar de betreffende applicatie ('Incenter Online' of bijv. 'MS Office') maar kan ook nar en locatie verwijzen (bijv. 'ServiceMax NAM')
Impact = {'3 - Low', '2 - Medium', '1 - High'}

Als ik een opschoning doe door veel voorkomende afkortingen om te zetten alsmede email adressen weg te halen wordt het nog beter (hoewel de beste 'val loss' iets hoger lijkt uit te komen- ruim 74%:

Percentage correct : 0.744321608040201
Een 2e keer hetzelfde, met anders geshuffelde gegevens, geeft iets vergelijkbaars.
 
Percentage correct : 0.7276381909547739


>>> confusion_matrix(np.round(test_y),np.round(predicts))
array([[   0,    0,    4,    4,   19,    1,    0,    0],
       [   0,    0,    1,    0,    0,    0,    0,    0],
       [   0,    0,  404,  595,  205,    6,    0,    0],
       [   0,    0,  144,  764,  738,   10,    0,    0],
       [   0,    0,   16,  181, 1017,   45,    0,    0],
       [   0,    0,    5,   67,  423,   51,    2,    0],
       [   0,    0,    7,   42,  186,   29,    3,    0],
       [   0,    0,    0,    1,    4,    1,    0,    0]], dtype=int64)