Использование tf.contrib.opt.ScipyOptimizerInterface с tf.keras.layers, потери не меняются - PullRequest
0 голосов
/ 28 февраля 2019

Я хочу использовать интерфейс внешнего оптимизатора в тензорном потоке, чтобы использовать оптимизаторы Ньютона, поскольку в tf.train есть только оптимизаторы градиентного спуска первого порядка.В то же время я хочу построить свою сеть с использованием tf.keras.layers, поскольку это намного проще, чем использование tf.Variables при создании больших и сложных сетей.Я покажу свою проблему на следующем простом примере 1-мерной линейной регрессии:

import tensorflow as tf
from tensorflow.keras import backend as K
import numpy as np

#generate data
no = 100
data_x = np.linspace(0,1,no)
data_y = 2 * data_x + 2 + np.random.uniform(-0.5,0.5,no)
data_y = data_y.reshape(no,1)
data_x = data_x.reshape(no,1)

# Make model using keras layers and train
x = tf.placeholder(dtype=tf.float32, shape=[None,1])
y = tf.placeholder(dtype=tf.float32, shape=[None,1])

output = tf.keras.layers.Dense(1, activation=None)(x)

loss = tf.losses.mean_squared_error(data_y, output)
optimizer = tf.contrib.opt.ScipyOptimizerInterface(loss, method="L-BFGS-B")

sess = K.get_session()
sess.run(tf.global_variables_initializer())

tf_dict = {x : data_x, y : data_y}
optimizer.minimize(sess, feed_dict = tf_dict, fetches=[loss], loss_callback=lambda x: print("Loss:", x))

При выполнении этого убыток просто не меняется вообще.При использовании любого другого оптимизатора из tf.train он работает нормально.Кроме того, при использовании tf.layers.Dense () вместо tf.keras.layers.Dense () он работает с использованием ScipyOptimizerInterface.Поэтому на самом деле вопрос заключается в том, в чем разница между tf.keras.layers.Dense () и tf.layers.Dense ().Я видел, что переменные, созданные с помощью tf.layers.Dense (), имеют тип tf.float32_ref, а переменные, созданные с помощью tf.keras.layers.Dense (), имеют тип tf.float32.Насколько я сейчас, _ref указывает, что этот тензор изменчив.Так может в этом проблема?Но опять же, любой другой оптимизатор из tf.train прекрасно работает со слоями keras.

Спасибо

Ответы [ 2 ]

0 голосов
/ 06 июня 2019

После долгих поисков мне удалось найти возможное объяснение.

ScipyOptimizerInterface использует feed_dicts для имитации обновлений ваших переменных в процессе оптимизации.Он выполняет операцию присваивания только в самом конце.Напротив, оптимизаторы tf.train всегда выполняют операции назначения.Код ScipyOptimizerInterface не такой сложный, что вы можете легко это проверить.

Теперь проблема в том, что назначение переменных с помощью feed_dict работает в основном случайно.Вот ссылка , где я узнал об этом.Другими словами, присвоение переменных с помощью feed dict, что делает ScipyOptimizerInterface, является хакерским способом обновления.

Теперь этот хак в основном работает, за исключением случаев, когда это не так.tf.keras.layers.Dense использует ResourceVariables для моделирования весов модели.Это улучшенная версия простых переменных, которая имеет более чистую семантику чтения / записи.Проблема заключается в том, что в соответствии с новой семантикой обновление рассылки происходит после расчета потерь.Ссылка выше дает некоторые пояснения.

Теперь tf.layers в настоящее время является тонкой оболочкой для tf.keras.layer, поэтому я не уверен, почему это будет работать.Возможно, где-то в коде есть какая-то проверка совместимости.

Решения для устранения этой проблемы несколько просты.

  • Либо избегайте использования компонентов, использующих ResourceVariables.Это может быть довольно сложно.
  • Patch ScipyOptimizerInterface, чтобы всегда делать назначения для переменных.Это относительно просто, поскольку весь необходимый код находится в одном файле.

Были некоторые попытки заставить интерфейс работать с нетерпением (который по умолчанию использует ResourceVariables).Проверьте эту ссылку

0 голосов
/ 22 апреля 2019

Я думаю, что проблема со строкой

output = tf.keras.layers.Dense(1, activation=None)(x)

В этом формате output не является слоем, а скорее выводом слоя, который может препятствовать сбору оболочкивеса и уклоны слоя и передать их оптимизатору.Попробуйте написать его в две строки, например:

output = tf.keras.layers.Dense(1, activation=None)
res = output(x)

Если вы хотите сохранить исходный формат, вам, возможно, придется вручную собрать все обучаемые материалы и передать их оптимизатору с помощью опции var_list

optimizer = tf.contrib.opt.ScipyOptimizerInterface(loss, var_list = [Trainables], method="L-BFGS-B")

Надеюсь, это поможет.

...