Проблема с вашим решением и некоторыми другими, предложенными другими ответами в этом посте, заключается в том, что они не предотвращают тренировку этого веса.Они позволяют градиентному спуску тренировать несуществующий вес и затем перезаписывают его ретроспективно.Это приведет к тому, что сеть будет иметь ноль в этом месте по желанию, но отрицательно повлияет на ваш тренировочный процесс, так как вычисление обратного распространения не будет видеть шаг маскирования, так как он не является частью графика TensorFlow, и поэтому будет следовать градиентный спуск.путь, который включает в себя предположение, что этот вес оказывает влияние на результат (это не так).
Лучшим решением было бы включить шаг маскирования как часть вашего TensorFlowграфик, так что он может быть учтен в градиентном спуске.Поскольку шаг маскирования - это просто поэлементное умножение на ваш разреженный двоичный код martix mask
, вы можете просто включить матрицу mask
в качестве множителя элементарной матрицы в определении графа, используя tf.multiply
.
К сожалению, это означает прощание с простыми в использовании керасами, методами наложения слоев и более понятным подходом к TensorFlow.Я не вижу очевидного способа сделать это с помощью API слоев.
См. Реализацию ниже, я постарался предоставить комментарии, объясняющие, что происходит на каждом этапе.
import tensorflow as tf
## Graph definition for model
# set up tf.placeholders for inputs x, and outputs y_
# these remain fixed during training and can have values fed to them during the session
with tf.name_scope("Placeholders"):
x = tf.placeholder(tf.float32, shape=[None, 2], name="x") # input layer
y_ = tf.placeholder(tf.float32, shape=[None, 2], name="y_") # output layer
# set up tf.Variables for the weights at each layer from l1 to l3, and setup feeding of initial values
# also set up mask as a variable and set it to be un-trianable
with tf.name_scope("Variables"):
w_l1_values = [[0, 0.25],[0.2,0.3]]
w_l1 = tf.Variable(w_l1_values, name="w_l1")
w_l2_values = [[0.4,0.5],[0.45, 0.55]]
w_l2 = tf.Variable(w_l2_values, name="w_l2")
mask_values = [[0., 1.], [1., 1.]]
mask = tf.Variable(mask_values, trainable=False, name="mask")
# link each set of weights as matrix multiplications in the graph. Inlcude an elementwise multiplication by mask.
# Sequence takes us from inputs x to output final_out, which will be compared to labels fed to placeholder y_
l1_out = tf.nn.relu(tf.matmul(x, tf.multiply(w_l1, mask)), name="l1_out")
final_out = tf.nn.relu(tf.matmul(l1_out, w_l2), name="output")
## define loss function and training operation
with tf.name_scope("Loss"):
# some loss defined as a function of graph output: final_out and labels: y_
loss = tf.nn.sigmoid_cross_entropy_with_logits(logits=final_out, labels=y_, name="loss")
with tf.name_scope("Train"):
# some optimisation strategy, arbitrary learning rate
optimizer = tf.train.AdamOptimizer(learning_rate=0.001, name="optimizer_adam")
train_op = optimizer.minimize(loss, name="train_op")
# create session, initialise variables and train according to inputs and corresponding labels
# This should show that the values of the first layer weights change, but the one set to 0 remains at 0
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
initial_l1_weights = sess.graph.get_tensor_by_name("Variables/w_l1:0")
print(initial_l1_weights.eval())
inputs = [[0.05, 0.10]]
labels = [[0.01, 0.99]]
ans = sess.run(train_op, feed_dict={"Placeholders/x:0": inputs, "Placeholders/y_:0": labels})
train_steps = 1
for i in range(train_steps):
initial_l1_weights = sess.graph.get_tensor_by_name("Variables/w_l1:0")
print(initial_l1_weights.eval())
Или используйте ответ, предоставленный сегодня для дружественного керасу варианта.