исправить / заморозить отдельные веса ядра в сверточной операции

#python-3.x #tensorflow #conv-neural-network

#python-3.x #тензорный поток #conv-нейронная сеть

Вопрос:

Я пытаюсь найти обходной путь для исправления отдельных весов ядра в сверточной операции в TensorFlow с использованием Python 3.7. Я делаю это, создавая

  1. обучаемая переменная,
  2. идентичная необучаемая переменная и
  3. тензор «маски», состоящий из 1 с и 0 с той же формой, что и созданные переменные на шаге 1 и 2 выше.

1 в тензоре «маски» указывает, что я хочу исправить / заморозить этот удельный вес во время обучения, т. Е. Не Обновлять его при обратном проходе.

Теперь это обходное решение отлично работает при применении к полностью подключенному слою, но терпит неудачу при применении к сверточному слою, и я не могу понять, почему или как заставить его работать.

Похоже, что-то происходит в вызове функции tf.nn.conv2d() (см. Пример кода ниже), и, согласно документации, это то, что они делают:

Задан входной тензор формы [batch, in_height, in_width, in_channels]
и тензор фильтра / ядра формы
[filter_height, filter_width, in_channels, out_channels] , эта операция
выполняет следующее:
1. Сглаживает фильтр до 2-мерной матрицы с формой
[filter_height * filter_width * in_channels, output_channels] .
2. Извлекает участки изображения из входного тензора для формирования виртуального
тензор формы [batch, out_height, out_width,<br>
filter_height * filter_width * in_channels]
.
3. Для каждого исправления перемножает матрицу фильтра и
вектор исправления изображения.

Но поскольку я использую weights_frozen, который является тензором и зависит от обучаемой переменной, необучаемой переменной и mask_weights, он должен получать градиенты с нулевым значением в позициях, где у меня есть 1 в тензоре mask_weights.

 def conv(input_, layer_name...):

    weights = tf.get_variable(shape=[filter_height, filter_width, in_channels, out_channels], dtype=tf.float32, initializer=tf.glorot_uniform_initializer(), trainable=True)

    weights_fixed = tf.Variable(tf.identity(weights), trainable=False)

    mask_weights = tf.placeholder(tf.float32, weights.shape)


    weights_frozen = tf.add(tf.multiply(mask_weights, weights_fixed), tf.multiply((1 - mask_weights), weights))


    out_conv = tf.nn.conv2d(input=input_, filter=weights_frozen, strides=strides_, padding='SAME')
    out_add = tf.nn.bias_add(value=out_conv, bias=biases_frozen)

    out = tf.nn.relu(features=out_add)

    return out
  

Как уже упоминалось, я ожидаю получить градиенты с нулевым значением в позициях, где у меня есть 1 в тензоре mask_weights, но вместо этого они ненулевые, и поэтому эти веса обучаются, а это не то поведение, которого я пытаюсь достичь.