Каков наилучший способ реализации ограничений веса в TensorFlow?
Предположим, что мы имеем веса
x = tf.Variable(np.random.random((5,10)))
cost = ...
И мы используем оптимизатор GD:
upds = tf.train.GradientDescentOptimizer(lr).minimize(cost)
session.run(upds)
Как мы можем реализовать, например, неотрицательность по весам?
Я попробовал обрезать их:
upds = tf.train.GradientDescentOptimizer(lr).minimize(cost)
session.run(upds)
session.run(tf.assign(x, tf.clip_by_value(x, 0, np.infty)))
Но это замедляет мою тренировку в 50 раз.
Кто-нибудь знает хороший способ реализовать такие ограничения на весах в TensorFlow?
P.S.: в эквивалентном алгоритме Анано я имел
T.clip(x, 0, np.infty)
и он прошел гладко.
Ответы
Ответ 1
Вы можете воспользоваться лагранжевым подходом и просто добавить штраф за функции переменной, которую вы не хотите.
например. Чтобы theta
был неотрицательным, вы можете добавить следующее к целевой функции оптимизатора.
added_loss = -tf.minimum( tf.reduce_min(theta),0)
Если какой-либо theta
отрицательный, то add2loss будет положительным, в противном случае - нолем. Масштабирование этого значения до значимого значения остается в качестве упражнения для читателя. Масштабирование слишком малое не будет оказывать достаточного давления. Слишком много может сделать вещи неустойчивыми.
Ответ 2
Запустив
sess.run(tf.assign(x, tf.clip_by_value(x, 0, np.infty)))
вы последовательно добавляете узлы в график и делаете его медленнее и медленнее.
На самом деле вы можете просто определить clip_op
при построении графика и запускать его каждый раз после обновления весов:
# build the graph
x = tf.Variable(np.random.random((5,10)))
loss = ...
train_op = tf.train.GradientDescentOptimizer(lr).minimize(loss)
clip_op = tf.assign(x, tf.clip(x, 0, np.infty))
# train
sess.run(train_op)
sess.run(clip_op)
Ответ 3
Начиная с TensorFlow 1.4 существует новый аргумент до tf.get_variable
, который позволяет передать функцию ограничения, которая применяется после обновления оптимизатора. Вот пример, который обеспечивает ограничение неотрицательности:
with tf.variable_scope("MyScope"):
v1 = tf.get_variable("v1", …, constraint=lambda x: tf.clip_by_value(x, 0, np.infty))
: необязательная функция проекции, применяемая к переменная после обновления с помощью Optimizer
(например, используемого для реализации нормы ограничения или ограничения значений для весов слоев). Функция должна в качестве входных данных введите непроектированный тензор, представляющий значение переменная и вернуть Тензор для прогнозируемого значения (которые должны иметь одинаковую форму). Ограничения небезопасны для использовать при выполнении асинхронного распределенного обучения.