zondag 28 januari 2018

data-science-bowl-2018 - Verbetering data opsplitsing.

Ik ben er iig uit waarom ik foutmeldingen krijg in het geleende neuraal netwerk model. Bij Keras kan gekozen worden uit 2 back-end systemen. Normaal was het gebaseerd op Theano maar tegenwoordig is er het alternatief van Tensorflow, Het door Google ontwikkelde systeem. In een Keras file kan worden geconfigureerd welke wordt gebruikt:

$HOME/.keras/keras.json

{
    "image_data_format": "channels_last",
    "epsilon": 1e-07,
    "floatx": "float32",
    "backend": "tensorflow"
}

Helaas kan ik tensorflow minder goed gebruiken omdat het mij nog niet is gelukt om die backend met mijn GPU te laten samenwerken. Ik zie wel dat ik de 'padding' ook van 'same' op 'valid' kan zetten waardoor het probleem lijkt verholpen. (Het wordt mij helaas niet geheel duidelijk wat het verschil is)

Om iets aan de rare vierkantjes proberen te doen besluit ik de selecties wat groter te maken van 80x80 naar 120x120. Helaas ontstaat daarbij problemen in het model,


A `Concatenate` layer requires inputs with matching shapes except for the concat axis. Got inputs shapes: [(None, 14, 14, 64), (None, 15, 15, 64)]

In de laag:


u6 = concatenate([u6, c4])

160x160 geeft dat probleem niet. Dus maar opnieuw de data genereren. Helaas duurt dat vreemd genoeg nogal lang. (ongeveer 267 seconden per afbeelding =  50 uur!!!)
Ik besluit gelijktijdig wat geprogrammeerde vervuiling toe te voegen:


Het her-genereren van de data begint nu extreem veel tijd te nemen. Ik besluit tot een iets andere aanpak. I.p.v. numpy 'vstack' gebruik ik nu met een python list de 'append' voor de afbeeldingen. Dat is een enorme verbetering. Had ik eerder moeten doen. Maar een paar minuten later kan ik mijn training al aan de gang zetten nadat ik eerst nog wel de shape heb moeten aanpassen van de image array (X_train en Y_train). Het aantal images is nu 170901 (feitelijk 189891 maar 10% is voor validatie). 56967 gewone afbeeldingen en even veel met horizontale en verticale 'verminkingen'. Ik ben benieuwd.

>>> x.shape
(189891, 1, 160, 160, 3)
>>> np.asarray(Y_train).shape

(189891, 1, 160, 160)
   


zaterdag 27 januari 2018

data-science-bowl-2018 - Trainen

Het opsplitsen van evrschillend formaat afbeeldingen in stukjes van 80 x 80 pixels is gelukt. Het neem wat lang maar ik heb nu 80620 afbeeldingen om mee te trainen. Dat is best aardig. Komt mede doordat ik een stapgrootte van 30 pixels heb genomen. Hier een voorbeeld van zo'n afbeelding met het bijbehorende masker:

Mooie scheiding van de celkernen.

Ik train met een U-model neuraal netwerk dat ik overneem uit dit voorbeeld. Vreemd genoeg krijg ik foutmeldingen. Een heeft te maken met de 'mean_iou functie' die bijgevoegd is om de meting volgens de competitie evaluatie te bepalen. 

Failed to convert object of type <class 'theano.tensor.var.TensorVariable'> to Tensor.

De auteur geeft echter aan dat deze waarschijnlijk nog niet correct is dus die kan ik verwijderen. De  2e melding is een Keras melding dat in de Conv2DTranspose functie een 'even aantal' in de matrix niet ondersteund wordt bij padding='same'. 

ValueError: In `Conv2DTranspose`, with padding mode `same`, even kernel sizes are not supported with Theano. You can set `kernel_size` to an odd number.

Het wordt mij niet duidelijk waarom het model in het voorbeeld wel werkt en bij mij niet. Ik maak daarom een aanpassing van 2x2 naar 3x3.  Ik zie nu dat ik dat ook voor de Conv2D layers zelf heb gedaan.  Wellicht wat overbodig. Ik zet deze terug naar 2x2. Ben benieuwd naar het effect later. 

Het trainen van het netwerk neemt zoals gebruikelijk meerdere dagen. Het lukt gelukkig vrij snel om de test afbeeldingen in delen van 80x80 aan te bieden, te evalueren, en vervolgens weer samen te stellen. De resultaten lijken aardig.    
Een 'artefact'
Hier lijkt het model nog verre van goed. De celkernen worden lang niet allemaal herkent.
Maar ook zie je de 80x80 grenzen hier en daar terug. Met als sterkste natuurlijk het gele vierkant.
Vreemd dat de gele vierkanten soms blijven terugkomen. Wellicht een gebrek aan basis informatie. 
Hoewel overall redelijk blijven ook hier de overgangsgebieden van de 80x80 'vensters' zichtbaar

Ik besluit de resultaten toch maar aan te bieden. Dan is dat deel iig ook eens getest. Het lukt goed maar nog met een relatief lage score. Om e.o.a. reden zijn, gek genoeg, de dropout layers uit mijn model verdwenen. Omdat ik veel vergelijkbare afbeeldingen heb is het inbrengen van dropout denk ik nog belangrijker om het systeem robuuster te maken en de kans op overfitting te verminderen.

Valt altijd tegen de eerste submissies ... Het voorbeeld model had al veel een hogere waarde: LB 0.277 





data-science-bowl-2018 - Strategie bepalen

Een gangbare strategie bij het werken met afbeeldingen van verschillend formaat in een neuraal netwerk is het 'resizen' van alle afbeeldingen naar een vast, kleiner formaat. Kleiner omdat anders het NN wel erg groot kan gaan worden. Als er vervolgens iets met de locatie gedaan moet worden, zoals in dit geval de locatie van de celkernen bepalen, moeten de resultaten weer worden opgeschaald naar het oorspronkelijke formaat.



Echter bij deze afbeeldingen is er heel veel 'herhaling'. Ook een uitsnede van de afbeelding laat meetstal meerdere celkernen zien. Ik ga kijken of ik hier iets mee kan door de afbeeldingen in vaste, kleine, gelijke delen op te delen. Bijvoorbeeld delen van 80x80 pixels. Ook de maskers moeten dan uiteraard in het zelfde formaat worden opgesplitst. Hierdoor gaat er geen informatie verloren zoals bij de 'resize' optie wel het geval is. Tevens creëer ik een veelfout aan afbeeldingen hetgeen voor het trainen van een neuraal netwerk altijd beter is.

Voordat ik dat doe moet ik echter de verschillende masker-afbeeldingen per cel-plaatje samenvoegen. Daar gebruik ik ook weer een geleend algoritme voor. Ik zie echter dat de maskers regelmatig elkaar raken of overlappen. Tevens lijken de maskers iets ruim om de celkernen heen te vallen. Om hieraan iets te doen maak ik een functie die een rand van de maskers weghaalt. Ik verwijder daartoe elke pixel als die een 'zwarte' raakt. Dat is uiteraard een stevige klus. Het lukt mij om die behoorlijk te versnellen door eerst te testen of het wel een witte pixel betreft en vervolgens te testen of de matrix rond de pixel een zwarte pixel bevat. Ik ga hierbij even de mist in omdat ik bij een logische matrix vergelijking verwacht de .any uitgang te moeten gebruiken. Het moet echter de .all zijn.

                if img[x,y]!=0 and img[x-1:x+1,y-1:y+1].all() == 0:

                    h[x,y]=0

Het neemt nog wel even maar uiteindeljk heb ik per preparaat een prachtig samengesteld masker.
Voorbeeld samengesteld masker

We kunnen nu gaan werken aan het opsplitsen in kleine afbeeldingen zoals hierboven beschreven.

data-science-bowl-2018 - Herkennen van de bronnen

Bij een Kaggle competitie wordt gelukkig al verrassend snel voorbeeld code gedeeld van mede competitie teams / spelers. Dat maakt dat je niet alles zelf vanaf de bodem hoeft uit te programmeren. Ik 'leen' vooral veel code van dit 'Notebook': Keras U-Net starter - LB 0.277.
Met name omdat ik ook met de Keras deeplearning library wil gaan werken en het beschreven U-net al eerder in een dergelijke competitie ben tegengekomen.

Het zelfstandig ontdekken van groeperingen kan met behulp van het 'un-superviced learning algoritme',  K-means.  De Scikit - learn bibliotheek heeft daar heel goed bruikbare oplossing voor.

 In basic terms, the algorithm has three steps. The first step chooses the initial centroids, with the most basic method being to choose  samples from the dataset . After initialization, K-means consists of looping between the two other steps. The first step assigns each sample to its nearest centroid. The second step creates new centroids by taking the mean value of all of the samples assigned to each previous centroid. The difference between the old and the new centroids are computed and the algorithm repeats these last two steps until this value is less than a threshold. In other words, it repeats until the centroids do not move significantly. 

Je moet dus wel zelf het aantal gewenste clusters opgeven maar dan classificeert Kmeans de data naar grootste afwijkingen. Lijkt precies wat ik nodig heb om de verschillende microscoop-bronnen te kunnen onderscheiden.

Mijn intuïtie is dat de verschillende afbeeldingen een verschillende kleuropbouw zullen hebben. Ik maak daarom een frequentie verdeling van de kleurwaarden van de afbeelding. Omdat een afbeelding uit 3 lagen (channels) bestaat doe ik dat per laag. Ik kies uiteindelijk voor 20 bins (20 aparte vakjes per laag) .  Ik koppel ze aan elkaar zodat ik per afdeling 60 'features' krijg waar Kmeans zijn kunsten op kan botvieren. Omdat het unsuperviced is kan ik ook de test afbeeldingen meenemen in de classificatie. Het lijkt heel aardig te werken. Ik experimenteer wat met verschillende aantallen clusters maar er zit toch af en toe een vreemde 'eend in de bijt'. Omdat de bron ook voor een deel het formaat van de afbeelding lijkt te bepalen voeg ik die waarden ook toe aan de features. (Dat doe ik - iets overbodig - per laag zodat het aantal features uiteindelijk 66 wordt.
Het levert dus een klassenummer per afbeelding op. Deze ga ik wellicht later gebruiken als extra informatie bij het DL dat de maskers moet gaan samenstellen.

Voorbeelden van histogrammen:

Channel 0 (R)
Mogelijk dat de hoge waarden in het 'nul' domein iets teveel invloed hebben t.o.v. de rest van de verdeling voor een goede 'fingerprint'. Kijk ik later nog eens na.
Channel 1 (G)
Channel 2 (B)




data-science-bowl-2018 - De data

De data bestaat uit 670 afbeeldingen van preparaten met cellen inclusief de bijbehorende 'maskers' om een algoritme mee te trainen. De maskers bestaan uit afbeeldingen met witte vlekken waar de cellen zich bevinden. Bijvoorbeeld:







Bij 65 vergelijkbare, maar zeker ook afwijkende, afbeeldingen dienen dan automatisch de juiste maskers gevonden te worden. Het lijkt erop dat er bewust heel andere afbeeldingen bij zijn gekozen. Bijvoorbeeld met 'vervuiling':


Ook zitten er preparaten van zeer verschillende microscopen bij. Zoals deze:


Ik besluit eerst maar eens te kijken of ik de verschillende bronnen zou kunnen herkennen.



Data Sciene Bowl 2018

Tijd om mij weer eens lekker op een nieuw DL avontuur te gooien! Kort geleden is de jaarlijkse Kaggle competitie 'Data Sciene bowl' weer gestart. Ook deze keer gaat het weer om een medische toepassing. Namelijk het identificeren van celkernen in diverse preparaten.

 "... create an algorithm to automate nucleus detection. By participating, teams will work to automate the process of identifying nuclei, which will allow for more efficient drug testing, shortening the 10 years it takes for each new drug to come to market." 

 Er is een mooie video voor uitgebracht.

 


Nou als dat niet enthousiast maakt! :-)

Ook de 'poster' lijkt veelbelovend:



Aan de slag dan maar!