【问题标题】:How to turn 'off' individual neurons in a fully connected, single hidden layer network如何在完全连接的单隐藏层网络中“关闭”单个神经元
【发布时间】:2018-04-24 11:58:13
【问题描述】:

我有一个在 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 隐藏层为 -100000000,以便它会压倒通常存在的任何激活(其余的将由 relu 完成)。这有点像动态破解偏见。

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

这两个看起来都有些骇人听闻,想知道其他人的想法。

【问题讨论】:

  • 这听起来像是推理时的 Dropout,这是你想要做的吗?
  • 不完全。我们有一种非常具体的方式来选择要关闭的节点子集。我们有兴趣了解当这些节点不再对输出层做出贡献时的预测结果。

标签: tensorflow keras


【解决方案1】:

我认为最好的方法是在密集层之后放置一个带有遮罩的 lambda 层。

没有一点hacking就没有办法做到这一点,但这是一个相当干净的hack。

为掩码创建一个变量:

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 模型,将 maskInput(tensor=mask) 一起添加一个输入。不过,我不知道这样做是否有任何优势。

【讨论】:

  • 如果我们有 3x 层,每层 200 个节点,这个方法仍然有效吗?(完全连接)
  • 每个 Dense 层都需要一个 lambda 层。每个 lambda 层都将使用自己的“掩码”变量,每个掩码都需要形状 (1,200) 或 (samples,200)。
  • 使用 K.constant 代替 K.variable 会更好(或有所作为)吗?
  • 我不确定您是否可以在常量上使用“set_value”,但您可以尝试。如果可能的话,也许最好使用常量来避免开销。变量具有跟踪反向传播的功能,如果您想将它们用作可训练的。
猜你喜欢
  • 2020-06-11
  • 1970-01-01
  • 1970-01-01
  • 2017-05-21
  • 2017-12-20
  • 1970-01-01
  • 2011-03-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多