更新 感谢Q&A here,我能够使用tensorflow构建一个工作步骤函数。 (见下面的代码)
现在我的问题演变为
如何利用
list
中创建的tf_stepy
激活功能在tensorflow
中工作?
我尝试使用以下代码在keras中使用keras
,但不能正常工作:
tf_stepy
以下是使用tensorflow创建的步骤激活功能
from tensorflow_step_function import tf_stepy
def buy_hold_sell(x):
return tf_stepy(x)
get_custom_objects().update({'custom_activation': Activation(buy_hold_sell)})
原始问题
我想根据步进功能的想法在keras中编写一个激活函数,如下图所示
在numpy中,这样的步骤激活功能应该如下:
# tensorflow_step_function.py
import tensorflow as tf
import keras.backend as K
from keras.backend.tensorflow_backend import _to_tensor
import numpy as np
def stepy(x):
if x < 0.33:
return 0.0
elif x > 0.66:
return 1.0
else:
return 0.5
import numpy as np
np_stepy = np.vectorize(stepy)
def d_stepy(x): # derivative
if x < 0.33:
return 0.0
elif x > 0.66:
return 1.0
else:
return 0.5
np_d_stepy = np.vectorize(d_stepy)
import tensorflow as tf
from tensorflow.python.framework import ops
np_d_stepy_32 = lambda x: np_d_stepy(x).astype(np.float32)
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 tf_d_stepy(x,name=None):
with ops.op_scope([x], name, "d_stepy") as name:
y = tf.py_func(np_d_stepy_32,
[x],
[tf.float32],
name=name,
stateful=False)
return y[0]
def stepygrad(op, grad):
x = op.inputs[0]
n_gr = tf_d_stepy(x)
return grad * n_gr
np_stepy_32 = lambda x: np_stepy(x).astype(np.float32)
def tf_stepy(x, name=None):
with ops.op_scope([x], name, "stepy") as name:
y = py_func(np_stepy_32,
[x],
[tf.float32],
name=name,
grad=stepygrad) # <-- here's the call to the gradient
return y[0]
with tf.Session() as sess:
x = tf.constant([0.2,0.7,0.4,0.6])
y = tf_stepy(x)
tf.initialize_all_variables().run()
print(x.eval(), y.eval(), tf.gradients(y, [x])[0].eval())
我设法将步骤函数从numpy版本转换为keras.tensor版本。它的工作原理如下:
def step_func(x, lower_threshold=0.33, higher_threshold=0.66):
# x is an array, and return an array
for index in range(len(x)):
if x[index] < lower_threshold:
x[index] = 0.0
elif x[index] > higher_threshold:
x[index] = 1.0
else:
x[index] = 0.5
虽然此功能可单独使用,但在应用于模型时会导致错误。我怀疑,作为激活层,它不应该访问张量的每个元素值。
如果是这样,那么编写这一步激活函数的正确方法是什么?
谢谢!
答案 0 :(得分:1)
这不起作用。非线性仍然必须是可微分的。阶梯函数不可微分,因此无法计算梯度。
您始终可以尝试构建一个近似于该步骤的可微函数。这已经是一个sigmoid或tanh为一步一步做的事情。版本
我希望这有点帮助:)
答案 1 :(得分:0)
此步骤函数在tensorflow中工作,因为tensorflow在ops中提供框架,当您调用RegisterGradient时,它使用用户定义的函数作为gridient函数。但是,当您在keras中使用它时,如您所述,您没有将用户定义的渐变函数添加到(比方说)keras框架中。所以它不会起作用。然后如何使它工作。 keras使用tensorflow作为后端,因此当你在tensorflow中调用函数时,你总是可以调用keras.backend中的函数。因此,如果可以,请使用keras.backend实现step函数及其渐变函数。