LookupError: функция `__class__` не существует. При использовании tf.функции

Я пытаюсь переопределить функцию потерь keras / tf2.0 пользовательской функцией, абстрагированной в двоичном файле WebAssembly. Вот соответствующий код.

@tf.function
def custom_loss(y_true, y_pred):
    return tf.constant(instance.exports.loss(y_true, y_pred))

и я использую это таким образом

model.compile(optimizer_obj, loss=custom_loss)
# and then model.fit(...)

Я не совсем уверен, как работает нетерпеливое выполнение tf2.0, поэтому любые идеи по этому поводу были бы полезны.

Я не думаю, что функция instance.exports.loss имеет отношение к ошибке, однако, если вы уверены, что все остальное в порядке, дайте мне знать, и я поделюсь дополнительной информацией.

Вот трассировка стека и фактическая ошибка: https://pastebin.com/6YtH75ay


person Viktor Velev    schedule 31.07.2019    source источник


Ответы (1)


Прежде всего, вам не нужно использовать @tf.function для определения настраиваемых потерь.

Мы можем с радостью (хотя и бессмысленно) сделать что-то вроде этого:

def custom_loss(y_true, y_pred):
  return tf.reduce_mean(y_pred)

model.compile(optimizer='adam',
              loss=custom_loss,
              metrics=['accuracy'])

при условии, что все операции, которые мы используем внутри custom_loss , дифференцируемы тензорным потоком

Таким образом, вы можете удалить декоратор @tf.function, но тогда я подозреваю, что вы столкнетесь с сообщением об ошибке примерно такого рода:

[Some trace info] - Please make sure that all of your ops have a gradient defined (i.e. are differentiable). Common ops without gradient: K.argmax, K.round, K.eval.

потому что tenorflow не может найти градиенты функции в двоичном файле webassembly. Все внутри этой функции потерь должно быть чем-то, что tenorflow может понимать и вычислять градиенты, иначе он не сможет оптимизировать для более низкого значения потерь.

Возможно, лучшим путем вперед было бы воспроизвести функциональность внутри instance.exports.loss, используя операции, на которых тензорный поток может вычислять градиенты, вместо того, чтобы пытаться ссылаться на него напрямую?

person Stewart_R    schedule 01.08.2019
comment
Отличный ответ, спасибо. Как вы определяете операции, на которых тензорный поток может вычислять градиенты? Что для этого нужно? Должен ли он быть обязательно в python, или я могу использовать тензорный поток C ++ для операций, а затем использовать их в python? - person Viktor Velev; 02.08.2019
comment
@ViktorVelev Мое удовольствие :-) Если это помогло, не стесняйтесь голосовать и / или принимать! Требуется, чтобы математическая функция была дифференцируемой и чтобы тензорный поток знал, как преобразовать ее в одну из своих операций. Я понимаю, что последнее предложение в этом предложении не очень ясное - я думаю, это из-за замечательной работы, которую команда tf проделала над автографом, чтобы автоматически преобразовать большую часть функциональности python в операции, которые граф tf может вычислить. Вы определенно находитесь в безопасности, когда используете tf. [Some_function], если some_function является дифференцируемым. - person Stewart_R; 02.08.2019
comment
Я полагаю, что где-то читал, что написание собственных пользовательских операций на C ++ выполнимо, но я никогда не пробовал этого, поэтому не могу посоветовать. Я предполагаю, что тогда вам нужно будет знать, как составить градиенты самостоятельно. Что именно делает двоичная функция потерь? Почти для всех случаев использования мы можем использовать завершение tf ops. - person Stewart_R; 02.08.2019
comment
Цель - модульность и секретность (функция обучения python не должна иметь доступа к исходному коду функции потерь) - person Viktor Velev; 03.08.2019