神经网络
基于多层感知机实现的逻辑运算可以表示任何复杂的函数,甚至可以表示整个计算机的复杂处理,但是,感知机设定权重的工作还是由人工来完成,这项工作的完成不仅仅是复杂低效的,而且需要具有极强的先验知识,这与人工智能的基本思想大相近庭。
朴素感知机与神经网络的基本区别就在于神经网络可以自动地从数据中学习到合适的权重参数。
首先,我们使用一个图示来表示神经网络:
如图中所示,最左边代表输入层,即输入的数据;最右边一层称为输出层,即输出的数据;而中间称为中间层或隐藏层,意味着这些层对于网络的使用者是不可见的,若网络层多于三层,除了输入和输出层以外都称为隐藏层。我们可以看出,神经网络的连接方式与感知机并没有任何差异。
接下来我们来看神经网络的与朴素感知机的第一个区别——激活函数。
朴素感知机可以数学表达为一个分段函数:
y
=
{
0
(
w
1
×
x
1
+
w
2
×
x
2
+
b
⩽
0
)
1
(
w
1
×
x
1
+
w
2
×
x
2
+
b
>
0
)
y = \left\{\begin{matrix} 0\quad(w1\times x1 + w2\times x2 + b \leqslant 0) \\ 1\quad(w1\times x1 + w2\times x2 +b >0 ) \end{matrix}\right.
y={0(w1×x1+w2×x2+b⩽0)1(w1×x1+w2×x2+b>0)
现在我们将输出换一个表达方式:
y
=
h
(
θ
)
y = h(\theta)
y=h(θ)
其中θ表示上一层神经网络数据的组合计算的结果,即数据与权重、偏执的线性运算。
对于以上模型θ=w1x1+w2x2+b。
使用了激活函数后的模型可以表示为:
即将上一层的计算结果进行函数映射后生成当前节点的结果,这个函数就是激活函数。
当我们的激活函数为阶跃函数:
h
(
x
)
=
{
0
x
⩽
0
1
x
>
1
h(x) = \left\{\begin{matrix} 0\quad x\leqslant0 \\ 1\quad x> 1 \end{matrix}\right.
h(x)={0x⩽01x>1
时,就是我们前面所说的朴素感知机。当我们的激活函数为其他的非线性函数时,就变为了神经网络。
现代深度学习中常用的激活函数有
- sigmoid函数;
- ReLU函数;
sigmoid函数的数学表达为:
h
(
x
)
=
1
1
+
e
x
p
(
−
x
)
h(x) = \frac{1}{1+exp(-x)}
h(x)=1+exp(−x)1
sigmoid函数的图像为:
图中,蓝线为阶跃函数,绿线为Sigmoid函数图像。
从图中可以看出,阶跃函数与Sigmoid函数的区别:首先,Sigmoid函数是平滑的,而阶跃函数以0为界,输出发生剧烈变化,Sigmoid函数的平滑性对神经网络的学习具有非常重要的意义;其次,相对于阶跃函数的输出只能为0或1,Sigmoid函数的返回可以是任意在0到1间的实数。
另外,神经网络的激活函数必须使用非线性函数是有意义的,因为如果神经网络中使用了线性函数,加深神经网络的层数就没有任何意义,因为任何一个复合的线性运算都可以分解为多个简单的线性运算,比如y(x)=h(h(x)),如果h(x)为线性运算,假设为乘以一个常数c1,那么y(x)=c1 × c1 × x,但是这个复合的运算我们可以简单的表示为y(x)=c2 × x (c2=c1 × c1)
ReLU函数(Rectified Linear Unit)的数学表达为:
h
(
x
)
=
{
x
(
x
>
0
)
0
(
x
⩽
0
)
h(x) = \left\{\begin{matrix} x \quad (x > 0)\\ 0 \quad (x\leqslant 0) \end{matrix}\right.
h(x)={x(x>0)0(x⩽0)
ReLU函数的图像为:
以下为三种激活函数的代码实现:
import numpy as np
def sigmoid(x):
return 1/(1+np.exp(-x))
def step(x):
y = x > 0
return y.astype(np.int)
def ReLU(x):
return np.maximum(0,x)
在实现以上激活函数时,使用到了numpy的广播原理,使得激活函数可以接受一个矩阵,可以对一个层的数据进行批量激活。