Charles
Charles

Reputation: 83

Custom loss function which depends on another neural network in keras

I have a "How can I do that" question with keras :

Assuming that I have a first neural network, say NNa which has 4 inputs (x,y,z,t) which is already trained. If I have a second neural network, say NNb, and that its loss function depends on the first neural network.

The custom loss function of NNb customLossNNb calls the prediction of NNa with a fixed grid (x,y,z) and just modify the last variable t.

Here in pseudo-python-code what I would like to do to traine the second NN : NNb:

grid=np.mgrid[0:10:1,0:10:1,0:10:1].reshape(3,-1).T

Y[:,0]=time
Y[:,1]=something

def customLossNNb(NNa,grid):
     def diff(y_true,y_pred): 
         for ii in range(y_true.shape[0]):
               currentInput=concatenation of grid and y_true[ii,0]
               toto[ii,:]=NNa.predict(currentInput)
               #some stuff with toto
         return #...
     return diff

Then

NNb.compile(loss=customLossNNb(NNa,K.variable(grid)),optimizer='Adam')
NNb.fit(input,Y)

In fact the line that cause me troubles is currentInput=concatenation of grid and y_true[ii,0]

I tried to send to customLossNNb the grid as a tensor with K.variable(grid). But I can't defined a new tensor inside the loss function, something like CurrentY which has a shape (grid.shape[0],1) fill with y[ii,0](i.e. the current t) and then concatenate grid and currentY to build currentInput

Any ideas?

Thanks

Upvotes: 1

Views: 1909

Answers (2)

Daniel Möller
Daniel Möller

Reputation: 86600

First, make NNa untrainable. Notice that you should do this recursively if your model has inner models.

def makeUntrainable(layer):
    layer.trainable = False

    if hasattr(layer, 'layers'):
        for l in layer.layers:
            makeUntrainable(l)

makeUntrainable(NNa)

Then you have two options:

  • Attach NNa to the end of your model (notice that both y_true and y_pred will be changed)
    • Then change your targets (predict with NNa) for correct results since your model is now expecting the output of NNa, not NNb.
  • Create a custom loss function that uses NNa inside it, without changing your targets

Option 1 - Attaching models

inputs = NNb.inputs   
outputs = NNa(NNb.outputs) #make sure NNb is outputing 4 tensors to match NNa inputs   
fullModel = Model(inputs,outputs)

#changing the targets:
newY_train = NNa.predict(oldY_train)    

Option 2 - Creating a custom loss

Warning: please test whether NNa's weights are really frozen while training this configuration

from keras.losses import binary_crossentropy

def customLoss(true,pred):
    true = NNa(true)
    pred = NNa(pred)

    #use some of the usual losses or create your own
    binary_crossentropy(true,pred)

NNb.compile(optimizer=anything, loss = customLoss)

Upvotes: 0

Andrey Kite Gorin
Andrey Kite Gorin

Reputation: 1040

You can include your custom loss function into the graph using functional API of keras. The model in this case can be used as a function, something like this:

for l in NNa.layers: 
    l.trainable=False
x=Input(size)
y=NNb(x)
z=NNa(y)

Predict method will not work, since loss function should be part of the graph, and predict method returns np.array

Upvotes: 1

Related Questions