深度学习框架 (from《深度学习入门之PyTorch》)
TensorFlow
TensorFlow由Google开源。
TensorFlow是使用C++语言开发的开源数学计算软件,使用数据流图(Data Flow Graph)的形式进行计算。图中的节点代表数学运算,而图中的线条表示多维数据数组(tensor)之间的交互。
TensorFlow灵活的架构可以部署在一个或多个CPU,GPU的台式及服务器中,或者使用单一的API应用在移动设备中。
TensorFlow是深度学习界框架默认的老大。
目前TensorFlow是全世界使用人数最多、社区最为庞大的一个框架。因为Google公司出品,所以维护和更新也比较频繁,由python和C++的接口,教程也非常完善,同时很多论文复现的第一个版本都是基于TensorFlow写的。
吴恩达老师讲解TensorFlow的示例:TensorFlow
Caffe
Caffe由加州大学伯克利的Phd贾扬清开发,是一个清晰而高效的开源深度学习框架,目前由伯克利视觉学中心维护。
从它的名字就可以看出其对卷积网络支持特别好,同时也是用C++写的,但是并没有提供python接口,只提供了C++接口。
Caffe之所以流行,是因为之前很多ImageNet比赛中使用的网络都是用Caffe写的,所以如果你想使用致谢比赛中的网络模型就只能使用Caffe。
Caffe的缺点是不够灵活,同时占用内存高,只提供C++的接口,目前Caffe的升级版本Caffe2已经开源了,修复了一些问题,同时工程水平得到了进一步提高。
Torch
Torch是一个有大量机器学习算法支持的科学计算框架,其诞生已有十年之久,但其真正起势得益于FaceBook开源了大量Torch的深度学习模块和拓展。
Torch的特点在于特别灵活,但另一个特殊之处是采用了编程语言Lua。
在目前深度学习大部分以Python为编程语言的大环境下,Lua这一小众的语言增加了学习使用Torch这个框架的成本。
Pytorch的前身就是Torch,其底层和Torch框架一样,但是用Python重新写了很多内容,不仅更加灵活,支持动态图,也提供了Python接口。
Pytorch
PyTorch简介
PyTorch由torch7团队开发,使用了Python作为开发语言。
所谓的“python first”,说明它是一个以Python优先的深度学习框架,不仅能够实现强大GPU加速,同时还支持动态神经网络,这是现在很多主流框架比如TensorFlow等不支持的。
PyTorch既可以看作加入了GPU支持的numpy,同时也可以看成拥有自动求导的强大的深度神经网络。
为何要使用PyTorch
-
掌握一个框架并不能一劳永逸
现在深度学习并没有谁拥有绝对的垄断地位,所以只学习TensorFlow并不够(本人还没学TensorFlow)。
同时现在的研究者使用各个框架的都有,要去看他们实现的代码,至少也要了解他们使用的框架。 -
极高的速度和灵活性
TensorFlow和Caffe都是命令式的编程语言,而且是静态的。首先必须构建一个神经网络,然后一次又一次使用相同的结构。如果想改变网络的结构,就必须从头开始。
但是PyTorch,通过反向求导的技术,可以零延迟地任意改变神经网络的结构。尽管这项技术并不是PyTorch独有,但目前为止它实现是最快的,能够为你任何疯狂想法的实现获得极高的速度和极高的灵活性。
而这也是PyTorch对比TensorFlow最大的优势。 -
线性、直观、易于使用
PyTorch的设计思路是线性、直观、易于使用的。
当你执行一行代码时,他会忠实地执行,并没有异步的世界观。
所以当你的代码出现Bug的时候,可以通过这些信息轻松地找到出错的代码,不会让你在Debug的时候因为错误的指向或者异步和不透明的引擎浪费太多的时间。 -
代码简洁友好
PyTorch的代码相对于TensorFlow而言,更加简洁直观。同时对于TensorFlow高度工业化的很难看懂的底层代码,PyTorch的源代码要友好得多,更容易看懂。
深入API,理解PyTorch底层肯定是一件令人高兴的事。一个底层架构能看懂的架构,你对其的理解会更深。
最后简要总结一下PyTorch的特点:
- 支持GPU
- 动态神经网络
- Python优先
- 命令式体验
- 轻松扩展
选择深度学习框架的标准
回归问题 vs 分类问题
分类问题和回归问题是机器学习和深度学习的第一步,拿到任何一个问题,我们都需要先确定其到底是分类还是回归,然后再进行算法设计。
分类问题
分类问题希望把数据集分到某一类。比如一个 3 分类问题,那么对于任何一个数据点,我们都希望找到其到底属于哪一类,最终的结果只有三种情况,{0, 1, 2},所以这是一个离散的问题。
这里有一个挺有意思的小demo,来演示神经网络来分类的过程。
回归问题
回归问题是一个连续的问题,比如曲线的拟合,我们可以拟合任意的函数结果,这个结果是一个连续的值。
激活函数 of 神经网络
激活函数在神经网络中作用的机理
对于单个神经元,首先接受数据输入,然后通过计算得到计算结果,接着经过激活函数,再传给下一层神经元。
神经网络使用的激活函数都是非线性的。每个激活函数都输入一个值,然后做一种特定的数学运算得到一个结果。
常见的激活函数有:Sigmoid、ReLU
ReLU 是在神经网络中广泛使用的激活函数(《深度学习入门之Pytorch》中说有90%)。
由 ReLU 构成的神经网络,一层的神经网络的公式就是
y
=
m
a
x
(
0
,
w
x
+
b
)
y = max(0, w x + b)
y=max(0,wx+b) ,两层的神经网络就是
y
=
w
2
m
a
x
(
0
,
w
1
x
+
b
1
)
+
b
2
y = w_2\ max(0, w_1 x + b_1) + b_2
y=w2 max(0,w1x+b1)+b2 ,非常简单,但是却很有效。
使用这个激活函数能够加快梯度下降法的收敛速度,同时对比与其他的激活函数,这个激活函数计算更加简单,所以现在变得非常流行。
从数学角度理解激活函数的必要性
举例一个两层的神经网络,使用 A 表示激活函数,那么
y
=
w
2
A
(
w
1
x
)
y = w_2 A(w_1 x)
y=w2A(w1x)
如果我们不使用激活函数,那么神经网络的结果就是
y
=
w
2
(
w
1
x
)
=
(
w
2
w
1
)
x
=
w
ˉ
x
y = w_2 (w_1 x) = (w_2 w_1) x = \bar{w} x
y=w2(w1x)=(w2w1)x=wˉx
可以看到,我们将两层神经网络的参数合在一起,用
w
ˉ
\bar{w}
wˉ 来表示,两层的神经网络其实就变成了一层神经网络,只不过参数变成了新的
w
ˉ
\bar{w}
wˉ,所以如果不使用激活函数,那么不管多少层的神经网络,
y
=
w
n
⋯
w
2
w
1
x
=
w
ˉ
x
y = w_n \cdots w_2 w_1 x = \bar{w} x
y=wn⋯w2w1x=wˉx,就都变成了单层神经网络。
激活函数对神经网络的影响 - 万能逼近能力
看到使用了激活函数之后,神经网络可以通过改变权重实现任意形状,越是复杂的神经网络能拟合的形状越复杂,这就是著名的神经网络万有逼近定理。
前向传播和反向传播
详见该博客
详解神经网络的前向传播和反向传播(从头推导)
他的推导过程恰到好处,能把道理说得明白又不显得冗余。(膜一波
尤其是他在梯度下降和局部最优的部分用的小恶魔的比喻,真实太形象了。
深度卷积网络的结构
输入层
输入为三维矩阵,代表一张图片。
矩阵的长宽代表图片的大小,矩阵的深度代表图像的通道,如黑白为1,RGB为3。
卷积层
卷积层试图对神经网络的每一小块(滤波器扫到的区域)进行分析,得到抽象程度更高的特征。
一般来说,通过卷积层处理后的结点矩阵深度会增加。
卷积过程是由一个带有参数的矩阵(称为滤波器),按一定的步长扫过输入矩阵,被扫到的位置依次相乘求和作为输出矩阵的一个元素,得到降维的输出矩阵。
(如何计算输出矩阵的维度
池化层
池化层能够缩小矩阵的大小,但不会改变三维矩阵的深度,从而达到减少参数的目的。
池化的过程可以看做将一个高分辨率图片转化为低分辨率图片的过程。
全连接层
经过多轮卷积和池化后,经过1-2个全连接层来进行输出。
可以将卷积层和池化层看做特征提取,最后的全连接层来进行分类。