6

I am trying to build a custom loss function in keras. Unfortunately i have little knowledge with tensor flow. Is there a way i can convert the incoming tensors into a numpy array so i can compute my loss function?

Here is my function:

def getBalance(x_true, x_pred):

    x_true = np.round(x_true)
    x_pred = np.round(x_pred)

    NumberOfBars = len(x_true)
    NumberOfHours = NumberOfBars/60

    TradeIndex = np.where( x_pred[:,1] == 0 )[0]

    ##remove predictions that are not tradable
    x_true = np.delete(x_true[:,0], TradeIndex)
    x_pred = np.delete(x_pred[:,0], TradeIndex)

    CM = confusion_matrix(x_true, x_pred)

    correctPredictions = CM[0,0]+CM[1,1]
    wrongPredictions = CM[1,0]+CM[0,1]
    TotalTrades = correctPredictions+wrongPredictions
    Accuracy = (correctPredictions/TotalTrades)*100

    return Accuracy 

If its not possible to use numpy array's what is the best way to compute that function with tensorflow? Any direction would be greatly appreciated, thank you!

Edit 1: Here are some details of my model. I am using a LSTM network with heavy drop out. The inputs are a multi-variable multi-time step. The outputs are a 2d array of binary digits (20000,2)

model = Sequential()

model.add(Dropout(0.4, input_shape=(train_input_data_NN.shape[1], train_input_data_NN.shape[2])))

model.add(LSTM(30, dropout=0.4, recurrent_dropout=0.4))

model.add(Dense(2))

model.compile(loss='getBalance', optimizer='adam')

history = model.fit(train_input_data_NN, outputs_NN, epochs=50,  batch_size=64, verbose=1, validation_data=(test_input_data_NN, outputs_NN_test))

1 Answer 1

1

EDIT: 1 Here is an untested substitution:

(took the liberty of normalizing the variable names )

def get_balance(x_true, x_pred):

    x_true = K.tf.round(x_true)
    x_pred = K.tf.round(x_pred)

    # didnt see the  need for these
    # NumberOfBars = (x_true)
    # NumberOfHours = NumberOfBars/60

    trade_index = K.tf.not_equal(x_pred[:,1], 0 )

    ##remove predictions that are not tradable
    x_true_tradeable = K.tf.boolean_mask(x_true[:,0], trade_index)
    x_pred_tradeable = K.tf.boolean_mask(x_pred[:,0], trade_index)

    cm = K.tf.confusion_matrix(x_true_tradeable, x_pred_tradeable)

    correct_predictions = cm[0,0]+cm[1,1]
    wrong_predictions = cm[1,0]+cm[0,1]
    total_trades = correction_predictions + wrong_predictions
    accuracy = (correct_predictions/total_trades)*100

    return accuracy 

Original Answer

Welcome to SO. As you might know we need to compute the the gradient on the loss function. We can't compute the gradient correctly on numpy arrays (they're just constants).

What is done ( in keras/theano which are the backends one uses with keras) is automatic differentiation on Tensors (e.g tf.placeholder()).This is not the entire story but what you should know at this point is that tf / theano gives us gradients by default on operators like tf.max, tf.sum.

What that means for you is all the operations on tensors (y_true and y_pred) should be rewritten to use tf / theano operators.

I'll comment with what I think would be rewritten and you can substitute accordingly and test.

See tf.round used as K.tf.round where K is the reference to the keras backend imported as import keras.backend as K

x_true = np.round(x_true)  
x_pred = np.round(x_pred)

Grab the shape of the tensor x_true. K.shape. Compute the ratio over a constant could remain as it as Here

NumberOfBars = len(x_true) 
NumberOfHours = NumberOfBars/60

See tf.where used as K.tf.where

TradeIndex = np.where( x_pred[:,1] == 0 )[0] 

You could mask the tensor w/ a condition instead of deleting - see masking

##remove predictions that are not tradable
x_true = np.delete(x_true[:,0], TradeIndex) 
x_pred = np.delete(x_pred[:,0], TradeIndex)

See tf.confusion_matrix

CM = confusion_matrix(x_true, x_pred)

The computation that follow are computation overs constants and so remain essentially the same ( conditioned on
whatever changes have to made given the new API )

Hopefully I can update this answer with a valid substitution that runs. But I hope this sets on the right path.

A suggestion on coding style: I see you use three version of variable naming in your code choose one and stick with it.

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks for the help! My prediction array is (20000,2) binary numbers (1's & 0's). Will x_true,x_pred be the same format? Will the numbers be binary as well? I checked the shape of x_true it is (2,) instead.
Yes, they are the same shape and binary, without accounting for the number of examples
So i tried creating my mask like so : TradeIndex = K.tf.where( x_pred[:,1] == 0 ); x_true = K.tf.boolean_mask(x_true[:,0], TradeIndex) But i get an error: Shapes (?,) and (?, 0) are incompatible
see updated example that should help address the sizing issue
in the two lines below you dont need to index: x_true_tradeable = K.tf.boolean_mask(x_true[:,0], trade_index) x_pred_tradeable = K.tf.boolean_mask(x_pred[:,0], trade_index)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.