Keras和/或TFLearn的自定义激活功能和衍生产品

时间:2016-12-20 02:35:24

标签: tensorflow deep-learning theano keras tflearn

我想尝试一些没有经典导数的激活函数(即导数包含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)因为这意味着更多的挣扎和转换。

非常感谢你。

0 个答案:

没有答案