繁体   English   中英

"使用 Keras 和 TensorFlow 查找最大化神经网络输出的输入"

[英]Find input that maximises output of a neural network using Keras and TensorFlow

按照本教程<\/a>,我使用 Keras 和 TensorFlow 对Fashion MNIST<\/a>进行分类。

它使用AdamOptimizer<\/a>来找到模型参数的值,以最小化网络的损失函数。 网络的输入是一个形状为 [28, 28] 的二维张量,输出是一个形状为 [10] 的一维张量,它是 softmax 函数的结果。

一旦网络经过训练,我想将优化器用于另一项任务:找到一个使输出张量的一个元素最大化的输入。 如何才能做到这一点? 是否可以使用 Keras 来做到这一点,或者必须使用较低级别的 API?

由于输入对于给定的输出不是唯一的,如果我们可以对输入可以采用的值施加一些限制,那就更好了。

训练好的模型具有以下格式

model = keras.Sequential([
    keras.layers.Flatten(input_shape=(28, 28)),
    keras.layers.Dense(128, activation=tf.nn.relu),
    keras.layers.Dense(10, activation=tf.nn.softmax)
])

我觉得你会想要关于输入冻结模型的所有权重。 你能做的是:

  1. 在输入图层后面添加一个与输入相同尺寸的密集图层,并将其设置为可训练
  2. 冻结模型的所有其他图层。 (除了你添加的那个)
  3. 作为输入,输入单位矩阵并根据您想要的输出训练您的模型。

文章, 这个如果你想基于输入而不是backprop后也许能帮助你。 这有点像你的目标,但你可以获得直觉。

它与可视化卷积网络的滤波器的方式非常相似:我们将在输入空间中进行梯度上升优化,以最大化特定滤波器的响应

以下是如何操作:训练结束后,首先我们需要指定输出并定义一个我们想要最大化的损失函数:

from keras import backend as K

output_class = 0 # the index of the output class we want to maximize
output = model.layers[-1].output
loss = K.mean(output[:,output_class]) # get the average activation of our desired class over the batch

接下来,我们需要采用上面针对输入层定义的损失的梯度:

grads = K.gradients(loss, model.input)[0] # the output of `gradients` is a list, just take the first (and only) element

grads = K.l2_normalize(grads) # normalize the gradients to help having an smooth optimization process

接下来,我们需要定义一个后端函数,它接受初始输入图像并将损失和梯度值作为输出,以便我们可以在下一步中使用它来实现优化过程:

func = K.function([model.input], [loss, grads])

最后,我们实现了渐变上升优化过程:

import numpy as np

input_img = np.random.random((1, 28, 28)) # define an initial random image

lr = 1.  # learning rate used for gradient updates
max_iter = 50  # number of gradient updates iterations
for i in range(max_iter):
    loss_val, grads_val = func([input_img])
    input_img += grads_val * lr  # update the image based on gradients

请注意,在此过程完成后,要显示图像,您可能需要确保图像中的所有值都在[0,255](或[0,1])范围内。

有趣。 也许解决方案是将所有数据提供给网络,并且每个样本在softmax之后保存output_layer

这样一来,对于3类 ,要找到1类最佳的投入,你正在寻找的输出,其中第一部分是高的。 例如: [1 0 0]

实际上,输出意味着样本是其中一个类的概率或网络的置信度。

在Saket Kumar Singh给出答案的提示之后,我写下了似乎可以解决问题的以下内容。

我创建了两个自定义图层。 也许Keras已经提供了一些与它们相当的类。

第一个是可训练的输入:

class MyInputLayer(keras.layers.Layer):
    def __init__(self, output_dim, **kwargs):
        self.output_dim = output_dim
        super(MyInputLayer, self).__init__(**kwargs)

    def build(self, input_shape):
        self.kernel = self.add_weight(name='kernel',
                                      shape=self.output_dim,
                                      initializer='uniform',
                                      trainable=True)
        super(MyInputLayer, self).build(input_shape)

    def call(self, x):
        return self.kernel

    def compute_output_shape(self, input_shape):
        return self.output_dim

第二个获得感兴趣的标签的概率:

class MySelectionLayer(keras.layers.Layer):
    def __init__(self, position, **kwargs):
        self.position = position
        self.output_dim = 1
        super(MySelectionLayer, self).__init__(**kwargs)

    def build(self, input_shape):
        super(MySelectionLayer, self).build(input_shape)

    def call(self, x):
        mask = np.array([False]*x.shape[-1])
        mask[self.position] = True
        return tf.boolean_mask(x, mask,axis=1)

    def compute_output_shape(self, input_shape):
        return self.output_dim

我用这种方式使用它们:

# Build the model
layer_flatten =  keras.layers.Flatten(input_shape=(28, 28))
layerDense1 = keras.layers.Dense(128, activation=tf.nn.relu)
layerDense2 = keras.layers.Dense(10, activation=tf.nn.softmax)
model = keras.Sequential([
    layer_flatten,
    layerDense1,
    layerDense2
])

# Compile the model
model.compile(optimizer=tf.train.AdamOptimizer(),
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

# Train the model
# ...

# Freeze the model
layerDense1.trainable = False
layerDense2.trainable = False

# Build another model
class_index = 7

layerInput =  MyInputLayer((1,784))
layerSelection = MySelectionLayer(class_index)

model_extended = keras.Sequential([
    layerInput,
    layerDense1,
    layerDense2,
    layerSelection
])

# Compile it
model_extended.compile(optimizer=tf.train.AdamOptimizer(),
              loss='mean_absolute_error')

# Train it
dummyInput = np.ones((1,1))
target = np.ones((1,1))
model_extended.fit(dummyInput, target,epochs=300)

# Retrieve the weights of layerInput
layerInput.get_weights()[0]

有趣的巧合我只是在研究同样的“问题”。 我对对抗训练的方向感兴趣等。我做的是在输入后插入一个LocallyConnected2D图层,然后训练所有的数据,并将目标作为感兴趣的类。

作为我使用的模型

batch_size = 64
num_classes = 10
epochs = 20
input_shape = (28, 28, 1)


inp = tf.keras.layers.Input(shape=input_shape)
conv1 = tf.keras.layers.Conv2D(32, kernel_size=(3, 3),activation='relu',kernel_initializer='he_normal')(inp)
pool1 = tf.keras.layers.MaxPool2D((2, 2))(conv1)
drop1 = tf.keras.layers.Dropout(0.20)(pool1)
flat  = tf.keras.layers.Flatten()(drop1)
fc1   = tf.keras.layers.Dense(128, activation='relu')(flat)
norm1 = tf.keras.layers.BatchNormalization()(fc1)
dropfc1 = tf.keras.layers.Dropout(0.25)(norm1)
out   = tf.keras.layers.Dense(num_classes, activation='softmax')(dropfc1)

model = tf.keras.models.Model(inputs = inp , outputs = out)

model.compile(loss=tf.keras.losses.categorical_crossentropy,
              optimizer=tf.keras.optimizers.RMSprop(),
              metrics=['accuracy'])
model.summary()

训练后我插入新图层

def insert_intermediate_layer_in_keras(model,position, before_layer_id):
    layers = [l for l in model.layers]

    if(before_layer_id==0) :
        x = new_layer
    else:
        x = layers[0].output
    for i in range(1, len(layers)):
        if i == before_layer_id:
            x = new_layer(x)
            x = layers[i](x)

        else:
            x = layers[i](x)

    new_model = tf.keras.models.Model(inputs=layers[0].input, outputs=x)
    return new_model

def fix_model(model):
    for l in model.layers:
        l.trainable=False


fix_model(model)    
new_layer = tf.keras.layers.LocallyConnected2D(1, kernel_size=(1, 1),
                                               activation='linear',
                                               kernel_initializer='he_normal',
                                                use_bias=False)
new_model = insert_intermediate_layer_in_keras(model,new_layer,1)
new_model.compile(loss=tf.keras.losses.categorical_crossentropy,
              optimizer=tf.keras.optimizers.RMSprop(),
              metrics=['accuracy'])

最后用我的假数据重新训练。

X_fake = np.ones((60000,28,28,1))
print(Y_test.shape)
y_fake = np.ones((60000))
Y_fake = tf.keras.utils.to_categorical(y_fake, num_classes)
new_model.fit(X_fake, Y_fake, epochs=100)
weights = new_layer.get_weights()[0]

imshow(weights.reshape(28,28))
plt.show()

结果还不令人满意,但我对这种方法充满信心并猜测我需要与优化器一起玩。

对于密集模型,您可以像本文一样可视化输入的影响

这是文章中输入对第一层的影响的图片: 在此处输入图像描述

暂无
暂无

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

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