多层感知机

前言

感知机是一个古老的深度学习模型,由于它的不完美造成了一次AI寒冬。现在多层感知机就变得稍许完美一些了,不废话了…
之前学习了2个经典的回归算法,线性回归和softmax回归,他们都是用来预测结果的,但他们要求样本一定要有线性关系,就像房价与房屋属性必须有线性关系,这个就使得这两个算法的应用场景有点局限了,那么本文所谈的MLP(多层感知机)就可以解决一些非线性问题了。

原理

多层感知机的学习其实能让我们对神经网络有了更进一步的理解。

先来回顾一下之前softmax回归用到的神经网络图:

机器学习头歌原题答案多层感知器向前网络 多层感知机模型_点乘


这题的背景就是n张图,一张图784个像素;n张图最终分成10类,这10类的每一类对于784的像素点都有各自的权重值。

当时输入层就是Rn*784,权重值就是W784*10,偏移量就是B1*10,那么输出层就是Rn*784点乘W784*10+B1*10=On*10回忆一下,这不就是单层神经网络嘛,输入层相当于就是784个神经节点,输出层就是10个神经节点,再看这个点乘公式,线性的吧,那么我们的MLP可以解决非线性问题,这个公式就要做一些改变了,接下来介绍。

机器学习头歌原题答案多层感知器向前网络 多层感知机模型_深度学习_02


在MLP中加了个隐藏层,这里就放了一个隐藏层,搞清楚原理之后,这个深度可以自己按情况增加的。在softmax回归中等于是输入层点乘一下权值直接出结果了,那么MLP就是输入层点乘一下权重值加个偏移值输出到隐藏层,隐藏层再点乘另一组权重值再加另一组偏移值成为输出层。

还是那个784像素的例子,输入层至隐藏层:

输入层:Rn*784,权重值1:W1784*h,他们点乘的结果就是nh的形状对吧,那么这个h就是隐藏层神经元的个数了,这个隐藏层神经元个数算是个超参数,自己定义,通常是2n个神经元。偏移值1:B11*h
Hn*h=Rn*784点乘W1784*h+B11*h
隐藏层至输出层:上面输出的H就是这里的输入层了,输入层:Hn*h,权重值2:W2h*10,这里点乘后的形状就是n
10了,相当于输出层10个神经元,那么我们这个问题想要的结果也就是n幅图属于10个类别的概率,偏移值2:B21*10

On*10=Hn*h点乘W2h*10+B21*10

这时发现好像和softmax那些回归相比不过就是加个中间层,这不还是线性嘛,接下来开始对公式优化让他非线性。

Hn*h=𝜎(Rn*784点乘W1784*h+B11*h

On*10=Hn*h点乘W2h*10+B21*10

这个𝜎函数是啥,这个函数称之为激活函数,有3种常见形态可以实现非线性:

激活函数1:Relu

修正线性单元(Rectified linear unit,ReLU),公式非常简单,名字非常有逼格。

Relu(X)=max(0,X)

机器学习头歌原题答案多层感知器向前网络 多层感知机模型_机器学习头歌原题答案多层感知器向前网络_03


输入的x为正,导数为1,输入的x<=0,导数为0。

激活函数2:sigmoid函数

这个函数将使得最后的值在0到1之间波动,公式如下:

机器学习头歌原题答案多层感知器向前网络 多层感知机模型_人工智能_04


机器学习头歌原题答案多层感知器向前网络 多层感知机模型_人工智能_05


x值达到0时,导数为0.25,x值越偏离0,导数值越趋近0。

机器学习头歌原题答案多层感知器向前网络 多层感知机模型_深度学习_06

激活函数3:tanh函数

这个函数使得最后的值在-1至1之间,公式如下:

机器学习头歌原题答案多层感知器向前网络 多层感知机模型_人工智能_07


机器学习头歌原题答案多层感知器向前网络 多层感知机模型_人工智能_08


x值趋近0时,导数趋近1,x值越偏离0,导数值越趋近0。

机器学习头歌原题答案多层感知器向前网络 多层感知机模型_机器学习_09


这三个激活函数套在Xw+b的外面,就使得原有公式不再具有线性的特点,最普遍使用的激活函数是Relu。

我们再回顾一下套用激活函数后的非线性神经网络公式:

Hn*h=𝜎(Rn*784点乘W1784*h+B11*h

On*10=Hn*h点乘W2h*10+B21*10

接下来的步骤就和之前softmax回归的方式一样了,多次迭代,每一次迭代中都用随机梯度下降的方式对损失函数作优化,以获得最优的权重值和偏离值。

实现方法

导包

import torch
from torch import nn
from d2l import torch as d2l

数据集获取

还是使用softmax用到过的数据集,对几千张图分成10个类。

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)

初始化模型参数

这里我们用到的方法和原理中所举的例子一致,只建立一个隐藏层,那么就有2组权重和偏移。
再回顾一下原理中的2个公式,这里的参数就好理解了。
Hn*h=𝜎(Rn*784点乘W1784*h+B11*h
On*10=Hn*h点乘W2h*10+B21*10
这里的w1w2b1b2都是对应的。

#输入层、输出层、隐藏层神经元个数
num_inputs, num_outputs, num_hiddens = 784, 10, 256 
#这里的随机函数使得数据符合正态分布,乘0.01使得权重更小一点那么方差也小一点
W1 = nn.Parameter(torch.randn(
    num_inputs, num_hiddens, requires_grad=True) * 0.01)
b1 = nn.Parameter(torch.zeros(num_hiddens, requires_grad=True))
W2 = nn.Parameter(torch.randn(
    num_hiddens, num_outputs, requires_grad=True) * 0.01)
b2 = nn.Parameter(torch.zeros(num_outputs, requires_grad=True))

params = [W1, b1, W2, b2]

激活函数

这里使用Relu

def relu(X):
    a = torch.zeros_like(X)#让a这个全0的矩阵和输入x的形状保持一致
    return torch.max(X, a)

模型建立

def net(X):
	#这里的原始数据实际上是3维的,就是n个二维数据,n个28*28的矩阵
	#这句话就是将28*28的矩阵平铺成一维长度784的数据,变成n*784的形状
    X = X.reshape((-1, num_inputs))
    #输入层至隐藏层,加上激活函数使得它非线性
    H = relu(X@W1 + b1)  # 这里“@”代表矩阵乘法
    #隐藏层至输出层,这里不用relu函数了
    return (H@W2 + b2)

这里可以看到如果要多个隐藏层,那么这里的函数可能要写很多行了,下个blog介绍的框架实现就方便很多了。

损失函数

这里的损失函数与softmax作了结合,上一个blog有介绍,这里直接使用

loss = nn.CrossEntropyLoss(reduction='none')

训练与预测

这两步实际上和softmax回归的方法一样,直接使用上篇的框架了。

#训练
num_epochs, lr = 10, 0.1
updater = torch.optim.SGD(params, lr=lr)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, updater)
#预测
d2l.predict_ch3(net, test_iter)

结果如下:

机器学习头歌原题答案多层感知器向前网络 多层感知机模型_深度学习_10


预测结果:

机器学习头歌原题答案多层感知器向前网络 多层感知机模型_机器学习头歌原题答案多层感知器向前网络_11

小结

通过MLP的学习,相信对神经网络有了一个很深入的理解,实际上我们不用每次都去搭建这个复杂的模型,下篇blog介绍框架实现MLP。