tensorflow / probability

Probabilistic reasoning and statistical analysis in TensorFlow
https://www.tensorflow.org/probability/
Apache License 2.0
4.26k stars 1.1k forks source link

AttributeError: 'UserRegisteredTypeKerasTensor' object has no attribute 'mean' error raised. #1484

Open Diogenes4Sinope opened 2 years ago

Diogenes4Sinope commented 2 years ago

Please can anyone let me know why the following code:

from tensorflow.keras.layers import Input
from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import Concatenate
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam

def neg_log_likelihood(y, distr): 
    return -distr.log_prob(y) 

def my_dist(params): #723 
    return tfd.Normal(loc=params, scale=1)

inputs = Input(shape=(1,))
params = Dense(1)(inputs)
dist = tfp.layers.DistributionLambda(my_dist)(params) 
model_sd1 = Model(inputs=inputs, outputs=dist) 
model_sd1.compile(Adam(), loss=neg_log_likelihood) 

And then running the following code;

model_mean_sd1 = Model(inputs=inputs, outputs=dist.mean())

leads to the following error:

AttributeError: 'UserRegisteredTypeKerasTensor' object has no attribute 'mean'

Any help will be greatly appreciated. Thanks.

anilkunwar commented 2 years ago

dist = tfp.layers.DistributionLambda(my_dist)(params) ... model_mean_sd1 = Model(inputs=inputs, outputs=dist.mean())

In case of tfp version 0.13.0, I also get the same error in the above line. The code however runs perfect in tfp version 0.8.0 . Temporary solution :- installing tfp version =0.8.0 will work pip install tensorflow-probability==0.8.0

It seems there have been a change in the newer versions of tensorflow_probability library.

Which version of tensorflow_probability (tfp) is installed in your computer ?

macot commented 2 years ago

after version 0.12 use the "convert_to_tensor_fn" for outputs' manipulation. ex: dist1 = tfp.layers.DistributionLambda( make_distribution_fn=my_dist, convert_to_tensor_fn=tfp.distributions.Distribution.mean )(params)
model_mean_sd_1 = Model(inputs=inputs, outputs=dist1)

asaranti commented 1 year ago

What should one do, if one wants to get both the mean and the stddev ? Thanks in advance.

TF Version 2.13.0 TFP Version 0.20.1

ricopicone commented 1 year ago

@asaranti did you figure that out?

asaranti commented 1 year ago

@asaranti did you figure that out?

Sadly not, but if I do I will share it.

ricopicone commented 1 year ago

Thanks!

auspect commented 1 year ago

What should one do, if one wants to get both the mean and the stddev ? Thanks in advance.

TF Version 2.13.0 TFP Version 0.20.1

I'm not sure if that answers your question, but I think we can calculate the mean and variance like this :

means = model(x).mean() # not model.predict
vars = model(x).variance() # not model.predict

At least for my use case it worked fine

egolfbr commented 11 months ago

What should one do, if one wants to get both the mean and the stddev ? Thanks in advance. TF Version 2.13.0 TFP Version 0.20.1

I'm not sure if that answers your question, but I think we can calculate the mean and variance like this :

means = model(x).mean() # not model.predict
vars = model(x).variance() # not model.predict

At least for my use case it worked fine

I think the goal is to create a keras.Model instance where the outputs are a tfp.layers.distributionLambda function that is created by a user defined tfp.Distribution. So while your method operates on the existing model, the goal is to create a new model.....i think

egolfbr commented 11 months ago

This solved it for me

def NLL(y, distr):
  return -distr.log_prob(y) 

def my_dist(params): 
  return tfd.Normal(loc=params[:,0:1], scale=1e-3 + tf.math.softplus(0.05 * params[:,1:2]))# both parameters are learnable

inputs = Input(shape=(1,))
out1 = Dense(1)(inputs) #A
hidden1 = Dense(30,activation="relu")(inputs)
hidden1 = Dense(20,activation="relu")(hidden1)
hidden2 = Dense(20,activation="relu")(hidden1)
out2 = Dense(1)(hidden2) #B
params = Concatenate()([out1,out2]) #C
dist = tfp.layers.DistributionLambda(my_dist)(params) 
distmean = tfp.layers.DistributionLambda(my_dist, convert_to_tensor_fn=tfp.distributions.Distribution.mean)(params) 
diststddev = tfp.layers.DistributionLambda(my_dist, convert_to_tensor_fn=tfp.distributions.Distribution.stddev)(params) 

model_flex_sd = Model(inputs=inputs, outputs=dist)
model_flex_sd.compile(Adam(learning_rate=0.01), loss=NLL)

model_flex_sd_mean = Model(inputs=inputs, outputs=distmean)
model_flex_sd_sd = Model(inputs=inputs, outputs=diststddev)
auspect commented 11 months ago

This solved it for me

def NLL(y, distr):
  return -distr.log_prob(y) 

def my_dist(params): 
  return tfd.Normal(loc=params[:,0:1], scale=1e-3 + tf.math.softplus(0.05 * params[:,1:2]))# both parameters are learnable

inputs = Input(shape=(1,))
out1 = Dense(1)(inputs) #A
hidden1 = Dense(30,activation="relu")(inputs)
hidden1 = Dense(20,activation="relu")(hidden1)
hidden2 = Dense(20,activation="relu")(hidden1)
out2 = Dense(1)(hidden2) #B
params = Concatenate()([out1,out2]) #C
dist = tfp.layers.DistributionLambda(my_dist)(params) 
distmean = tfp.layers.DistributionLambda(my_dist, convert_to_tensor_fn=tfp.distributions.Distribution.mean)(params) 
diststddev = tfp.layers.DistributionLambda(my_dist, convert_to_tensor_fn=tfp.distributions.Distribution.stddev)(params) 

model_flex_sd = Model(inputs=inputs, outputs=dist)
model_flex_sd.compile(Adam(learning_rate=0.01), loss=NLL)

model_flex_sd_mean = Model(inputs=inputs, outputs=distmean)
model_flex_sd_sd = Model(inputs=inputs, outputs=diststddev)

Yes, this is indeed more helpful! Thank you for providing this piece of code.