神经网络
感知机设置权重的工作还是人工进行的
神经网络的一个重要性质是它可以自动地从数据中学习到合适的权重参数
- 输入层 第0层
- 中间层(隐藏层) 第1层
- 输出层 第2层
激活函数
将输入信号的总和转换为输出信号
比如感知机,h(x)就是激活函数:
表示神经元的○中明确显示了激活函数的计算过程
- 节点a 信号的加权总和
- h() 激活函数
sigmoid函数
- $exp(−x)$ 表示$e^{−x}$的意思
- $e$ 纳皮尔常数2.7182
1 | def sigmoid(x): |
0.7310585786300049
0.8807970779778823
**图形**
1 | x = np.arange(-5.0, 5.0, 0.1) |
阶跃函数
1 | def step_function(x): |
1 | def step_function(x): |
1 | import numpy as np |
sigmoid函数和阶跃函数的比较
- 平滑性
- 感知机中神经元之间流动的是0或1的二元信号(阶跃函数)
- 神经网络中流动的是连续的实数值信号(sigmoid函数)
- 形状相似
- 非线性函数 ($h(x)=cx$为线性函数)
神经网络的激活函数必须使用非线性函数
线性函数:不管如何加深层数,总是存在与之等效的“无隐藏层的神经网络”
ReLU函数
ReLU函数在输入大于0时,直接输出该值;在输入小于等于0时,输出0
1 | def relu(x): |
多维数组的运算
神经网络的内积
1 | X = np.array([1, 2]) |
3层神经网络的实现
符号:
- 右上角表示权重和神经元的层号(从输入层开始)
- 右下角前面对应后一层的神经元
- 右下角后面对应前一层的神经元
各层间信号传递的实现
- 灰色的为表示偏置的神经元(右下角的神经元只有一个)
公式表达为
矩阵乘法运算公式为
其中,$A^(1)、X、B^(1)、W^(1)$如下所示
具体代码和流程
1 | import numpy as np |
1 | W2 = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]]) |
**代码总结**从第2层到输出层的信号传递的激活函数,一般地,回归问题可以使用恒等函数,二元分类问题可以使用sigmoid函数,多元分类问题可以使用softmax函数
1 | def init_network(): |
输出层的设计
一般而言,回归问题用恒等函数,分类问题用softmax函数
- 分类问题是数据属于哪一个类别的问题
- 回归问题是根据某个输入预测一个(连续的)数值的问题
softmax函数
softmax函数数学公式
softmax函数的实现中要进行指数函数的运算,但是此时指数函数的值很容易变得非常大
softmax函数数学公式改进
1 | def softmax(a): |
softmax函数特征
- softmax函数的输出是0.0到1.0之间的实数
- softmax函数的输出值的总和是1
- 可以把softmax函数的输出解释为“概率”
输出层的神经元数量需要根据待解决的问题来决定
手写数字识别
import sys,os sys.path.append(os.pardir)
sys.path.append(os.pardir)语句实际上是把父目录加入到sys.path(Python的搜索模块的路径集)中,从而可以导入父目录下的任何目录中的任何文件Python有
pickle
这个便利的功能。这个功能可以将程序运行中的对象保存为文件。如果加载保存过的pickle文件,可以立刻复原之前程序运行中的对象
MNIST数据集
1 | # coding: utf-8 |
1 | # coding: utf-8 |
神经网络的推理处理
1 | # coding: utf-8 |
np.argmax(x)
函数取出数组中的最大值的索引- 正规化 把数据限定到某个范围内的处理,最常规是0~1
- 预处理 对神经网络的输入数据进行某种既定的转换,比如正规化
批处理
- 批 打包式的输入数据
- 批处理一次性计算大型数组要比分开逐步计算各个小型数组速度更快
1 | batch_size = 100 # 批数量 |
代码解释
range(start, end, step)
生成的列表中的下一个元素会增加step指定的值x[i:i+batch_size]
切片抽取批数据np.argmax(y_batch, axis=1)
沿着第1维方向找到值最大的元素的索引
矩阵的第0维是列方向,第1维是行方向
对于数组或列表的比较,例如
array1 == array2
,会返回一个布尔数组