2017-07-17 4 views
1

Aktualisiert Dank Q&A here kann ich eine Arbeitsschrittfunktion mit Tensorflow bauen. (Siehe Code unten)Wie schreibe ich step_function als Aktivierungsfunktion in Keras?

Nun meine Frage entwickelt sich zu

Wie Verwendung dieser tf_stepy Aktivierungsfunktion in tensorflow erstellt, um in keras zu arbeiten?

Ich habe versucht, den folgenden Code tf_stepy in keras zu nutzen, aber nicht funktioniert:

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

Unten ist die Schritt-Aktivierungsfunktion mit tensorflow erstellt

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

original Frage

Ich möchte eine Aktivierungsfunktion in keras schreiben basiert auf der Idee der Stufenfunktion, wie die Grafik unten enter image description here

In numpy sollten solche Schritt Aktivierungsfunktion verhalten sich wie folgt:

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 

ich es geschafft um die Schrittfunktion von numpy version in keras.tensor version zu transformieren. Es funktioniert wie folgt:

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

Obwohl diese Funktion eigenständig funktioniert, verursacht sie einen Fehler, wenn sie auf ein Modell angewendet wird. Mein Verdacht ist, dass als Aktivierungsschicht nicht auf jeden Elementwert eines Tensors zugegriffen werden soll.

Wenn ja, was ist der richtige Weg, diese Schrittaktivierungsfunktion zu schreiben?

Danke!

+0

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

Antwort

1

Dies wird nicht funktionieren. Die Nichtlinearitäten müssen noch differenzierbar sein. Eine Schrittfunktion ist nicht differenzierbar, so dass die Gradienten nicht berechnet werden können.

Sie können immer versuchen, eine differenzierbare Funktion zu erstellen, die den Schritt approximiert. Dies ist bereits, was ein Sigmoid oder ein Tanh für eine "Ein-Schritt" Version tun.

Ich hoffe, das hilft ein wenig :)

+0

Danke Nassim, können Sie sich das aktualisierte Teil ansehen?Ich habe keine Ahnung, wie es in Keras funktioniert, wenn 'tf_stepy' im Tensorflow arbeitet. – Daniel

0

Dieser Schritt Funktion Arbeit in tensorflow weil tensorflow einen Rahmen in ops liefern, wenn Sie RegisterGradient nennen, ist es die benutzerdefinierte Funktion als gridient Funktion verwenden. Wenn Sie es jedoch in Keras verwenden, wie Sie beschrieben haben, haben Sie die benutzerdefinierte Farbverlaufsfunktion zum Beispiel nicht zu keras framework hinzugefügt. Also würde es nicht funktionieren. Dann, wie es funktioniert. keras verwenden Tensorflow als Backend, so dass man Funktionen in keras.backend immer aufrufen kann, wenn man Funktionen im Tensorflow aufruft. Also implementieren Sie die Step-Funktion und ihre Gradientenfunktion mit keras.backend, wenn Sie könnten.

Verwandte Themen