Пользовательская регуляризация в keras с помощью tf.gather

#python #python-3.x #tensorflow #keras #tensorflow2.0

#python #python-3.x #тензорный поток #keras #tensorflow2.0

Вопрос:

Я пытаюсь реализовать пользовательский регуляризатор в keras. Идея заключается в том, что область регуляризации ограничена двумя столбцами из набора данных. Вот игрушечный набор данных:

 # dataset
from sklearn.datasets import load_breast_cancer
data = load_breast_cancer()
x = data.data # x.shape() == (569, 30)
y = data.target
  

Вот как я написал регуляризатор:

 import tensorflow as tf # tf.__version__ == 2.0.0

class MyRegularizer(tf.keras.regularizers.Regularizer):

    def __init__(self, strength):
        self.strength = strength

    def __call__(self, x):
        # print(tf.shape(x))
        return self.strength * tf.reduce_sum(tf.subtract(tf.gather(params=x,indices=[29],axis=1),
                                                         tf.gather(params=x,indices=[28],axis=1)
                                                        )
                                            )
  

Вот игрушечная модель:

 # model
inputs = tf.keras.layers.Input(shape=x.shape[1])
dense = tf.keras.layers.Dense(1, kernel_regularizer=MyRegularizer(0.01)
                             )(inputs)
model = tf.keras.models.Model(inputs = inputs, outputs = dense)
model.compile(loss='binary_crossentropy')
model.summary()

model.fit(x,y)
  

Ошибка, которую я получаю, выглядит следующим образом:

InvalidArgumentError: segment_ids[0] = 28 находится вне диапазона [0, 1)

Я пытался проверить функцию вывода регуляризатора вне модели

 tf.reduce_sum(tf.subtract(tf.gather(x,[29],axis=1),tf.gather(x,[28],axis=1)))
  

и он работает нормально.

Так что, вероятно, есть проблема с формой тензора, который отправляется регуляризатору. Я понятия не имею, как это решить (играл с именами переменных, типами данных, формами ввода, все без удачи). Модель без регуляризатора подходит без каких-либо ошибок.

Потоки в Интернете, касающиеся вышеупомянутой ошибки, вращаются вокруг встраивания измерений, и мне не удалось найти решение, которое сработало бы для меня.

Ответ №1:

В вашем подклассе аргумент «x», переданный в методе ‘call ()’, является ядром слоя (веса). Поскольку у вас есть одна ячейка в слое Dence, метод «tf.gather» не может найти элемент index [28] на второй оси в ядре.

InvalidArgumentError: segment_ids[0] = 28 находится вне диапазона [0, 1)

если вы хотите получить вес, соответствующий вводу [28]; Я думаю, приведенный ниже код может работать (измените значение оси на ноль):

 import tensorflow as tf # tf.__version__ == 2.0.0

class MyRegularizer(tf.keras.regularizers.Regularizer):

def __init__(self, strength):
    self.strength = strength

def __call__(self, x):
    # print(tf.shape(x))
    return self.strength * tf.reduce_sum(tf.subtract(tf.gather(params=x,indices=[29],axis=0),
                                                     tf.gather(params=x,indices=[28],axis=0)
                                                    )
                                        )