Keras model.evaluate and model.predict give different results - tensorflow

When I build a model using Lambda layer to calculate the sum along an axis, model.evaluate() gives different result in comparison to manually calculating from model.predict(). I have checked the output data types and shapes and it did not help. The problem only occurs when I use tensorflow as Keras backend. It works fine when I use CNTK as backend.
Here is a minimal code that can reproduce this behavior.
from keras.layers import Input,Lambda
import keras.backend as K
from keras.models import Model
import numpy as np
inp=Input((2,))
out=Lambda(lambda x:K.sum(x,axis=-1),output_shape=(1,))(inp)
model=Model(input=inp,output=out)
model.compile(loss="mse",optimizer="sgd")
xs=np.random.random((3,2))
ys=np.sum(xs,axis=1)
print(np.mean((model.predict(xs)-ys)**2)) # This is zero
print(model.evaluate(xs,ys)) # This is not zero
I establish a network with no parameters and should simply calculate the sum for each x, and ys are constructed so that it should be the same with the output from the model. model.predict() gives the same results as ys, but model.evaluate() gives something non-zero when I use tensorflow as backend.
Any idea about why this should happen? Thanks!

Related

Irreproducible results Tensorflow

I have a very basic code that tries to create a single-layered Dense neural net and predicts the output for a deterministic input. The code is as follows:
import tensorflow as tf
from tensorflow.keras import layers
model = tf.keras.models.Sequential()
model.add(layers.Dense(units = 10))
import numpy as np
inp = np.ones((1,10))
model.predict(inp)
But the output that I am getting isn't being deterministic. I think it is related to initializing the weights and biases. So, how do I fix this without writing the initializing function from scratch?
Set global seed before initializing model tf.random.set_seed(42)
You can also set seed for specific parts of model, e.g. kernel_initializer in Dense layer, but with this approach, you may miss initializers that will still be nondeterministic. In your case setting it globally will be the best solution.

Learning a Categorical Variable with TensorFlow Probability

I would like to use TFP to write a neural network where the output are the probabilities of a categorical variable with 3 classes, and train it using the negative log-likelihood.
As I'm moving my first steps with TF and TFP, I started with a toy model where the input layer has only 1 unit receiving a null input, and the output layer has 3 units with softmax activation function. The idea is that the biases should learn (up to an additive constant) the log of the probabilities.
Here below is my code, true_p are the true parameters I use to generate the data and I would like to learn, while learned_p is what I get from the NN.
import numpy as np
import tensorflow as tf
from tensorflow import keras
from functions import nll
from tensorflow.keras.optimizers import SGD
import tensorflow.keras.layers as layers
import tensorflow_probability as tfp
tfd = tfp.distributions
# params
true_p = np.array([0.1, 0.7, 0.2])
n_train = 1000
# training data
x_train = np.array(np.zeros(n_train)).reshape((n_train,))
y_train = np.array(np.random.choice(len(true_p), size=n_train, p=true_p)).reshape((n_train,))
# model
input_layer = layers.Input(shape=(1,))
p_layer = layers.Dense(len(true_p), activation=tf.nn.softmax)(input_layer)
p_y = tfp.layers.DistributionLambda(tfd.Categorical)(p_layer)
model_p = keras.models.Model(inputs=input_layer, outputs=p_y)
model_p.compile(SGD(), loss=nll)
# training
hist_p = model_p.fit(x=x_train, y=y_train, batch_size=100, epochs=3000, verbose=0)
# check result
learned_p = np.round(model_p.layers[1].call(tf.constant([0], shape=(1, 1))).numpy(), 3)
learned_p
With this setup, I get the result:
>>> learned_p
array([[0.005, 0.989, 0.006]], dtype=float32)
I over-estimate the second category, and can't really distinguish between the first and the third one. What's worst, if I plot the probabilities at the end of each epoch, it looks like they are converging monotonically to the vector [0,1,0], which doesn't make sense (it seems to me the gradient should push in the opposite direction once I start to over-estimate).
I really can't figure out what's going on here, but have the feeling I'm doing something plain wrong. Any idea? Thank you for your help!
For the record, I also tried using other optimizers like Adam or Adagrad playing with the hyper-params, but with no luck.
I'm using Python 3.7.9, TensorFlow 2.3.1 and TensorFlow probability 0.11.1
I believe the default argument to Categorical is not the vector of probabilities, but the vector of logits (values you'd take softmax of to get probabilities). This is to help maintain precision in internal Categorical computations like log_prob. I think you can simply eliminate the softmax activation function and it should work. Please update if it doesn't!
EDIT: alternatively you can replace the tfd.Categorical with
lambda p: tfd.Categorical(probs=p)
but you'll lose the aforementioned precision gains. Just wanted to clarify that passing probs is an option, just not the default.

Finding TensorFlow equivalent of Pytorch GRU feature

I am confused about how to reconstruct the following Pytorch code in TensorFlow. It uses both the input size x and the hidden size h to create a GRU layer
import torch
torch.nn.GRU(64, 64*2, batch_first=True, return_state=True)
Instinctively, I first tried the following:
import tensorflow as tf
tf.keras.layers.GRU(64, return_state=True)
However, I realize that it does not really account for h or the hidden size. What should I do in this case?
The hidden size is 64 in your tensorflow example. To get the equivalent, you should use
import tensorflow as tf
tf.keras.layers.GRU(64*2, return_state=True)
This is because the keras layer does not require you to specify your input size (64 in this example); it is decided when you build or run your model for the first time.

How do i write a custom wavelet activation function for a Wavelet Neural Network using Keras or tensorflow

Trying to build a Wavelet Neural Network using Keras/Tensorflow. For this Neural Network I am supposed to use a Wavelet function as my activation function.
I have tried doing this by simply calling creating a custom activation function. However there seems to be an issue in regards to the backpropagation
import numpy as np
import pandas as pd
import pywt
import matplotlib.pyplot as plt
import tensorflow as tf
from keras.models import Model
import keras.layers as kl
from keras.layers import Input, Dense
import keras as kr
from keras.layers import Activation
from keras import backend as K
from keras.utils.generic_utils import get_custom_objects
def custom_activation(x):
return pywt.dwt(x, 'db1') -1
get_custom_objects().update({'custom_activation':Activation(custom_activation)})
model = Sequential()
model.add(Dense(12, input_dim=8, activation=custom_activation))
model.add(Dense(8, activation=custom_activation)
model.add(Dense(1, activation=custom_activation)
i get the following error for running the code in its entirety
SyntaxError: invalid syntax
if i run
model = Sequential()
model.add(Dense(12, input_dim=8, activation=custom_activation))
model.add(Dense(8, activation=custom_activation)
i get the following error
SyntaxError: unexpected EOF while parsing
and if i run
model = Sequential()
model.add(Dense(12, input_dim=8, activation=custom_activation))
I get the following error
TypeError: Cannot convert DType to numpy.dtype
model.add() is a function call. You must close parenthesis, otherwise it is a syntax error.
These two lines in your code example will cause a syntax error.
model.add(Dense(8, activation=custom_activation)
model.add(Dense(1, activation=custom_activation)
Regarding the 2nd question:
I get the following error
TypeError: Cannot convert DType to numpy.dtype
This seems like a numpy function was invoked with the incorrect arguments. Perhaps you can try to figure out which line in the script caused the error.
Also, an activation function must be written in keras backend operations. Or you need to manually compute the gradients for it. Neural network training requires being able to compute the gradients of a function on the reverse pass in order to adjust the weights. As far as I understand it you can't just call an arbitrary python library as an activation function; you have to either re-implement its operations using tensor operations or you have the option of using python operations on eager tensors if you know how to compute the gradients manually.

Keras isn't raising Tensorflow errors?

I'm writing a custom Tensorflow loss function for Keras, and I tried debugging it by using Tensorflow assertions, but these don't seem to raise errors anywhere even when I'm sure they ought to. I can boil it down to the following example:
from keras.models import Sequential
from keras.layers import Dense
import tensorflow as tf
import numpy as np
def demo_loss(y_true, y_pred):
tf.assert_negative(tf.ones([1,1]))
return tf.square(y_true - y_pred)
model = Sequential()
model.add(Dense(1, input_dim=1, activation='linear'))
model.compile(optimizer='rmsprop', loss=demo_loss)
model.fit(np.ones((1000,1)), np.ones((1000,1)), epochs=10, batch_size=100)
This really seems to me like it should emit an InvalidArgumentError. Why doesn't it?
(Alternately, what's the more sensible way to debug my custom loss functions?)
Your TensorFlow code is not working because there is nothing which forces the assertion to be executed. To make it work you need to add a control dependency to it, something like:
def demo_loss(y_true, y_pred):
with tf.control_dependencies([tf.assert_negative(tf.ones([1,1]))]):
return tf.square(y_true - y_pred)
I'm not sure whether the code should stop... your loss function will be compiled together with your model in a single graph, and that tf.assert command is totally disconnected from everything.
These functions are not meant to be debugged. They're created to achieve the highest performance possible, that's why it's made first as a graph, and only later you feed the data.
When I want to debug, I go for a little model and predict:
trueInput = Input(outputShape)
predInput = Input(outputShape)
output = Lambda(lambda x: demo_loss(x[0],x[1]))([trueInput,predInput])
debugModel = Model([trueInput,predInput], output)
Now use this model to predict:
retults = degugModel.predict([someNumpyTrue, someNumpyPred])
You can divide the function in smaller functions, each one in a different Lambda layer, and see each output separately.