问题
I've been stuck for several hours on some tensor manipulations in Tensorflow. I'm trying to implement some loss function within the Keras framework using Tensorflow backend, but was unsuccessful so far (though I believe I'm getting closer). The loss function in question is that of the loss function of YOLO algorithm. The problem with this function, is that it is a $L_2$ norm but weighted by some coefficients depending on the value of $y_true$. Therefore, in order to build my loss function, I have to look into the value of $y_true$, which Tensorflow seems not to allow... Anyway, so far, I've come up with this trick:
def defineMarkUp(y_true):
num_example = y_true.shape[0]
grid_h, grid_w = config.GRID_H, config.GRID_W
box_nbr = config.BOX_NBR
class_nbr = config.CLASS_NBR
coord_c = config.COORD_C
noobj_c = config.NOOBJ_C
s = 5 + class_nbr
mask = np.zeros(y_true.shape)
for i in range(num_example):
for j in range(grid_h):
for k in range(grid_w):
for l in range(box_nbr):
if np.sum(y_true[i, j, k, l * s + 5 : (l + 1) * s]) > 0:
mask[i, j, k, l * s : l * s + 4] = np.sqrt(coord_c)
mask[i, j, k, l * s + 4 : (l + 1) * s] = 1.0
else:
mask[i, j, k, l * s + 4] = np.sqrt(noobj_c)
return mask
def yoloLoss(markups):
grid_h, grid_w = config.GRID_H, config.GRID_W
box_nbr = config.BOX_NBR
class_nbr = config.CLASS_NBR
s = 5 + class_nbr
def loss(y_true, y_pred):
mask = np.zeros((1, grid_h, grid_w, box_nbr * s))
mask = mask.astype(np.float32)
for k in range(box_nbr):
mask[:, :, :, k * s + 2 : k * s + 4] = 1.0
dim_y_true = tf.sqrt(tf.multiply(y_true, mask))
dim_y_pred = tf.sqrt(tf.multiply(y_pred, mask))
other_y_true = tf.multiply(y_true, 1 - mask)
other_y_pred = tf.multiply(y_pred, 1 - mask)
new_y_true = other_y_true + dim_y_true
new_y_pred = other_y_pred + dim_y_pred
return tf.reduce_mean(tf.square(tf.multiply(tf.cast(markups, tf.float32), (new_y_true - new_y_pred))))
return loss
A little bit of explanation : here, the function defineMarkUp look at the all labels as np.array and create some masks (contains the different weights depending on the position etc...), and then I call something like:
model.compile(loss = [yoloLoss(Y_train)], optimizer = 'adadelta')
The problem is, when using batch, since the all dataset does not have the same dimension as our batch, the mask doesn't fit anymore, meaning I need to build 'markups' on the fly given $y_true$ as a tensor. So I tried something like this:
def defineMarkUp(y_true):
num_example = y_true.get_shape().as_list()[0]
grid_h, grid_w = config.GRID_H, config.GRID_W
box_nbr = config.BOX_NBR
class_nbr = config.CLASS_NBR
coord_c = config.COORD_C
noobj_c = config.NOOBJ_C
s = 5 + class_nbr
mask = np.zeros(y_true.get_shape().as_list())
for i in range(num_example):
for j in range(grid_h):
for k in range(grid_w):
for l in range(box_nbr):
if np.sum(y_true[i, j, k, l * s + 5 : (l + 1) * s]) > 0:
mask[i, j, k, l * s : l * s + 4] = np.sqrt(coord_c)
mask[i, j, k, l * s + 4 : (l + 1) * s] = 1.0
else:
mask[i, j, k, l * s + 4] = np.sqrt(noobj_c)
return mask
def yoloLossFinal(y_true, y_pred):
grid_h, grid_w = config.GRID_H, config.GRID_W
box_nbr = config.BOX_NBR
class_nbr = config.CLASS_NBR
s = 5 + class_nbr
coord_c, noobj_c = config.COORD_C, config.NOOBJ_C
markups = defineMarkUp(y_true)
mask = np.zeros((1, grid_h, grid_w, box_nbr * s))
mask = mask.astype(np.float32)
for k in range(box_nbr):
mask[:, :, :, k * s + 2 : k * s + 4] = 1.0
dim_y_true = tf.sqrt(tf.multiply(y_true, mask))
dim_y_pred = tf.sqrt(tf.multiply(y_pred, mask))
other_y_true = tf.multiply(y_true, 1 - mask)
other_y_pred = tf.multiply(y_pred, 1 - mask)
new_y_true = other_y_true + dim_y_true
new_y_pred = other_y_pred + dim_y_pred
return tf.reduce_mean(tf.square(tf.multiply(tf.cast(markups, tf.float32), (new_y_true - new_y_pred))))
But now I got this error:
Traceback (most recent call last): File "network.py", line 214, in yolo.compile(loss = yoloLossFinal, optimizer = 'adadelta') File "/anaconda3/lib/python3.6/site-packages/keras/engine/training.py", line 830, in compile sample_weight, mask) File "/anaconda3/lib/python3.6/site-packages/keras/engine/training.py", line 429, in weighted score_array = fn(y_true, y_pred) File "network.py", line 192, in yoloLossFinal markups = defineMarkUp(y_true) File "network.py", line 143, in defineMarkUp mask = np.zeros(y_true.get_shape().as_list()) TypeError: 'NoneType' object cannot be interpreted as an integer
Therefore, I tried something else :
def defineMarkUp(y_true):
sess = tf.Session()
with sess.as_default():
yy = y_true.eval()
num_example = yy.shape[0]
grid_h, grid_w = config.GRID_H, config.GRID_W
box_nbr = config.BOX_NBR
class_nbr = config.CLASS_NBR
coord_c = config.COORD_C
noobj_c = config.NOOBJ_C
s = 5 + class_nbr
mask = np.zeros(y_true.shape)
for i in range(num_example):
for j in range(grid_h):
for k in range(grid_w):
for l in range(box_nbr):
if np.sum(yy[i, j, k, l * s + 5 : (l + 1) * s]) > 0:
mask[i, j, k, l * s : l * s + 4] = np.sqrt(coord_c)
mask[i, j, k, l * s + 4 : (l + 1) * s] = 1.0
else:
mask[i, j, k, l * s + 4] = np.sqrt(noobj_c)
return mask
But now I get this very long error message :
Traceback (most recent call last): File "/anaconda3/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 1322, in _do_call return fn(*args) File "/anaconda3/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 1307, in _run_fn options, feed_dict, fetch_list, target_list, run_metadata) File "/anaconda3/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 1409, in _call_tf_sessionrun run_metadata) tensorflow.python.framework.errors_impl.InvalidArgumentError: You must feed a value for placeholder tensor 'conv2d_4_target' with dtype float and shape [?,?,?,?] [[Node: conv2d_4_target = Placeholderdtype=DT_FLOAT, shape=[?,?,?,?], _device="/job:localhost/replica:0/task:0/device:CPU:0"]]
During handling of the above exception, another exception occurred:
Traceback (most recent call last): File "network.py", line 218, in yolo.compile(loss = yoloLossFinal, optimizer = 'adadelta') File "/anaconda3/lib/python3.6/site-packages/keras/engine/training.py", line 830, in compile sample_weight, mask) File "/anaconda3/lib/python3.6/site-packages/keras/engine/training.py", line 429, in weighted score_array = fn(y_true, y_pred) File "network.py", line 196, in yoloLossFinal markups = defineMarkUp(y_true) File "network.py", line 137, in defineMarkUp yy = y_true.eval() File "/anaconda3/lib/python3.6/site-packages/tensorflow/python/framework/ops.py", line 710, in eval return _eval_using_default_session(self, feed_dict, self.graph, session) File "/anaconda3/lib/python3.6/site-packages/tensorflow/python/framework/ops.py", line 5180, in _eval_using_default_session return session.run(tensors, feed_dict) File "/anaconda3/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 900, in run run_metadata_ptr) File "/anaconda3/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 1135, in _run feed_dict_tensor, options, run_metadata) File "/anaconda3/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 1316, in _do_run run_metadata) File "/anaconda3/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 1335, in _do_call raise type(e)(node_def, op, message) tensorflow.python.framework.errors_impl.InvalidArgumentError: You must feed a value for placeholder tensor 'conv2d_4_target' with dtype float and shape [?,?,?,?] [[Node: conv2d_4_target = Placeholderdtype=DT_FLOAT, shape=[?,?,?,?], _device="/job:localhost/replica:0/task:0/device:CPU:0"]]
Caused by op 'conv2d_4_target', defined at: File "network.py", line 218, in yolo.compile(loss = yoloLossFinal, optimizer = 'adadelta') File "/anaconda3/lib/python3.6/site-packages/keras/engine/training.py", line 725, in compile dtype=K.dtype(self.outputs[i])) File "/anaconda3/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py", line 508, in placeholder x = tf.placeholder(dtype, shape=shape, name=name) File "/anaconda3/lib/python3.6/site-packages/tensorflow/python/ops/array_ops.py", line 1808, in placeholder return gen_array_ops.placeholder(dtype=dtype, shape=shape, name=name) File "/anaconda3/lib/python3.6/site-packages/tensorflow/python/ops/gen_array_ops.py", line 4848, in placeholder "Placeholder", dtype=dtype, shape=shape, name=name) File "/anaconda3/lib/python3.6/site-packages/tensorflow/python/framework/op_def_library.py", line 787, in _apply_op_helper op_def=op_def) File "/anaconda3/lib/python3.6/site-packages/tensorflow/python/framework/ops.py", line 3392, in create_op op_def=op_def) File "/anaconda3/lib/python3.6/site-packages/tensorflow/python/framework/ops.py", line 1718, in init self._traceback = self._graph._extract_stack() # pylint: disable=protected-access
InvalidArgumentError (see above for traceback): You must feed a value for placeholder tensor 'conv2d_4_target' with dtype float and shape [?,?,?,?] [[Node: conv2d_4_target = Placeholderdtype=DT_FLOAT, shape=[?,?,?,?], _device="/job:localhost/replica:0/task:0/device:CPU:0"]
]
I've relentlessly trying to implement this loss function, so I really hope somebody could help me understanding what's going wrong :(. So far, I also have a more general question, that of which is probably linked to my problem: how to really implement a loss function in Tensorflow, meaning : what are we allowed to do and what are we not allowed to do?
Thank you a lot!
来源:https://stackoverflow.com/questions/51246475/some-tensor-manipulations-in-tensorflow