我想尝试一些没有经典导数的激活函数(即导数包含Dirac脉冲,对于梯度下降类型的学习不是很有用)。 因此,我需要为Keras和/或TFLearn定义和添加激活函数集。不仅仅是一个新的激活功能,还有它定义的衍生功能。创造一个"假的"衍生物已经用于二值化神经网络。 所以,我发现了this并且我用它来定义它自己:
import numpy as np
import tensorflow as tf
from tensorflow.python.framework import ops
def nsign(x):
if x<0.0:
return -1.0
else:
return 1.0
np_nsign = np.vectorize(nsign)
def d_nsign(x):
if x>-1.0 and x<1.0:
return 1.0
else:
return 0.0
np_d_nsign = np.vectorize(d_nsign)
np_d_nsign_32 = lambda x: np_d_nsign(x).astype(np.float32)
def tf_d_nsign(x,name=None):
with ops.op_scope([x], name, "d_nsign") as name:
y = tf.py_func(np_d_nsign_32,
[x],
[tf.float32],
name=name,
stateful=False)
return y[0]
def py_func(func, inp, Tout, stateful=True, name=None, grad=None):
# Need to generate a unique name to avoid duplicates:
rnd_name = 'PyFuncGrad' + str(np.random.randint(0, 1E+8))
tf.RegisterGradient(rnd_name)(grad) # see _MySquareGrad for grad example
g = tf.get_default_graph()
with g.gradient_override_map({"PyFunc": rnd_name}):
return tf.py_func(func, inp, Tout, stateful=stateful, name=name)
def nsigngrad(op, grad):
x = op.inputs[0]
n_gr = tf_d_nsign(x)
return grad * n_gr
np_nsign_32 = lambda x: np_nsign(x).astype(np.float32)
def tf_nsign(x, name=None):
with ops.op_scope([x], name, "nsign") as name:
y = py_func(np_nsign_32,
[x],
[tf.float32],
name=name,
grad=nsigngrad) # <-- here's the call to the gradient
return y[0]
with tf.Session() as sess:
x = tf.constant([-0.2,0.7,1.2,-1.7])
y = tf_nsign(x)
tf.initialize_all_variables().run()
print(x.eval(), y.eval(), tf.gradients(y, [x])[0].eval())
除了TF抱怨tf.op_scope被弃用之外,这是有效的。 接下来的步骤是将上面的代码带到Keras中,以获得像cifar10演示代码这样的简单代码,并将所有relus更改为n_sign,如下所示:
model.add(Activation(n_sign))
不幸的是,这导致了以下错误:
Traceback (most recent call last):
File "cifar10_bin_tf.py", line 96, in <module>
model.add(Convolution2D(32, 3, 3))
File "/home/enzo/anaconda2/envs/neural/lib/python2.7/site-packages/keras/models.py", line 324, in add
output_tensor = layer(self.outputs[0])
File "/home/enzo/anaconda2/envs/neural/lib/python2.7/site-packages/keras/engine/topology.py", line 474, in __call__
self.assert_input_compatibility(x)
File "/home/enzo/anaconda2/envs/neural/lib/python2.7/site-packages/keras/engine/topology.py", line 415, in assert_input_compatibility
str(K.ndim(x)))
Exception: Input 0 is incompatible with layer convolution2d_2: expected ndim=4, found ndim=None
ndim听起来像&#34;维数&#34;这应该是一个标量函数是莫名其妙的。为TH找到了另一个trick,但一旦适应,它会导致一个非常类似的错误(再次抱怨ndim)。
问题: 1)你能建议修复上述内容吗?
2)你能否提出另一种简单的方法来做我想要的东西,比如Keras或TFLearn这样的高水平?
3)上面的代码是否可以在TFLearn中使用?
4)如果我将cifar10直接转换为TF并在那里使用它,上面的代码是否会起作用?
显然我想避免4)因为这意味着更多的挣扎和转换。
非常感谢你。