由于最近在啃EMCapsule(EMCapsule论文)的源码(EMcapsule源码),或者说在啃tensorflow源码,由于没有系统学习过tensorflow,所以看起代码那叫一个蛋疼菊紧,特别是看到capsule_em.py 中的em_routing时,感到很疑惑,如此复杂的操作,这个network是如何实现反向传播的。
关于反向传播的知识,可以参考反向传播,注意tensor的反向传播中实际上分两步:
1.对神经网络中的所有神经元(如下图中的x1,x2)求偏导,对应tensorflow的函数为:
tf.train.AdamOptimizer().compute_gradients(loss)
2.而相邻两层layer之间的连线上的权值的更新可以借用loss对其(连线)连接的下一个神经元的导数(反向传播时逐层计算好的值)轻松得到,对应tensorflow的函数为:
grad=tf.train.AdamOptimizer().compute_gradients(loss)
tf.train.AdamOptimizer().apply_gradients(grad, global_step=global_step)
有些同学会说,如果有些连线上的权值我不要神经网络帮我们更新,有时候这些权值是固定的(这种情况还是有的,EMCapsule中就有这样的情况)。另外有时候有些权值并不一定都是卷积核或fully_connected的连线权值,有可能是我们自己定义的某个variable,而我们在tensorflow中定义variable通常是v1=tf.get_variable(xxx),此时v1默认是可被训练的(trainable),如果我们不想让它被训练,可以v1=tf.get_variable(xxx,istrain=False),这样就可以不让神经网络在方向传播时update这个变量了。
可是有些同学还是觉得很奇怪,tensorflow中的神经网络究竟是怎么反向传播的,我们明明没有定义反向传播层啊,它是如何从loss求导到输入的?
在此之前,我们先来了解一下tensor的概念,刚撸tensor时的时候,我觉得tensor很奇怪,为什么不能中途将tensor中的值打印出来,而后来我才发现tensor之所以不能中途打印出来是因为tensor本质上是一个operation,在下面tensor c中,可以看到type(c)为
<class 'tensorflow.python.framework.ops.Tensor'>,注意绿色的这个"ops",指的就是operation:
>>> a=tf.constant(1)
>>> b=tf.constant(1)
>>> c=a+b
>>> c
<tf.Tensor 'add:0' shape=() dtype=int32>
>>> type(c)
<class 'tensorflow.python.framework.ops.Tensor'>
>>>
而以这些tensor作为节点构成了一个Graph,一个从输入到输出的Graph,,实际上这些operation(tensor)可以看成是一个个函数f,而很多时候这些operation们(函数们)都是可以求导的不论是add,max(是的,max也是可以求导的),mean,conv,fully_connected,sigmod,softmax,甚至reshape都是可以求导的(reshape本质上就是赋值,只是将原tensor的shape变换了一下)。
如有错误,希望各位踊跃指出。