Я пытаюсь добавить накопитель в конвейер Dasaset Tensorflow. В принципе, у меня есть это:
def _filter_bcc_labels(self, labels, labels_table, bcc_count):
bg_counter = tf.zeros(shape=(), dtype=tf.int32)
def _add_to_counter():
tf.add(bg_counter, 1)
# Here the bg_counter is always equal to 0
tf.Print(bg_counter, [bg_counter])
return tf.constant(True)
return tf.cond(tf.greater_equal(bg_counter, tf.constant(bcc_count, dtype=tf.int32)),
true_fn=lambda: tf.constant(False),
false_fn=_add_to_counter)
ds = ds.filter(lambda file, position, img, lbls: self._filter_bcc_labels(lbls, {"BCC": 0, "BACKGROUND": 1}, 10))
Моя цель здесь - bg_counter
при достижении tf.cond
false_fn
но моя переменная всегда имеет значение 0, оно никогда не увеличивается. Кто-то может объяснить мне, что происходит?
Имейте в виду, что я использую TF нетерпеливо, и я не могу использовать ds.make_initializable_iterator()
затем bg_counter
исходное значение bg_counter
. Спасибо
Я действительно нашел ответ на свой вопрос благодаря @MPękalski за то, что указал мне в правильном направлении. Теперь код выглядит следующим образом:
def _filter_bcc_labels(self, bg_counter, labels, labels_table, bcc_count):
bg_counter = tf.zeros(shape=(), dtype=tf.int32)
def _add_to_counter():
nonlocal bg_counter
bg_counter.assign_add(1)
# Prints the counter value
tf.Print(bg_counter, [bg_counter])
return tf.constant(True)
return tf.cond(tf.greater_equal(bg_counter, tf.constant(bcc_count, dtype=tf.int32)),
true_fn=lambda: tf.constant(False),
false_fn=_add_to_counter)
bg_counter = tf.get_variable("bg_counter_" + step, initializer=lambda: tf.zeros(shape=[], dtype=tf.int32), dtype=tf.int32, trainable=False)
ds = ds.filter(lambda file, position, img, lbls: self._filter_bcc_labels(bg_counter, lbls, {"BCC": 0, "BACKGROUND": 1}, 10))
Имейте в виду, что это решение не работает, если вы дважды повторяете в своем наборе данных, поскольку счетчик не получает повторной инициализации в этом случае. И если вы переместите bg_counter = tf.get_variable("bg_counter_" + step, initializer=lambda: tf.zeros(shape=[], dtype=tf.int32), dtype=tf.int32, trainable=False)
внутри ds.filter
то вы получаете объект 'Tensor' object has no attribute 'assign_add'
из-за режима ожидания.
Если вы действительно хотите сделать это правильно, вам нужно создать счетчик, когда вы перебираете свои партии, за пределами конвейера набора данных.
Возможно, вы захотите обернуть свой счетчик в классе, поскольку переменные в Eager будут удалены, когда они выйдут из области видимости.
Код:
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import tensorflow as tf
tf.enable_eager_execution()
import tensorflow.contrib.eager as tfe
dataset = tf.data.Dataset.from_tensor_slices(([1,2,3,4,5], [-1,-2,-3,-4,-5]))
class My(object):
def __init__(self):
self.x = tf.get_variable("mycounter", initializer=lambda: tf.zeros(shape=[], dtype=tf.float32), dtype=tf.float32
, trainable=False)
v = My()
print(v.x)
tf.assign(v.x,tf.add(v.x,1.0))
print(v.x)
def map_fn(x,v):
tf.cond(tf.greater_equal(v.x, tf.constant(5.0))
,lambda: tf.constant(0.0)
,lambda: tf.assign(v.x,tf.add(v.x,1.0))
)
return x
dataset = dataset.map(lambda x,y: map_fn(x,v)).batch(1)
for batch in tfe.Iterator(dataset):
print("{} | {}".format(batch, v.x))
Журнал:
<tf.Variable 'mycounter:0' shape=() dtype=float32, numpy=0.0>
<tf.Variable 'mycounter:0' shape=() dtype=float32, numpy=1.0>
[1] | <tf.Variable 'mycounter:0' shape=() dtype=float32, numpy=2.0>
[2] | <tf.Variable 'mycounter:0' shape=() dtype=float32, numpy=3.0>
[3] | <tf.Variable 'mycounter:0' shape=() dtype=float32, numpy=4.0>
[4] | <tf.Variable 'mycounter:0' shape=() dtype=float32, numpy=5.0>
[5] | <tf.Variable 'mycounter:0' shape=() dtype=float32, numpy=5.0>
Рабочий пример: https://www.kaggle.com/mpekalski/tfe-conditional-stateful-counter
Я думаю, что то, что вы пытаетесь сделать, требует метода assign_add(), а не метода add. Обратите внимание, что аргумент должен быть переменной.
Также будьте осторожны с tf.cond для общего использования за пределами нетерпения. Здесь обсуждается одно и то же.