深度学习入门
2020-12-21 18:00:31 3 举报
AI智能生成
深度学习入门 基于Python的理论与实现(更新中)
作者其他创作
大纲/内容
Chapter 1:Python入门
Part 1:安装
Anaconda ×64 + Python3
Part 2:Python语法
1. 运算
+,-,*,/
Python 2.x中,int/int结果为int
Python 3.x中,int/int结果为float
Python 3.x中,int/int结果为float
2. 数据类型
type(x)
int / float / str / bool
3. 变量
4. 列表
数组a[1,2,3,4,5]
a[0:2] =>[1,2]
a[1:] =>[2,3,4,5]
a[:3] =>[1,2,3]
a[:-1] =>[1,2,3,4]
a[:-2] =>[1,2,3]
a[1:] =>[2,3,4,5]
a[:3] =>[1,2,3]
a[:-1] =>[1,2,3,4]
a[:-2] =>[1,2,3]
5. 字典
student={'name':'Bob','age':21}
6. if语句
if xxx:
xxx
elif:
xxx
else:
xxxx
xxx
elif:
xxx
else:
xxxx
7. for语句
for i in [1,2,3]:
xxx
xxx
8. 函数
def hello():
print('Hello World!')
print('Hello World!')
9. 类
class 类名:
def __init__(self,参数,...):
xxxx
def 方法名1(self,参数,...):
xxxx
......
def __init__(self,参数,...):
xxxx
def 方法名1(self,参数,...):
xxxx
......
Part 3:Python 库
1. Numpy
import numpy as np
np.array =>生成NumPy数组
其它方法后续代码中补充
2. Matplotlib
import matplotlib.pyolot as plt
其它方法后续代码中补充
3. 其它
Chapter 2:感知机(Perceptron)
Part 1:逻辑电路
1. 与门(AND)
定义
仅当两个输入均为1时输出1,其它时候输出0
真值表
2. 与非门(NAND)
定义
仅当两个输入均为1时输出0,其它时候输出1
真值表
3. 或门(OR)
定义
只要有一个输入是1,输出就为1
真值表
Part 2:感知机
1. 简单感知机
原理
感知机接收多个输入信号,输出一个信号
公式表达
有两个输入的简单感知机
1. Python代码简单实现
与门 Python代码
2. 权重w和偏置b
导入偏置后的公式更新
与门Python代码(加入偏置b后)
Part 3:感知机的局限性
异或门(XOR)
定义
仅当两输入值相同时输出0,否则输出1
真值表
感知机无法实现异或门
局限性
只能由一条直线分割线性空间
Part 4:多层感知机MLP
(Multi-Layered Perceptron)
(Multi-Layered Perceptron)
异或门的实现
通过叠加层来表示异或门
Python实现
Chapter 3:神经网络
Part 1:感知机到神经网络
1. 神经网络
神经网络的一个重要性质是它可以自动从数据中学习到合适的权重参数
2. 感知机(复习)
原公式
引入新函数h(x),改写原公式为
新函数h(x)
引入偏置
3. 激活函数
激活函数是连接感知机和神经网络的桥梁
作用
决定如何来激活输入信号的总和
Part 2:激活函数
1.sigmoid函数
定义
Python实现
def sigmoid(x):
return 1 / (1 + np.exp(-x))
return 1 / (1 + np.exp(-x))
图形
2. 阶跃函数
定义
Python实现
def step_function(x):
y = x > 0
return y.astype(np.int)
y = x > 0
return y.astype(np.int)
图形
3. sigmoid函数和阶跃函数比较
不同点
平滑性
sigmoid函数是一条平滑的曲线,输出随着输入发生连续性的变化
阶跃函数以0为界,输出发生急剧性变化
连续性
sigmoid函数返回连续型的实数
阶跃函数只能返回0或1
相同点
当输入信号为重要信息时,阶跃函数和sigmoid函数都会输出较大值
当输入信号为不重要信息时,阶跃函数和sigmoid函数都会输出较小值
当输入信号为不重要信息时,阶跃函数和sigmoid函数都会输出较小值
不管输入信号有多小或者多大,输出信号值都在0和1之间
4. 非线性函数
神经网络的激活函数必须使用非线性函数
如果使用线性函数,加深神经网络层数没有意义
为了发挥叠加层所带来的优势,激活函数必须使用非线性函数
5. ReLU函数(Rectified Linear Unit)
1. 函数定义
2. Python代码
Part 3:多维数组运算
1. 多维数组
获取数组的维数=>np.ndim( )
获取数组形状=>np.shape( )
2. 矩阵(Matrix)
线性代数内容
Python实现
np.dot(A,B)
3. 神经网络内积
Part 4:3层神经网络实现
1. 3层神经网络结构图
2. 符号确认
表示第l层的权重,由第l层的第j个神经元指向第l+1层的第i个神经元
Part 5:输出层的设计
恒等函数和softmax函数
回归问题
恒等函数会将输入按原样输出,对于输入的信息,不加以任何改动地直
接输出。
接输出。
分类问题
softmax函数
softmax函数
改进后的softmax函数
softmax函数的输出是0.0到1.0之间的实数,并且输出值之和为1 (概率)
Part 6:手写数字识别
1. 数据集
2. 读取数据集
方法1:python直接读取
书上附带的代码可以运行
方法2:TensorFlow读取
需要安装
3. 推理处理
正规化(normalization)
预处理(pre-processing)
4. 批处理
Chapter 4:神经网络的学习
Part 1:从数据中学习
神经网络的特征就是可以从数据中学习
训练数据和测试数据
泛化能力
欠拟合和过拟合
Part 2:损失函数
1. 均方误差
yk:神经网络的输出,tk:训练数据,k:数据的维数
Python实现
def mean_squared_error(y, t):
return 0.5 * np.sum((y-t)**2)
return 0.5 * np.sum((y-t)**2)
2. 交叉熵误差
log:log e。yk:神经网络的输出,tk:正确解标签
Python实现
def cross_entropy_error(y, t):
delta = 1e-7
return -np.sum(t * np.log(y + delta))
delta = 1e-7
return -np.sum(t * np.log(y + delta))
3. mini-batch学习
神经网络的学习是从训练数据中选出一批数据(称为mini-batch,小批量),然后对每个mini-batch进行学习
通过Numpy库中的np.random.choice()进行随机选取
4. mini-batch 交叉熵误差
def cross_entropy_error(y, t):
if y.ndim == 1:
t = t.reshape(1, t.size)
y = y.reshape(1, y.size)
batch_size = y.shape[0]
return -np.sum(t * np.log(y + 1e-7)) / batch_size
if y.ndim == 1:
t = t.reshape(1, t.size)
y = y.reshape(1, y.size)
batch_size = y.shape[0]
return -np.sum(t * np.log(y + 1e-7)) / batch_size
Part 3:数值微分
1. 导数/微分
定义
表示某个瞬间的变化量
Python实现
def numerical_diff(f, x):
h = 10e-50
return (f(x+h) - f(x)) / h
h = 10e-50
return (f(x+h) - f(x)) / h
2. 偏导数
Part 4:梯度
1. 梯度法
梯度下降法
寻找最小值
Python实现
def gradient_descent(f, init_x, lr=0.01, step_num=100):
x = init_x
for i in range(step_num):
grad = numerical_gradient(f, x)
x -= lr * grad
return x
x = init_x
for i in range(step_num):
grad = numerical_gradient(f, x)
x -= lr * grad
return x
学习率η
学习率过大,会发散成一个很大的值
学习率过小,基本上没怎么更新就结束
学习率过小,基本上没怎么更新就结束
梯度上升法
寻找最大值
2. 神经网络的梯度
Part 5:学习算法实现
1. 前提
神经网络存在合适的权重和偏置
2. 学习步骤
Step 1:mini-batch
从训练数据中随机选取一部分数据
Step 2:计算梯度
求出各个权重的梯度
Step 3:更新参数
将权重参数沿梯度方向进行微小更新
Step 4:重复
重复1,2,3步骤
随机梯度下降法(Stochastic Gradient Descent)
Chapter 5:误差反向传播法
Part 0:对反向传播的理解方法
基于数学公式理解
基于计算图理解
Part 1:计算图
1. 计算图求解
Step 1:构建计算图
Step 2:在计算图上,从左往右进行计算
正向传播(forward propagation)
2. 局部计算
无论全局发生了什么,都能只根据自己相关的信息输出接下来的结果
各节点处只需进行与自己有关的计算,不用考虑全局
计算图可以集中精力于局部计算。无论全局的计算有多么复杂,各个步骤索要做的就是对象节点的局部计算
3. 为何使用计算图?
优点
1)局部计算
2)可以将中间的计算结果全部保存下来
3)可以通过正向传播和反向传播高效计算导数
Part 2:链式法则
1. 计算图的反向传播
沿着与正方向 相反的方向,乘上局部导数
2. 链式法则
复合函数
偏导数
3. 链式法则和计算图
链式法则的计算图
Part 3:反向传播
1. 加法节点的反向传播
以z=x+y为例
偏导数
z对x的偏导数
z对y的偏导数
计算图表示
正向传播
反向传播
加法节点的反向传播只是将输入信号输出到下一节点
2. 乘法节点的反向传播
以z=xy为例
偏导数
z对x的偏导数
z对y的偏导数
计算图表示
正向传播
反向传播
乘法的反向传播会将上游的值乘以正向传播时的输入信号的翻转值后传递给下游
翻转值表示一种翻转关系
翻转值表示一种翻转关系
Part 4:简单层的实现
1. 乘法层的实现(MulLayer)
class MulLayer:
def __init__(self):
self.x = None
self.y = None
def forward(self, x, y):
self.x = x
self.y = y
out = x * y
return out
def backward(self, dout):
dx = dout * self.y # 翻转x和y
dy = dout * self.x
return dx, dy
def __init__(self):
self.x = None
self.y = None
def forward(self, x, y):
self.x = x
self.y = y
out = x * y
return out
def backward(self, dout):
dx = dout * self.y # 翻转x和y
dy = dout * self.x
return dx, dy
apple = 100
apple_num = 2
tax = 1.1
# layer
mul_apple_layer = MulLayer()
mul_tax_layer = MulLayer()
# forward
apple_price = mul_apple_layer.forward(apple, apple_num)
price = mul_tax_layer.forward(apple_price, tax)
print(price) # 220
apple_num = 2
tax = 1.1
# layer
mul_apple_layer = MulLayer()
mul_tax_layer = MulLayer()
# forward
apple_price = mul_apple_layer.forward(apple, apple_num)
price = mul_tax_layer.forward(apple_price, tax)
print(price) # 220
# backward
dprice = 1
dapple_price, dtax = mul_tax_layer.backward(dprice)
dapple, dapple_num = mul_apple_layer.backward(dapple_price)
print(dapple, dapple_num, dtax) # 2.2 110 200
dprice = 1
dapple_price, dtax = mul_tax_layer.backward(dprice)
dapple, dapple_num = mul_apple_layer.backward(dapple_price)
print(dapple, dapple_num, dtax) # 2.2 110 200
2. 加法层的实现(AddLayer)
class AddLayer:
def __init__(self):
pass
def forward(self, x, y):
out = x + y
return out
def backward(self, dout):
dx = dout * 1
dy = dout * 1
return dx, dy
def __init__(self):
pass
def forward(self, x, y):
out = x + y
return out
def backward(self, dout):
dx = dout * 1
dy = dout * 1
return dx, dy
Part 5:激活函数层的实现
1. ReLU层
计算图
Python代码实现
class Relu:
def __init__(self):
self.mask = None
def forward(self, x):
self.mask = (x <= 0)
out = x.copy()
out[self.mask] = 0
return out
def backward(self, dout):
dout[self.mask] = 0
dx = dout
return dx
def __init__(self):
self.mask = None
def forward(self, x):
self.mask = (x <= 0)
out = x.copy()
out[self.mask] = 0
return out
def backward(self, dout):
dout[self.mask] = 0
dx = dout
return dx
2. Sigmoid层
计算图
Python代码实现
class Sigmoid:
def __init__(self):
self.out = None
def forward(self, x):
out = 1 / (1 + np.exp(-x))
self.out = out
return out
def backward(self, dout):
dx = dout * (1.0 - self.out) * self.out
return dx
def __init__(self):
self.out = None
def forward(self, x):
out = 1 / (1 + np.exp(-x))
self.out = out
return out
def backward(self, dout):
dx = dout * (1.0 - self.out) * self.out
return dx
Part 6:Affine/Softmax层的实现
1. Affine层
定义
神经网络的正向传播中进行的矩阵乘积运算在几何学称为仿射变换。仿射变换的处理称为Affine层
计算图
2. 批版本的Affine层
定义
N个数据一起进行正向传播
计算图
3. Softmax-with-Loss层
(Softmax函数和交叉熵误差)
(Softmax函数和交叉熵误差)
包含作为损失函数的交叉熵误差(cross entropy error),称为“Softmax-with-Loss层”
Part 7:误差反向传播法的实现
1. 神经网络学习的全貌图
Step 1:mini-batch
从训练数据中随机选择一部分数据
Step 2:计算梯度
计算损失函数关于各个权重参数的梯度
Step 3:更新参数
将权重参数沿梯度方向进行微小的更新
Step 4:重复
重复上述1,2,3步骤
2. 误差反向传播法的实现
Python代码实现
Chapter 6:与学习相关的技巧
Part 1:参数的更新
1. 随机梯度下降法(SGD)
定义
使用参数的梯度,沿梯度方向更新参数,并且重复这个步骤多次,从而逐渐靠近最优参数的过程
数学表达式
Python实现
缺点
如果函数的形状非均向,搜索的路径就会非常低效(会出现振荡的情况)
SGD低效的根本原因
梯度的方向并没有指向最小值的方向
2. Momentum
定义
数学表达式
Python实现
3. AdaGrad
学习率η
学习率过小,会导致学习花费过多时间
学习率过大,会导致学习发散而不能正确进行
学习率衰减
随着学习的进行,使学习率逐渐减小
AdaGrad
为参数的每个元素适当调整学习率
数学表达式
⊙表示对应矩阵元素的乘法
⊙表示对应矩阵元素的乘法
参数的元素中变动较大(被大幅度更新)的元素的学习率会变小
可以按参数元素进行学习率衰减,使得变动大的参数的学习率逐渐减小
4. Adam
融合Momentum和AdaGrad方法
超参数的偏置校正
Part 2:权重的初始值
1. 初始值设置
为了防止权重均一化(为了瓦解权重的对称结构),必须随机生成初始值
2. 隐藏层的激活值的分布
偏向0和1的数据分布会造成反向传播中梯度的值不断变小,最后消失。这个问题称为梯度消失
激活值在分布上有所偏向会出现“表现力受限”的问题
各层的激活值的分布都要求有适当的广度
Xavier初始值
3. ReLU权重初始值
He初始值
当前一层的节点数为n时,He初始值使用标准差为sqrt(2/n) 的高斯分布
4. 权重初始值的比较
当激活函数使用ReLU时,权重初始值使用He初始值
当激活函数为sigmoid或tanh等S型曲线函数时,初始值使用Xavier初始值
Part 3:Batch Normalization
1. 算法
优点
可以使学习快速进行(可以增大学习率)
不那么依赖初始值(对于初始值不用那么神经质)
抑制过拟合(降低Dropout等的必要性)
思路
调整各层的激活值分布使其拥有适当的广度
定义
以进行学习时的mini-batch为单位,按mini-batch进行正规化
步骤
Step 1:
进行使数据分布的均值为0、方差为1的正规化
数学表示
Step 2:
Batch Norm层对正规化后的数据进行缩放和平移的变换
数学表示
2. 评估
通过使用Batch Norm可以推动学习的进行
对权重初始值变得健壮(表示不那么依赖初始值)
Part 4:正则化
1. 过拟合
定义
只能拟合训练数据,但不能很好地拟合不包含在训练数据中的其他数据的状态
产生原因
模型拥有大量参数、表现力强
训练数据少
2. 权值衰减
通过在学习的过程中对大的权重进行惩罚,来抑制过拟合
加惩罚项
L1 Norm
L2 Norm
3. Dropout
定义
在学习过程中随机删除神经元的方法
具体做法
训练时,随机选出隐藏层的神经元,然后将其删除,被删除的神经元不再进行信号的传递
Part 5:超参数的验证
1. 验证数据
根据不同的数据,可以事先分为训练数据,验证数据,测试数据三部分,有些也可只分为训练数据和测试数据
2. 超参数的最优化
步骤
Step 0:
设定超参数的范围
Step 1:
从设定的超参数范围中随机采样
Step 2:
使用步骤1中采样到的超参数的值进行学习,通过验证数据评估识别精度
Step 3:
重复步骤1和2(100次等),根据它们识别精度的结果,缩小超参数的范围
Chapter 7:卷积神经网络
Part 1:整体结构
CNN中新出现了卷积层(Convolution)和池化层(Pooling)
CNN的层的连接顺序
Convolution - ReLU - (Pooling)
Part 2:卷积层
1. 全连接层存在的问题
数据的形状被忽视了
2. 卷积运算
图像说明
3. 填充(padding)
在进行卷积层的处理之前,有时要向输入数据的周围填入固定的数据
4. 步幅(stride)
应用滤波器的位置间隔
5.3维数据的卷积运算
在3维数据的卷积运算中,输入数据和滤波器的通道数要设置为相同的值
6. 结合方块思考
以长方体为例
3维数据表示为多维数组时,书写顺序是(channel,height,width)
滤波器也一样,要按(channel,height,width)顺序来写
滤波器权重数据要按(output_channel,input_channel,height,width)顺序来写
7. 批处理
通过批处理可以实现处理的高效化和学习时对mini-batch的对应
卷积运算按照(batch_num,channel,height,width)顺序保存数据也可以实现批处理
Part 3:池化层
1. 池化的定义
池化是缩小高、长方向上的空间运算
一般来说,池化的窗口大小会和步幅设定成相同的值
2. 池化的分类
Max池化
获取最大值的运算
Average池化
计算目标区域的平均值
3. 池化的特征
没有要学习的参数
池化只是从目标区域中获取最大值(或者平均值),所以不存在要学习的参数
通道数不发生变化
经过池化运算,输入数据和输出数据的通道数不会发生变化
对微小的位置变化具有鲁棒性(健壮)
数据发生微小偏差时,池化仍然会返回相同的结果
Part 4:卷积层和池化层的实现
1. 4维数组
CNN中各层传递的数据是4维数据
2. 基于im2col的展开
im2colS是一个函数,将输入数据展开以适合滤波器(权重)
3. 卷积层的实现
4. 池化层的实现
Part 5:CNN的实现
Part 6:CNN的可视化
1. 第1层权重的可视化
第1层卷积层中提取到边缘或者斑块等“低级”信息
2. 基于分层结构的信息提取
随着层次的加深,提取的信息也越来越抽象
Part 7:具有代表性的CNN
1. LeNet(1998年)
CNN的元祖
和现在CNN相比
激活函数
LeNet
sigmoid函数
现在的CNN
ReLU函数
处理数据
LeNet
通过子采样(subsampling)来缩小中间数据的大小
现在的CNN
Max池化
2. AlexNet(2012年)
引发深度学习热潮的导火线
和LeNet相比
激活函数使用ReLU函数
使用进行局部正规化的LRN(Local Response Normalization)层
使用Dropout
Chapter 8:深度学习
Part 1:加深网络
1. 向更深的网络出发
特点
基于3×3的小型滤波器的卷积层
激活函数是ReLU
全连接层的后面使用Dropout层
基于Adam的最优化
使用He初始值作为权重初始值
2. 进一步提高识别精度
提高识别精度的技术
集成学习
学习率衰减
Data Augmentation(数据扩充)
基于算法人为地扩充输入图像(训练图像)
对于输入图像
旋转
垂直或水平方向上的移动
裁剪图像的“crop处理”
将图像左右翻转的“flip处理”
增加亮度等外观的变化
放大缩小等尺度上的变化
3. 加深层的动机
层越深,识别性能越高
减少网络的参数数量
使学习更加高效
通过加深层,可以分层次地传递信息
Part 2:深度学习的历史
1. ImageNet
拥有超过100万张图像的数据集,包含各种各样的图像并且每张图像都被关联了标签
2. VGG
由卷积层和池化层构成的基础的CNN
其特点在于将有权重的层(卷积层或者全连接层)叠加至16层(或者19层),具备了深度
基于3×3的小型滤波器的卷积层的运算是连续进行的
3. GoogLeNet
网络不仅在纵向上有深度,在横向上也有深度(广度)-Inception结构
Inception结构使用了多个大小不同的滤波器(和池化),最后再合并它们的结果
4. ResNet
微软开发的网络
其特征在于具有比以前的网络更深的结构
在深度学习中,过度加深层的话,很多情况下学习将不能顺利进行,导致最终性能不佳
为了解决这类问题,导入了“快捷结构”(也称为“捷径”或“小路”)
导入这个快捷结构后,就可以随着层的加深而不断提高性能了
Part 3:深度学习的高速化
1. 需要解决的问题
卷积层上耗费时间较多
2. 基于GPU的高速化
GPU(Graphics Processiing Unit)
NVIDIA
大多数深度学习框架只受益于NVIDIA的GPU
深度学习的框架中使用了NVIDIA提供的CUDA这个面向GPU计算的综合开发环境
AMD
高速进行并行数值计算
深度学习中需要进行大量的乘积累加运算(或者大型矩阵的乘积运算)。这种大量的并行运算正是GPU所擅长的
3. 分布式学习
TensorFlow-Google
CNTK(Computational Network Toolki)-Micorsoft
4. 运算精度的位数缩减
内存容量
需要考虑将大量的权重参数或中间数据放在内存中
总线带宽
当流经GPU(或者CPU)总线的数据超过某个限制时,就会成为瓶颈
Part 4:深度学习的应用
1. 物体检测
从图像中确定物体的位置,并进行分类的问题
2. 图像分割
在像素水平上对图像进行分类
FCN(Fully Convolutional Network)
3. 图像标题的生成
给出一个图像后,会自动生成介绍这个图像的文字(图像的标题)
NIC(Neural Image Caption)
Part 5:深度学习的未来
1. 图像风格的变换
输入两个图像后,会生成一个新的图像。两个输入图像中,一个称为“内容图像”,另一个称为“风格图像”
2. 图像的生成
生成新的图像时不需要任何图像(虽然需要事先使用大量的图像进行学习,但在“画”新图像时不需要任何图像)
DCGAN(Deep Convolutional Generative Adversarial Network)
3. 自动驾驶
4. Deep Q-Network(强化学习)
让计算机也在摸索试验的过程中自主学习
基本框架
代理(Agent)根据环境选择行动,然后通过这个行动改变环境。根据环境的变化,代理获得某种报酬
强化学习的基本框架
目的
决定代理的行动方针,以获得更好的报酬
DQN(Deep Q-Netwaok)
0 条评论
下一页