我有一个在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个神经元中的一些神经元,防止它们将激活传递到输出层。
mask_i = [0,0,1,0,1,...... 0,1,0,0](1x600)
使得对于输入图像i,具有1的掩码索引对应于在处理图像i时被关闭的节点。
这样做的最佳方法是什么?
我们是否有来自输入的另一个节点,其权重为TOWARDS -1000000的隐藏层,因此无论通常存在什么激活,它都会淹没(并且relu会完成剩下的工作)。这有点像动态地破解偏见。
我们是否创建了另一个隐藏层,其中每个600个节点直接连接到第一个隐藏层(本身)的一个节点,动态权重为0(关闭)或1(正常运行)然后完全将新的隐藏层连接到输出?
这两个看起来都有点hackish,想知道其他人的想法。
答案 0 :(得分:0)
我认为最好的方法是在密集层之后放置一个带有蒙版的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模型,使用mask
Input(tensor=mask)
一个额外输入。不过,我不知道这样做是否有任何好处。