2017-07-17 107 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函數及其漸變函數。