tensorflow自定义激活函数实例
前言:因为研究工作的需要,要更改激活函数以适应自己的网络模型,但是单纯的函数替换会训练导致不能收敛。这里还有些不清楚为什么,希望有人可以给出解释。查了一些博客,发现了解决之道。下面将解决过程贴出来供大家指正。
1.背景
之前听某位老师提到说tensorflow可以在不给梯度函数的基础上做梯度下降,所以尝试了替换。我的例子时将ReLU改为平方。即原来的激活函数是
单纯替换激活函数并不能较好的效果,在我的实验中,迭代到一定批次,准确率就会下降,最终降为10%左右保持稳定。而事实上,这中间最好的训练精度为92%。资源有限,问了对神经网络颇有研究的同学,说是激活函数的问题,然而某篇很厉害的论文中提到其精度在99%,着实有意思。之后开始研究自己些梯度函数以完成训练。
2.大概流程
首先要确定梯度函数,之后将其处理为tf能接受的类型。
2.1定义自己的激活函数
defsquare(x): returnpow(x,2)
2.2定义该激活函数的一次梯度函数
defsquare_grad(x): return2*x
2.3让numpy数组每一个元素都能应用该函数(全局)
square_np=np.vectorize(square) square_grad_np=np.vectorize(square_grad)
2.4转为tf可用的32位float型,numpy默认是64位(全局)
square_np_32=lambdax:square_np(x).astype(np.float32) square_grad_np_32=lambdax:square_grad_np(x).astype(np.float32)
2.5定义tf版的梯度函数
defsquare_grad_tf(x,name=None): withops.name_scope(name,"square_grad_tf",[x])asname: y=tf.py_func(square_grad_np_32,[x],[tf.float32],name=name,stateful=False) returny[0]
2.6定义函数
defmy_py_func(func,inp,Tout,stateful=False,name=None,my_grad_func=None): #needtogenerateauniquenametoavoidduplicates: random_name="PyFuncGrad"+str(np.random.randint(0,1E+8)) tf.RegisterGradient(random_name)(my_grad_func) g=tf.get_default_graph() withg.gradient_override_map({"PyFunc":random_name,"PyFuncStateless":random_name}): returntf.py_func(func,inp,Tout,stateful=stateful,name=name)
2.7定义梯度,该函数依靠上一个函数my_py_func计算并传播
def_square_grad(op,pred_grad): x=op.inputs[0] cur_grad=square_grad(x) next_grad=pred_grad*cur_grad returnnext_grad
2.8定义tf版的square函数
defsquare_tf(x,name=None): withops.name_scope(name,"square_tf",[x])asname: y=my_py_func(square_np_32, [x], [tf.float32], stateful=False, name=name, my_grad_func=_square_grad) returny[0]
3.使用
跟用其他激活函数一样,直接用就行了。input_data:输入数据。
h=square_tf(input_data)
over.学艺不精,多多指教!
以上这篇tensorflow自定义激活函数实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。