Зачем вам добавлять переменную в список _trainable_weights слоя? - PullRequest
2 голосов
/ 24 октября 2019

В этой записной книжке https://nbviewer.jupyter.org/github/krasserm/bayesian-machine-learning/blob/master/bayesian_neural_networks.ipynb, автор определяет функцию

def mixture_prior_params(sigma_1, sigma_2, pi):
    params = K.variable([sigma_1, sigma_2, pi], name='mixture_prior_params')
    sigma = np.sqrt(pi * sigma_1 ** 2 + (1 - pi) * sigma_2 ** 2)
    return params, sigma

, которая создает переменную и возвращает кортеж. Этот метод затем называется

prior_params, prior_sigma = mixture_prior_params(sigma_1=1.0, sigma_2=0.1, pi=0.2)

Затем в классе DenseVariational, который является пользовательским слоем, в методе build глобальная переменная prior_params добавляется в личный список * 1012. *

def build(self, input_shape):
    self._trainable_weights.append(prior_params)
    ...

Зачем это нужно? Если я попытаюсь напечатать обучаемые параметры либо пользовательского слоя, либо модели, изготовленной из этого пользовательского слоя, например

# Create the model with DenseVariational layers
model = Model(x_in, x_out)
print("model.trainable_weights =", model.trainable_weights)

, я увижу, что каждый слой DenseVariational содержит обучаемый параметр mixture_prior_params. Зачем объявлять mixture_prior_params, точнее, sigma_1, sigma_2 и pi вне слоя, если они являются обучаемыми параметрами слоя?

1 Ответ

1 голос
/ 24 октября 2019

После рассмотрения этого вопроса Можно ли разделить веса между слоями keras, но есть другие параметры, отличающиеся? и его ответ (https://stackoverflow.com/a/45258859/3924118) и напечатав значения обучаемых переменных моделипосле обучения модели кажется, что это способ совместного использования переменной между различными уровнями, учитывая, что значение этой переменной кажется одинаковым для всех слоев после обучения модели.

Iсоздали простой пример (с TensorFlow 2.0.0 и Keras 2.3.1), который показывает это

import numpy as np
from keras import activations, initializers
from keras import backend as K
from keras import optimizers
from keras.layers import Input
from keras.layers import Layer
from keras.models import Model

shared_variable = K.variable([0.3], name='my_shared_variable')


class MyLayer(Layer):
    def __init__(self, output_dim, activation=None, **kwargs):
        self.output_dim = output_dim
        self.activation = activations.get(activation)
        super().__init__(**kwargs)

    def build(self, input_shape):
        self._trainable_weights.append(shared_variable)
        self.my_weight = self.add_weight(name='my_weight',
                                         shape=(input_shape[1], self.output_dim),
                                         initializer=initializers.normal(),
                                         trainable=True)
        super().build(input_shape)

    def call(self, x):
        return self.activation(K.dot(x, self.my_weight * shared_variable))

    def compute_output_shape(self, input_shape):
        return input_shape[0], self.output_dim


if __name__ == "__main__":
    # Define the architecture of the model.
    x_in = Input(shape=(1,))
    h1 = MyLayer(20, activation='relu')(x_in)
    h2 = MyLayer(20, activation='relu')(h1)
    x_out = MyLayer(1)(h2)

    model = Model(x_in, x_out)
    print("h1.trainable_weights (before training) =", model.layers[1].trainable_weights[0])
    print("h2.trainable_weights (before training) =", model.layers[2].trainable_weights[0])

    # Prepare the model for training.
    model.compile(loss="mse", optimizer=optimizers.Adam(lr=0.03))

    # Generate dataset.
    X = np.linspace(-0.5, 0.5, 100).reshape(-1, 1)
    y = 10 * np.sin(2 * np.pi * X)

    # Train the model.
    model.fit(X, y, batch_size=1, epochs=100, verbose=0)

    print("h1.trainable_weights (after training) =", model.layers[1].trainable_weights[0])
    print("h2.trainable_weights (after training) =", model.layers[2].trainable_weights[0])

Выходные данные

h1.trainable_weights (before training) = <tf.Variable 'my_shared_variable:0' shape=(1,) dtype=float32, numpy=array([0.3], dtype=float32)>
h2.trainable_weights (before training) = <tf.Variable 'my_shared_variable:0' shape=(1,) dtype=float32, numpy=array([0.3], dtype=float32)>
h1.trainable_weights (after training) = <tf.Variable 'my_shared_variable:0' shape=(1,) dtype=float32, numpy=array([0.7049409], dtype=float32)>
h2.trainable_weights (after training) = <tf.Variable 'my_shared_variable:0' shape=(1,) dtype=float32, numpy=array([0.7049409], dtype=float32)>
...