dinsdag 31 mei 2016

01 - Ultrasound - De start. Ga ik mee doen?

Een nieuwe Kaggle competitie met een medisch onderwerp! Ultrasound! Uiteraard leuk om weer mee te doen hoewel er een aantal andere projecten nog in de wachtkamer zitten. Mijn 'helpdesk' en de 'robotarm'. Nou ja. Even de zinnen weer verzetten. 100.000 dollar aan prijzengeld! Kat in 't bakkie :-)

Eerst maar een wat onderzoek doen. Uit onbegrijpelijke echobeelden vol met ruis moet de lokatie van een hals zenuw worden gevonden. De 'maskers' worden meegegeven. Hieronder nog een beetje begrijpbare locatie. De meesten lijken gewoon nergens op. Boven een verzameld overzicht van alle 5071 trainingsmaskers. Een groot deel daarvan blijkt leeg.  


maandag 23 mei 2016

02 - Helpdesk

Het nadeel van de gekozen opzet is natuurlijk dat ik de nauwkeurigheid van het NN niet echt kan testen. Uiteraard geven mijn validatie descriptions afwijkende antwoorden:

0 Short description  : user claim the counterdesk is closed                        
0 Suggested solution : code new link sent to user code 

0 Real solution      : advice user to contact the receptionist or contact the management of the counterdesk user acknowledge

1 Short description  : i am unable to install any software from software portal                    
1 Suggested solution : transfer lendie humble
1 Real solution      : called the user on      user informed that the issue is resolved gave consent to closethe call 

2 Short description  : dropped chat                            
2 Suggested solution : dropped invalid call
2 Real solution      : dropped chat  chat crashed could not recover chat log

3 Short description  : email  user mentioned sometime he did not receive email                    
3 Suggested solution : transfer lendie humble
3 Real solution      : code pankaj confirmed the messages are getting through just fine  issues resolved  code 

4 Short description  : aventail not working                           
4 Suggested solution : dropped invalid call

4 Real solution      : uninstall aventail deleted aventail log installed aventail 


Het voorbeeld nummer 2 hier lijkt het (toevallig?) aardig te doen. Maar de rest is nog ver van juist.
En hoewel de 'loss' en 'validation loss' per Epoch aan het afnemen zijn is het moeilijk te bepalen hoe goed of slecht mijn NN het doet. Wellicht kan ik de resultaten testen door in de 'short descriptions' van de 'learndata' wat random variatie te gooien en dat dan als validatie descriptions aanbieden.
De oplossing is daarnaast niet zo 'scalable'. Nu heb ik nog 'maar' 17.207 mogelijke uitkomsten. Ik vind het al knap dat mijn putertje dat aankan. Als ik per nieuw ticket een oplossing blijf aanbieden wordt de matrix echter onhanteerbaar. Hmmm. Vraagt dus een andere strategie. Eventjes laten bezinnen.

Ik heb naast de 'short description' en de 'solution' ook nog een 'service offering'. Die kan ik wel gebruiken. Bijvoorbeeld om tickets automatisch te classificeren. Ik maak een 2e, vergelijkbare NN aan maar nu met de service offerings als output. Met de validatie records kan ik nu wel een betrouwbaarheidsmeting doen. Ik kom uit op ongeveer 50%. Ook als ik mijn LSTM ombouw naar een 'gewoon' NN. Wellicht komt dat door een onzorgvuldige selectie van de offering bij de registratie van de tickets. Is 'unable to connect' bijvoorbeeld een software / hardware  of netwerk issue?
Er moet toch iets meer intelligentie uit te halen zijn. Ook maar eens even laten bezinnen ...  

Om meer inzicht te krijgen in het verloop van het leerproces probeer ik Keras 'plot model' te gebruiken.


from keras.utils.visualize_util import plot

Dat werkt helaas niet zomaar. 'pydot' en 'graphviz' krijg ik blijkbaar niet zomaar met 'pip' installatie gekoppeld. Ik wordt verwezen naar 'MacPorts'.  Als ik dan na installatie daarvan


$ sudo port install graphviz-gui

intyp gaat hij een hele hoop dependencies installeren:


--->  Dependencies to be installed: graphviz expat fontconfig freetype bzip2 libpng zlib libiconv gd2 jpeg tiff xz gettext ncurses xpm xorg-libXext xorg-libX11 xorg-kbproto xorg-libXau xorg-xproto xorg-libXdmcp xorg-libxcb python27 db48 libedit openssl python2_select python_select readline sqlite3 xorg-libpthread-stubs xorg-xcb-proto libxml2 xorg-xextproto xorg-libXt xorg-libsm xorg-libice gts glib2 libffi pcre libnetpbm libLASi pango Xft2 xrender xorg-renderproto cairo libpixman xorg-xcb-util gobject-introspection libtool py27-mako py27-beaker py27-setuptools py27-markupsafe harfbuzz graphite2 urw-fonts webp xorg-libXaw xorg-libXmu

Gelukkig blijkt mij Theano nog steeds te werken. Ook moet ik nog de applicatie graphviz installeren. Phoe... Het resultaat is wat teleurstellend. Althans ik was naar wat anders op zoek:



Met de volgende statements kom ik wat verder:


from keras.callbacks import History

history = History()

model.fit(x_train, y_train, batch_size=64, nb_epoch=1, validation_data=(x_test, y_test), callbacks=[history])
print( history.history['loss'])

Daar kan ik iig het verloop (van o.a. de 'loss') mee vastleggen in een variabele en dan bijvoorbeeld in een grafiek plotten.

01 - Helpdesk

Chatbots zijn 'in' dit jaar. En aangezien deze natuurlijk iets zinnigs te vertellen moeten hebben zouden die heel goed inzetbaar moeten zijn / worden als helpdesk. Reden om eens te kijken of ik een eenvoudige vorm daarvan aan de praat kan krijgen op basis van helpdesk tickets. Concreet wil ik eens kijken of er, op basis van de korte beschrijving, een bijpassend 'meest waarschijnlijk' antwoord kan worden gegenereerd.



Een interessante oefening (vind ik dan toch :-) om ook eens met Keras LSTM (Long Short Term Memory) te werken. De gedachte is dat woorden in een zin een volgorde hebben die relevant is voor de keuze van het resultaat. Ik heb al eens eerder met LSTMs geƫxperimenteerd zodat ik 'nieuwe verhalen' kon schrijven op basis van een bestand boek. Daar werd steeds het eerstvolgende woord (of letter) gegenereerd. Nu wil ik als eerste dat de index van de oplossing van de vaag wordt gegenereerd. Gelukkig heeft Keras een aardig en eenvoudig voorbeeld model:

model = Sequential() model.add(LSTM(32, return_sequences=True, input_shape=(timesteps, data_dim))) # returns a sequence of vectors of dimension 32 model.add(LSTM(32, return_sequences=True)) # returns a sequence of vectors of dimension 32 model.add(LSTM(32)) # return a single vector of dimension 32 model.add(Dense(10, activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])

Een gelaagd LSTM model met een uitkomst in dit geval van 10 vectoren.

De uitdaging voor mij is om de woorden in de korte omschrijvingen te 'vectoriseren' (gewoon een indexnummer toekennen). Ik overweeg nog even om een word2vec 'ertussen' te bouwen zodat er meer 'betekenis' in de vectoren komt maar dat komt later misschien nog wel een keer.

Er zijn 17207 tickets nadat ik die 'zonder aangegeven oplossing' eruit heb gehaald. Zoals al eerder is he eerst een uitdaging om de tekst schoon te krijgen. Er blijkt in de 'oplossingen' ook veel html-code te zitten. Die haal ik eruit met een bibliotheek die 're' heet:

import re
def cleanhtml(raw_html):
    cleanr =re.compile('<.*?>')
    cleantext = re.sub(cleanr,'', raw_html)

    return cleantext

Daarnaast zie ik ook een aantal Chinese karakters. Het is blijkbaar een unicode bestand. Het vertalen naar ascii vraagt om wat vreemde truckage: (De reload is blijkbaar noodzakelijk)

import sys
reload(sys)

sys.setdefaultencoding('utf8')

Intxt = Intxt.encode('ascii', errors='ignore')

Met nog wat vervangingen van wat codes en vrijwel alle tekens lukt het om de gewenste 'schone tekst' te krijgen.

Voor de indexering gebruik ik weer een eerder afgekeken enumerate in een 'dictionary'.

char_indices = dict((c, i) for i, c in enumerate(words))

indices_char = dict((i, c) for i, c in enumerate(words))

Ik splits de dataset na een 'shuffle' op in een 'train' gedeelte van 15486 en een validatie gedeelte van 1721 samples. Van de uitkomstwaarden (Y) maak ik een boolean array ter grootte van het aantal records. Dat is dus wel een uitdaging voor een NN! Van, zeg, gemiddeld een 10-tal woorden een keuze maken uit 17207 oplossingen! Hmmm misschien wat te hoog gegrepen.





 
  

     

woensdag 11 mei 2016

Reenforcement learning revisited.

Door de successen van DeepMind met het automatisch leren van Atari spelen maar meer nog de overwinning op de wereld speler GO onlangs is re-enforcementlearning een zeer interessante machinelearning tak geworden. Er is een aardige website waar e.e.a. is beschreven. Eens kijken of we daar ook iets mee kunnen.  Dat loopt samen met de wens om een robotarm aan proberen te sturen met DL. Als simulatie daarvan heb ik een virtuele robotarm in twee delen gemaakt die een steeds wisselend target moet gaan grijpen (gele stip). Het lukt al snel om de random beweging met een 'cost-functie' in de richting van het target te sturen. Nu nog met behulp van RL.  




Dit lijkt sterk op het OpenAI voorbeeld 'Reacher'.
Het beschreven Q-learning algoritme lijkt redelijk eenvoudig van structuur:















De vertaling naar het probleem met de virtuele robotarm zou als volgt kunnen zijn. Het 'replay memory' wordt gebruikt om een NN te leren. Het NN moet de winst ('r' - of verlies - we zullen hier even alleen spreken over winst) weergeven van een situatie (state - 's') en een bijbehorende actie. De totale ingeschatte winst voor de toekomstige opeenvolgende stappen bepaald 'normaal' de selectie van de volgende actie. (via de Q - quality functie) Dat is ook de reden dat de resulterende situatie (s') in het replay memory wordt vastgelegd.
De opdrachtregel "select a = argmax Q(s, a')" moet ik nog juist zien te vertalen. In principe selecteren we de actie met de hoogste toekomstige winst gegeven een status 's'. Wat a' daarin doet begrijp ik nog niet helemaal.
In een bepaald percentage (Epsilon) van de acties zullen we op 'ontdekkingstocht' gaan om mogelijk betere alternatieven te ontdekken.

Voor mijn eenvoudige model is de state gegeven door de hoek ('A' - en lengte) van de 'onderarm', de hoek ('B' - en lengte) van de 'bovenarm' en de coƶrdinaten van het 'target'. In principe dus 4 waarden. De lengte houden we constant en blijven dus in principe buiten beschouwing.
De mogelijke acties zijn vergroten, verkleinen of gelijk houden van hoek A en/of B. Totaal 8 verschillende acties.

Mijn 'loss function' of te wel winst (r) wordt bepaald door de afstand tussen het uiteinde van de 'bovenarm' en het target. Eenvoudig te bepalen met behulp van Pythagoras. (sqrt((x1-x2)^2+ (y1-y2)^2)) Dit helpt tevens de 'terminate conditie' (of beter 'replay conditie') wanneer de afstand bijvoorbeeld kleiner is dan 2 beeldposities.

Het NN trainen we met de status (s) en de actie (a) en de geobserveerde winst (r) vanuit het 'replay memory'. De beschreven trainmethode vraagt nog wat bestudering. Ook hier lijken de toekomstige beloningsverwachtingen voor de volgende stappen meegenomen te worden om het NN te trainen.