简体   繁体   English

Tensorflow / Keras sigmoid 在密集层的单输出上

[英]Tensorflow / Keras sigmoid on single output of dense layer

I have a simple CNN model in tensorflow that takes in an image and predicts a 6 element label vector.我在 tensorflow 中有一个简单的 CNN 模型,它接收图像并预测 6 元素标签向量。 The final layer of my mode is therefore Dense(6).因此,我的模式的最后一层是 Dense(6)。 Label[0] is supposed to be binary, while Label[1:6] is continuous valued. Label[0] 应该是二进制的,而 Label[1:6] 是连续值。 I therefore want to apply a sigmoid activation to the output layer on only the first node of the output, while leaving the other 5 outputs as is.因此,我只想在输出的第一个节点上对输出层应用 sigmoid 激活,而其他 5 个输出保持原样。 How do I do this with tensorflow.keras?我如何使用 tensorflow.keras 做到这一点? For simplicity, my model building code currently looks something like:为简单起见,我的模型构建代码目前类似于:

model = tf.keras.models.Sequential()
model.add(Reshape((image_size, image_size, 1), input_shape = (image_size, image_size))
model.add(Conv2D(8, **parameters))
model.add(BatchNormalization())
model.add(Activation('relu')
Model.add(MaxPool2D())
model.add(Flatten())
model.add(Dense(6))

How do I add to this to use sigmoid activation on the first index of the last layer?我如何添加到最后一层的第一个索引上使用 sigmoid 激活?

Say that we get the output of your model as pred, then pred would be a tensor of shape(1, 6), so in order to achieve your objective you can do something like this:假设我们将模型的输出作为 pred,那么 pred 将是一个形状为 (1, 6) 的张量,因此为了实现您的目标,您可以执行以下操作:

sigmoid_input = pred.numpy()[0][0]
sigmoid_output = tf.keras.activations.sigmoid(sigmoid_input)

So first you need to convert the Tensor to a Numpy ndarray and then access just the first element of your Tensor.因此,首先您需要将张量转换为 Numpy ndarray,然后仅访问张量的第一个元素。 After that we pass the new variable sigmoid_input holding that value to a sigmoid as planned.之后,我们按计划将保存该值的新变量 sigmoid_input 传递给 sigmoid。

You can define a simple custom Lambda layer and do exactly what you want.您可以定义一个简单的自定义Lambda层并完全按照您的意愿进行操作。 Here is an example initially without an activation function.这是一个最初没有激活函数的示例。 Pay attention to the output:注意输出:

import tensorflow as tf
tf.random.set_seed(2)

def custom_layer(tensor):
    activated_node = tf.nn.sigmoid(tensor[:, :1])
    return tf.concat([activated_node, tensor[:, 1:]], axis=1)

model = tf.keras.Sequential()
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(6))

model(tf.random.uniform((2, 5)))
<tf.Tensor: shape=(2, 6), dtype=float32, numpy=
array([[-1.1554979 ,  0.29463094,  0.57452184,  0.40530735, -0.15730543,
         0.16329125],
       [-1.1518296 ,  1.2684885 ,  0.50156784,  1.2273686 ,  0.13656075,
        -0.7025717 ]], dtype=float32)>

And now with the custom Lambda layer, which applies an activation function to the first node in your tensor:现在使用自定义Lambda层,它将激活函数应用于张量中的第一个节点:

import tensorflow as tf
tf.random.set_seed(2)

def custom_layer(tensor):
    activated_node = tf.nn.sigmoid(tensor[:, :1])
    return tf.concat([activated_node, tensor[:, 1:]], axis=1)

model = tf.keras.Sequential()
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(6))
model.add(tf.keras.layers.Lambda(custom_layer, name="activation_layer"))

model(tf.random.uniform((2, 5)))
<tf.Tensor: shape=(2, 6), dtype=float32, numpy=
array([[ 0.23948632,  0.29463094,  0.57452184,  0.40530735, -0.15730543,
         0.16329125],
       [ 0.24015504,  1.2684885 ,  0.50156784,  1.2273686 ,  0.13656075,
        -0.7025717 ]], dtype=float32)>

You can clearly see how the first element of each sample (I am using batch_size=2) is squeezed between 0 and 1.您可以清楚地看到每个样本的第一个元素(我使用的是 batch_size=2)是如何在 0 和 1 之间挤压的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM