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

#python #tensorflow #keras #conv-neural-network

#python #tensorflow #keras #conv-neural-network

Вопрос:

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

Я не знаю, как скопировать нетерпеливый тензор в пользовательском слое. Я попытался использовать tf.identity и библиотеку копирования, но оба выдали мне ошибки, хотя, безусловно, возможно, что я неправильно это реализовал. Любые советы будут оценены. Я прикрепил одну из приведенных ниже ошибок, в которой говорится, что она должна работать, если выполняется быстрое выполнение, что меня смутило, поскольку я использую tensorflow 2, и по умолчанию должно быть включено быстрое выполнение.

 class RevertWeightMatrixDenseLayer(keras.layers.Layer):
def __init__(self, units, prob, **kwargs):
    super(RevertWeightMatrixDenseLayer, self).__init__(**kwargs)
    self.units = units
    self.prob = prob


def build(self, input_shape):
    self.w = self.add_weight(
        shape=(input_shape[-1], self.units),
        initializer="random_normal",
        trainable=True,
    )
    self.b = self.add_weight(
        shape=(self.units,), initializer="random_normal", trainable=True
    )

    self.last_weight_1 = self.w
    self.last_weight_2 = self.w

def call(self, inputs, training=False):
    current_weights = self.w
    if training:
        if self.prob > random.random():
            self.w.assign(self.last_weight_2)  # Assign preserves tf.Variable
        #deep copy all the weights here here before assignement
        self.last_weight_2 = self.last_weight_1 
        self.last_weight_1 = current_weights
    else:
        pass #could think about multiplying all weights by a constant here
    return tf.nn.relu(tf.matmul(inputs, self.w)   self.b)


model = make_base_model() #sets up a sequential model with some conv layers
model.add(ResetWeightMatrixDenseLayer(units=dense_units, prob=0.1)) #Custom layer
model.add(ResetWeightMatrixDenseLayer(units=dense_units, prob=0.1)) #Custom layer

model.add(layers.Dense(classes, activation='softmax'))

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

history = model.fit(train_dataset, validation_data=validation_dataset, epochs=epochs)
plot(history)
 

Попытка глубокого копирования, где я прокомментировал, приводит к следующей ошибке * NotImplementedError: deepcopy() доступна только при активном выполнении. включено.*

Комментарии:

1. попробуйте использовать get_weights() / set_weights() . Но я не уверен, что можно установить веса в call() методе

Ответ №1:

Вы хотите сохранить состояния в своем слое: это именно то tf.Variable , для чего они нужны. (См. Руководство: Введение в переменные)

Установите ваше last_weights значение как необучаемое tf.Variable и используйте assign для копирования значений вокруг.

 class RevertWeightMatrixDenseLayer(keras.layers.Layer):
    def __init__(self, units, prob, **kwargs):
        super(RevertWeightMatrixDenseLayer, self).__init__(**kwargs)
        self.units = units
        self.prob = prob


    def build(self, input_shape):
        self.w = self.add_weight(
            shape=(input_shape[-1], self.units),
            initializer="random_normal",
            trainable=True,
        )
        self.b = self.add_weight(
            shape=(self.units,), initializer="random_normal", trainable=True
        )

        self.last_weight_1 = tf.Variable(self.w, trainable=False)
        self.last_weight_2 = tf.Variable(self.w, trainable=False)
        # we need an extra Variable to store the original value of w
        # when shuffling around
        self.tmp = tf.Variable(self.w, trainable=False)

    def call(self, inputs, training=False):
        self.tmp.assign(self.w)
        if training:
            if self.prob > random.random():
                self.w.assign(self.last_weight_2)  # Assign preserves tf.Variable
            self.last_weight_2.assign(self.last_weight_1)
            self.last_weight_1.assign(self.tmp)
        else:
            pass #could think about multiplying all weights by a constant here
        return tf.nn.relu(tf.matmul(inputs, self.w)   self.b)