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))
To convert back from tensor to numpy array you can simply run . eval() on the transformed tensor.
Creating custom loss functions in Keras A custom loss function can be created by defining a function that takes the true values and predicted values as required parameters. The function should return an array of losses. The function can then be passed at the compile stage.
numpy . This allows running NumPy code, accelerated by TensorFlow, while also allowing access to all of TensorFlow's APIs.
Tensorflow is consistently much slower than Numpy in my tests.
(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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With