1

I'm trying to write a custom activation layer in keras. The problem is, I've tried to do it with a sigmoid and with a relu activation function. The examples are pratically identical, but one works while the other doesn't. The working example is:

class ParamRelu(Layer):
    def __init__(self, alpha, **kwargs):
        super(ParamRelu, self).__init__(**kwargs)
        self.alpha = K.cast_to_floatx(alpha)

    def call(self, inputs):
        return K.sigmoid(self.alpha * inputs) * inputs

    def get_config(self):
        config = {'alpha': float(self.alpha)}
        base_config = super(ParamRelu, self).get_config()
        return dict(list(base_config.items()) + list(config.items()))

    def compute_output_shape(self, input_shape):
        return input_shape


def aafcnn(alpha_row):
    (x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()
    x_train = x_train[:, :, :, np.newaxis] / 255.0
    x_test = x_test[:, :, :, np.newaxis] / 255.0
    y_train = to_categorical(y_train)
    y_test = to_categorical(y_test)

    model = Sequential()

    model.add(Conv2D(filters=16, kernel_size=3, padding='same', input_shape=(28, 28, 1)))
    model.add(ParamRelu(alpha=alpha_row[0]))
    model.add(MaxPooling2D(pool_size=2))
    model.add(Conv2D(filters=32, kernel_size=3, padding='same'))
    model.add(ParamRelu(alpha=alpha_row[1]))
    model.add(MaxPooling2D(pool_size=2))
    model.add(Conv2D(filters=64, kernel_size=3, padding='same'))
    model.add(ParamRelu(alpha=alpha_row[2]))
    model.add(MaxPooling2D(pool_size=2))
    model.add(Flatten())
    model.add(Dense(50, activation='relu'))
    model.add(Dense(10, activation='softmax'))
    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

    model.summary()

    model.fit(x_train, y_train, epochs=1, validation_split=0.1)

    _, test_acc = model.evaluate(x_test, y_test)
    print(test_acc)


alpha_matrix = np.random.rand(10, 3)
for i in range(10):
    aafcnn(alpha_matrix[i])

This works. This doesn't:

class ParamRelu(Layer):
    def __init__(self, alpha, **kwargs):
        super(ParamRelu, self).__init__(**kwargs)
        self.alpha = K.cast_to_floatx(alpha)

    def call(self, inputs):
        return K.max((self.alpha * inputs), 0)

    def get_config(self):
        config = {'alpha': float(self.alpha)}
        base_config = super(ParamRelu, self).get_config()
        return dict(list(base_config.items()) + list(config.items()))

    def compute_output_shape(self, input_shape):
        return input_shape


def aafcnn(alpha_row):
    (x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()
    x_train = x_train[:, :, :, np.newaxis] / 255.0
    x_test = x_test[:, :, :, np.newaxis] / 255.0
    y_train = to_categorical(y_train)
    y_test = to_categorical(y_test)

    model = Sequential()

    model.add(Conv2D(filters=16, kernel_size=3, padding='same', input_shape=(28, 28, 1)))
    model.add(ParamRelu(alpha=alpha_row[0]))
    model.add(MaxPooling2D(pool_size=2))
    model.add(Conv2D(filters=32, kernel_size=3, padding='same'))
    model.add(ParamRelu(alpha=alpha_row[1]))
    model.add(MaxPooling2D(pool_size=2))
    model.add(Conv2D(filters=64, kernel_size=3, padding='same'))
    model.add(ParamRelu(alpha=alpha_row[2]))
    model.add(MaxPooling2D(pool_size=2))
    model.add(Flatten())
    model.add(Dense(50, activation='relu'))
    model.add(Dense(10, activation='softmax'))
    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

    model.summary()

    model.fit(x_train, y_train, epochs=1, validation_split=0.1)

    _, test_acc = model.evaluate(x_test, y_test)
    print(test_acc)


alpha_matrix = np.random.rand(10, 3)
for i in range(10):
    aafcnn(alpha_matrix[i])

The error is:

ValueError: Input 0 of layer max_pooling2d is incompatible with the layer: expected ndim=4, found ndim=3. Full shape received: [28, 28, 16]

I've tried using input_shape=(None, 28, 28, 1) instead of input_shape=(28, 28, 1), but in this case the error becomes:

ValueError: Input 0 of layer conv2d is incompatible with the layer: expected ndim=4, found ndim=5. Full shape received: [None, None, 28, 28, 1]

What am I doing wrong?

1 Answer 1

2

The problem is, that in the second case, with the line:

return K.max((self.alpha * inputs), 0)

you reduce the dimensions by one in the axis=0.

So the max_pooling2d will not get the required 4D input.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.