Как написать собственный слой stdandardization с помощью tf.keras - PullRequest
0 голосов
/ 29 января 2020

В настоящее время я строю свои первые нейронные сети с API-интерфейсом tenorflow и keras. Я хочу написать слой для стандартизации входных данных, потому что выполнение этого в препроцессе может привести к ошибкам при использовании модели после обучения. Поэтому я хочу передать свой тренировочный набор данных функции init этого слоя и вычислить среднее и стандартное отклонение.

Проблема заключается в том, что я также хочу сохранить и загрузить модель после тренировки. Но если я вызову load_model (modelname), я получу ошибку, потому что функция init ожидает данные обучения в качестве аргумента. Кроме того, я не уверен, правильно ли указывать среднее значение и стандартное значение как переменную tf.Variable или есть ли лучший способ сделать это так, чтобы эти значения загружались при использовании load_model / load_weights.

I ' Я рад каждому ответу.

Следующий код представляет основную идею c для такого слоя.

class stdLayer(tf.keras.layers.Layer):
    def __init__(self, train_x, trainable=False,**kwargs):
        super(stdLayer, self).__init__(trainable=trainable,**kwargs)
        means=np.mean(train_x,axis=0)
        stds=np.std(train_x,axis=0)
        self.means = tf.Variable(means,
                                dtype=tf.float32,
                                name="means",
                                trainable=False)
        self.stds = tf.Variable(stds,
                                dtype=tf.float32,
                                name="stds",
                                trainable=False)


    def call(self, input):
        input_st = (input-self.means)/self.stds
        return input_st

1 Ответ

0 голосов
/ 29 января 2020

Возможно, вы могли бы просто иметь слой BatchNormalization в начале вашей модели.

Однако во всех случаях вам необходимо, чтобы ваши производственные данные были в том же формате, что и данные обучения.


В качестве альтернативы, вместо передачи данных обучения, передайте только means и stds.

class StdLayer(tf.keras.layers.Layer):
    def __init__(self, means, stds, trainable=False,**kwargs):
        ...
        self.means_init = means
        self.stds_init = stds
        ...

    def build(self, input_shape):
        self.means = self.add_weight(name='means', 
                                      shape=self.means_init.shape,
                                      initializer='zeros',
                                      trainable=True) 
                                       #if you put false here, they will never be trainable
        self.stds =  self.add_weight(name='stds', 
                                      shape=self.stds_init.shape,
                                      initializer='ones',
                                      trainable=True)
                                      #if you put false here, they will never be trainable

        keras.backend.set_value(self.means, self.means_init)
        keras.backend.set_value(self.stds, self.stds)

        self.built = True

    def call(self, inputs):
        ...

    def compute_output_shape(self, input_shape):
        ...

    def get_config(self):
        config = {
            'means_init': self.means_init,
            'stds_init': self.stds_init,
        }
        base_config = super(StdLayer, self).get_config()
        return dict(list(base_config.items()) + list(config.items()))

Если честно, я не уверен, можно ли передать массивы numpy в config.
Вы можете использовать __init__(self, means=None, stds=None, ... и поместить if внутрь build для set_values. Найдите другой способ вычисления фигур в add_weight, и вы сможете избавиться от config переменных.

...