2017-07-17 108 views
1

更新 感谢Q&A here,我能够建立tensorflow的工作步骤功能。 (请参见下面的代码)如何将step_function作为keras中的激活函数来编写?

现在我的问题演变成

如何利用在tensorflow创造了这个tf_stepy激活功能在keras工作?

我想下面的代码,以利用在keras tf_stepy,但不工作:

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)}) 

下面是tensorflow

# 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()) 

原来的创建步骤激活功能问题

我想根据阶梯函数的想法写在keras的激活功能,如下面 enter image description here

在numpy的图形,如步激活功能应该表现如下:

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 

我管理将step功能从numpy版本转换为keras.tensor版本。它的工作原理如下:

import tensorflow as tf 
import keras.backend as K 
from keras.backend.tensorflow_backend import _to_tensor 
import numpy as np 
def high_med_low(x, lower_threshold=0.33, higher_threshold=0.66): 
    """ 
    x: tensor 
    return a tensor 
    """ 
    # x_shape = K.get_variable_shape(x) 
    # x_flat = K.flatten(x) 
    x_array = K.get_value(x) 
    for index in range(x_array.shape[0]): 
     if x_array[index,0] < lower_threshold: 
      x_array[index,0] = 0.0 
     elif x_array[index,0] > higher_threshold: 
      x_array[index,0] = 1.0 
     else: 
      x_array[index,0] = 0.5 

    # x_return = x_array.reshape(x_shape) 
    return _to_tensor(x_array, x.dtype.base_dtype) 

x = K.ones((10,1)) * 0.7 
print(high_med_low(x)) 

# the following line of code is used in building a model with keras 
get_custom_objects().update({'custom_activation': Activation(high_med_low)}) 

尽管此功能可以自行工作,但在应用于模型时会导致错误。我怀疑是作为激活层,它不应该访问张量的每个元素值。

如果是这样,那么写这个步骤激活函数的正确方法是什么?

谢谢!

+0

https://stackoverflow.com/questions/43915482/how-do-you-create-a-custom-activation-function-with-keras – desertnaut

回答

1

这不起作用。非线性仍然是可以区分的。阶梯函数不可微分,因此无法计算梯度。

您总是可以尝试构建一个近似于该步骤的可微分函数。对于“一步式”版本,这已经是一个S形或双曲正方形。

我希望这有助于一点:)在tensorflow

+0

感谢Nassim,你可以看看更新的部分?我不知道如何使它在keras中工作,因为'tf_stepy'工作在张量流中。 – Daniel

0

这一步功能的工作,因为在tensorflow OPS提供一个框架,当你调用RegisterGradient,它使用用户定义函数gridient功能。但是,当您在keras中使用它时,如您所描述的那样,您没有将用户定义的渐变函数添加到(比方说)keras框架中。所以它不会工作。那么如何使它工作。 keras使用tensorflow作为后端,因此当您调用tensorflow中的函数时,您始终可以在keras.backend中调用函数。所以,如果可以的话,用keras.backend来实现step函数及其渐变函数。