本文将为大家分享入门AI的必经之路,也是深度学习(Deep Learning)的基础—神经网络(NN,Neural Network)。
文章大纲
1.为什么是神经网络?
人类之所以在所有灵长类动物中处于绝对优势地位,是因为我们与其他动物相比,具有高度发达的大脑🧠,复杂的抽象思维、语言、自我意识以及解决问题的能力,其中模仿能力是我们在漫长的时间里存活下来的重要手段,也是创新创造的灵感源泉。
人类大脑使得我们可以处理眼睛看到的”图像“,耳朵听到的”文本“,还有各种各样超级复杂的计算。这种无以伦比的信息处理能力让人无比憧憬 🤩,在很多影视剧我们都可以看到人们对于AI的想象,计算机从设计之初的基础配置,不断学习,慢慢产生自我意识,逐渐达到与人类无法区分的水平,让我想起了🎥 《迷你黑镜》 那个短片,墙裂推荐去看一下。正如人类看到鸟儿在空中飞翔模仿出飞机一样,为了接近智能这一目标,走在人类前沿的科学家们试图用计算机💻模仿人脑,赋予其“学习”的能力,因此构造出了”人工神经网络“,简称神经网络。
2.什么是神经网络?
在中学生物课本中📖我们曾学习过神经元,其由细胞体、树突、轴突构成,树突用于接收其他神经元的信号,轴突向其它神经元发送信号,而细胞体是处理信号的”司令部“,多个神经元借助突触相互连接形成的网络,就是神经网络。
2.1 人脑中神经网络的数学表达
在神经网络中,神经元之间可以传递信号,一个神经元接收其它神经元传来的信号,并判断这些信号之和是否超过某个阈值,若超过该阈值,则神经元作出相应的反应,称之为“点火”;否则忽略该信号,不作出反应。其中接收的信号也大小不一,这是因为各个信号的重要程度不一样,也就引入了“权重(weight)”的概念,也叫回归系数(regression coefficient)。如此便可以将神经网络数学化表示,我们假设接收来自神经元 x1 ,x2 ,x3 的信号,其相对应的权重分别是 w1,w2 ,w3 ,则神经元接收的输入信号之和就可以表示为 w 1 x 1 + w 2 x 2 + w 3 x 3 {w}_{1}{x}_{1}+{w}_{2}{x}_{2}+{w}_{3}{x}_{3} w1x1+w2x2+w3x3
我们假设上文提到的阈值为θ,那么根据阈值大小判断是否点火就对应于是否有输出,进而可以将无输出表示为y=0,有输出表示为y=1,那总体数学表达如下所示:
{
w
1
x
1
+
w
2
x
2
+
w
3
x
3
<
θ
,
无
输
出
y
=
0
w
1
x
1
+
w
2
x
2
+
w
3
x
3
≥
θ
,
有
输
出
y
=
1
\left\{\begin{matrix} {w}_{1}{x}_{1}+{w}_{2}{x}_{2}+{w}_{3}{x}_{3}<θ,无输出y=0\\ {w}_{1}{x}_{1}+{w}_{2}{x}_{2}+{w}_{3}{x}_{3}\geq θ,有输出y=1 \end{matrix}\right.
{w1x1+w2x2+w3x3<θ,无输出y=0w1x1+w2x2+w3x3≥θ,有输出y=1
其图像为
将上式移项得到
{
w
1
x
1
+
w
2
x
2
+
w
3
x
3
−
θ
<
0
,
无
输
出
y
=
0
w
1
x
1
+
w
2
x
2
+
w
3
x
3
−
θ
≥
0
,
有
输
出
y
=
1
\left\{\begin{matrix} {w}_{1}{x}_{1}+{w}_{2}{x}_{2}+{w}_{3}{x}_{3}-θ<0,无输出y=0\\ {w}_{1}{x}_{1}+{w}_{2}{x}_{2}+{w}_{3}{x}_{3}-θ\geq 0,有输出y=1 \end{matrix}\right.
{w1x1+w2x2+w3x3−θ<0,无输出y=0w1x1+w2x2+w3x3−θ≥0,有输出y=1
则图像变化如下图所示
这就是单位阶跃函数 u ( z ) = { 0 , ( z < 0 ) 1 , ( z ≥ 0 ) u(z)=\left\{\begin{matrix} 0,(z<0)\\ 1,(z\geq 0) \end{matrix}\right. u(z)={0,(z<0)1,(z≥0)
综合上述函数,统一化表示为 y = u ( w 1 x 1 + w 2 x 2 + w 3 x 3 − θ ) y=u({w}_{1}{x}_{1}+{w}_{2}{x}_{2}+{w}_{3}{x}_{3}- θ) y=u(w1x1+w2x2+w3x3−θ)
式子中的阈值θ代表了神经元的感应能力,θ越大,表示神经元感应迟钝,越小表示感应灵敏,神经元越容易兴奋。数学是一门美丽的学科,它充满了和谐与奇异,而在这个式子中最后的-θ在一排加号中却显得有些异类,我们考虑将式子中的-θ改写成+b,那么对应的式子变为
⭐
⭐
y
=
u
(
w
1
x
1
+
w
2
x
2
+
w
3
x
3
+
b
)
⭐
⭐
⭐⭐ y=u({w}_{1}{x}_{1}+{w}_{2}{x}_{2}+{w}_{3}{x}_{3}+b) ⭐⭐
⭐⭐y=u(w1x1+w2x2+w3x3+b)⭐⭐
其中
⭐
⭐
z
=
w
1
x
1
+
w
2
x
2
+
w
3
x
3
+
b
⭐
⭐
⭐⭐z={w}_{1}{x}_{1}+{w}_{2}{x}_{2}+{w}_{3}{x}_{3}+b⭐⭐
⭐⭐z=w1x1+w2x2+w3x3+b⭐⭐ ,这也就是神经网络中的一般表达。这里的b称之为偏置(bias),也叫截距(intercept)对应在神经网络图中可以增加一个虚拟输入1,权重为偏置b,由此形成整个神经网络的数学表达基础,后续所有问题都在此基础上展开,如图
将该图转换成更简洁的数学图形表示
🔸 将图中的输入和权重向量化表示,则
X
=
[
x
1
,
x
2
,
x
3
]
X=[{x}_{1},\, {x}_{2},\, {x}_{3}]
X=[x1,x2,x3] ,
w
=
[
w
1
,
w
2
,
w
3
]
w=[{w}_{1},\, {w}_{2},\, {w}_{3}]
w=[w1,w2,w3] ,
那么
z
^
=
X
w
\hat{z}=Xw
z^=Xw 。这里的向量表示1个样本的3个特征, 表示一个样本的三个权重
🔸 若将1个样本的特征推广到n个特征,则
X
=
[
x
1
,
x
2
,
…
…
,
x
n
]
X=[{x}_{1},\, {x}_{2}, ……,{x}_{n}]
X=[x1,x2,……,xn],
w
=
[
w
1
,
w
2
,
…
…
,
w
n
]
w=[{w}_{1},\, {w}_{2},\,…… ,{w}_{n}]
w=[w1,w2,……,wn]
🔸 将该式继续推广到m个样本,每个样本有n个特征,则
X
=
[
x
11
,
x
12
,
…
…
,
x
1
n
]
X=[{x}_{11},\, {x}_{12}, ……,{x}_{1n}]
X=[x11,x12,……,x1n] ,下标第一个位置表示第几个样本,第二个位置表示该样本的第几个特征,因为共用一套权重,所以权重矩阵不需要变化。这样推广下来,我们就可以将其用矩阵形式表示出来,如下图
3. 如何实现神经网络
3.1 单层神经网络—线性回归
有了神经网络的数学表达我们就可以很清楚的做一些推导,那么如何在计算机里实现神经网络呢?😕
中学我们学过y=ax+b这种简单的一元函数,看起来和我们前面的数学表达如出一辙,那么a就是神经网络中的权重,b是偏置,y在神经网络中常用z来表示,在神经网络的任务中,我们输入的样本含有多个特征,将这些特征输入到我们的神经网络,最终要得到的是合适的w和b,也就是训练完成我们的神经网络。这个函数就是我们的模型,输入特征得到相应的输出的过程就是预测,所以这种函数也叫预测函数。y=ax+b是一种线性函数,可以用来做回归预测,比如简单的根据城市人口预测数据预测利润,如图
根据已有的人口和利润的对应数据,我们就可以拟合出一条回归直线,然后预测出对应的结果。
我们将思绪拉回到最简单的公式 z = w 1 x 1 + w 2 x 2 + b z={w}_{1}{x}_{1}+{w}_{2}{x}_{2}+b z=w1x1+w2x2+b ,在这个公式里有两个特征,我们将根据这两个特征得到预测值 ,下图是该网络的结构
这就是最简单的单层神经网络,但是明明有两层为什么叫单层神经网络呢?这是因为在AI领域,通常在命名一个神经网络的时候不考虑输入层,只考虑输入层之后的层数。一般将1称为 ,这样能保证结构的整体性。把输入层的三个参数与相对应的权重相乘,在输出层加和就可以得到我们想要的预测值😏。
3.2 使用PyTorch实现单层神经网络
3.2.1 PyTorch简介
神经网络的实现需要借助深度学习框架(Deep learning framework),本文采用pytorch来实现。简单介绍一下,pytorch由FacebookAI实验室研发,基于torch,底层由C++实现的开源的深度学习框架,得益于其优秀的灵活性和支持海量数据运算等优势,目前pytorch在学术界非常流行。但是太不建议直接去官网查看API,官网虽然简洁,但是其模块却是按字母顺序排列😑,对新手极不友好,这里给出pytorch模块的整体框架,具体细节大家在使用中遇到问题再去查官方文档。
3.2.2 使用tensor实现神经网络
在介绍了pytorch之后,我们就可以使用其基本数据类型—tensor(张量)来建立神经网络,从神经网络的左边输入特征 ,右边输出预测值 ,这个过程就叫做神经网络的正向传播(forward spread)。下面给出一组数据
1 | 0 | 0 | -0.1 |
1 | 0 | 1 | 0.1 |
1 | 1 | 0 | 0.1 |
根据这组数据,我们利用tensor实现,代码如下:
import torch
X = torch.tensor([[1,0,0],[1,0,1],[1,1,0]], dtype = torch.float32)
z = torch.tensor([-0.1, 0.1, 0.1])
w = torch.tensor([-0.1,0.2,0.2])
def Linear1(X,w):
zhat = torch.mv(X,w)
return zhat
zhat = Linear1(X,w)
在jupyter lab上面的运行结果如下所示
可以看到输出的预测值 z ^ \hat{z} z^与我们设定的值 z z z是相同的,接下来我们使用深度学习框架来实现神经网络。
3.2.3 使用torch.nn实现单层神经网络
torch.nn是构建神经网络结构的包,在这个包中有神经网络的各种“层”(注:不含输入层),这些层都是nn.Module的子类,而线性层就是torch.nn.Linear这个类。同样使用前面的简单数据
1 | 0 | 0 | -0.1 |
1 | 0 | 1 | 0.1 |
1 | 1 | 0 | 0.1 |
torch.nn.Linear实现,代码如下
import torch
X = torch.tensor([[0,0],[0,1],[1,0]], dtype = torch.float32)
output = torch.nn.Linear(2,1) # 实例化,并传入参数
zhat = output(X)
可以看出,使用nn.Linear实现神经网络,代码非常简洁,当数据量变大,网络变复杂时,这种简洁的优势会更加明显。
🔶nn.Linear的第一个参数是指上一层的神经元数,第二个参数指本层神经元个数,根据前面的神经网络架构图,可以清楚的看出在例子中,上一层是输入层,神经元个数等于特征个数(2个),当前层是输出层,神经元个数只有1个。
🔶其中只定义了特征矩阵X,没有定义w和b,这是因为使用框架定义神经网络,类似nn.Linear的层,都会在实例化的同时随机初始化w和b。
🔶nn.Linear还有其他参数,如bias是控制是否需要偏置b的参数
jupyter lab运行结果
因为随机生成的w和b,所以输出的预测值 与我们设定的值 是不相同的,因为随机的缘故每次运行结果并不一样,如果要保证能够复现,可以设定随机数种子
torch.random.manual_seed(66) # 随机种子的数值自行设定就好
本文仅是简单介绍了神经网络,线性回归算是最简单的神经网络了,后续还会有逻辑回归,二分类神经网络,多分类神经网络,更进阶的有卷积神经网络CNN,循环神经网络RNN等等,但是殊途同归,掌握了简单的网络搭建,后续都只是在模型上增加复杂度而已。
接下来我还会继续分享神经网络的搭建,记录自己的学习与收获,欢迎大家一起讨论学习。
关注公z号—克鲁斯卡
End