Пользовательская функция активации с настраиваемым параметром в Tensorflow - PullRequest
0 голосов
/ 28 мая 2019

В настоящее время я пытаюсь определить свою собственную функцию активации с обучаемым параметром alpha в TensorFlow, но сталкиваюсь с ошибкой.Я следовал учебнику, найденному здесь о том, как его определить, но я продолжаю получать следующую ошибку при попытке его запустить:

InvalidArgumentError: ValueError: setting an array element with a sequence.
Traceback (most recent call last):

  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/script_ops.py", line 207, in __call__
    ret = func(*args)

  File "<ipython-input-29-5aa291759d1a>", line 63, in <lambda>
    np_ca_32 = lambda x: np_ca(x).astype(np.float32)

ValueError: setting an array element with a sequence.

Я полагаю, что проблема вызвана этимпараметр trainbale alpha, потому что без него я могу запустить его, но я хочу, чтобы это было alpha в моей функции активации.Будем очень благодарны за любые предложения или помощь по исправлению этой ошибки!

import numpy as np
import tensorflow as tf
from tensorflow.python.framework import ops

alpha = tf.Variable(tf.random_normal((1,1), 0, 1), 
trainable=True,name='alpha')
#Activation Function
def custom_act(x):
  if x>0:
    h1=x
    h2=0
  else:
    x=-x
    h1=0
    h2=x
  return (alpha)*h1+(1-alpha)*h2

#Convert to numpy function
import numpy as np
np_ca = np.vectorize(custom_act)

#Compute gradient
def d_ca(x):
    if x>0:
        return alpha
    else:
        return (1-alpha)
np_d_ca = np.vectorize(d_ca)

#Convert to TensorFlow function
import tensorflow as tf
from tensorflow.python.framework import ops

np_d_ca_32 = lambda x: np_d_ca(x).astype(np.float32)


def tf_d_spiky(x,name=None):
    with tf.name_scope(name, "d_ca", [x]) as name:
        y = tf.py_func(np_d_ca_32,
                        [x],
                        [tf.float32],
                        name=name,
                        stateful=False)
        return y[0]

#Get gradient      
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 ca_grad(op, grad):
    x = op.inputs[0]

    n_gr = tf_d_ca(x)
    return grad * n_gr 


np_ca_32 = lambda x: np_ca(x).astype(np.float32)

#Final activation function
def tf_ca(x, name=None):

    with tf.name_scope(name, "ca", [x]) as name:
        y = py_func(np_ca_32,
                        [x],
                        [tf.float32],
                        name=name,
                        grad=ca_grad)  # <-- here's the call to the 
                                       #gradient
        return y[0]

with tf.Session() as sess:

    x = tf.constant([0.2,0.7,1.2,1.7])
    y = tf_ca(x)
    tf.initialize_all_variables().run()

    print(x.eval(), y.eval(), tf.gradients(y, [x])[0].eval())
...