Tensorflow 如何转动';关闭';完全连接的单隐层网络中的单个神经元

Tensorflow 如何转动';关闭';完全连接的单隐层网络中的单个神经元,tensorflow,keras,Tensorflow,Keras,我有一个在MNIST上训练的简单模型,在一个隐藏层中有600个节点 一些先兆 from __future__ import print_function import keras from keras.datasets import mnist from keras.models import Sequential, Model from keras.layers import Dense, Dropout, InputLayer, Activation from keras.optimizer

我有一个在MNIST上训练的简单模型,在一个隐藏层中有600个节点

一些先兆

from __future__ import print_function
import keras
from keras.datasets import mnist
from keras.models import Sequential, Model
from keras.layers import Dense, Dropout, InputLayer, Activation
from keras.optimizers import RMSprop, Adam
import numpy as np
import h5py
import matplotlib.pyplot as plt
from keras import backend as K
import tensorflow as tf
MNIST加载

batch_size = 128
num_classes = 10
epochs = 50

(x_train, y_train), (x_test, y_test) = mnist.load_data()

x_train = x_train.reshape(60000, 784)
x_test = x_test.reshape(10000, 784)
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

# One hot conversion
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)
设计模型

model = Sequential() 
###Model###
model.add(Dense(600, input_dim=784))
model.add(Activation('relu'))
model.add(Dense(10))
model.add(Activation('softmax'))
model.summary()

tfcall = keras.callbacks.TensorBoard(log_dir='./keras600logs', histogram_freq=1, batch_size=batch_size, write_graph=True)

model.compile(loss='categorical_crossentropy',optimizer=Adam(), metrics=['accuracy'])

history = model.fit(x_train, y_train,
    batch_size=batch_size,
    epochs=10, #EPOCHS
    verbose=1,
    validation_data=(x_test, y_test),
    callbacks=[tfcall])
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
现在是新的部分。我想动态地(即,对于每个新的输入图像)能够定义一个“掩码”,它将关闭隐藏层中600个神经元中的一些,防止它们将激活传递到输出层

掩码i=[0,0,1,0,1,.0,1,0,0](1x600)

这样,对于输入图像i,具有1的掩码索引对应于在处理图像i时关闭的节点

做这件事最好的方法是什么

我们是否有另一个节点,从输入到隐藏层的权重为-100000000,这样它将覆盖通常存在的任何激活(剩下的由relu完成)。这有点像动态地消除偏见

我们是否创建另一个隐藏层,其中600个节点中的每个节点直接连接到第一个隐藏层(自身)中的一个节点,动态权重为0(关闭)或1(正常进行),然后将新隐藏层完全连接到输出


这两个看起来都有点老土,我想知道其他人怎么想。

我认为最好的办法是在致密层之后加上一个带遮罩的lambda层

没有一点黑客攻击是无法做到的,但这是一个相当干净的黑客攻击

为遮罩创建一个变量:

import keras.backend as K

#create a var with length 600 and 2D shape
mask = K.variable([[0,1,0,0,0,1,1,0,....,1]])
    #careful: 0 means off
    #(same number of dimensions of the output of the dense layer)
    #make sure the shape is either
        #(1,600) - same mask for all samples; or
        #(batch_size,600) - one mask per sample

#important: whenever you want to change the mask, you must use:
K.set_value(mask,newValue)
    #otherwise you will not be changing the variable connected to the model
在模型中添加lambda层:

....
model.add(Dense(600, input_dim=784))
model.add(Lambda(lambda x: x * mask))
model.add(Activation('relu'))
....


如果您想让它更优雅,可以使用函数式API模型,使用
input(tensor=mask)
生成一个额外的输入。不过,我不知道这样做是否有什么好处

这听起来像是推理时的辍学,这就是你想要做的吗?不完全是。我们有一种非常具体的方法来选择要关闭的节点子集。我们感兴趣的是,当这些节点不再对输出层做出贡献时,预测结果是什么。如果我们有3个层,每个层200个节点?(完全连接),那么这种方法仍然有效。每个密集层需要一个lambda层。每个lambda层将使用自己的“mask”变量,每个mask将需要形状(1200)或(样本,200)。使用K.constant而不是K.variable是否更好(或有所不同)?我不确定您是否可以对常量使用“set_value”,但您可以尝试。如果可能的话,最好使用常量以避免开销。如果您想将变量用作可训练变量,则变量具有跟踪反向传播的功能。