神经元的结构
在神经网络中每个神经元都有相同的结构:
每个神经元接受多个输入信号,对输入信号进行线性运算:
$$output = wx+b = \sum_i w_i x_i + b$$
然后,经过激活函数$f$(一般为非线性函数)处理,再输出。
激活函数的意义在后面讨论。
用矩阵乘法表示神经元运算
如果有$m$个神经元同时对同一个输入$x$做运算,且这些神经元使用同一个激活函数,那么我们就可以用一个矩阵运算来简化表示:
$$s = f(Wx)$$
注意,这里的$Wx$是将bias合并进W后的形式,将b当做了一个常数1的权重,具体见上一篇文章。
- $W$是一个$m \times (n+1)$矩阵,其中第$i$个行向量就是第$i$个神经元的权重向量。每个神经元接受n个输入,参数是n个权重和1个bias。
- $Wx$是一个m维向量,其中第$i$个维度对应于第$i$个神经元的线性运算结果。
- 最后,对$Wx$中的每一个维度分别使用激活函数$f$。最终结果还是一个m维向量,其中第$i$个维度对应于第$i$个神经元的激活函数输出。
这个形式常常用来表示一层神经元的计算。
同时计算多个输入样本的结果
我们还可以同时计算多个输入样本的结果:
$$S = f(WX)$$
其中X是一个矩阵,第$i$个样本是$X$的第i个列向量。$S$的第$i$个列向量就是第$i$个样本的输出结果。
关于矩阵运算的知识可以参考矩阵乘法的本质是什么? - 知乎。
神经网络
我们目前只讨论全连接层(fully-connected layer)的情况。全连接层每个神经元与上一层的所有神经元都有连接,处于同一层内的神经元之间没有连接。
二层神经网络示例
一个简单的2层神经网络的假设函数(hypothesis):
$$h = W_2 \max(0, W_1 x)$$
第一层为:
$$h_1 = \max(0, W_1 x)$$
第二层为:
$$h_2 = W_2x$$
前一层的输出向量是后一层的输入向量。
重点:全连接神经网络其实就是多次嵌套$f(Wx)$运算,每个全连接层做一次$f(Wx)$运算。$f(Wx)$的输入$x$是一个向量(第i个维度是上一层第i个神经元的输出),输出也是一个向量(第i个维度是这一层第i个神经元的输出)。
三层神经网络示例
上面展示的是二层神经网络的假设函数(hypothesis),同理地我们还可以写出三层神经网络的hypothesis:
$$h = W_3 \max(0, W_2 \max(0, W_1 x))$$
代码实现
用矩阵的方式来表示神经网络的前向传播计算,能够使得代码非常简练:
# 一个3层神经网络的前向传播:
f = lambda x: 1.0/(1.0 + np.exp(-x)) # 激活函数(用的sigmoid)
x = np.random.randn(3, 1) # 含3个特征的输入向量(3x1)
h1 = f(np.dot(W1, x) + b1) # 计算第一个隐层的激活数据(4x1)
h2 = f(np.dot(W2, h1) + b2) # 计算第二个隐层的激活数据(4x1)
out = np.dot(W3, h2) + b3 # 神经元输出(1x1)
激活函数
激活函数的意义
上面示例中的$max(x,y)$是非线性函数,夹在两次线性运算之间。它的作用是为神经网络的函数增加非线性。非线性操作是至关重要的:如果没有中间的max操作,那么连续的两次矩阵乘法可以写成一次矩阵乘法,神经网络函数退化成了一个线性函数。有了max这样的非线性过程,神经网络函数能够曲折弯曲,拟合更多样、更复杂的真实函数。
不一定要使用max来引入非线性性质。有多个非线性函数可以选择。
常用的激活函数以及对比
cs231n notes已经讲得很好了,在这方面我也没什么好总结的。
CS231n课程笔记翻译:神经网络笔记1(上)
训练
对于神经网络,需要训练的是$W_1,W_2...$(线性组合权重,它们决定了神经网络函数的形状),训练方法一般是随机梯度下降,计算梯度的方法一般是反向传播。
一些需要注意的细节
- 当我们说N层神经网络的时候,我们不把输入层算入,因为输入层第$i$个神经元只是用来提供输入向量$x$的第i维。可以参考前面二层和三层神经网络的例子。
- 神经网络的输出层(最后一层)一般不使用激活函数,或者说激活函数是$f(x)=x$。因为在最后一层做非线性转化的意义不大,参考“激活函数的意义”小节。并且,神经网络的输出一般表示【各个类的score(在分类问题中)】或者【预测值(在回归问题中)】,不需要用sigmoid将它们压缩到(0, 1)的范围(或者其他类似的非线性转化)。
- 在分类问题中,神经网络的输出向量一般是各个类别的分数。因此神经网络的hypothesis就是score function。(来自cs231n的这句话:"The whole network still expresses a single differentiable score function: from the raw image pixels on one end to class scores at the other.")
神经元与线性分类器的关系
只要一个神经网络结构能够计算一个线性分类器的hypothesis(假设函数),那么就可以用这个神经网络来做线性分类。
神经网络本身不需要计算loss function,loss function是用来训练神经网络的。
单个神经元→二类分类器
Logistic分类(Softmax多分类器)
单个神经元输入多个特征值组成的向量,乘以权重向量以后,经过一个激活函数的映射,最后输出一个实数。只要二分类器的hypothesis(假设函数)符合这种计算方式,就能用单个神经元来完成。比如Logistic分类的hypothesis:
$$h_\theta(x) = \frac{1}{1 + \exp(-\theta^\top x)} \equiv \sigma(\theta^\top x)$$
Logistic分类的hypothesis给出正类的概率,只需要判断$h_\theta(x)>0.5$就能预测$x$是正类还是负类。
Logistic分类就是Softmax多分类器经过改写以后的形式,它们之间的关系见Softmax分类器学习心得。注意,如果直接使用Softmax多分类器未改写的形式,则无法用单个神经元来完成计算。Softmax多分类器需要用输入计算两个类的score,然后通过softmax function:$\sigma (\boldsymbol z)_j \equiv \frac{e^{\boldsymbol z_j}}{\sum_k e^{\boldsymbol z_k}}$,将分数转化为概率。这个工作无法用单个神经元来完成,因为要对同一个输入向量计算两个类的score(softmax function需要所有类的分数),因此需要做两次向量乘法$wx$。
SVM二分类器
Binary Support Vector Machine的hypothesis可以使用单个神经元来计算:
$$h_\theta(x) = w^Tx$$
$h_\theta(x)$给出正类的分数,负类的分数是$-h_\theta(x)$。只需要判断$h_\theta(x)>0$就能预测$x$是正类还是负类。
与Softmax多分类器同样的道理,直接使用SVM多分类器的话,是无法用单个神经元来实现的,因为需要分别计算出$x$在两个类的score,而一个神经元仅能输出一个实数。
多个神经元→多类SVM分类器
在线性分类器中计算m个类的score时,可以认为有m个神经元在工作。
线性分类器通过score function: $s = Wx + b$, 将输入向量$x$(n维)转化为分数向量($x$在各个类的分数,m维),如下图:
上图表示的score计算可以看作是由三个神经元共同完成的,分别红绿蓝三个颜色高亮。
多类SVM分类器的hypothesis就是score function,因此可以用单层神经网络表示。第$i$个神经元的输入权重就是$W$中的第$i$个行向量,第$i$个神经元的bias就是$b$中的第$i$个维度值,第$i$个神经元的输出值就是第$i$个类的score。每个神经元的激活函数为$f(x)=x$,也可以当作不使用激活函数。
小结
全连接神经网络其实就是一种函数,这种函数可以嵌套多个$f(Wx)$运算,每个全连接层做一次$f(Wx)$运算。在分类问题中,函数将输入向量(比如说图片的像素值)映射为各个类的分数。
这种函数的表达能力很强,拥有至少一个隐层的神经网络是一个通用的近似器:只要选择合适的参数,神经网络能够近似任何函数。换句话说,没有它表达不出来的函数,就怕你训练不出合适的参数~
因此,如何训练出正确的参数才是困难所在:
- 一方面,我们不知道什么样的函数才是“正确”的。比如,通过一套房子的多项指标来预测它的成交价格,人类根本就不知道这样一个映射函数,却希望机器找出这种函数。因此我们永远不知道我们训练出的参数是不是绝对正确的,只能用它在测试集的预测正确率来衡量它。
- 另一方面,我们受到过拟合问题的困扰。在训练集中表现很好的参数,在实际使用的时候可能得到不准确的结果。我们希望参数能学习到隐藏在训练集中的“普适的规律”,而不是“局限于这个训练集中的、强行找出来的规律”。如何只学习到前者而避免后者?这是困难所在。
欢迎提出建议或者指出错误!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。