Search code examples
pythontensorflowmachine-learningconv-neural-networkloss-function

Tensorflow Custom Regularization Term comparing the Prediction to the True value


Hello I am in need of a custom regularization term to add to my (binary cross entropy) Loss function. Can somebody help me with the Tensorflow syntax to implement this? I simplified everything as much as possible so it could be easier to help me.

The model takes a dataset 10000 of 18 x 18 binary configurations as input and has a 16x16 of a configuration set as output. The neural network consists only of 2 Convlutional layer.

My model looks like this:

import tensorflow as tf
from tensorflow.keras import datasets, layers, models
EPOCHS = 10
model = models.Sequential()
model.add(layers.Conv2D(1,2,activation='relu',input_shape=[18,18,1]))
model.add(layers.Conv2D(1,2,activation='sigmoid',input_shape=[17,17,1]))
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=1e-3),loss=tf.keras.losses.BinaryCrossentropy())
model.fit(initial.reshape(10000,18,18,1),target.reshape(10000,16,16,1),batch_size = 1000, epochs=EPOCHS, verbose=1)
output = model(initial).numpy().reshape(10000,16,16) 

Now I wrote a function which I'd like to use as an aditional regularization terme to have as a regularization term. This function takes the true and the prediction. Basically it multiplies every point of both with its 'right' neighbor. Then the difference is taken. I assumed that the true and prediction term is 16x16 (and not 10000x16x16). Is this correct?

def regularization_term(prediction, true):
    order = list(range(1,4))
    order.append(0)
    
    deviation = (true*true[:,order]) - (prediction*prediction[:,order])
    deviation = abs(deviation)**2
    return 0.2 * deviation

I would really appreciate some help with adding something like this function as a regularization term to my loss for helping the neural network to train better to this 'right neighbor' interaction. I'm really struggling with using the customizable Tensorflow functionalities a lot. Thank you, much appreciated.


Solution

  • It is quite simple. You need to specify a custom loss in which you define your adding regularization term. Something like this:

    # to minimize!
    def regularization_term(true, prediction):
        order = list(range(1,4))
        order.append(0)
        
        deviation = (true*true[:,order]) - (prediction*prediction[:,order])
        deviation = abs(deviation)**2
        return 0.2 * deviation
    
    def my_custom_loss(y_true, y_pred):
        return tf.keras.losses.BinaryCrossentropy()(y_true, y_pred) + regularization_term(y_true, y_pred)
    
    
    model.compile(optimizer='Adam', loss=my_custom_loss)
    

    As stated by keras:

    Any callable with the signature loss_fn(y_true, y_pred) that returns an array of losses (one of sample in the input batch) can be passed to compile() as a loss. Note that sample weighting is automatically supported for any such loss.

    So be sure to return an array of losses (EDIT: as I can see now it is possible to return also a simple scalar. It doesn't matter if you use for example the reduce function). Basically y_true and y_predicted have as first dimension the batch size.

    here details: https://keras.io/api/losses/