养病中,不想继续写新东西了,先把之前一直想写但是没写的东西写一下。
谈梯度之前我们先谈谈方向导数:
其中
以上函数我们可以改写成向量的模式:
向量为单位向量
其中 则被称为梯度。用倒三角(del)表示或grad f
梯度的方向沿着函数值增长最快的方向。所以梯度下降则是沿着负梯度方向前进的。
激活函数:
Relu:
我们常用的激活函数有Relu,Sigmoid(Softmax),tanh
Relu我们很好理解它是一个分段函数。
当x大于等于0时,输出结果为x 。 当x小于0时,输出结果为0。
这样的好处是对于该函数的导数为1或者0,避免了梯度爆炸和消失的问题。
Sigmoid:
该函数是来源于优势比, 优势比的定义为p/(1-p)。
我们让求出p关于x的表达式,得到的就是sigmoid。
解得:
对该函数求导。我们得到:
提示 (u/v)' = (u'v-uv')/v^2
我们看到当x越接近0的时候,导数值越大。当x等于0时,导数值为极大值,此时p=1/2。
神经网络是一个梯度下降的过程,随着梯度的降低, x的绝对值越来越大。 sigmoid的p值则会趋近于0或者1。
因为其输出的是一个概率值,所以我们一般用于二分类的输出层。
双曲正切函数:
关于双曲正切函数我们可能没有接触过。
其实这里有两个恒等式:
sinh(iz) = isinz
cosh(iz) = cosz
我们通过欧拉恒等式求出sinz和cosz就可以得到双曲函数的表达式了。
这里直接给出结果:
我们这里继续求导:
我们这里设 u = e^x - e^(-x) 那么 u'=e^x +e^(-x) 设 v = e^x + e^(-x) 那么 v' = e^x - e^(-x)
我们发现这里u'=v v'=u 整理后得到 tanhx的导数 = 1-tanh^2x
之所以没用e表达,是 tanh是个已知函数,而且这个表达式比较简洁。
我们可以看到,与sigmoid类似,该函数也是在x=0时导数达到最大值,而且该函数的收敛速度要快于sigmoid。
梯度下降的过程中,x的绝对值越来越大, 函数值的绝对值趋近于1。
可以看出tanh也是有分类效果的,在特征差异明显的时候tanh应该会很好的工作。
比如在mnist中我们哪怕我们只使用DNN(DNN在输入时就已经破坏了图像的性质)通过tanh函数也可以得到很好的效果。
softmax:
这里先给出softmax的函数表达式:
我们用代码来完成,首先看看tensorflow给出的结果。
import numpy as np
import tensorflow as tf
x = np.array([3, 5, 7, 11]).astype('float32')
_softmax = tf.nn.softmax(x)
sess = tf.Session()
print(sess.run(_softmax))
[3.2852104e-04 2.4274604e-03 1.7936641e-02 9.7930741e-01]
我们用numpy来实现:
import numpy as np
x = np.array([3, 5, 7, 11])
lst = []
for i in x:
lst.append(np.exp(i)/np.sum(np.exp(x)))
print(lst)
[0.0003285210266737224, 0.002427460295770427, 0.017936640303374475, 0.9793073783741814]
我们可以看到这里并不是直接用 x[i]/np.sum(x)这种线性增长的模式, 而是用e^x[i],这里的增长速度是指数增长的。
因此x的微弱变化都会对softmax的输出产生很大的影响。