基于Python的理论与实现深度学习入门

基于Python的理论与实现深度学习入门
📘 深度学习入门:基于Python的理论与实现
📘 深度学习入门:基于Python的理论与实现
研究方向:自然语言处理及其应用,关注图像识别、机器学习、深度学习等领域。
特点:Python爱好者。
主要内容包括:
深度学习和神经网络的基础知识
误差反向传播法
卷积神经网络
学习相关的实用技巧
自动驾驶、图像生成、强化学习等应用
深层网络提高识别精度的原理
目录结构
章数 章节标题 页面
1 Python入门 1
2 感知机 21
3 神经网络 37
4 神经网络的学习 81
5 误差反向传播法 121
深度学习基础
深度学习概念
深度学习是机器学习的一个分支,通过构建和训练神经网络,以实现对数据的自动学习和特征提取。

神经网络
神经网络是一种模仿人脑神经元连接结构的计算模型,主要用于处理非线性关系。

误差反向传播法
误差反向传播法是一种用于训练神经网络的算法,通过计算损失函数的梯度来更新网络权重。

Python入门基础
1.1 Python是什么
Python是一种高级编程语言,因其简洁易读而广受欢迎,广泛应用于数据分析、机器学习等领域。

1.3 Python解释器
Python解释器用于执行Python代码,支持多种数据类型和结构,如数字、字符串、列表、字典等。

1.5 NumPy
NumPy是Python的一个库,主要用于科学计算,支持多维数组和矩阵运算。

感知机与神经网络
2.1 感知机是什么
感知机是最简单的神经网络模型,主要用于二分类问题。

2.5 多层感知机
多层感知机由多个感知机组成,能够处理更复杂的模式识别任务。

神经网络学习
4.2 损失函数
损失函数用于评估模型预测与真实值之间的差距,常见的有均方误差和交叉熵误差。

4.4 梯度
梯度是损失函数关于权重的导数,用于指导模型参数的优化。

误差反向传播法
5.2 链式法则
链式法则是计算复合函数导数的重要工具,广泛应用于深度学习中的梯度计算。

5.3 反向传播
反向传播是通过链式法则计算每层的梯度,从而实现权重的更新。

📊 深度学习与误差反向传播法
5.5 Sigmoid层
Sigmoid层是深度学习中的一种激活函数,通常用于二分类问题。它的数学表达式为:

KaTeX can only parse string typed expression
σ(x)=
1+e
−x

1

特点
输出范围:Sigmoid函数的输出值在0到1之间,适合表示概率。
导数:Sigmoid函数的导数可以通过其输出值表示:
KaTeX can only parse string typed expression
σ

(x)=σ(x)⋅(1−σ(x))
5.6 Affine/Softmax层的实现
5.6.1 Affine层
Affine层通过线性变换将输入映射到输出,数学表示为:

KaTeX can only parse string typed expression
y=Ax+b
其中,
KaTeX can only parse string typed expression
A是权重矩阵,
KaTeX can only parse string typed expression
b是偏置项。

5.6.2 批版本的Affine层
批量处理的Affine层同时处理多个输入,极大提高计算效率。对于输入批量
KaTeX can only parse string typed expression
x,输出
KaTeX can only parse string typed expression
y可以表示为:

KaTeX can only parse string typed expression
y=A⋅X+b
5.6.3 Softmax-with-Loss层

与损失函数结合时,Softmax层用于计算交叉熵损失。

5.7 误差反向传播法的实现
5.7.1 神经网络学习的全貌图
误差反向传播法是深度学习训练的核心算法,利用链式法则计算梯度。其基本步骤为:

前向传播:计算每层的输出。
损失计算:通过损失函数评估模型性能。
反向传播:从输出层向输入层计算梯度。
5.7.2 对应误差反向传播法的神经网络的实现
实现误差反向传播法的关键在于实现各层的前向传播和反向传播。

5.7.3 误差反向传播法的梯度确认
通过数值梯度和解析梯度的比较来确认实现的正确性。数值梯度的计算方法为:

KaTeX can only parse string typed expression
∂w
∂L



L(w+ϵ)−L(w−ϵ)

5.7.4 使用误差反向传播法的学习
在训练过程中,更新权重的方式为:

KaTeX can only parse string typed expression
w=w−η
∂w
∂L

其中,
KaTeX can only parse string typed expression
η为学习率。

6.1 参数的更新
6.1.1 探险家的故事
通过讲述探险家的故事来引入参数更新的重要性,强调在训练过程中调整参数以达到最佳性能。

6.1.2 SGD
随机梯度下降法(SGD)是最基础的优化算法,采用小批量数据计算梯度并更新参数。

6.1.3 SGD的缺点
可能会在局部最优解中震荡。
收敛速度慢。
6.1.4 Momentum
Momentum方法通过引入动量概念来加速SGD,公式为:

KaTeX can only parse string typed expression
v
t

=βv
t−1

+(1−β)
∂w
∂L

6.1.5 AdaGrad
AdaGrad根据每个参数的历史梯度自适应调整学习率,公式为:

KaTeX can only parse string typed expression
η
t

G
t



η

6.1.6 Adam
Adam是结合Momentum和AdaGrad的优化算法,具有自适应学习率的优点。

6.1.7 使用哪种更新方法呢
根据任务特性和数据集选择合适的优化算法,通常建议尝试多种优化器。

6.1.8 基于MNIST数据集的更新方法的比较
在MNIST数据集上比较不同更新方法的效果,以选择最佳参数更新策略。

6.2 权重的初始值
6.2.1 可以将权重初始值设为0吗
不建议将权重的初始值设为0,会导致神经元学习相同的特征。

6.2.2 隐藏层的激活值的分布
初始化时要确保权重分布合理,以避免激活值的消失或爆炸。

6.2.3 ReLU的权重初始值
使用He初始化为ReLU激活函数提供合适的权重初始值。

6.2.4 基于MNIST数据集的权重初始值的比较
比较不同初始化方法对模型性能的影响。

6.3 Batch Normalization
6.3.1 Batch Normalization的算法
Batch Normalization通过对每一层的输入进行标准化,减小内部协变量偏移。

6.3.2 Batch Normalization的评估
评估Batch Normalization提升模型训练速度和稳定性的效果。

6.4 正则化
6.4.1 过拟合
过拟合是指模型在训练集上表现良好,但在测试集上表现不佳的现象。

6.4.2 权值衰减
通过在损失函数中添加正则化项来防止过拟合,常用L2正则化。

6.4.3 Dropout
Dropout是一种随机丢弃神经元的方法,防止模型对特定路径过于依赖。

6.5 超参数的验证
6.5.1 验证数据
通过验证集来调整超参数,确保模型的泛化能力。

6.5.2 超参数的最优化
利用网格搜索或随机搜索优化超参数设置。

6.5.3 超参数最优化的实现
实现超参数优化的代码示例和流程。

6.6 小结
总结本章内容,强调参数更新、权重初始化和正则化在深度学习中的重要性。

🐍 Python入门
1.1 Python是什么
“Python是一个简单、易读、易记的编程语言,而且是开源的,可以免费地自由使用。”

Python具有类似英语的语法,易于初学者学习。
受欢迎的编程语言,广泛应用于计算机课程。
Python不仅适合初学者,也受到专业人士的青睐。
在科学领域,尤其是机器学习和数据科学中被广泛使用。
特点 描述
开源 免费使用
易读性 语法类似英语,容易理解
性能 写出高性能的代码,适用于大规模数据处理
库支持 有NumPy、SciPy等优秀的数值计算库,深度学习框架如TensorFlow、Caffe等均提供Python接口
1.2 Python的安装
1.2.1 Python版本
Python有两个主要版本:Python 2.x和Python 3.x。
注意:两个版本之间没有兼容性,本书使用Python 3.x。
1.2.2 使用的外部库
本书主要使用以下库:
NumPy:用于数值计算,提供矩阵操作。
Matplotlib:用于数据可视化。
1.2.3 Anaconda发行版
推荐使用Anaconda作为Python的发行版,集成了多个必要的库。
用户可以从官网下载安装相应的版本。
1.3 Python解释器
“Python解释器也被称为“对话模式”,用户能够以和Python对话的方式进行编程。”

1.3.1 算术计算
简单的算术操作示例:
python
Copy

1 - 2
-1
4 * 5
20
3 ** 2
9 # 乘方操作
1.3.2 数据类型
数据类型包括整数(int)、浮点数(float)、字符串(str)等。
使用type()函数查看数据类型:
python
Copy
type(10) # <class ‘int’>
type(2.718) # <class ‘float’>
type(“hello”) # <class ‘str’>
1.3.3 变量
使用字母定义变量,并进行赋值和计算:
python
Copy
x = 10
print(x) # 输出10
x = 100
print(x) # 输出100
1.3.4 列表
列表的创建和操作示例:
python
Copy
a = [1, 2, 3, 4, 5]
print(a) # 输出列表内容
a[0] # 访问第一个元素
1.3.5 字典
字典以键值对的形式存储数据:
python
Copy
me = {‘height’: 180}
me[‘weight’] = 70
print(me) # 输出 {‘height’: 180, ‘weight’: 70}
1.3.6 布尔型
布尔型变量取值为True或False:
python
Copy
hungry = True
sleepy = False
hungry and sleepy # 输出:False
1.3.7 if语句
使用if/else语句进行条件判断:
python
Copy
if hungry:
… print(“I’m hungry”) # 输出:I’m hungry
1.3.8 for语句
使用for语句进行循环:
python
Copy
for i in [1, 2, 3]:
… print(i) # 输出1, 2, 3
1.3.9 函数
定义函数并调用:
python
Copy
def hello():
… print(“Hello World!”)
hello() # 输出:Hello World!
1.4 Python脚本文件
1.4.1 保存为文件
创建一个名为hungry.py的文件,内容如下:
python
Copy
print(“I’m hungry!”)
1.4.2 类
使用class关键字定义新的类:
python
Copy
class Man:
def init(self, name):
self.name = name
print(“Initialized!”)
def hello(self):
print("Hello " + self.name + “!”)
m = Man(“David”)
m.hello() # 输出:Hello David!
1.5 NumPy
1.5.1 导入NumPy
使用import语句导入NumPy库:
python
Copy
import numpy as np
1.5.2 生成NumPy数组
创建NumPy数组的示例:
python
Copy
x = np.array([1.0, 2.0, 3.0])
1.5.3 NumPy的算术运算
NumPy数组的算术运算示例:
python
Copy
x + y # 对应元素的加法
1.5.4 NumPy的N维数组
生成二维数组(矩阵):
python
Copy
A = np.array([[1, 2], [3, 4]])
A + B # 矩阵的对应元素相加
📊 张量与广播
张量定义
张量(tensor)是将一般化之后的向量或矩阵等统称。书中将二维数组称为“矩阵”,三维数组及三维以上的数组称为“张量”或“多维数组”。

广播机制
广播简介
在NumPy中,形状不同的数组之间也可以进行运算。这种功能被称为广播(broadcast)。例如:

在进行矩阵运算时,如果将标量与矩阵相乘,标量会被扩展为与矩阵相同的形状后再进行运算。
示例
python
Copy
import numpy as np
A = np.array([[1, 2], [3, 4]])
B = np.array([10, 20])
result = A * B
运算结果为:

KaTeX can only parse string typed expression
array([[10,40],[30,80]])
如图所示,一维数组B被扩展为与二维数组A相同的形状,以对应元素的方式进行运算。

访问元素
索引及元素访问
NumPy数组的元素索引从0开始。可以使用以下方式访问元素:
python
Copy
X = np.array([[51, 55], [14, 19], [0, 4]])
print(X[0]) # 第0行
print(X[0][1]) # (0,1)的元素
使用for语句访问
可以使用for语句遍历数组的每一行:

python
Copy
for row in X:
print(row)
数组访问技巧
数组可以使用布尔索引访问特定元素:
python
Copy
XX>15X > 15X>15 # 获取大于15的元素
结果为:

KaTeX can only parse string typed expression
array([51,55,19])
Python与性能
Python等动态类型语言一般比C和C++等静态类型语言(编译型语言)运算速度慢。为了提高性能,通常会用C/C++编写处理程序,Python负责调用。

📈 Matplotlib绘图
绘制简单图形
绘制sin函数曲线
使用Matplotlib的pyplot模块,可以绘制图形。以下代码绘制了sin函数曲线:

python
Copy
import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 6, 0.1) # 生成0到6的数据
y = np.sin(x) # 计算sin值
plt.plot(x, y) # 绘制图形
plt.show() # 显示图形
添加cos函数图形
可以将cos函数的图形添加到同一图中,并使用pyplot的其他功能:

python
Copy
y2 = np.cos(x)
plt.plot(x, y1, label=“sin”)
plt.plot(x, y2, linestyle=“–”, label=“cos”)
plt.xlabel(“x”) # x轴标签
plt.ylabel(“y”) # y轴标签
plt.title(‘sin & cos’) # 标题
plt.legend() # 图例
plt.show() # 显示图形
📷 显示图像
使用imshow()方法可以显示图像。以下是一段示例代码:

python
Copy
from matplotlib.image import imread

img = imread(‘lena.png’) # 读入图像(确保路径正确)
plt.imshow(img) # 显示图像
plt.show() # 显示图像
小结
本章介绍了Python编程的基础知识及其在深度学习中的应用。
掌握了NumPy和Matplotlib的基本用法,能够进行数组运算和绘图。
参考书籍
《Python语言及其应用》:详细介绍Python编程的基础及应用。
《利用Python进行数据分析》:对NumPy进行了简单易懂的总结。
“Scipy Lecture Notes”:提供了NumPy和Matplotlib的详细介绍。
🔌 逻辑门与感知机

  1. 异或门的实现
    “非门、或门代入到‘?’中,就可以实现异或门!”

感知机的局限性
局限性:单层感知机无法表示异或门,或无法分离非线性空间。
通过组合感知机(叠加层)可以实现异或门。
异或门的配置
输入信号:
KaTeX can only parse string typed expression
x
1


KaTeX can only parse string typed expression
x
2

输出信号:
KaTeX can only parse string typed expression
y
实现结构:使用与非门和或门的组合来实现异或门。
真值表确认
使用图2-11的配置,检查
KaTeX can only parse string typed expression
s
1


KaTeX can only parse string typed expression
s
2

的输出,填入真值表(图2-12)。
KaTeX can only parse string typed expression
x
1

KaTeX can only parse string typed expression
x
2

KaTeX can only parse string typed expression
s
1

(与非门输出)
KaTeX can only parse string typed expression
s
2

(或门输出)
KaTeX can only parse string typed expression
y (与门输出)
0 0 1 0 0
0 1 1 1 1
1 0 1 1 1
1 1 0 1 0
2. 使用Python实现异或门
XOR函数实现
python
Copy
def XOR(x1, x2):
s1 = NAND(x1, x2)
s2 = OR(x1, x2)
y = AND(s1, s2)
return y
输出结果:
XOR(0, 0) # 输出0
XOR(1, 0) # 输出1
XOR(0, 1) # 输出1
XOR(1, 1) # 输出0
感知机表示异或门
采用多层结构的神经网络表示异或门(图2-13)。
层数 描述
第0层 输入层,接收
KaTeX can only parse string typed expression
x
1


KaTeX can only parse string typed expression
x
2

第1层 中间层,处理信号
第2层 输出层,输出
KaTeX can only parse string typed expression
y
3. 多层感知机的概念
结构与功能
2层感知机通过增加一层解决了单层感知机的局限性。
比喻:可以比作流水线的组装作业,各层神经元之间进行信号传递。
感知机的层次
图2-13中的感知机有3层,但实质上只有2层具有权重,因此称为“2层感知机”。
4. 从与非门到计算机
复杂电路的实现
多层感知机可以实现加法器、编码器等电路。
理论上,2层感知机足以构建计算机。
计算机与感知机的关系
“如果通过组合与非门可以实现计算机的话,那么通过组合感知机也可以表示计算机。”

推荐读物
《计算机系统要素:从零开始构建现代计算机》
5. 感知机的重要性
感知机的特性
感知机是简单的算法,具有输入和输出。
设定权重和偏置为参数。
能表示与门和或门等逻辑电路。
单层感知机只能表示线性空间,而多层感知机可以表示非线性空间。
章节小结
本章学习了感知机的基本概念及其应用,为下一章的神经网络打下基础。
🤖 神经网络中的激活函数与多维数组运算

  1. 激活函数的重要性
    “激活函数在神经网络中起着关键作用,决定了网络的非线性能力。”

1.1 线性函数的问题
使用线性函数(如
KaTeX can only parse string typed expression
h(x)=cx)作为激活函数时,加深神经网络的层数将没有实际意义。
线性函数的一个特性是,无论如何加深层数,总是存在一个等效的“无隐藏层的神经网络”。
示例
考虑三层神经网络的运算:
KaTeX can only parse string typed expression
y(x)=h(h(h(x)))=c⋅c⋅c⋅x 同样可以表示为:
KaTeX can only parse string typed expression
y(x)=ax(a=c
3
) 这表明,使用线性函数无法发挥多层网络的优势。

1.2 非线性函数的必要性
为了有效利用多层网络的结构,激活函数必须是非线性函数。

  1. ReLU(修正线性单元)函数
    ReLU函数在输入大于0时直接输出该值,在输入小于等于0时输出0。
    数学表示为:
    KaTeX can only parse string typed expression
    ReLU(x)=max(0,x)
    2.1 ReLU函数的实现
    以下是ReLU函数的实现代码:

python
Copy
def relu(x):
return np.maximum(0, x)
3. NumPy多维数组运算
3.1 多维数组的定义
多维数组是数字的集合,可以是1维、2维或更高维度的集合。
示例:生成一维数组
python
Copy
import numpy as np
A = np.array([1, 2, 3, 4])
print(A) # 输出: [1 2 3 4]
3.2 矩阵乘法
矩阵乘法是通过左侧矩阵的行与右侧矩阵的列的对应元素相乘后再求和得到的。
示例:矩阵乘法
python
Copy
A = np.array([[1,2], [3,4]])
B = np.array([[5,6], [7,8]])
result = np.dot(A, B)
print(result) # 输出: [[19, 22], [43, 50]]
3.3 矩阵乘法的条件
进行矩阵乘法时,左侧矩阵的列数必须等于右侧矩阵的行数。
3.4 神经网络中的内积
在神经网络中,通过矩阵的乘积进行运算。
示例:计算神经网络的输出
python
Copy
X = np.array([1, 2])
W = np.array([[1, 3, 5], [2, 4, 6]])
Y = np.dot(X, W)
print(Y) # 输出: [ 5 11 17]
4. 三层神经网络的实现
4.1 信号传递过程
从输入层到隐藏层的信号传递可以通过矩阵运算实现。
示例:前向传播的代码实现
python
Copy
def init_network():
network = {}
network[‘W1’] = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
network[‘b1’] = np.array([0.1, 0.2, 0.3])
return network

def forward(network, x):
W1 = network[‘W1’]
b1 = network[‘b1’]
a1 = np.dot(x, W1) + b1
z1 = sigmoid(a1)
return z1
4.2 输出层的设计
输出层的激活函数需根据解决的问题选择。
回归问题使用恒等函数。
分类问题使用softmax函数。
示例:softmax函数的实现
python
Copy
def softmax(a):
exp_a = np.exp(a)
sum_exp_a = np.sum(exp_a)
return exp_a / sum_exp_a
以上内容涵盖了激活函数的选择、NumPy多维数组的运算、以及三层神经网络的前向传播实现等关键概念,帮助学生全面理解神经网络的基本原理和计算方法。

🌐 Softmax函数及其应用

  1. Softmax函数的溢出问题
    “Softmax函数的实现虽然正确描述了式(3.10),但在计算机的运算上有一定的缺陷,这个缺陷就是溢出问题。”

溢出的定义
溢出(Overflow):在计算机中,当某个数值超出了可表示的范围时,系统无法正确处理该数值,导致错误结果。
溢出问题的发生
在softmax函数中,计算指数函数时,值可能会变得极大,例如:
KaTeX can only parse string typed expression
e
10
≈20000
KaTeX can only parse string typed expression
e
100
会变得极其庞大
KaTeX can only parse string typed expression
e
1000
将返回无穷大(inf)
2. 改进Softmax函数的实现
“通过对分子和分母同时乘以一个任意常数C,可以避免溢出问题。”

改进步骤
引入常数C:在softmax计算中,将分子和分母同时乘以一个常数C。
修改公式:将C转化为
KaTeX can only parse string typed expression
logC,并替换为符号
KaTeX can only parse string typed expression
C


使用最大值:通常选择输入信号中的最大值作为C,以避免溢出。
改进后的Softmax函数实现
python
Copy
def softmax(a):
c = np.max(a) # 获取输入中的最大值
exp_a = np.exp(a - c) # 溢出对策
sum_exp_a = np.sum(exp_a)
y = exp_a / sum_exp_a
return y
3. Softmax函数的特征
输出性质
输出范围:softmax函数的输出值在
KaTeX can only parse string typed expression
[0,1] 之间。
总和为1:softmax输出的总和为1,可以被解释为“概率”。
示例
python
Copy

a = np.array([0.3, 2.9, 4.0])
y = softmax(a)
print(y) # 输出概率
[0.01821127 0.24519181 0.73659691]
np.sum(y) # 输出总和
1.0
解释:
KaTeX can only parse string typed expression
y[0]的概率是1.8%,
KaTeX can only parse string typed expression
y[1]的概率是24.5%,
KaTeX can only parse string typed expression
y[2]的概率是73.7%。
大小关系保持
使用softmax后,各元素之间的大小关系不变,因为指数函数是单调递增的。

  1. 输出层的设计
    输出层神经元数量
    根据待解决的问题来决定输出层的神经元数量,通常等于分类类别的数量。
    示例:对于数字识别(0到9),输出层通常有10个神经元。
  2. 手写数字识别
    MNIST数据集
    MNIST是机器学习领域最著名的数据集之一,包含0到9的手写数字图像。
    训练图像有60,000张,测试图像有10,000张。
    数据预处理
    在加载MNIST数据时,可以选择是否进行正规化(normalization)和展平(flatten)处理。
    推理处理
    神经网络的输入层有784个神经元(对应28×28的图像),输出层有10个神经元(对应10个类别)。
    使用训练好的模型对输入数据进行分类。
    推理代码示例
    python
    Copy
    def predict(network, x):
    W1, W2, W3 = network[‘W1’], network[‘W2’], network[‘W3’]
    b1, b2, b3 = network[‘b1’], network[‘b2’], network[‘b3’]
    a1 = np.dot(x, W1) + b1
    z1 = sigmoid(a1)
    a2 = np.dot(z1, W2) + b2
    z2 = sigmoid(a2)
    a3 = np.dot(z2, W3) + b3
    y = softmax(a3)
    return y
    识别精度
    计算识别精度的方法是比较神经网络的预测结果与实际标签的匹配程度。
  3. 批处理的实现
    批处理的优势
    批处理可以大幅缩短每张图像的处理时间,因为大多数数值计算库都进行了优化。
    批处理代码示例
    python
    Copy
    batch_size = 100 # 批数量
    accuracy_cnt = 0
    for i in range(0, len(x), batch_size):
    x_batch = xi:i+batchsizei:i + batch_sizei:i+batchsize
    y_batch = predict(network, x_batch)
    p = np.argmax(y_batch, axis=1)
    accuracy_cnt += np.sum(p == ti:i+batchsizei:i + batch_sizei:i+batchsize)
    print(“Accuracy:” + str(float(accuracy_cnt) / len(x)))
    通过逐批处理数据,可以提高整体处理效率。
    📊 神经网络学习与损失函数
  4. 批处理与数据提取
    在神经网络中,批处理是一种有效的计算方法,能够提高运算速度。以下是通过 range() 函数生成批数据的示例:

python
Copy

list(range(0, 10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
list(range(0, 10, 3))
[0, 3, 6, 9]
从输入数据中提取批数据的代码为 xi:i+batchsizei:i+batch_sizei:i+batchsize,例如提取数据 x[0:100]、x[100:200] 等。接下来,通过 argmax() 获取值最大的元素的索引,注意在参数中指定 axis=1,表示在数组中沿第1维(列方向)查找最大值的索引。

示例代码
python
Copy

x = np.array([[0.1, 0.8, 0.1], [0.3, 0.1, 0.6],
… [0.2, 0.5, 0.3], [0.8, 0.1, 0.1]])
y = np.argmax(x, axis=1)
print(y)
[1 2 1 0]
通过比较预测结果与实际答案,利用 NumPy 数组的比较运算符生成布尔型数组并计算 True 的个数:

python
Copy

y = np.array([1, 2, 1, 0])
t = np.array([1, 2, 0, 0])
print(y == t)
[True True False True]
np.sum(y == t)
3

  1. 神经网络前向传播小结
    本章讨论了神经网络的前向传播,主要内容包括:

激活函数的使用:神经网络使用平滑变化的 sigmoid 函数或 ReLU 函数。
NumPy多维数组的利用:高效实现神经网络。
机器学习问题的分类:分为回归问题和分类问题。
输出层激活函数的选择:回归问题使用恒等函数,分类问题使用 softmax 函数。
批处理的概念:输入数据的集合称为批,能够实现高速运算。
3. 神经网络的学习
学习是指从训练数据中自动获取最优权重参数的过程。为此,我们引入损失函数作为指标,以此为基准寻找最优权重参数。

3.1 数据驱动学习
数据是机器学习的核心。机器学习的目标是通过数据寻找答案和发现模式,而不是依赖人为的经验和直觉。神经网络直接学习输入数据而避免人为干预。

3.2 训练数据与测试数据
数据通常分为训练数据和测试数据。训练数据用于学习和寻找最优参数,测试数据用于评估模型的泛化能力。泛化能力是指模型处理未见过数据的能力。

数据类型 说明
训练数据 用于学习,寻找最优参数
测试数据 用于评估模型的泛化能力
4. 损失函数
损失函数是表示神经网络性能的指标,通常使用 均方误差(Mean Squared Error)和 交叉熵误差(Cross Entropy Error)。

4.1 均方误差
均方误差计算公式为:

KaTeX can only parse string typed expression
MSE=
N
1

i=1

N

(y
i

−t
i

)
2

其中,
KaTeX can only parse string typed expression
y
i

为神经网络的输出,
KaTeX can only parse string typed expression
t
i

为监督数据。

示例代码
python
Copy
def mean_squared_error(y, t):
return 0.5 * np.sum((y - t) ** 2)
4.2 交叉熵误差
交叉熵误差计算公式为:

KaTeX can only parse string typed expression
CE=−
i=1

N

t
i

log(y
i

)
其中,
KaTeX can only parse string typed expression
t
i

为正确标签,
KaTeX can only parse string typed expression
y
i

为神经网络的输出。

示例代码
python
Copy
def cross_entropy_error(y, t):
delta = 1e-7
return -np.sum(t * np.log(y + delta))
4.3 Mini-Batch 学习
为了避免在大数据集中计算损失函数时的计算负担,使用 mini-batch 学习方法,从训练数据中随机选择一部分数据进行学习。

示例代码
python
Copy
train_size = x_train.shape[0]
batch_size = 10
batch_mask = np.random.choice(train_size, batch_size)
x_batch = x_train[batch_mask]
t_batch = t_train[batch_mask]
4.4 Mini-Batch 交叉熵误差实现
实现可以同时处理单个数据和批量数据的交叉熵误差函数:

python
Copy
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
以上内容涵盖了神经网络学习的核心概念和实现细节,确保学生能够理解并掌握相关知识,以备考试时使用。

📊 损失函数与神经网络学习

  1. 交叉熵误差的计算
    “交叉熵误差是神经网络中用于评估模型输出与真实标签之间差异的重要指标。”

1.1 One-Hot表示与交叉熵
在处理分类问题时,使用one-hot表示的标签,只有一个元素为1,其他元素为0。
当标签
KaTeX can only parse string typed expression
t 为0的元素的交叉熵误差也为0,因此这些元素的计算可以忽略。
如果能获得神经网络在正确解标签处的输出,就可以计算交叉熵误差。
1.2 交叉熵误差的实现
对于one-hot表示的标签计算交叉熵误差的公式为:
KaTeX can only parse string typed expression
L=−
i


t
i

log(y
i

)

KaTeX can only parse string typed expression
t 为标签形式时,可以用以下方式实现:
L = -\sum_{i} \log(ynp.arange(batch_size),t\text{np.arange(batch\_size)}, tnp.arange(batch_size),t)
其中,np.arange(batch_size)会生成一个从0到batch_size-1的数组,例如当batch_size为5时,生成的数组为 [0, 1, 2, 3, 4]。
1.3 示例说明
假设标签存储为
KaTeX can only parse string typed expression
t=[2,7,0,9,4],则
KaTeX can only parse string typed expression
y\text{np.arange(batch_size)}, t$$ 会生成数组
KaTeX can only parse string typed expression
[y[0,2],y[1,7],y[2,0],y[3,9],y[4,4]]。
2. 损失函数的重要性
“损失函数在神经网络学习中起到关键作用,是评估模型好坏的重要标准。”

2.1 损失函数的引入
有人可能会问:“为什么要导入损失函数呢?我们不是应该直接提高识别精度吗?”
实际上,损失函数的引入是为了优化参数(权重和偏置),并通过计算导数(梯度)来指导参数的更新。
2.2 导数的作用
对权重参数的损失函数求导,可以得出“如果稍微改变这个权重参数的值,损失函数的值会如何变化”。
导数为负时,向正方向改变权重参数可以减小损失函数值;导数为正时,则向负方向改变。
2.3 识别精度的局限性
不能将识别精度作为指标,因为在大多数情况下,导数将变为0,导致参数无法更新。
识别精度是离散的,无法对微小变化做出反应,而损失函数的值可以连续变化。
3. 导数与数值微分
3.1 导数的定义
导数表示某个瞬间的变化量,定义为:
KaTeX can only parse string typed expression
f

(x)=
h→0
lim

h
f(x+h)−f(x)

3.2 数值微分的实现
为了计算导数,可以通过以下方式实现数值微分:
python
Copy
def numerical_diff(f, x):
h = 1e-4 # 0.0001
return (f(x+h) - f(x-h)) / (2*h)
3.3 计算示例
计算函数
KaTeX can only parse string typed expression
y=0.01x
2
+0.1x 在
KaTeX can only parse string typed expression
x=5 和
KaTeX can only parse string typed expression
x=10 处的导数。
python
Copy
numerical_diff(function_1, 5) # 0.2
numerical_diff(function_1, 10) # 0.3
4. 梯度的概念
“梯度是由各个变量的偏导数组成的向量,指示函数值减小最快的方向。”

4.1 偏导数的计算
对于多变量函数,偏导数表示对某个变量的导数,同时将其他变量固定。
python
Copy
def function_2(x):
return x[0]**2 + x[1]**2
4.2 梯度的实现
python
Copy
def numerical_gradient(f, x):
h = 1e-4 # 0.0001
grad = np.zeros_like(x)
for idx in range(x.size):
tmp_val = x[idx]
x[idx] = tmp_val + h
fxh1 = f(x)
x[idx] = tmp_val - h
fxh2 = f(x)
grad[idx] = (fxh1 - fxh2) / (2*h)
x[idx] = tmp_val
return grad
5. 梯度法的应用
5.1 梯度下降法
“梯度下降法是通过不断沿梯度方向前进,寻找函数最小值的优化方法。”

5.2 更新公式
KaTeX can only parse string typed expression
x=x−η∇f(x)
其中,
KaTeX can only parse string typed expression
η 为学习率,控制参数更新的幅度。
5.3 示例代码
python
Copy
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
5.4 实例求解
使用梯度法寻找函数
KaTeX can only parse string typed expression
f(x)=x[0]
2
+x[1]
2
的最小值。
python
Copy
init_x = np.array(−3.0,4.0-3.0, 4.03.0,4.0)
gradient_descent(function_2, init_x=init_x, lr=0.1, step_num=100)
最终结果接近
KaTeX can only parse string typed expression
(0,0)。
📊 数的取值与学习率
学习率的重要性
“学习率是指在每次参数更新时,模型权重调整的幅度。合适的学习率能够加速收敛,而不合适的学习率则可能导致模型发散或收敛缓慢。”

实验验证
学习率过大的例子:设定学习率为
KaTeX can only parse string typed expression
lr=10.0

python
Copy
init_x = np.array(−3.0,4.0-3.0, 4.03.0,4.0)
gradient_descent(function_2, init_x=init_x, lr=10.0, step_num=100)
输出结果:

text
Copy
array($ -2.58983747e+13, -1.29524862e+12$)
学习率过小的例子:设定学习率为
KaTeX can only parse string typed expression
lr=1e−10

python
Copy
init_x = np.array(−3.0,4.0-3.0, 4.03.0,4.0)
gradient_descent(function_2, init_x=init_x, lr=1e-10, step_num=100)
输出结果:

text
Copy
array(−2.99999994,3.99999992-2.99999994, 3.999999922.99999994,3.99999992)
结论
学习率过大将导致模型发散。
学习率过小则更新幅度过小,几乎无法更新。
超参数与神经网络
超参数:如学习率等,需要人工设定,与通过训练数据自动获得的权重参数有所不同。
超参数的设定需要尝试多个值,以找到最优的设置。
梯度的计算
梯度的定义
“在神经网络中,梯度指的是损失函数相对于权重参数的导数。”

示例代码
我们定义一个简单的神经网络类 simpleNet 来计算梯度。

python
Copy
import sys, os
sys.path.append(os.pardir)
import numpy as np
from common.functions import softmax, cross_entropy_error
from common.gradient import numerical_gradient

class simpleNet:
def init(self):
self.W = np.random.randn(2,3) # 用高斯分布初始化权重
def predict(self, x):
return np.dot(x, self.W)
def loss(self, x, t):
z = self.predict(x)
y = softmax(z)
loss = cross_entropy_error(y, t)
return loss
计算梯度示例
python
Copy
net = simpleNet()
x = np.array([0.6, 0.9])
t = np.array([0, 0, 1]) # 正确解标签

def f(W):
return net.loss(x, t)

dW = numerical_gradient(f, net.W)
print(dW)
神经网络的学习步骤
神经网络的学习分为四个步骤:

步骤 描述
步骤1 从训练数据中随机选出一部分数据(mini-batch)。
步骤2 计算损失函数的梯度。
步骤3 沿着梯度更新权重参数。
步骤4 重复步骤1到步骤3。
随机梯度下降法 (SGD)
随机梯度下降法是对随机选择的数据进行的梯度下降法。
TwoLayerNet 类的实现
类的结构
python
Copy
class TwoLayerNet:
def init(self, input_size, hidden_size, output_size, weight_init_std=0.01):
self.params = {
‘W1’: weight_init_std * np.random.randn(input_size, hidden_size),
‘b1’: np.zeros(hidden_size),
‘W2’: weight_init_std * np.random.randn(hidden_size, output_size),
‘b2’: np.zeros(output_size)
}
重要变量与方法
变量名 描述
params 保存神经网络的参数
grads 保存梯度的字典型变量
方法名 描述
init 初始化网络参数
predict(self, x) 进行预测
loss(self, x, t) 计算损失函数的值
accuracy(self, x, t) 计算识别精度
numerical_gradient(self, x, t) 计算权重参数的梯度
mini-batch 学习实现
python
Copy

假设已经加载 MNIST 数据集

for i in range(iters_num):
batch_mask = np.random.choice(train_size, batch_size)
x_batch = x_train[batch_mask]
t_batch = t_train[batch_mask]

grad = network.numerical_gradient(x_batch, t_batch)

for key in ('W1', 'b1', 'W2', 'b2'):
    network.params[key] -= learning_rate * grad[key]

loss = network.loss(x_batch, t_batch)
train_loss_list.append(loss)

结果分析
通过反复学习,损失函数的值不断减小,表示神经网络在逐渐拟合数据,学习正常进行。

📈 神经网络的学习
过拟合与泛化能力
过拟合是指,虽然训练数据中的数字图像能被正确辨别,但是不在训练数据中的数字图像却无法被识别的现象。

泛化能力:神经网络学习的最初目标是掌握泛化能力。为了评价神经网络的泛化能力,必须使用不包含在训练数据中的数据。
训练与测试数据
训练数据:用于训练神经网络,使其能够学习到特定的模式。
测试数据:用于评估模型的泛化能力,即在未见过的数据上的表现。
Epoch的定义
Epoch:一个epoch表示学习中所有训练数据均被使用过一次时的更新次数。
例如,对于10000笔训练数据,用大小为100笔数据的mini-batch进行学习时,重复随机梯度下降法100次,所有的训练数据就都被“看过”了。
mini-batch的使用
一般做法是事先将所有训练数据随机打乱,然后按指定的批次大小生成mini-batch。
每个mini-batch都有一个索引号,遍历一次所有数据,就称为一个epoch。
学习算法的实现
导入必要的库
python
Copy
import numpy as np
from dataset.mnist import load_mnist
from two_layer_net import TwoLayerNet
数据加载
python
Copy
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)
初始化参数
超参数:
iters_num = 10000:总迭代次数。
batch_size = 100:每个mini-batch的大小。
learning_rate = 0.1:学习率。
网络初始化:
python
Copy
network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10)
训练过程
python
Copy
for i in range(iters_num):
# 获取mini-batch
batch_mask = np.random.choice(train_size, batch_size)
x_batch = x_train[batch_mask]
t_batch = t_train[batch_mask]

# 计算梯度
grad = network.numerical_gradient(x_batch, t_batch)

# 更新参数
for key in ('W1', 'b1', 'W2', 'b2'):
    network.params[key] -= learning_rate * grad[key]

loss = network.loss(x_batch, t_batch)
train_loss_list.append(loss)

# 每经过一个epoch计算识别精度
if i % iter_per_epoch == 0:
    train_acc = network.accuracy(x_train, t_train)
    test_acc = network.accuracy(x_test, t_test)
    train_acc_list.append(train_acc)
    test_acc_list.append(test_acc)
    print("train acc, test acc | " + str(train_acc) + ", " + str(test_acc))

识别精度的评估
每经过一个epoch,就对所有的训练数据和测试数据计算识别精度,并记录结果。
计算每个epoch的识别精度是因为在循环中频繁计算识别精度会浪费太多时间。
结果可视化
训练数据和测试数据的识别精度的推移可以用图表示。
精度类型 说明
实线 训练数据的识别精度
虚线 测试数据的识别精度
随着epoch的前进,训练数据和测试数据的识别精度均提高,二者基本重叠,说明没有发生过拟合现象。
学习的内容总结
机器学习中使用的数据集分为训练数据和测试数据。
神经网络用训练数据进行学习,并用测试数据评价学习到的模型的泛化能力。
神经网络的学习以损失函数为指标,更新权重参数,以使损失函数的值减小。
数值微分:利用某个给定的微小值的差分求导数的过程。
数值微分虽然费时间,但实现起来很简单。
🍏 计算图与层的实现

  1. 乘法层的实现
    1.1 MulLayer 类
    “乘法层(MulLayer)是计算图中的一个基本单元,用于实现两个数的相乘。”

python
Copy
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

init():初始化实例变量x和y,用于保存正向传播时的输入值。
forward():接收x和y两个参数,将它们相乘后输出。
backward():将从上游传来的导数乘以正向传播的翻转值,然后传给下游。
1.2 使用乘法层进行购买苹果的例子
python
Copy
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

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
正向传播:计算总价
反向传播:计算各个变量的导数
2. 加法层的实现
2.1 AddLayer 类
“加法层(AddLayer)用于实现两个数的相加。”

python
Copy
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

init():不需要特意进行初始化。
forward():接收x和y两个参数,将它们相加后输出。
backward():将上游传来的导数原封不动地传递给下游。
2.2 使用加法层和乘法层进行购买苹果和橘子的例子
python
Copy
apple = 100
apple_num = 2
orange = 150
orange_num = 3
tax = 1.1

layer

mul_apple_layer = MulLayer()
mul_orange_layer = MulLayer()
add_apple_orange_layer = AddLayer()
mul_tax_layer = MulLayer()

forward

apple_price = mul_apple_layer.forward(apple, apple_num) # (1)
orange_price = mul_orange_layer.forward(orange, orange_num) # (2)
all_price = add_apple_orange_layer.forward(apple_price, orange_price) # (3)
price = mul_tax_layer.forward(all_price, tax) # (4)

backward

dprice = 1
dall_price, dtax = mul_tax_layer.backward(dprice) # (4)
dapple_price, dorange_price = add_apple_orange_layer.backward(dall_price) # (3)
dorange, dorange_num = mul_orange_layer.backward(dorange_price) # (2)
dapple, dapple_num = mul_apple_layer.backward(dapple_price) # (1)

print(price) # 715
print(dapple_num, dapple, dorange, dorange_num, dtax) # 110 2.2 3.3 165 650
3. 激活函数层的实现
3.1 ReLU层
“ReLU(Rectified Linear Unit)层是神经网络中的一种激活函数,用于引入非线性特征。”

python
Copy
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

正向传播:将小于等于0的值设为0。
反向传播:只传递大于0的值的导数。
3.2 Sigmoid层
“Sigmoid层用于将输入值压缩到0到1之间,通常用于二分类问题。”

python
Copy
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

正向传播:计算sigmoid函数的值并保存。
反向传播:根据正向传播的输出计算导数。
4. Affine层的实现
“Affine层用于进行仿射变换,计算加权信号的总和。”

python
Copy
class Affine:
def init(self, W, b):
self.W = W
self.b = b
self.x = None
self.dW = None
self.db = None

def forward(self, x):
    self.x = x
    out = np.dot(x, self.W) + self.b
    return out

def backward(self, dout):
    dx = np.dot(dout, self.W.T)
    self.dW = np.dot(self.x.T, dout)
    self.db = np.sum(dout, axis=0)
    return dx

正向传播:使用权重和偏置计算输出。
反向传播:计算权重和偏置的导数。
5. Softmax-with-Loss层
“Softmax函数将输入值正规化为概率分布,常用于多分类问题的输出层。”

python
Copy
class SoftmaxWithLoss:
def init(self):
self.loss = None
self.y = None
self.t = None

def forward(self, x, t):
    self.t = t
    # 计算softmax
    y = np.exp(x) / np.sum(np.exp(x), axis=1, keepdims=True)
    self.y = y
    # 计算loss
    loss = -np.sum(t * np.log(y + 1e-7)) / len(x)
    self.loss = loss
    return loss

def backward(self):
    batch_size = self.t.shape[0]
    dx = (self.y - self.t) / batch_size
    return dx

正向传播:计算softmax和损失值。
反向传播:计算损失对输入的导数。
🔍 Softmax层与交叉熵误差
Softmax层的输出
在神经网络中,Softmax层的输出用于将得分转换为概率分布。其输出过程如下:

输入图像通过Affine层和ReLU层进行转换。
Softmax层将多个得分正规化,使其和为1。
例如,在图5-28中,“0”的得分为5.3,经过Softmax层后转换为0.008(0.8%);而“2”的得分为10.1,转换为0.991(99.1%)。

推理与学习阶段
神经网络的处理分为两个阶段:

**推理(Inference)**阶段

通常不使用Softmax层,直接使用最后一个Affine层的输出作为识别结果。
未正规化的输出称为“得分”。
**学习(Learning)**阶段

需要使用Softmax层来计算损失。
Softmax-with-Loss层的实现
Softmax-with-Loss层结合了Softmax函数和交叉熵误差(Cross Entropy Error)的计算。其计算图如图5-29所示,包含以下步骤:

Softmax层将输入得分正规化为概率输出(
KaTeX can only parse string typed expression
y
1

,y
2

,y
3

)。
Cross Entropy Error层通过比较Softmax的输出与监督标签(
KaTeX can only parse string typed expression
t
1

,t
2

,t
3

)来计算损失。
反向传播的结果
Softmax层的反向传播输出为
KaTeX can only parse string typed expression
(y
1

−t
1

,y
2

−t
2

,y
3

−t
3

),这是Softmax输出与监督标签的差分,直接表示了当前神经网络的输出与监督标签的误差。

注意: 神经网络学习的目的是通过调整权重参数,使输出接近监督标签。

示例:Softmax层的反向传播
考虑监督标签为
KaTeX can only parse string typed expression
(0,1,0),Softmax层输出为
KaTeX can only parse string typed expression
(0.3,0.2,0.5)。此时反向传播的输出为
KaTeX can only parse string typed expression
(0.3,−0.8,0.5),表示较大的误差。

相反,当监督标签为
KaTeX can only parse string typed expression
(0,1,0),Softmax输出为
KaTeX can only parse string typed expression
(0.01,0.99,0)时,反向传播的输出为
KaTeX can only parse string typed expression
(0.01,−0.01,0),表示较小的误差。

Softmax-With-Loss类的实现
python
Copy
class SoftmaxWithLoss:
def init(self):
self.loss = None # 损失
self.y = None # softmax的输出
self.t = None # 监督数据(one-hot vector)

def forward(self, x, t):
    self.t = t
    self.y = softmax(x)
    self.loss = cross_entropy_error(self.y, self.t)
    return self.loss

def backward(self, dout=1):
    batch_size = self.t.shape[0]
    dx = (self.y - self.t) / batch_size
    return dx

误差反向传播法的实现
在神经网络中,学习的步骤如下:

mini-batch:随机选择一部分训练数据。
计算梯度:计算损失函数关于各个权重参数的梯度。
更新参数:沿梯度方向进行微小更新。
重复:重复上述步骤。
TwoLayerNet类的实现
python
Copy
class TwoLayerNet:
def init(self, input_size, hidden_size, output_size, weight_init_std=0.01):
# 初始化权重
self.params = {}
self.params[‘W1’] = weight_init_std * np.random.randn(input_size, hidden_size)
self.params[‘b1’] = np.zeros(hidden_size)
self.params[‘W2’] = weight_init_std * np.random.randn(hidden_size, output_size)
self.params[‘b2’] = np.zeros(output_size)

    # 生成层
    self.layers = OrderedDict()
    self.layers['Affine1'] = Affine(self.params['W1'], self.params['b1'])
    self.layers['Relu1'] = Relu()
    self.layers['Affine2'] = Affine(self.params['W2'], self.params['b2'])
    self.lastLayer = SoftmaxWithLoss()

def predict(self, x):
    for layer in self.layers.values():
        x = layer.forward(x)
    return x

def loss(self, x, t):
    y = self.predict(x)
    return self.lastLayer.forward(y, t)

def accuracy(self, x, t):
    y = self.predict(x)
    y = np.argmax(y, axis=1)
    if t.ndim != 1: 
        t = np.argmax(t, axis=1)
    accuracy = np.sum(y == t) / float(x.shape[0])
    return accuracy

def numerical_gradient(self, x, t):
    loss_W = lambda W: self.loss(x, t)
    grads = {}
    grads['W1'] = numerical_gradient(loss_W, self.params['W1'])
    grads['b1'] = numerical_gradient(loss_W, self.params['b1'])
    grads['W2'] = numerical_gradient(loss_W, self.params['W2'])
    grads['b2'] = numerical_gradient(loss_W, self.params['b2'])
    return grads

def gradient(self, x, t):
    self.loss(x, t)
    dout = 1
    dout = self.lastLayer.backward(dout)
    layers = list(self.layers.values())
    layers.reverse()
    for layer in layers:
        dout = layer.backward(dout)

    grads = {}
    grads['W1'] = self.layers['Affine1'].dW
    grads['b1'] = self.layers['Affine1'].db
    grads['W2'] = self.layers['Affine2'].dW
    grads['b2'] = self.layers['Affine2'].db
    return grads

梯度确认
在确认误差反向传播法的实现是否正确时,需要比较数值微分与误差反向传播法求出的梯度。这一操作称为梯度确认。

梯度确认的实现代码
python
Copy
import sys, os
sys.path.append(os.pardir)
import numpy as np
from dataset.mnist import load_mnist
from two_layer_net import TwoLayerNet

读入数据

(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)
network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10)
x_batch = x_train[:3]
t_batch = t_train[:3]

grad_numerical = network.numerical_gradient(x_batch, t_batch)
grad_backprop = network.gradient(x_batch, t_batch)

for key in grad_numerical.keys():
diff = np.average(np.abs(grad_backprop[key] - grad_numerical[key]))
print(key + “:” + str(diff))
通过上述代码,可以确认数值微分与误差反向传播法计算的梯度之间的差异是否在可接受范围内,以确保实现的正确性。

🧠 神经网络学习与优化
通过误差反向传播法求梯度
在神经网络的学习过程中,通过误差反向传播法计算梯度是至关重要的。以下是实现过程:

python
Copy
grad = network.gradient(x_batch, t_batch)
for key in (‘W1’, ‘b1’, ‘W2’, ‘b2’):
network.params[key] -= learning_rate * grad[key]
loss = network.loss(x_batch, t_batch)
train_loss_list.append(loss)
训练与测试准确度
每经过一个训练周期(epoch),我们需要评估训练和测试的准确度:

python
Copy
if i % iter_per_epoch == 0:
train_acc = network.accuracy(x_train, t_train)
test_acc = network.accuracy(x_test, t_test)
train_acc_list.append(train_acc)
test_acc_list.append(test_acc)
print(train_acc, test_acc)
计算图与误差反向传播法
计算图的基本概念
计算图:是一种将计算过程可视化的工具。
节点与边:计算图的节点由局部计算构成,节点之间通过边相连,表示数据流动。
正向传播与反向传播
正向传播:通过计算图进行一般的计算。
反向传播:通过计算图计算各个节点的导数,进而实现梯度计算。
层的模块化
神经网络的组成元素实现为层(如ReLU层、Softmax-with-Loss层、Affine层等),通过这些层可以高效地计算梯度。层的模块化使得神经网络的构建更加灵活。

参数的更新
神经网络学习的目标是找到使损失函数值最小的参数。这个过程称为最优化方法。由于神经网络的参数空间复杂,最优解难以找到,通常使用随机梯度下降法(SGD)进行参数更新。

随机梯度下降法(SGD)
SGD的公式如下:

KaTeX can only parse string typed expression
W←W−η⋅
∂W
∂L

其中:

(W) 为需要更新的权重参数。
(\eta) 为学习率(learning rate)。
(\frac{\partial L}{\partial W}) 为损失函数关于(W)的梯度。
SGD的实现
以下是SGD的简单实现:

python
Copy
class SGD:
def init(self, lr=0.01):
self.lr = lr

def update(self, params, grads):
    for key in params.keys():
        params[key] -= self.lr * grads[key]

优化方法的比较
探险家的比喻
在寻找最优参数的过程中,可以比作一个探险家在未知的地形中寻找最深的谷底。探险家只能依靠当前的坡度来判断前进的方向。

Momentum 方法
Momentum方法通过引入速度概念来加速收敛,其公式为:

KaTeX can only parse string typed expression
v←αv−η⋅
∂W
∂L

W←W+v
这里,(v) 是速度,(\alpha) 是动量因子。

AdaGrad 方法
AdaGrad方法为每个参数提供自适应的学习率,其更新公式为:

KaTeX can only parse string typed expression
h←h+(
∂W
∂L

)
2

W←W−
h


η


∂W
∂L

Adam 方法
Adam方法结合了Momentum和AdaGrad的优点,其更新公式为:

KaTeX can only parse string typed expression
m←β
1

m+(1−β
1

)
∂W
∂L

v←β
2

v+(1−β
2

)(
∂W
∂L

)
2

W←W−
v


η

m
其中,(\beta_1) 和 (\beta_2) 分别为一阶和二阶动量的衰减率。

更新方法的比较
以下是不同优化方法的比较:

方法 特点 优点
SGD 简单易实现 广泛使用,基础方法
Momentum 引入动量概念 加速收敛,减少震荡
AdaGrad 自适应学习率 对每个参数进行个性化更新
Adam 结合了Momentum和AdaGrad 自适应学习率与动量,效果显著
权重的初始值
权重的初始值对神经网络学习的成功与否至关重要。通常,权重初始化为小的随机值,如使用高斯分布生成的值乘以一个小的常数(如0.01)。

权重初始值设为0的问题
将权重初始值设为0会导致所有神经元的权重在学习过程中进行相同的更新,从而导致无法正确学习。因此,权重初始值不应设置为0,应该选择合适的小随机值。

🧠 神经网络权重初始化与Batch Normalization

  1. 权重初始化的重要性
    “神经网络的权重初始化对学习过程和效果有着重要影响。”

1.1 权重对称性问题
在神经网络的第二层中,如果所有神经元都接收到相同的输入值,反向传播时所有权重将被相同更新。
对称性导致神经网络的表现力丧失,因此需要随机生成初始权重来打破这种对称性。
1.2 隐藏层激活值分布实验
实验目的:观察权重初始值如何影响隐藏层的激活值分布。
使用 sigmoid 函数的五层神经网络,输入为随机生成的数据。
实验代码示例
python
Copy
import numpy as np
import matplotlib.pyplot as plt

def sigmoid(x):
return 1 / (1 + np.exp(-x))

x = np.random.randn(1000, 100) # 1000个数据
node_num = 100 # 各隐藏层的节点数
hidden_layer_size = 5 # 隐藏层数
activations = {}

for i in range(hidden_layer_size):
if i != 0:
x = activationsi−1i-1i1
w = np.random.randn(node_num, node_num) * 1
z = np.dot(x, w)
a = sigmoid(z)
activations[i] = a
绘制直方图:各层激活值的分布情况。
python
Copy
for i, a in activations.items():
plt.subplot(1, len(activations), i+1)
plt.title(str(i+1) + “-layer”)
plt.hist(a.flatten(), 30, range=(0,1))
plt.show()
1.3 激活值分布的影响
使用标准差为1的高斯分布,激活值分布偏向0和1,导致梯度消失(gradient vanishing)问题。
改变标准差为0.01,激活值分布集中在0.5附近,表现力受限。
1.4 Xavier初始值
为了在各层之间保持激活值的广度,Xavier初始值的标准差设置为:
KaTeX can only parse string typed expression
标准差=
n

1

适用于 sigmoid 和 tanh 函数的激活。
实验代码示例
python
Copy
w = np.random.randn(node_num, node_num) / np.sqrt(node_num)
1.5 He初始值
当激活函数为 ReLU 时,推荐使用 He 初始值,标准差设置为:
KaTeX can only parse string typed expression
标准差=
n
2

  1. Batch Normalization
    “Batch Normalization通过正规化层来调整激活值分布,能提升学习效果。”

2.1 Batch Normalization的算法
Batch Normalization(下文简称Batch Norm)通过对mini-batch进行正规化,使得数据均值为0、方差为1。
数学公式
KaTeX can only parse string typed expression
x
^

σ
B
2


x−μ
B

其中,
KaTeX can only parse string typed expression
μ
B


KaTeX can only parse string typed expression
σ
B
2

分别为mini-batch的均值和方差,
KaTeX can only parse string typed expression
ϵ是防止除以0的微小值。
2.2 Batch Norm的正向传播
Batch Norm层对正规化后的数据进行缩放和平移,数学表达为:
KaTeX can only parse string typed expression
y=γ
x
^

其中,
KaTeX can only parse string typed expression
γ 和
KaTeX can only parse string typed expression
β 是在训练过程中学习的参数。
2.3 Batch Norm的效果评估
在使用MNIST数据集的实验中,可以观察到使用Batch Norm层的学习速度显著提升。
实验结果示例
学习方法 学习速度
使用Batch Norm 更快
不使用Batch Norm 学习效果差
2.4 权重初始值对学习的影响
通过实验比较不同权重初始值的效果(标准差为0.01、Xavier初始值、He初始值),可以发现:
权重初始值设置不当会导致学习停滞。
使用Xavier和He初始值的学习效果更佳,尤其是He初始值学习速度更快。
结论
在神经网络的训练中,权重的初始值和Batch Normalization的使用都是提升学习效果的关键因素,适当的权重初始化能够防止梯度消失和表现力受限,而Batch Norm能够加速学习过程并降低对初始值的依赖。

📊 训练与测试精度的变化
训练过程概述
在训练神经网络的过程中,我们使用批量(batch)数据来更新网络的参数。以下是主要步骤:

初始化训练和测试精度列表:train_acc_list 和 test_acc_list。
计算每个周期的迭代次数:iter_per_epoch = \max(\frac{train_size}{batch_size}, 1)。
通过一个循环进行多次训练迭代。
训练迭代示例
python
Copy
for i in range(1000000000):
batch_mask = np.random.choice(train_size, batch_size)
x_batch = x_train[batch_mask]
t_batch = t_train[batch_mask]
grads = network.gradient(x_batch, t_batch)
optimizer.update(network.params, grads)
if i % iter_per_epoch == 0:
train_acc = network.accuracy(x_train, t_train)
test_acc = network.accuracy(x_test, t_test)
train_acc_list.append(train_acc)
test_acc_list.append(test_acc)
epoch_cnt += 1
if epoch_cnt >= max_epochs:
break
识别精度的变化
训练和测试精度图示
训练精度和测试精度之间的关系在不同的周期(epoch)内发生变化。
在经过约100个周期后,训练数据的识别精度接近100%,而测试数据的精度则相对较低,这表明模型可能存在过拟合。
周期数(epochs) 训练精度(train) 测试精度(test)
50 0.8 0.6
100 0.9 0.7
150 1.0 0.8
200 1.0 0.9
正则化
权值衰减
权值衰减是一种对抗过拟合的常用方法,通过惩罚大的权重以抑制过拟合。其实现方式为在损失函数中加入权重的L2范数。

L2范数定义
权重为
KaTeX can only parse string typed expression
W=(w
1

,w
2

,…,w
n

),则L2范数为:
KaTeX can only parse string typed expression
∥W∥
2

w
1
2

+w
2
2

+…+w
n
2

在损失函数中加入L2范数的形式为:
KaTeX can only parse string typed expression
Loss=original_loss+λ∥W∥
2
2

其中,
KaTeX can only parse string typed expression
λ是控制正则化强度的超参数。

Dropout
Dropout是另一种有效的正则化方法,通过在训练过程中随机删除神经元来抑制过拟合。

Dropout实现示例
python
Copy
class Dropout:
def init(self, dropout_ratio=0.5):
self.dropout_ratio = dropout_ratio
self.mask = None

def forward(self, x, train_flg=True):
    if train_flg:
        self.mask = np.random.rand(*x.shape) > self.dropout_ratio
        return x * self.mask
    else:
        return x * (1.0 - self.dropout_ratio)

def backward(self, dout):
    return dout * self.mask

实验结果
使用Dropout的网络相比于不使用Dropout的网络,训练和测试精度的差距明显减小,且训练精度未达到100%,从而有效地抑制了过拟合。
超参数的验证
在神经网络中,超参数(如学习率和权值衰减系数)的设置对模型性能至关重要。以下是验证超参数的基本步骤:

验证数据
训练数据用于学习,测试数据用于评估模型的泛化能力。
为了调整超参数,需要使用专门的验证数据集。
超参数优化步骤
设定超参数的范围。
从设定的范围中随机采样超参数。
使用采样的超参数进行学习,通过验证数据评估识别精度。
根据识别精度结果缩小超参数的范围。
重复以上步骤,直到找到合适的超参数值。
小结
本章介绍了几种重要的技巧,包括:

参数更新方法(如SGD、Momentum、AdaGrad、Adam等)。
权重初始化方法(如Xavier和He初始化)。
正则化技术(如权值衰减和Dropout)。
超参数优化有效方法(如随机采样和验证数据的使用)。
🖼️ 卷积神经网络概述
7.2 卷积层
7.2.1 输入特征图与特征图
“图像是3维形状,这个形状中应该含有重要的空间信息。”

图像输入形状为(1, 28, 28),被展平为784个数据输入到全连接层。
全连接层会忽视数据的空间信息,而卷积层可以保持数据的形状。
输入特征图 输出特征图
输入数据(3维) 输出数据(3维)
7.2.2 卷积运算
卷积运算是卷积层的核心,类似于图像处理中的“滤波器运算”。在卷积运算中:

输入数据与滤波器(或称为“核”)进行处理。
例如,输入大小为(4, 4),滤波器大小为(3, 3),输出大小为(2, 2)。
卷积运算计算步骤
滤波器在输入数据上滑动。
计算当前位置上滤波器和输入数据对应元素的乘积,然后求和。
将结果保存到输出的对应位置。
乘积累加运算:是指将滤波器的元素与输入对应元素相乘后求和的过程。
偏置处理
卷积运算中会加上偏置,通常只有1个偏置值,会被加到应用滤波器的所有元素上。
7.2.3 填充
填充(padding)是指在输入数据周围填入固定的数据(如0),以调整输出大小。例如:

输入数据(4, 4)应用幅度为1的填充,变为(6, 6)。
填充的作用是保持卷积运算的输出大小。
7.2.4 步幅
步幅(stride)是指应用滤波器的位置间隔。增大步幅会减小输出大小。例如:

步幅为1的卷积运算,输入大小为(7, 7),滤波器大小为(3, 3),输出大小为(3, 3)。
7.2.5 3维数据的卷积运算
对于3维数据(如图像),需要处理通道方向。
输入数据和滤波器的通道数必须相同。
7.2.6 多个滤波器的运算
使用多个滤波器可以生成多个特征图。例如,对于输入数据和滤波器的输出,可以得到形状为(FN, OH, OW)的特征图。

7.2.7 批处理
批处理是对多个输入数据进行同时处理。数据需按(batch_num, channel, height, width)顺序保存,能够提高处理效率。

7.3 池化层
池化层用于缩小特征图的高和宽,主要有以下特征:

无学习参数:池化过程只取最大值或平均值。
通道数不变:池化运算不改变通道数。
池化类型
Max池化:获取最大值,通常用于图像处理。
Average池化:计算平均值。
池化的特征
对微小的位置变化具有鲁棒性,即输入数据的微小偏差不会影响输出结果。
7.4 卷积层和池化层的实现
卷积层和池化层的实现可使用Python,通过4维数组进行数据传递。
im2col函数可以将输入数据展开为适合滤波器的格式。
示例代码
python
Copy
import numpy as np

随机生成数据

x = np.random.rand(10, 1, 28, 28)
注意事项
在实现卷积运算时,应避免使用复杂的循环,以提高效率。
特征 说明
输入数据 4维数组,形状为(batch_num, channel, height, width)
计算效率 使用im2col展开可提高计算效率
卷积与池化 卷积层和池化层的实现需考虑4维数据
🧮 卷积层和池化层的实现

  1. 矩阵计算优化
    “在现代计算中,矩阵计算的实现已被高度最优化,可以高速地进行大矩阵的乘法运算。”

  2. im2col 函数
    im2col(“图像到矩阵”的缩写)是卷积层实现中的重要函数。它的功能是将输入数据展开为一个二维矩阵,以便进行高效的矩阵乘法。

im2col 函数接口
python
Copy
im2col(input_data, filter_h, filter_w, stride=1, pad=0)
input_data:由(数据量,通道,高,长)的4维数组构成的输入数据
filter_h:滤波器的高
filter_w:滤波器的长
stride:步幅
pad:填充
3. 卷积层的实现
3.1 卷积层类定义
python
Copy
class Convolution:
def init(self, W, b, stride=1, pad=0):
self.W = W
self.b = b
self.stride = stride
self.pad = pad

def forward(self, x):
    FN, C, FH, FW = self.W.shape
    N, C, H, W = x.shape
    out_h = int(1 + (H + 2*self.pad - FH) / self.stride)
    out_w = int(1 + (W + 2*self.pad - FW) / self.stride)
    col = im2col(x, FH, FW, self.stride, self.pad)
    col_W = self.W.reshape(FN, -1).T
    out = np.dot(col, col_W) + self.b
    out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2)
    return out

3.2 重要概念
滤波器(权重):形状为
KaTeX can only parse string typed expression
(FN,C,FH,FW),其中 FN 为滤波器数量,C 为通道数,FH 和 FW 为滤波器的高和宽。
输出计算:通过 im2col 将输入数据展开为二维数组,然后与展开的滤波器进行矩阵乘法。
3.3 示例代码
python
Copy
import numpy as np
x1 = np.random.rand(1, 3, 7, 7)
col1 = im2col(x1, 5, 5, stride=1, pad=0)
print(col1.shape) # (9, 75)
4. 池化层的实现
池化层的实现与卷积层相似,但在通道方向上是独立的。

4.1 池化层类定义
python
Copy
class Pooling:
def init(self, pool_h, pool_w, stride=1, pad=0):
self.pool_h = pool_h
self.pool_w = pool_w
self.stride = stride
self.pad = pad

def forward(self, x):
    N, C, H, W = x.shape
    out_h = int(1 + (H - self.pool_h) / self.stride)
    out_w = int(1 + (W - self.pool_w) / self.stride)
    col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad)
    col = col.reshape(-1, self.pool_h * self.pool_w)
    out = np.max(col, axis=1)
    out = out.reshape(N, out_h, out_w, C).transpose(0, 3, 1, 2)
    return out

4.2 实现流程
展开输入数据。
求各行的最大值。
转换为合适的输出大小。
5. CNN 的实现
5.1 CNN 构成
CNN 的基本构成如下:

卷积层(Convolution)
激活层(ReLU)
池化层(Pooling)
全连接层(Affine)
输出层(Softmax)
5.2 SimpleConvNet 类定义
python
Copy
class SimpleConvNet:
def init(self, input_dim=(1, 28, 28),
conv_param={‘filter_num’: 30, ‘filter_size’: 5, ‘pad’: 0, ‘stride’: 1},
hidden_size=100, output_size=10, weight_init_std=0.01):
# 省略初始化代码

def predict(self, x):
    for layer in self.layers.values():
        x = layer.forward(x)
    return x
    
def loss(self, x, t):
    y = self.predict(x)
    return self.last_layer.forward(y, t)
  1. 可视化卷积层
    在卷积层中,滤波器的可视化有助于理解模型学习到的特征。

6.1 可视化示例
学习前后滤波器的变化可以通过图像显示,观察其从随机初始化到学习后的规律性变化。

通过以上内容,学生可以全面理解卷积层和池化层的实现及其在卷积神经网络中的应用。

🖥️ 卷积神经网络(CNN)基础

  1. 卷积层的权重与图像显示
    “虽然权重的元素是实数,但是在图像的显示上,统一将最小值显示为黑色(0),最大值显示为白色(255)。”

权重的显示
卷积层的权重在图像上以黑白形式表示,黑色代表最小值(0),白色代表最大值(255)。
2. 滤波器的作用
观察内容
“如果要问图7-24中右边的有规律的滤波器在‘观察’什么,答案就是它在观察边缘(颜色变化的分界线)和斑块(局部的块状区域)等。”

示例滤波器
滤波器1:左半部分为白色、右半部分为黑色,对垂直方向上的边缘有响应。
滤波器2:对水平方向上的边缘有响应。
输出图像
输出图像 描述
输出图像1 对垂直方向上的边缘有响应
输出图像2 对水平方向上的边缘有响应
3. 分层结构的信息提取
信息提取的层次
“随着层次加深,提取的信息(正确地讲,是反映强烈的神经元)也越来越抽象。”

CNN结构示意
第1层:边缘或斑块
第3层:纹理
第5层:物体部件
全连接层:物体的类别(如狗或车)
示例网络
网络名称:AlexNet
层次结构:多层卷积层和池化层,最后经过全连接层输出结果。
4. 代表性的CNN网络
4.1 LeNet
“LeNet在1998年被提出,是进行手写数字识别的网络。”

结构特点
连续的卷积层和池化层。
激活函数使用sigmoid。
4.2 AlexNet
“AlexNet是引发深度学习热潮的导火线。”

结构特点
多个卷积层和池化层,最后经过全连接层。
激活函数使用ReLU。
使用局部正规化的LRN层和Dropout层。
5. 深度学习的性质
加深网络的优势
减少参数数量:加深层的网络可以用更少的参数达到同等水平的表现力。
高效学习:通过分层次学习,可以减少学习数据的需求,提高学习效率。
深度学习的历史
ILSVRC大赛:2012年,基于深度学习的方法(AlexNet)以压倒性的优势胜出,成为深度学习发展的转折点。
6. 深度学习的技术趋势
6.1 VGG
由卷积层和池化层构成,层数可达16层或19层。
6.2 GoogLeNet
结合“Inception结构”,在横向和纵向上都有深度。
6.3 ResNet
通过“快捷结构”解决了深度学习中的学习困难,允许更深的网络结构。
7. 数据扩充技术
“Data Augmentation基于算法‘人为地’扩充输入图像。”

应用实例
旋转、平移、裁剪等方式增加训练图像数量,尤其在数据集图像数量有限时有效。
8. 复习要点
CNN通过卷积层和池化层提取信息,层次越深提取的信息越复杂。
LeNet和AlexNet是CNN的重要代表。
深度学习技术的进步依赖于大数据和计算能力的提升。
🧠 深度学习的小历史
ResNet的构成要素
图8-12展示了ResNet的构成要素,其中的“weight layer”(权重层)是指卷积层。ResNet的设计思想在于通过快捷结构(skip connection)来有效传递输入数据。

快捷结构的作用
快捷结构原封不动地传递输入数据,这样在反向传播时,来自上游的梯度不会被处理,而是直接传递给下游。
重点在于不对来自上游的梯度进行任何处理,这样能够有效缓解梯度消失问题,使得网络层数可以更深。
ResNet的创新
ResNet在VGG网络的基础上,引入了快捷结构以加深网络层数。
实验结果显示,ResNet可以加深到150层以上,且识别精度持续提高。
在ILSVRC大赛中,ResNet的错误识别率为3.5%,表现令人惊讶。
🚀 深度学习的高速化
深度学习计算的挑战
随着大数据和网络的发展,深度学习需要大量的运算。单用CPU进行计算无法满足需求,因此需要借助GPU(图形处理器)来加速。

计算时间分析
图8-14以AlexNet的forward处理为例,展示了各层所耗费的时间:

层次 GPU时间占比 CPU时间占比
卷积层 95% 89%
池化层 - -
全连接层 - -
正规化层 - -
因此,高速、高效地进行卷积层的运算是深度学习的重要课题。

基于GPU的高速化
GPU不仅用于图像处理,还可进行通用数值计算,擅长并行运算。
相比于CPU,使用GPU进行深度学习的运算可实现显著的速度提升。
图8-15显示,使用GPU进行AlexNet学习的时间显著低于使用CPU的时间。
分布式学习的必要性
随着网络层数的加深,学习时间可达数天至数周,因此分布式学习变得重要。
使用多个GPU或多台机器进行分布式计算,可以显著缩短学习时间。
分布式学习效果
图8-16显示了基于TensorFlow的分布式学习效果,随着GPU数量的增加,学习速度显著提高。

运算精度的位数缩减
在深度学习中,内存容量和总线带宽可能成为瓶颈。
使用较少位数表示数值(如16位的半精度浮点数)可以有效减少内存使用和带宽负担。
实验表明,使用半精度浮点数进行学习不会显著影响识别精度。
📊 深度学习的应用案例
物体检测
物体检测是从图像中确定物体的位置和类别的问题。相比物体识别,物体检测更为复杂,通常使用基于卷积神经网络(CNN)的方法,如R-CNN。

R-CNN处理流
R-CNN的处理流包括:

提取候选区域。
计算CNN特征。
图像分割
图像分割是在像素水平上对图像进行分类的技术。FCN(全卷积网络)是基于神经网络进行图像分割的一种有效方法。

FCN的特征
FCN使用卷积层替代全连接层,以保持中间数据的空间信息。
通过双线性插值法进行输出数据的扩大。
图像标题的生成
图像标题生成涉及计算机视觉和自然语言处理,使用深度学习模型如NIC(Neural Image Caption)自动生成图像描述。

NIC模型结构
NIC结合了CNN和RNN,以CNN提取图像特征,RNN生成文本。

🔮 深度学习的未来
图像风格变换
利用深度学习进行图像风格变换,可以将一种图像的艺术风格应用于另一种图像。

图像的生成
使用DCGAN(深度卷积生成对抗网络)可以生成从未见过的全新图像。

自动驾驶
自动驾驶技术需要结合多种技术,深度学习在环境识别方面展现出巨大潜力。

强化学习
强化学习让计算机通过试错学习来自主决策,Deep Q-Network(DQN)是当前热门的强化学习方法。

🧠 强化学习与深度学习
Q学习与DQN
Q学习的概念
“Q学习是一种强化学习算法,通过学习一个被称为最优行动价值函数的函数,来确定最合适的行动。”

DQN的应用
DQN(深度Q网络)结合了深度学习和Q学习,利用卷积神经网络(CNN)来近似最优行动价值函数。具体来说,DQN的工作流程如下:

通过输入游戏图像的帧(连续4帧),DQN输出各个动作的“价值”,如控制杆的移动量和按钮操作的有无。
这一方法的创新之处在于,DQN只需输入游戏图像,而无需事先提取游戏状态,从而提升了其适用性。
DQN的成功案例
DQN在多个电子游戏中实现了超过人类的操作水平,这表明其算法的有效性。例如,DQN能够在《吃豆人》和Atari等游戏中表现优异。

AlphaGo的技术
AlphaGo的背景
AlphaGo是一个广受关注的人工智能项目,它击败了围棋冠军。AlphaGo的技术同样结合了深度学习和强化学习,具体实施如下:

学习了3000万个专业棋手的棋谱。
通过自我对战积累了大量的学习经验。
深度学习与强化学习的结合
DQN与AlphaGo的共同点在于,两者都由Google的DeepMind公司开发,展示了深度学习在不同领域的广泛应用潜力。

深度学习的未来
章节小结
本章总结了深度学习的几个重要方面:

深层网络在手写数字识别上获得了超过99%的识别精度。
深度学习在图像识别大赛中表现突出,常见的网络包括VGG、GoogLeNet和ResNet。
深度学习的应用不仅限于物体识别,还扩展到物体检测、图像分割等领域。
深度学习的趋势
深度学习的研究和应用持续快速发展,未来可能会带来无法想象的技术进步,值得全球研究者关注。

算法与模型的计算图
Softmax与交叉熵
在深度学习中,Softmax函数和交叉熵误差(Cross Entropy Error)用来构建损失函数。它们的组合称为Softmax-with-Loss层,用于优化模型的学习过程。

Softmax层的计算
Softmax函数可由以下公式表示:

KaTeX can only parse string typed expression
y
i


j=1
n

e
a
j

e
a
i

其中,
KaTeX can only parse string typed expression
a
i

为输入,
KaTeX can only parse string typed expression
y
i

为输出。

交叉熵误差的计算
交叉熵误差可由下式表示:

KaTeX can only parse string typed expression
L=−
i=1

n

t
i

log(y
i

)
反向传播的过程
反向传播涉及以下几个步骤:

反向传播的初始值为1。
“×”节点的反向传播将正向传播时的输入值翻转,乘以上游传过来的导数后,再传给下游。
“+”节点将上游传来的导数原封不动地传给下游。
重要概念总结
概念 描述
Q学习 强化学习算法,通过最优行动价值函数确定最合适的行动。
DQN 结合深度学习的Q学习,使用CNN来近似最优行动价值函数。
AlphaGo 结合深度学习和强化学习的围棋AI,学习大量棋谱并自我对战。
Softmax 用于多分类问题的输出层函数,输出为各类别的概率分布。
交叉熵误差 用于评估分类模型性能的损失函数,量化预测与真实标签的差异。
深度学习的未来充满可能,研究者和技术专家的持续努力将推动这一领域的发展。

📚 深度学习文献综述
重要文献
作者 主题 来源 年份
Karen Simonyan, Andrew Zisserman 大规模图像识别的深层卷积网络 arXiv:1409.1556 [cs] 2014
Christian Szegedy et al 深度卷积的进一步研究 IEEE 计算机视觉与模式识别会议 (CVPR) 2015
Kaiming He et al 深度残差学习在图像识别中的应用 arXiv:1512.03385 [cs] 2015
数据集
作者 数据集主题 来源 年份
J. Deng et al ImageNet: 一个大规模的分层图像数据库 IEEE 计算机视觉与模式识别会议 (CVPR) 2009
计算的高速化
作者 主题 来源 年份
Jia Yangqing 大规模学习语义图像表示 加州大学伯克利分校博士论文 2014
NVIDIA 深度学习的推进与新系统 NVIDIA 博客 -
Martín Abadi et al TensorFlow: 大规模机器学习在异构分布式系统上的应用 arXiv:1603.04467 [cs] 2016
MNIST数据集识别精度排行榜及方法
作者 主题 来源 年份
Li Wan et al 使用DropConnect的神经网络正则化 第30届国际机器学习会议 (ICML2013) 2013
深度学习的应用
作者 主题 来源 年份
Ross Girshick et al 精确的物体检测和语义分割的丰富特征层次 - 2014
Shaoqing Ren et al Faster R-CNN: 面向实时物体检测的区域提议网络 Advances in Neural Information Processing Systems 28 2015
Jonathan Long et al 语义分割的全卷积网络 IEEE 计算机视觉与模式识别会议 (CVPR) 2015
深度学习的最新进展
作者 主题 来源 年份
Volodymyr Mnih et al 通过深度强化学习实现人类级控制 Nature 2015
David Silver et al 使用深度神经网络和树搜索掌握围棋游戏 Nature 2016

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值