深度前馈网络

Posted by RAIS on 2020-07-05
  • 本文首发自公众号:RAIS,点击直接关注。

前言

本系列文章为《Deep Learning》读书笔记,可以参看原书一起阅读,效果更佳。从本文开始将继续学习本书的第二部分,将从第一部分介绍深度学习所需要的基础知识过渡到构建深度网络,是理论的应用与提高。

深度前馈网络

也叫 多层感知机 或者是 前馈神经网络,是典型的深度学习模型。这种模型是一种前向的映射模型,由最初的输入,经过函数 f 映射到结果 y,模型的输出和模型本身没有反馈(有反馈的称作循环神经网络)。这里网络的概念是一种有向无环图,最简单的是链式连接,输入的 x 经过 f1 再经过 f2 再经过 f3,最后的到结果 y。引入层的概念,如 f2 就是一层,f3 为输出层,训练数据给出了 x 和 y,却没有定义其中中间层的输入和输出,因此中间层也被称为隐藏层。

线性模型分为逻辑回归(分类问题)和线性回归(连续值预测问题),可以高效可靠的拟合,但问题是其能力距现在了线性函数范围内,无法理解输入变量间的相互作用,因此我们考虑将输入 x,先做非线性变换 φ(x),然后线性函数作用在 φ(x) 上。这里涉及到的问题是 φ(x) 如何选择:

  1. 通用的 φ,有足够高的维数,则可以将输入与输出很好的拟合,问题是泛化往往很不好。

  2. 手动设计 φ,专家去设计算法,手动编码 φ,问题是这是针对特定问题进行的算法设计,难以迁移。

  3. 去学习 φ,φ(x;θ) 将以 θ 为参数,进行训练,并且可以通过使用广泛的函数族或人为编码帮助泛化使之可以实现上述两种情况。

学习异或函数(XOR)

异或的含义为:x1 和 x2 相同为 0,不同为 1。我们设置代价函数为:

$$
J(θ)=\frac{1}{4}\sum_{x∈X}{(f^*(x)-f(x;θ))^2}
\\
其中:f(x;θ)=f(x;w,b)=x^Tw+b
$$

解得:w=0,b=1/2,这显然是不对的,为什么会这样?x1=0 时,模型输出随着 x2 增大而增大,x1=1 时,模型输出随着 x2 增大而减小,这用线性模型怎么可能做得到,因此得到了错误的结果。

要解决这个问题,我们引入了一层隐藏层,构成前馈神经网络:

$$
h=f^1(x;W,c)
\\
y=f^2(h;w,b)
\\
∴f(x;W,c,w,b)=f^2(f^1(x))
$$

前馈神经网络

这里我们需要考虑 h 应为怎样的函数,如果是线性函数,代入 y 得到的结果仍然为线性函数,前面的分析我们知道这无法满足需求,因此 h 需为非线性函数。这里使用激活函数,修正线性单元(RELU,Rectified Linear Unit):g(z)=max{0, z}。

RELU

则网络为:

$$
f(x;W,c,w,b)=w^Tmax\{0,W^Tx+c\}+b
\\
一组解为:W=\left[
\begin{matrix}
1&1\\
1&1
\end{matrix}
\right]
\\
c=\left[\begin{matrix}0\\-1\end{matrix}\right]
\\
w=\left[\begin{matrix}1\\-2\end{matrix}\right]
\\
b=0
\\
$$

则可以计算结果:

$$
X=\left[
\begin{matrix}
0&0\\
0&1\\
1&0\\
1&1\\
\end{matrix}
\right]
\\
y_1=XW+c^T=\left[\begin{matrix}
0&0\\
1&1\\
1&1\\
2&2
\end{matrix}\right]+c^T=\left[\begin{matrix}
0&-1\\
1&0\\
1&0\\
2&1
\end{matrix}\right]
\\
y_2=max(0,y_1)=max(0,\left[\begin{matrix}
0&0\\
1&0\\
1&0\\
2&1
\end{matrix}\right])
\\
y=y_2w=\left[\begin{matrix}
0\\
1\\
1\\
0
\end{matrix}\right]
$$

到这里,就完成异或函数的基于深度学习模型的构建。

代码

MATLAB

1
2
3
4
5
6
7
8
% matlab
W=[1 1; 1 1]
c=[0;-1]
w=[1;-2]
b=0

X=[0 0; 0 1; 1 0; 1 1]
max(0, X*W+c')*w+b

Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def xor():
W = np.array([[1, 1], [1, 1]])
c = np.array([[0], [-1]])
w = np.array([[1], [-2]])
b = 0

X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])

# y1 = X * W + c'
y1 = np.dot(X, W) + c.T
print(y1)

# y1 = max(0, y1)
y1[y1 < 0] = 0
print(y1)

# y2 = y1 * w + b
y2 = np.dot(y1, w) + b
print(y2)

总结

到这里,我们构建了一个非常简单的深度前馈网络。知道了网络模型,就是一种数学的映射或函数表达,没有类似于相同为 0 不同为 1 这样的判断,而都是一种矩阵的运算,这也是需要转换的一种思维。计算机是一种固化的数学,在这里体现的尤为明显。下一篇我们重新从新的角度讨论梯度学习。

  • 本文首发自公众号:RAIS,点击直接关注。