Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/tensorflow/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Tensorflow中仅使用Python创建自定义激活函数?_Python_Tensorflow_Neural Network_Deep Learning_Activation Function - Fatal编程技术网

如何在Tensorflow中仅使用Python创建自定义激活函数?

如何在Tensorflow中仅使用Python创建自定义激活函数?,python,tensorflow,neural-network,deep-learning,activation-function,Python,Tensorflow,Neural Network,Deep Learning,Activation Function,假设您需要创建一个激活函数,而仅使用预定义的tensorflow构建块是不可能的,您可以做什么 因此,在Tensorflow中,可以创建自己的激活函数。但是它相当复杂,你必须用C++编写,重新编译整个TysFooS.< 有更简单的方法吗?是的,有 积分: 很难找到信息并使其正常工作,但下面是一个从原理和代码中复制的示例 要求: 在我们开始之前,这需要两个条件才能成功。首先,您需要能够将激活作为函数写入numpy阵列。其次,您必须能够将该函数的导数编写为Tensorflow中的函数(更容易),或者

假设您需要创建一个激活函数,而仅使用预定义的tensorflow构建块是不可能的,您可以做什么

因此,在Tensorflow中,可以创建自己的激活函数。但是它相当复杂,你必须用C++编写,重新编译整个TysFooS.<
有更简单的方法吗?

是的,有

积分: 很难找到信息并使其正常工作,但下面是一个从原理和代码中复制的示例

要求: 在我们开始之前,这需要两个条件才能成功。首先,您需要能够将激活作为函数写入numpy阵列。其次,您必须能够将该函数的导数编写为Tensorflow中的函数(更容易),或者在最坏的情况下编写为numpy数组中的函数

写入激活功能:

with tf.Session() as sess:

    x = tf.constant([0.2,0.7,1.2,1.7])
    y = tf_spiky(x)
    tf.initialize_all_variables().run()
    
    print(x.eval(), y.eval(), tf.gradients(y, [x])[0].eval())
让我们以这个函数为例,我们希望使用一个激活函数:

def spiky(x):
    r = x % 1
    if r <= 0.5:
        return r
    else:
        return 0
现在我们应该写出它的导数

激活梯度: 在我们的例子中很容易,如果x mod 1<0.5,则为1,否则为0。因此:

def d_spiky(x):
    r = x % 1
    if r <= 0.5:
        return 1
    else:
        return 0
np_d_spiky = np.vectorize(d_spiky)
tf.py\u func
作用于张量列表(并返回张量列表),这就是为什么我们有
[x]
(并返回
y[0]
)。
stateful
选项是告诉tensorflow函数是否总是为相同的输入提供相同的输出(stateful=False),在这种情况下tensorflow可以简单地绘制tensorflow图,这是我们的情况,在大多数情况下可能都是这样。此时需要注意的一点是,numpy使用了
float64
,但tensorflow使用了
float32
,因此您需要先将函数转换为使用
float32
,然后才能将其转换为tensorflow函数,否则tensorflow会抱怨。这就是为什么我们需要首先制作
np_d_spiky_32

梯度呢?只做上述操作的问题是,尽管我们现在有了
tf_d_spiky
,这是
np_d_spiky
的tensorflow版本,但如果我们想要,我们不能将其用作激活函数,因为tensorflow不知道如何计算该函数的梯度

获取梯度的方法:如上所述,可以使用
tf.registerGradent
tf.Graph.grade\u override\u map
定义函数的梯度。从中复制代码,我们可以修改
tf.py_func
函数,使其同时定义渐变:

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)
现在我们差不多完成了,唯一需要传递给上面py_func函数的梯度函数需要采用一种特殊形式。它需要接受一个操作,以及操作之前的渐变,并在操作之后向后传播渐变

梯度函数:因此,对于我们的尖峰激活函数,我们将这样做:

def spikygrad(op, grad):
    x = op.inputs[0]

    n_gr = tf_d_spiky(x)
    return grad * n_gr  
激活功能只有一个输入,这就是为什么
x=op.inputs[0]
。如果操作有许多输入,我们需要返回一个元组,每个输入一个梯度。例如,如果操作是
a-b
,那么相对于
a
的梯度是
+1
,相对于
b
的梯度是
-1
,因此我们将有
返回+1*梯度,-1*梯度
。请注意,我们需要返回输入的tensorflow函数,这就是为什么need
tf_d_spiky
np_d_spiky
不起作用,因为它不能作用于tensorflow张量。或者,我们可以用张量流函数写出导数:

def spikygrad2(op, grad):
    x = op.inputs[0]
    r = tf.mod(x,1)
    n_gr = tf.to_float(tf.less_equal(r, 0.5))
    return grad * n_gr  
将其组合在一起:现在我们有了所有的片段,我们可以将它们组合在一起:

np_spiky_32 = lambda x: np_spiky(x).astype(np.float32)

def tf_spiky(x, name=None):
    
    with tf.name_scope(name, "spiky", [x]) as name:
        y = py_func(np_spiky_32,
                        [x],
                        [tf.float32],
                        name=name,
                        grad=spikygrad)  # <-- here's the call to the gradient
        return y[0]
[0.20.699999 1.2000005 1.70000005][0.20.0.2000005 0.][1.0.1.0.]


成功

为什么不简单地使用tensorflow中已有的函数来构建新函数呢

对于中的
spiky
函数,可以如下所示

def spiky(x):
    r = tf.floormod(x, tf.constant(1))
    cond = tf.less_equal(r, tf.constant(0.5))
    return tf.where(cond, r, tf.constant(0))

我会认为这要简单得多(甚至不需要计算任何梯度),除非你想做一些奇异的事情,我几乎无法想象TySoFrof不能为构建高度复杂的激活函数提供构建块。但如果你告诉我们你想创建什么样的激活函数(函数族),也许有人能帮助你。@lahwran这并不是你想在现实生活中使用的激活函数。这只是一个如何实现自定义激活功能的示例,如果你需要的话。是的,它可以工作:)但我没有尝试在实际的学习问题中使用网络it,我需要制作一个比我的目的更复杂的激活功能,但是在这里的帖子里,我只放了一个玩具激活功能,我并没有试着用它来学习。太棒了!注意:对于当前希望使用您的方法的用户,您应该将op.scope替换为tf.name\u scope,因为前者已被弃用。op.scope的参数顺序如下:op.scope(值,名称,“default_name”),而tf.name_scope的参数顺序是tf.name_scope(名称,default_名称,值),因此应该使用tf.name_scope(名称,“spiky”,[x])@patapouf\u TensorFlow在自定义函数上使用GPU加速吗?也就是说,这种激活是否会并行应用于CUDA内核中的许多张量元素?@patapouf_ai对创建自定义张量流函数的最清晰解释,我迄今为止已经看过了-谢谢!是的,的确,spiky可以用tf原语来完成,但是spiky只是一个简单的例子,不会被复杂性搞糊涂

with tf.Session() as sess:

    x = tf.constant([0.2,0.7,1.2,1.7])
    y = tf_spiky(x)
    tf.initialize_all_variables().run()
    
    print(x.eval(), y.eval(), tf.gradients(y, [x])[0].eval())
def spiky(x):
    r = tf.floormod(x, tf.constant(1))
    cond = tf.less_equal(r, tf.constant(0.5))
    return tf.where(cond, r, tf.constant(0))