maandag 25 februari 2019

Matters that matter IV

Het probleem met de verschillende OneHot uitkomsten zit vermoedelijk in het type dat tussendoor wordt gebruikt. (uint8). Hoewel er geen fouten ontstaan heeft dit datatype onvoldoende ruimte om de OneHot van > 30K woorden 'weer te geven'.
Ik heb de vraag overigens hier nog uitstaan.



Inmiddels werkt het model als een 'zonnetje', ook in een Sequential Keras implementatie:



De resultaten zijn veel belovend. Ik test het effect als ik het model 2x zo klein en 2x zo groot maak.


2x zo klein model
2x zo groot model
Het model heeft dus echt wel zijn omvang nodig om de variatie in de teksten goed vast te kunnen leggen. 

zaterdag 16 februari 2019

Matters that matter III

Het model met een voorgeprepareerde OneHot werkt dus behoorlijk goed met een validation accurracy naar de 60% . Alleen geeft het dus op een gegeven moement ene memory error in verband met de extreem grote X_train file van meer dan 23 gB. Het zou niet uit mogen maken om de OneHot in een layer 'On-the-spot' aan te brengen. Bij de eerste poging heb ik een 'TimeDistributed layer toegevoegd omdat er in eerste instatie complilatie fouten werden gemeld. Maar feitelijk zou dat niet nodig hoeven zijn.   Een nieuwe poging dus maar met de OneHot functie:



Ik verwijder de TimeDistributed layer en na wat debugging blijkt het te werken! En snel ook! Zo'n 23 seconden per epoch met 10K documenten. Dat was bij het model met de geprepareerde data wel anders. Een kleine 200 seconden. Helaas is het resultaat ook veel minder. De validation accuracy komt niet snel veel verder dan 20%. Waar kan dit verschil nou inzitten? Ik vergelijk de beide modellen:

Model met Onehot in de data geprepareerd.

Layer (type)                 Output Shape              Param #
=================================================================
conv1d_9 (Conv1D)            (None, 59, 256)           55612672
_________________________________________________________________
conv1d_10 (Conv1D)           (None, 57, 64)            49216
_________________________________________________________________
max_pooling1d_3 (MaxPooling1 (None, 19, 64)            0
_________________________________________________________________
conv1d_11 (Conv1D)           (None, 17, 128)           24704
_________________________________________________________________
conv1d_12 (Conv1D)           (None, 15, 128)           49280
_________________________________________________________________
global_average_pooling1d_3 ( (None, 128)               0
_________________________________________________________________
dropout_3 (Dropout)          (None, 128)               0
_________________________________________________________________
dense_3 (Dense)              (None, 1919)              247551
=================================================================

Model met Onehot layer

Layer (type)                 Output Shape              Param #
=================================================================
lambda_1 (Lambda)            (None, 64, 36206)         0
_________________________________________________________________
conv1d_1 (Conv1D)            (None, 59, 256)           55612672
_________________________________________________________________
conv1d_2 (Conv1D)            (None, 57, 64)            49216
_________________________________________________________________
max_pooling1d_1 (MaxPooling1 (None, 19, 64)            0
_________________________________________________________________
conv1d_3 (Conv1D)            (None, 17, 128)           24704
_________________________________________________________________
conv1d_4 (Conv1D)            (None, 15, 128)           49280
_________________________________________________________________
global_average_pooling1d_1 ( (None, 128)               0
_________________________________________________________________
dropout_1 (Dropout)          (None, 128)               0
_________________________________________________________________
dense_1 (Dense)              (None, 1919)              247551
=================================================================

Ik zie niet echt een verschil. En toch is het gedrag van beide oplossingen totaal anders.

OneHot functie

OneHot in data
Duidelijk verschil in opbouw dus. Vreemd!



Matters that matter II

Omdat een eerder model beter werkte (tot 86% val_acc meen ik) toch maar eens geprobeerd om dat model met de mega hoeveelheid data aan de praat te krijgen. Het probleem is memory. En dat komt met name door de lengte van de woordenlijst. In de eerste stap in het model worden de indices van de woorden omgezet naar ene OneHot van evenveel booleans als het aantal woorden. Dat geeft ook dat het model daarna in de eerste laag evenzoveel leerparameters maal de batch grootte maal de grootte van de 2e laag in het model. Daar kan het geheugen van de videokaart niet goed tegen.

Een 2e probleem is dat alle data van de documenten nogmaals worden opgeslagen in een gigantisch array (x_train).

Het formaat hiervan is #documenten * #woorden in een document * #woorden in de vocubalary (in booleans)

In het vorige model is dat opgelost door de conversie naar booleans op te nemen in een extra layer in het model:

model = Sequential()
model.add(OneHot(input_dim=input_dim,
input_length=input_length))
model.add(TimeDistributed(Dense(256)))
model.add(Conv1D(256, 6, activation='relu'))
model.add(Conv1D(64, 3, activation='relu'))
model.add(MaxPooling1D(3))
model.add(Conv1D(128, 3, activation='relu'))
model.add(Conv1D(128, 3, activation='relu'))
model.add(GlobalAveragePooling1D())
model.add(Dropout(0.5))
model.add(layers.Dense(labels_max, activation='softmax'))
    
Maar dat lijkt helaas dus niet zo goed te functioneren. Het is mij nog niet duidelijk waarom niet.

Ik besluit dus terug te gaan naar het eerdere model door


  • Reduceren van de woordenlijst (Alle woorden die minder dan 20x voorkomen worden eruit gefilterd.)
  • In batches van 10.000 docs aanbieden van de trainingsdata. (6 epochs per serie)
   Dat geeft al veel betere resultaten en grappige grafieken:

Helaas loopt die na 11 rondes in een memory error. Hoe dat komt is mij niet duidelijk. Ik maak (vrijwel) geen aanvullende data aan. Alleen de lists om loss en accuracy vast te leggen groeien ele ronde iets. Maar dat kan het niet zijn:

getsizeof(acc)
272

Het echte probleem lijkt nog steeds bij x_train: 23 gB !!!

getsizeof(x_train)
23.171.840.128
x_train.shape
(10000, 64, 36206)

Daar maak ik een kopie van in x_train_part (80%)
getsizeof(x_train_part)
128
Hmmm ... pythons / numpy's manier van 'kopieen maken' redt my hier blijkbaar maar geeft dus geen oplossing.

Natuurlijk kan ik het aantal docs per keer kleiner maken. Of niet alle woorden meenemen uit de docs. Of de vocabulare verder verkleinen.
Daarnaast concureert Python met andere programma's op mijn desktop. Dus het niet gebruiken daarvan helpt wellicht ook. Of natuurlijk meer memory kopen ...


donderdag 14 februari 2019

Matters that matter

Een korte weergave van onderhanden onderzoek om voor documenten automatisch een juiste 'folder' voor te stellen om in op te bergen.
We hebben daartoe een selectie van 242.543 documenten beschikbaar met een totale, vermoedelijk nog met leestekens ed vervuilde, 'woordenlijst' van 394.384 woorden.
Deze moeten in 1919 verschillende folders kunnen worden ondergebracht.
Een stevige uitdaging die al snel tot allerlei memory fouten leidt!

Hier een aantal resultaten van wat verkorte testen:




All words 30K docs


30K docs word frequency > 4
30K docs word frequency > 9
Onehot(original) word freq > 20 / 10K docs
Voorlopige conclusie: Het maakt niet veel uit op het resultaat om woorden met een lage frequentie eruit te halen. Het oorspronkelijke model met een tevoren geprepareerde OneHot  lijkt iets beter te performen.