0
votes

I am trying to train a LSTM NN using Keras on a self-defined evaluation_metric that I use as loss function. The structure of my Neural Network is:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_2 (InputLayer)         (None, 15, 1)             0         
_________________________________________________________________
lstm_2 (LSTM)                (None, 20)                1760      
_________________________________________________________________
dense_3 (Dense)              (None, 10)                210       
_________________________________________________________________
dense_4 (Dense)              (None, 1)                 11        
=================================================================

Let me give you some context: my NN produces an array of numerical values. These values have been scaled by some mathematical function. In order to compare it with the actual values, I need to first undo the scaling to transform it back to the original context. For this, I have created the function decode_output_values:

import numpy as np

[....]

def decode_output_values(pred_scaled,Y_train):
    #Decodes the output values back to the original context
    Y_min = np.nanmin(Y_train)
    Y_max = np.nanmax(Y_train)

    Y_pred = np.exp(pred_scaled*(np.log(Y_max)-np.log(Y_min))+np.log(Y_min))
    return Y_pred

Now that the output values are decoded, I make another change in order to be able to compare it with the real output values in the test set that are known. These real output values in the test set have a lot of NA values and only numerical values on some rows. Therefore, I only look at the corresponding indices of the rows that have non-NA values and calculate the RMSE between these values, using a function "evaluation_metric" that I have created:

I have created my own function evaluation_metric:

from sklearn.metrics import mean_squared_error
from math import sqrt

[....]

def evaluation_metric(y_true, y_pred_scaled):
    #Convert predictions back to original scale
    y_pred = decode_output_values(y_pred_scaled, Y_train)

    #Get all non-NA values of true values and predictions
    mask = ~np.isnan(y_true)

    y_true = y_true[mask]
    y_pred = y_pred[mask]

    error = sqrt(mean_squared_error(y_true, y_pred))
    return error

When I try to compile the model using Keras with the following code:

import keras

[....]

visible = Input(shape=(np.size(X_train_scaled,1),1))
hidden1 = LSTM(20)(visible)
hidden2 = Dense(10, activation='relu')(hidden1)
output = Dense(1, activation='linear')(hidden2)
initial_model = Model(inputs=visible, outputs=output)
initial_model.compile(loss=evaluation_metric, optimizer='rmsprop', metrics=
[evaluation_metric])

I get the following error:

AttributeError: 'Tensor' object has no attribute 'exp'

Full traceback:

Traceback (most recent call last):

  File "<ipython-input-108-9c67c532405a>", line 1, in <module>
    initial_model.compile(loss=evaluation_metric, optimizer='rmsprop', metrics=[evaluation_metric])

  File "/Users/XX/anaconda3/envs/Research_Paper/lib/python3.6/site-
packages/keras/engine/training.py", line 860, in compile
sample_weight, mask)

  File "/Users/XX/anaconda3/envs/Research_Paper/lib/python3.6/site-
packages/keras/engine/training.py", line 459, in weighted
score_array = fn(y_true, y_pred)

  File "<ipython-input-82-086ae61141e0>", line 3, in evaluation_metric
    y_pred = decode_output_values(y_pred_scaled, Y_train)

  File "<ipython-input-82-086ae61141e0>", line 25, in decode_output_values
    Y_pred = np.exp(pred_scaled*(np.log(Y_max)-np.log(Y_min))+np.log(Y_min))

AttributeError: 'Tensor' object has no attribute 'exp'

I am using Python 3.6 with Spyder 3.2.6 on MacOS. All used packages are updated to the latest version.

Can someone help me with this error?

1
Does it take a long time to run this code? If not, try ctrl + . and restart the kernel. It looks like you re-bound np to something other than numpy module, probably in the console window. - roganjosh
Are nans a huge problem in your data? Because if yes - try to use keras.backend functions instead of numpy functions. - Marcin Możejko
@roganjosh it does not run long, I get the error immediately. - Peter Lawrence
@MarcinMożejko the NaN's are a huge problem indeed, I will try using the keras.backend functions like you are suggesting - Peter Lawrence
Ok, but the reason I asked was because restarting the kernel will delete any existing data you had from parts of your code that do run. If it doesn't take long to rebuild whatever you had, I'd just try a hard restart. - roganjosh

1 Answers

0
votes

Simply change numpy to keras.backend:

import keras.backend as K

def decode_output_values(pred_scaled,Y_train):
    #Decodes the output values back to the original context
    Y_min = np.nanmin(Y_train)
    Y_max = np.nanmax(Y_train)

    Y_pred = K.exp(pred_scaled*(K.log(Y_max)-K.log(Y_min)) + K.log(Y_min))
    return Y_pred