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.
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.
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)
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