千层神经网络

This commit is contained in:
yinkanglong_lab
2020-10-20 15:52:36 +08:00
parent 5e0041c064
commit ade9729a85
6 changed files with 101 additions and 42 deletions

View File

@@ -7,13 +7,28 @@
![](2020-10-14-11-48-42.png)
### 神经网络分层
* 输入层----隐藏层----输出层
* **向量化** 实现一个神经网络时,如果需要遍历整个训练集,并不需要直接使用 for 循环。采用向量化的方法代替for 循环
* **计算过程**
### 神经元
输入层只有一个参数:激活值。输出层、隐藏层神经元有三个参数:
* **权重**:指的是和输入层某个神经元的紧密关系。联系越紧密这个值越大($W$)。
* **激活值**:输入的值乘以权重,然后相加。$z = W^T*X+bias$
* **偏置**表示输入的截距bias。
### 计算过程
* 正向过程forward pass或者叫**正向传播步骤forward propagation step**
* 反向过程backward pass或者叫**反向传播步骤backward propagation step**。
### 向量化
* **向量化** 实现一个神经网络时,如果需要遍历整个训练集,并不需要直接使用 for 循环。采用向量化的方法代替for 循环
## 用神经网络进行监督学习
### 应用领域

View File

@@ -2,7 +2,7 @@
> 介绍神经网络的编程基础。看完视频,在总结这一部分。每一个视频,完成开始做笔记。
## 识别图片上的猫
## 1 识别图片上的猫
### 问题定义
* 场景定义:监督学习。图像识别领域。非结构化数据输入。
@@ -16,7 +16,7 @@
* 输出的标签,用于训练的标签:$y \in 0,1$
* 训练集:$\{(x^{(1)},y^{(1)}),\dots,(x^{(m)},y^{(m)})\}$紧凑矩阵表示训练集。约定使用列向量。
## Logistic回归
## 2 Logistic回归模型
> Logistic 回归是一个用于二分分类的算法。
@@ -36,7 +36,7 @@ $$s = \sigma(w^Tx+b) = \sigma(z) = \frac{1}{1+e^{-z}}$$
![LogReg_kiank](LogReg_kiank.png)
## 损失函数和代价函数
## 3 损失函数和代价函数
### 损失函数loss function和代价函数cost function
@@ -52,8 +52,9 @@ $$L(\hat{y},y) = -(y\log\hat{y})-(1-y)\log(1-\hat{y})$$
$$J(w,b) = \frac{1}{m}\sum_{i=1}^mL(\hat{y}^{(i)},y^{(i)})$$
## 梯度下降法Gradient Descent
## 4 梯度下降法Gradient Descent
### 梯度定义
* 函数的 **梯度gradient** 指出了函数的最陡增长方向。即是说,按梯度的方向走,函数增长得就越快。那么按梯度的负方向走,函数值自然就降低得最快了。
* 模型的训练目标即是寻找合适的 w 与 b 以最小化代价函数值。简单起见我们先假设 w 与 b 都是一维实数,那么可以得到如下的 J 关于 w 与 b 的图:
@@ -73,29 +74,43 @@ $$w := w - \alpha\frac{dJ(w, b)}{dw}$$
$$b := b - \alpha\frac{dJ(w, b)}{db}$$
## 计算图Computation Graph
## 5 计算图Computation Graph
### 神经网络与计算图
* 由各个算子表示的节点构成的计算过程图形。
* 一个神经网络可以表示成一个计算图
### 前向计算
* 前向传播:通过自左向右的执行计算图,能够计算一个函数的值。
### 后向计算
* 后向传播:通过自右向左的执行计算图,计算导数,遵循链式法则。
![](2020-10-14-14-20-07.png)
## Logistic 回归中的梯度下降法
> ### 神经元正向传播与反向传播的理解
> 神经网络总结。在正向传播过程中,神经元输入包括激活值、权重和偏置,输出是神经元的输出。在反向传播过程中,神经元的输入是链式偏导的过程,输出是链式偏导的结果。神经元的后向传播值表示的是,在后边的神经元修改一个值,这个神经元的输出,会变动多大的值。是输出的变动值。如果要求输入的或者参数的变动值,还需要对相应的输入和参数进行求导。
> * 与一个神经元相关的值,包括激活值、权重、偏置、输出、偏导。
> * 向上一个神经元传递的偏导,等于这个神经元的偏导对对应激活值的偏导数。然后把正向传播过程中的各个计算值代入到公式当中。
> * 求权重的偏导,等于这个神经元的偏导,对对应的权重的偏导数。然后把正向传播过程中的各个计算值代入到公式中。
假设输入的特征向量维度为 2即输入参数共有 x1, w1, x2, w2, b 这五个。可以推导出如下的计算图:
### 计算图反向传播过程
* 给出计算图:假设输入的特征向量维度为 2即输入参数共有 x1, w1, x2, w2, b 这五个。可以推导出如下的计算图:
![Logistic-Computation-Graph](Logistic-Computation-Graph.png)
首先反向求出 L 对于 a 的导数:
* 首先反向求出 L 对于 a 的导数:
$$da=\frac{dL(a,y)}{da}=\frac{y}{a}+\frac{1y}{1a}$$
然后继续反向求出 L 对于 z 的导数:
* 然后继续反向求出 L 对于 z 的导数:
$$dz=\frac{dL}{dz}=\frac{dL(a,y)}{dz}=\frac{dL}{da}\frac{da}{dz}=ay$$
依此类推求出最终的损失函数相较于原始参数的导数之后,根据如下公式进行参数更新:
* 依此类推求出最终的损失函数相较于原始参数的导数之后,根据如下公式进行参数更新:
$$w _1:=w _1\alpha dw _1$$
@@ -103,28 +118,28 @@ $$w _2:=w _2\alpha dw _2$$
$$b:=b\alpha db$$
接下来我们需要将对于单个用例的损失函数扩展到整个训练集的代价函数:
* 接下来我们需要将对于单个用例的损失函数扩展到整个训练集的代价函数:
$$J(w,b)=\frac{1}{m}\sum^m_{i=1}L(a^{(i)},y^{(i)})$$
$$a^{(i)}=\hat{y}^{(i)}=\sigma(z^{(i)})=\sigma(w^Tx^{(i)}+b)$$
我们可以对于某个权重参数 w1其导数计算为
* 我们可以对于某个权重参数 w1其导数计算为
$$\frac{\partial J(w,b)}{\partial{w\_1}}=\frac{1}{m}\sum^m_{i=1}\frac{\partial L(a^{(i)},y^{(i)})}{\partial{w\_1}}$$
完整的 Logistic 回归中某次训练的流程如下,这里仅假设特征向量的维度为 2
### m个样本的训练过程
![whole-logistic-training](whole-logistic-training-update.png)
然后对 w1、w2、b 进行迭代。
* 完整的 Logistic 回归中某次训练的流程如下,这里仅假设特征向量的维度为 2。然后对 w1、w2、b 进行迭代。
上述过程在计算时有一个缺点:你需要编写两个 for 循环。第一个 for 循环遍历 m 个样本,而第二个 for 循环遍历所有特征。如果有大量特征,在代码中显式使用 for 循环会使算法很低效。**向量化**可以用于解决显式使用 for 循环的问题。
* 上述过程在计算时有一个缺点:你需要编写两个 for 循环。第一个 for 循环遍历 m 个样本,而第二个 for 循环遍历所有特征。如果有大量特征,在代码中显式使用 for 循环会使算法很低效。**向量化**可以用于解决显式使用 for 循环的问题。
## 向量化Vectorization
## 6 向量化Vectorization
在 Logistic 回归中,需要计算 $$z=w^Tx+b$$如果是非向量化的循环方式操作,代码可能如下:
### 向量化计算
* 在 Logistic 回归中,需要计算 $z=w^Tx+b$ 如果是非向量化的循环方式操作,代码可能如下:
```py
z = 0;
@@ -133,13 +148,13 @@ for i in range(n_x):
z += b
```
而如果是向量化的操作,代码则会简洁很多,并带来近百倍的性能提升(并行指令):
* 而如果是向量化的操作,代码则会简洁很多,并带来近百倍的性能提升(并行指令):
```py
z = np.dot(w, x) + b
```
不用显式 for 循环,实现 Logistic 回归的梯度下降一次迭代(对应之前蓝色代码的 for 循环部分。这里公式和 NumPy 的代码混杂,注意分辨):
### 向量化逻辑回归
* 不用显式 for 循环,实现 Logistic 回归的梯度下降一次迭代(对应之前蓝色代码的 for 循环部分。这里公式和 NumPy 的代码混杂,注意分辨):
$$Z=w^TX+b=np.dot(w.T, x) + b$$
$$A=\sigma(Z)$$
@@ -149,9 +164,9 @@ $$db=\frac{1}{m}np.sum(dZ)$$
$$w:=w-\sigma dw$$
$$b:=b-\sigma db$$
正向和反向传播尽管如此,多次迭代的梯度下降依然需要 for 循环。
* 正向和反向传播尽管如此,多次迭代的梯度下降依然需要 for 循环。
## 广播broadcasting
## 7 广播broadcasting
Numpy 的 Universal functions 中要求输入的数组 shape 是一致的。当数组的 shape 不相等的时候,则会使用广播机制,调整数组使得 shape 一样,满足规则,则可以运算,否则就出错。
@@ -162,9 +177,33 @@ Numpy 的 Universal functions 中要求输入的数组 shape 是一致的。当
3. 如果输入数组的某个轴和输出数组的对应轴的长度相同或者其长度为 1 时,这个数组能够用来计算,否则出错;
4. 当输入数组的某个轴的长度为 1 时,沿着此轴运算时都用此轴上的第一组值。
## NumPy 使用技巧
## 8 NumPy 使用技巧
* 转置必须作用在矩阵上向量和数组不能转置。所以转置的numpy数组至少有两个维度。转置对秩为 1 的数组无效。因此,应该避免使用秩为 1 的数组,用 n * 1 的矩阵代替。例如,用`np.random.randn(5,1)`代替`np.random.randn(5)`。如果得到了一个秩为 1 的数组,可以使用`reshape`进行转换。
转置对秩为 1 的数组无效。因此,应该避免使用秩为 1 的数组,用 n * 1 的矩阵代替。例如,用`np.random.randn(5,1)`代替`np.random.randn(5)`
```py
[1,2,3].shape=(3,)
[[1,2,3]].shape = (1,3)
[[1],[2],[3]].shape = (3,1)
# 第2、3行是两个维度可以进行转置操作第一行只有一个维度不能进行转置。
```
* 向量的外积可以获得一个矩阵。向量的內积是一个标量。.dot()行列是內积,列行是外积。
* 在使用numpy编程过程中最好把numpy定义二维矩阵。这样在转置过程中也不会出错。而且最好是列向量。我们以列向量方便理解。
* 使用assert语句进行快速测试。
![](2020-10-17-02-45-44.png)
## 9 logistics回归损失函数的理解
$$
if(y = 1),p(y|x)=\hat{y}\\
if(y = 0),p(y|x)=1=\hat{y}\\
p(y|x) = \hat{y}^y*(1-\hat{y})^{(1-y)}\\
cost = \log p(y|x)
loss = \log \prod p(y|x)\\
= \sum \log p(y|xf)
$$
如果得到了一个秩为 1 的数组,可以使用`reshape`进行转换。

View File

@@ -1,20 +1,23 @@
# 浅层神经网络
## 神经网络表示
* ReLU,recfied linear unit修正线性单元
竖向堆叠起来的输入特征被称作神经网络的**输入层the input layer**。
神经网络的 **隐藏层a hidden layer** 。“隐藏”的含义是 **在训练集中** ,这些中间节点的真正数值是无法看到的。
## 神经网络表示
**输the output layer** 负责输出预测值
* 竖向堆叠起来的输入特征被称作神经网络的**输the input layer**
* 神经网络的 **隐藏层a hidden layer** 。“隐藏”的含义是 **在训练集中** ,这些中间节点的真正数值是无法看到的。
* **输出层the output layer** 负责输出预测值。
* 下图被称为双层神经网络。包括隐藏层和输出层,一般不考虑输入层。
![single_hidden_layer_neural_network](single_hidden_layer_neural_network.png)
如图是一个**双层神经网络**,也称作**单隐层神经网络a single hidden layer neural network**。当我们计算网络的层数时,通常不考虑输入层,因此图中隐藏层是第一层,输出层是第二层。
* 如图是一个**双层神经网络**,也称作**单隐层神经网络a single hidden layer neural network**。当我们计算网络的层数时,通常不考虑输入层,因此图中隐藏层是第一层,输出层是第二层。
约定俗成的符号表示
### 约定俗成的符号表示:
* 输入层的激活值为 $a^{[0]}$
* 同样,隐藏层也会产生一些激活值,记作 $a^{[1]}$
@@ -23,33 +26,35 @@
## 计算神经网络的输出
### 神经网络的计算原理
![neural_network_like_logistic](neural_network_like_logistic.png)
实际上,神经网络只不过将 Logistic 回归的计算步骤重复很多次。对于隐藏层的第一个节点,有
$$z _1^{[1]} = (W _1^{[1]})^TX+b _1^{[1]}$$
### 神经网络的向量化计算过程
$$a _1^{[1]} = \sigma(z _1^{[1]})$$
我们可以类推得到,对于第一个隐藏层有下列公式:
![](2020-10-20-11-23-02.png)
* 隐藏层计算
$$z^{[1]} = (W^{[1]})^Ta^{[0]}+b^{[1]}$$
$$a^{[1]} = \sigma(z^{[1]})$$
其中,$a^{[0]}$可以是一个列向量,也可以将多个列向量堆叠起来得到矩阵。如果是后者的话,得到的 $z^{[1]}$和 $a^{[1]}$也是一个矩阵。
同理,对于输出层有:
* 输出层计算
$$z^{[2]} = (W^{[2]})^Ta^{[1]}+b^{[2]}$$
$$\hat{y} = a^{[2]} = \sigma(z^{[2]})$$
值得注意的是层与层之间参数矩阵的规格大小。
### 注意事项
* 输入层和隐藏层之间:${(W^{[1]})}^T$的 shape 为`(4,3)`,前面的 4 是隐藏层神经元的个数,后面的 3 是输入层神经元的个数;$b^{[1]}$的 shape 为`(4,1)`,和隐藏层的神经元个数相同。
* 隐藏层和输出层之间:${(W^{[2]})}^T$的 shape 为`(1,4)`,前面的 1 是输出层神经元的个数,后面的 4 是隐藏层神经元的个数;$b^{[2]}$的 shape 为`(1,1)`,和输出层的神经元个数相同。
### 样本的向量化计算
![](2020-10-20-11-43-18.png)
## 激活函数
有一个问题是神经网络的隐藏层和输出单元用什么激活函数。之前我们都是选用 sigmoid 函数,但有时其他函数的效果会好得多。

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1010 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 669 KiB