Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keras error "You must feed a value for placeholder tensor"

I have simple seq2seq model:

import seq2seq
import numpy as np
import keras.backend as K

from seq2seq.models import Seq2Seq
from keras.models import Model
from keras.models import Sequential
from keras.layers import Embedding, Input, TimeDistributed, Activation

BLOCK_LEN = 60
EVENTS_CNT = 462

input = Input((BLOCK_LEN,))
embedded = Embedding(input_dim=EVENTS_CNT+1, output_dim=200)(input)
emb_model = Model(input, embedded)

seq_model = Seq2Seq(batch_input_shape=(None, BLOCK_LEN, 200), hidden_dim=200, output_length=BLOCK_LEN, output_dim=EVENTS_CNT)
model = Sequential()
model.add(emb_model)
model.add(seq_model)
model.add(TimeDistributed(Activation('softmax')))

model.summary()
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
model_1 (Model)              (None, 60, 200)           92600     
_________________________________________________________________
model_12 (Model)             (None, 60, 462)           1077124   
_________________________________________________________________
time_distributed_2 (TimeDist (None, 60, 462)           0         
=================================================================
Total params: 1,169,724
Trainable params: 1,169,724
Non-trainable params: 0
_________________________________________________________________

And I'm trying to create my own metric:

def symbol_acc(true, predicted):
    np_y_true = K.get_value(true)
    np_y_pred = K.get_value(predicted)
    return K.mean(np_y_true == np_y_pred)

And if I try to compile model with this metric I get an error "You must feed a value for placeholder tensor" with the following message:

InvalidArgumentError                      Traceback (most recent call last)
C:\Users\Anna\Anaconda3\lib\site-packages\tensorflow\python\client\session.py in _do_call(self, fn, *args)
   1322     try:
-> 1323       return fn(*args)
   1324     except errors.OpError as e:

C:\Users\Anna\Anaconda3\lib\site-packages\tensorflow\python\client\session.py in _run_fn(session, feed_dict, fetch_list, target_list, options, run_metadata)
   1301                                    feed_dict, fetch_list, target_list,
-> 1302                                    status, run_metadata)
   1303 

C:\Users\Anna\Anaconda3\lib\site-packages\tensorflow\python\framework\errors_impl.py in __exit__(self, type_arg, value_arg, traceback_arg)
    472             compat.as_text(c_api.TF_Message(self.status.status)),
--> 473             c_api.TF_GetCode(self.status.status))
    474     # Delete the underlying status object from memory otherwise it stays alive

InvalidArgumentError: You must feed a value for placeholder tensor 'time_distributed_2_target' with dtype float and shape [?,?,?]
     [[Node: time_distributed_2_target = Placeholder[dtype=DT_FLOAT, shape=[?,?,?], _device="/job:localhost/replica:0/task:0/device:CPU:0"]()]]

But the following code is working fine (doesn't produce any exceptions):

def symbol_acc2(true, predicted):
    true = np.array(true)
    predicted = np.array(predicted)
    return K.variable((true == predicted).mean())

Can you please explain me what does that exception mean? I thought symbol_acc and symbol_acc2 are doing the same thing. I'm new in NNs and keras so maybe I don't see some obvious things. I saw similar questions on stackoverflow but didn't find the fit answer for my situation.

like image 523
Anna Avatar asked May 13 '18 22:05

Anna


2 Answers

In symbol_acc, the non-working version, tf.keras.backend.get_value() (K.get_value() in your code) will go and fetch the value of a variable as a Numpy array. Then this line K.mean(np_y_true == np_y_pred) first creates another (boolean) Numpy array based on equality, and tf.keras.backend.mean() tries to treat that Numpy array as a tensor and it just doesn't work this way.

The error is shown because at graph creation time the true has no value yet, hasn't been fed.

symbol_acc2 doesn't throw an error, but would not work either, because at graph creation time true and predicted are just empty tensors. Numpy will not change that, but the comparison will fail, taking the mean of that will yield zero, and you're just creating a variable with the value zero. Consider this code (tested):

import keras.backend as K
import numpy as np

true = K.placeholder( ( 2, ) )
predicted = K.placeholder( ( 2, ) )
a = np.array( true )
b = np.array( predicted )
c = a == b
print( c, c.mean() )

outputs:

(False, 0.0)

regardless of the data (there's not even data in the tensors yet.)

In order to achieve what you want, that is calculating the accuracy of your predictions, you can simply use

def symbol_acc( true, predicted ):
    return K.mean( K.cast_to_floatx( K.equal( true, predicted ) ) )

Or you can make your own life easier, and look into Keras' own categorical_accuracy metric.

like image 26
Peter Szoldan Avatar answered Nov 16 '22 20:11

Peter Szoldan


Metrics, losses, and the entire model are "symbolic" tensors.

This means, they have absolutely no data (or value) until the moment you start fitting or predicting.

When you call K.get_value you're trying to get a value that doesn't exist. (It will only exist when you "feed the data" to the model. What it calls a placeholder is an empty input tensor that is expecting to receive the data when fitting or predicting).

The solution to your problem is simply not trying to get the values. (The numpy version will not work either, the values don't exist at the moment this function is compiled).

You gotta keep all operations symbolic, and they will be performed when you feed the data.

So:

def symbol_acc(true, predicted):
    isEqual = K.cast(K.equal(true,predicted),K.floatx())
    return K.mean(isEqual)
like image 96
Daniel Möller Avatar answered Nov 16 '22 22:11

Daniel Möller