2017-01-12 5 views
2

In Keras möchte ich ein Ensemble von Modellen trainieren, die einige Schichten teilen. Sie sind in der folgenden Form:Modelensemble mit geteilten Ebenen

x ---> f (x) ---> g_1 (f (x))

x ---> f (x) ---> g_2 (f (x))

...

x ---> f (x) ---> G_N (f (x))

hier f (x) sind einige nicht-triviale shared Schichten . g_1 bis g_n haben ihre spezifischen Parameter.

In jeder Trainingsstufe werden die Daten x in eines der n Netzwerke, sagen wir das i-te, eingegeben. Ein Verlust von g_i (f (x)) wird dann über Gradienten-Optimierer minimiert/verringert. Wie könnte ich ein solches Modell definieren und trainieren?

Vielen Dank im Voraus!

Antwort

7

Sie können dies einfach mit dem funktionalen Modell tun.

Ein kleines Beispiel .. können Sie darauf bauen:

import numpy as np 
from keras.models import Model 
from keras.layers import Dense, Input 

X = np.empty(shape=(1000,100)) 
Y1 = np.empty(shape=(1000)) 
Y2 = np.empty(shape=(1000,2)) 
Y3 = np.empty(shape=(1000,3)) 

inp = Input(shape=(100,)) 
dense_f1 = Dense(50) 
dense_f2 = Dense(20) 

f = dense_f2(dense_f1(inp)) 

dense_g1 = Dense(1) 
g1 = dense_g1(f) 

dense_g2 = Dense(2) 
g2 = dense_g2(f) 

dense_g3 = Dense(3) 
g3 = dense_g3(f) 


model = Model([inp], [g1, g2, g3]) 
model.compile(loss=['mse', 'binary_crossentropy', 'categorical_crossentropy'], optimizer='rmsprop') 

model.summary() 

model.fit([X], [Y1, Y2, Y3], nb_epoch=10) 

Edit:

Basierend auf Ihre Kommentare, Sie immer verschiedene Modelle machen und schreiben können, die Ausbildung Schleife sich auf, wie Du brauchst dein Training. Sie können in der model.summary() alle Modelle die ersten Ebenen teilen sehen. Hier ist die Erweiterung zu dem Beispiel

model1 = Model(inp, g1) 
model1.compile(loss=['mse'], optimizer='rmsprop') 
model2 = Model(inp, g2) 
model2.compile(loss=['binary_crossentropy'], optimizer='rmsprop') 
model3 = Model(inp, g3) 
model3.compile(loss=['categorical_crossentropy'], optimizer='rmsprop') 
model1.summary() 
model2.summary() 
model3.summary() 

batch_size = 10 
nb_epoch=10 
n_batches = X.shape[0]/batch_size 


for iepoch in range(nb_epoch): 
    for ibatch in range(n_batches): 
     x_batch = X[ibatch*batch_size:(ibatch+1)*batch_size] 
     if ibatch%3==0: 
      y_batch = Y1[ibatch*batch_size:(ibatch+1)*batch_size] 
      model1.train_on_batch(x_batch, y_batch)  
     elif ibatch%3==1: 
      y_batch = Y2[ibatch*batch_size:(ibatch+1)*batch_size] 
      model2.train_on_batch(x_batch, y_batch)  
     else: 
      y_batch = Y3[ibatch*batch_size:(ibatch+1)*batch_size] 
      model3.train_on_batch(x_batch, y_batch)  
+0

Danke für die Antwort! Es ist hilfreich, löst das Problem aber immer noch nicht vollständig. In Ihrem Beispiel möchte ich jede Minibuch von X nur durch eine der drei Pipelines geschoben werden. Mit anderen Worten, es gibt eine Indikatorvariable, die einen der drei Verluste auswählt. – wolfustc

+1

Aktualisiert nach dem Kommentar. – indraforyou

+0

Das ist toller Job! Vielen Dank! Ein weiteres Problem: Ich glaube, dass train_on_batch() lediglich einen SGD-Schritt ausführt, ohne bessere Optimierungstechniken zu verwenden, z. B. Momentum SGD. Wäre es möglich, stattdessen model_i.fit (x_batch_i, y_batch_i, optimizer = 'schicker Optimierer') aufzurufen, wobei i = 1,2,3. Meine Sorge in diesem Fall ist, dass diese drei separaten Aufrufe den gleichen internen Optimierungszustand (z. B. die Geschwindigkeit des Moments SGD) für die Parameter in der Funktion f teilen. Es scheint mir, dass diese Bedingungen geteilt werden sollten, um eine Optimierung zu erreichen. – wolfustc