分享

tensorflow自定义网络层、激活函数(self

 雪柳花明 2017-07-20




[python] view plain copy
  1. # highly based on :  
  2. # http:///questions/39921607/tensorflow-how-to-make-a-custom-activation-function-with-only-python  
  3. # https://gist.github.com/harpone/3453185b41d8d985356cbe5e57d67342  
  4.   
  5.   
  6. # making a numpy function to a tensorflow function:  
  7. # we will use 1) tf.py_func(func, inp, Tout, stateful=stateful, name=name), https://www./api_docs/python/tf/py_func  
  8. # which transforms any numpy function to a tensorflow function  
  9. # we will use 2) tf.RegisterGradient  
  10. # https://www./versions/r0.11/api_docs/python/framework/defining_new_operations#RegisterGradient  
  11. # https://www./versions/r0.11/api_docs/python/framework/#RegisterGradient  
  12. # we will use 3) tf.Graph.gradient_override_map  
  13. # https://www./versions/r0.11/api_docs/python/framework/  
  14. # https://www./versions/r0.11/api_docs/python/framework/core_graph_data_structures#Graph.gradient_override_map  
  15.   
  16.   
  17.   
  18.   
  19. import numpy as np  
  20. import tensorflow as tf  
  21. from tensorflow.python.framework import ops  
  22.   
  23.   
  24. # define common custom relu function  
  25. def my_relu_def(x, threshold=0.05):  
  26.     if x<threshold:  
  27.         return 0.0  
  28.     else:  
  29.         return x  
  30.   
  31. def my_relu_grad_def(x, threshold=0.05):  
  32.     if x<threshold:  
  33.         return 0.0  
  34.     else:  
  35.         return 1.0  
  36.   
  37. # making a common function into a numpy function  
  38. my_relu_np = np.vectorize(my_relu_def)  
  39. my_relu_grad_np = np.vectorize(my_relu_grad_def)  
  40. # numpy uses float64 but tensorflow uses float32  
  41. my_relu_np_32 = lambda x: my_relu_np(x).astype(np.float32)  
  42. my_relu_grad_np_32 = lambda x: my_relu_grad_np(x).astype(np.float32)  
  43.   
  44.   
  45.   
  46. def my_relu_grad_tf(x, name=None):  
  47.     with ops.name_scope(name, "my_relu_grad_tf", [x]) as name:  
  48.         y = tf.py_func(my_relu_grad_np_32,  
  49.                        [x],  
  50.                        [tf.float32],  
  51.                        name=name,  
  52.                        stateful=False)  
  53.         return y[0]  
  54.   
  55. def my_py_func(func, inp, Tout, stateful=False, name=None, my_grad_func=None):  
  56.     # Need to generate a unique name to avoid duplicates:  
  57.     random_name = 'PyFuncGrad' + str(np.random.randint(01E+8))  
  58.     tf.RegisterGradient(random_name)(my_grad_func)  # see _my_relu_grad for grad example  
  59.     g = tf.get_default_graph()  
  60.     with g.gradient_override_map({"PyFunc": random_name, "PyFuncStateless": random_name}):  
  61.         return tf.py_func(func, inp, Tout, stateful=stateful, name=name)  
  62.   
  63. # The grad function we need to pass to the above my_py_func function takes a special form:  
  64. # It needs to take in (an operation, the previous gradients before the operation)  
  65. # and propagate(i.e., return) the gradients backward after the operation.  
  66. def _my_relu_grad(op, pre_grad):  
  67.     x = op.inputs[0]  
  68.     cur_grad = my_relu_grad_tf(x)  
  69.     next_grad = pre_grad * cur_grad  
  70.     return next_grad  
  71.   
  72. def my_relu_tf(x, name=None):  
  73.     with ops.name_scope(name, "my_relu_tf", [x]) as name:  
  74.         y = my_py_func(my_relu_np_32,  
  75.                        [x],  
  76.                        [tf.float32],  
  77.                        stateful=False,  
  78.                        name=name,  
  79.                        my_grad_func=_my_relu_grad)  # <-- here's the call to the gradient  
  80.         return y[0]  
  81.   
  82. with tf.Session() as sess:  
  83.     x = tf.constant([-0.30.0050.080.12])  
  84.     y = my_relu_tf(x)  
  85.     tf.global_variables_initializer().run()  
  86.     print x.eval()  
  87.     print y.eval()  
  88.     print tf.gradients(y, [x])[0].eval()  
  89.   
  90. # [-0.30000001  0.005       0.08        0.12      ]  
  91. # [ 0.    0.    0.08  0.12]  
  92. # [ 0.    0.    1.  1.]  


# -*- coding: utf-8 -*-
import numpy as np
import tensorflow as tf
from tensorflow.python.framework import ops


# define common custom relu function
#定义常用的relu函数定义
def my_relu_def(x, threshold=0.05):
if x<threshold:
return 0.0
else:
return x

def my_relu_grad_def(x, threshold=0.05):
if x<threshold:
return 0.0
else:
return 1.0

# making a common function into a numpy function
#numpy数组中的每一个元素应用一个函数
my_relu_np = np.vectorize(my_relu_def)
my_relu_grad_np = np.vectorize(my_relu_grad_def)

#类型转换,numpy使用float64,Tensorflow使用float32
# numpy uses float64 but tensorflow uses float32
my_relu_np_32 = lambda x: my_relu_np(x).astype(np.float32)
my_relu_grad_np_32 = lambda x: my_relu_grad_np(x).astype(np.float32)


#定以tf版的my_relu_grad函数
def my_relu_grad_tf(x, name=None):
with ops.name_scope(name, "my_relu_grad_tf", [x]) as name:
y = tf.py_func(my_relu_grad_np_32,
[x],
[tf.float32],
name=name,
stateful=False)
return y[0]

#定义函数
def my_py_func(func, inp, Tout, stateful=False, name=None, my_grad_func=None):
# Need to generate a unique name to avoid duplicates:
random_name = 'PyFuncGrad' + str(np.random.randint(0, 1E+8))
tf.RegisterGradient(random_name)(my_grad_func) # see _my_relu_grad for grad example
g = tf.get_default_graph()
with g.gradient_override_map({"PyFunc": random_name, "PyFuncStateless": random_name}):
return tf.py_func(func, inp, Tout, stateful=stateful, name=name)

# 该梯度函数,通过上面的my_py_func计算并且传播,参数包括,一个op,一个前面的梯度
# The grad function we need to pass to the above my_py_func function takes a special form:
# It needs to take in (an operation, the previous gradients before the operation)
# and propagate(i.e., return) the gradients backward after the operation.
def _my_relu_grad(op, pre_grad):
x = op.inputs[0]
cur_grad = my_relu_grad_tf(x)
next_grad = pre_grad * cur_grad
return next_grad


def my_relu_tf(x, name=None):
with ops.name_scope(name, "my_relu_tf", [x]) as name:
y = my_py_func(my_relu_np_32,
[x],
[tf.float32],
stateful=False,
name=name,
my_grad_func=_my_relu_grad) # <-- here's the call to the gradient
return y[0]

with tf.Session() as sess:
x = tf.constant([-0.3, 0.005, 0.08, 0.12])
y = my_relu_tf(x)
tf.global_variables_initializer().run()
print x.eval()
print y.eval()
print tf.gradients(y, [x])[0].eval()



    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多