多层感知机的基本知识
深度学习主要关注多层模型。在这里,我们将以多层感知机(multilayer perceptron,MLP)为例,介绍多层神经网络的概念。
隐藏层
下图展示了一个多层感知机的神经网络图,它含有一个隐藏层,该层中有5个隐藏单元。
我们先来看一种含单隐藏层的多层感知机的设计。其输出
O
∈
R
n
×
q
\boldsymbol{O} \in \mathbb{R}^{n \times q}
O∈Rn×q的计算为
H = X W h + b h , O = H W o + b o , \begin{aligned} \boldsymbol{H} &= \boldsymbol{X} \boldsymbol{W}_h + \boldsymbol{b}_h,\\ \boldsymbol{O} &= \boldsymbol{H} \boldsymbol{W}_o + \boldsymbol{b}_o, \end{aligned} HO=XWh+bh,=HWo+bo,
也就是将隐藏层的输出直接作为输出层的输入。如果将以上两个式子联立起来,可以得到
O = ( X W h + b h ) W o + b o = X W h W o + b h W o + b o . \boldsymbol{O} = (\boldsymbol{X} \boldsymbol{W}_h + \boldsymbol{b}_h)\boldsymbol{W}_o + \boldsymbol{b}_o = \boldsymbol{X} \boldsymbol{W}_h\boldsymbol{W}_o + \boldsymbol{b}_h \boldsymbol{W}_o + \boldsymbol{b}_o. O=(XWh+bh)Wo+bo=XWhWo+bhWo+bo.
隐藏层也是线性层,无论添加多少隐藏层都等价单层的神经网络,解决方法————添加非线性的变换
激活函数
下面我们介绍几个常用的激活函数:
ReLU函数
ReLU(rectified linear unit)函数提供了一个很简单的非线性变换。给定元素 x x x,该函数定义为
ReLU
(
x
)
=
max
(
x
,
0
)
.
\text{ReLU}(x) = \max(x, 0).
ReLU(x)=max(x,0).
可以看出,ReLU函数只保留正数元素,并将负数元素清零。为了直观地观察这一非线性变换,我们先定义一个绘图函数xyplot。
Sigmoid函数
sigmoid函数可以将元素的值变换到0和1之间:
sigmoid ( x ) = 1 1 + exp ( − x ) . \text{sigmoid}(x) = \frac{1}{1 + \exp(-x)}. sigmoid(x)=1+exp(−x)1.
tanh函数
tanh(双曲正切)函数可以将元素的值变换到-1和1之间:
tanh ( x ) = 1 − exp ( − 2 x ) 1 + exp ( − 2 x ) . \text{tanh}(x) = \frac{1 - \exp(-2x)}{1 + \exp(-2x)}. tanh(x)=1+exp(−2x)1−exp(−2x).
当输入接近0时,tanh函数接近线性变换。虽然该函数的形状和sigmoid函数的形状很像,但tanh函数在坐标系的原点上对称。
关于激活函数的选择
ReLu函数是一个通用的激活函数,目前在大多数情况下使用。但是,ReLU函数只能在隐藏层中使用。
用于分类器时,sigmoid函数及其组合通常效果更好。由于梯度消失问题,有时要避免使用sigmoid和tanh函数。
在神经网络层数较多的时候,最好使用ReLu函数,ReLu函数比较简单计算量少,而sigmoid和tanh函数计算量大很多。
在选择激活函数的时候可以先选用ReLu函数如果效果不理想可以尝试其他激活函数。
多层感知机
多层感知机就是含有至少一个隐藏层的由全连接层组成的神经网络,且每个隐藏层的输出通过激活函数进行变换。多层感知机的层数和各隐藏层中隐藏单元个数都是超参数。以单隐藏层为例并沿用本节之前定义的符号,多层感知机按以下方式计算输出:
H = ϕ ( X W h + b h ) , O = H W o + b o , \begin{aligned} \boldsymbol{H} &= \phi(\boldsymbol{X} \boldsymbol{W}_h + \boldsymbol{b}_h),\\ \boldsymbol{O} &= \boldsymbol{H} \boldsymbol{W}_o + \boldsymbol{b}_o, \end{aligned} HO=ϕ(XWh+bh),=HWo+bo,
其中 ϕ \phi ϕ表示激活函数。
多层感知机pytorch实现
初始化模型和各个参数
num_inputs, num_outputs, num_hiddens = 784, 10, 256
##使用fashion mnist数据集输入28x28=784的图像;输出为10种类型;256为隐藏层输入
#初始化网络
net = nn.Sequential(
d2l.FlattenLayer(), #第一层数据变化,输入由28*28成784
nn.Linear(num_inputs, num_hiddens), #隐藏层/线性层(输入,输出)
nn.ReLU(),
nn.Linear(num_hiddens, num_outputs), #隐藏层/线性层(输入,输出)
)
#初始化参数,将网络中参数取出,进行正态初始化
for params in net.parameters():
init.normal_(params, mean=0, std=0.01)
训练
batch_size = 256 # #一次训练所选取的样本数。
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size,root='/home/kesci/input/FashionMNIST2065')
loss = torch.nn.CrossEntropyLoss() #交叉熵损失函数
optimizer = torch.optim.SGD(net.parameters(), lr=0.5) #随机梯度下降,要优化的是网络参数,学习率为0.5
num_epochs = 5 #训练周期5
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size, None, None, optimizer)