多层感知机

多层感知机

  1. 多层感知机的基本知识
  2. 使用多层感知机图像分类的从零开始的实现
  3. 使用pytorch的简洁实现

多层感知机的基本知识

深度学习主要关注多层模型。在这里,我们将以多层感知机(multilayer perceptron,MLP)为例,介绍多层神经网络的概念。

隐藏层

下图展示了一个多层感知机的神经网络图,它含有一个隐藏层,该层中有5个隐藏单元。

表达公式

具体来说,给定一个小批量样本\(\boldsymbol{X} \in \mathbb{R}^{n \times d}\),其批量大小为\(n\),输入个数为\(d\)。假设多层感知机只有一个隐藏层,其中隐藏单元个数为\(h\)。记隐藏层的输出(也称为隐藏层变量或隐藏变量)为\(\boldsymbol{H}\),有\(\boldsymbol{H} \in \mathbb{R}^{n \times h}\)。因为隐藏层和输出层均是全连接层,可以设隐藏层的权重参数和偏差参数分别为\(\boldsymbol{W}_h \in \mathbb{R}^{d \times h}\)和 \(\boldsymbol{b}_h \in \mathbb{R}^{1 \times h}\),输出层的权重和偏差参数分别为\(\boldsymbol{W}_o \in \mathbb{R}^{h \times q}\)和\(\boldsymbol{b}_o \in \mathbb{R}^{1 \times q}\)。

我们先来看一种含单隐藏层的多层感知机的设计。其输出\(\boldsymbol{O} \in \mathbb{R}^{n \times q}\)的计算为

\[
\begin{aligned} \boldsymbol{H} &= \boldsymbol{X} \boldsymbol{W}_h + \boldsymbol{b}_h,\\ \boldsymbol{O} &= \boldsymbol{H} \boldsymbol{W}_o + \boldsymbol{b}_o, \end{aligned}
\]

也就是将隐藏层的输出直接作为输出层的输入。如果将以上两个式子联立起来,可以得到

\[
\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.
\]

从联立后的式子可以看出,虽然神经网络引入了隐藏层,却依然等价于一个单层神经网络:其中输出层权重参数为\(\boldsymbol{W}_h\boldsymbol{W}_o\),偏差参数为\(\boldsymbol{b}_h \boldsymbol{W}_o + \boldsymbol{b}_o\)。不难发现,即便再添加更多的隐藏层,以上设计依然只能与仅含输出层的单层神经网络等价。

激活函数

上述问题的根源在于全连接层只是对数据做仿射变换(affine transformation),而多个仿射变换的叠加仍然是一个仿射变换。解决问题的一个方法是引入非线性变换,例如对隐藏变量使用按元素运算的非线性函数进行变换,然后再作为下一个全连接层的输入。这个非线性函数被称为激活函数(activation function)。

下面我们介绍几个常用的激活函数:

ReLU函数

ReLU(rectified linear unit)函数提供了一个很简单的非线性变换。给定元素\(x\),该函数定义为

\[
\text{ReLU}(x) = \max(x, 0).
\]

可以看出,ReLU函数只保留正数元素,并将负数元素清零。为了直观地观察这一非线性变换,我们先定义一个绘图函数xyplot。

%matplotlib inline
import torch
import numpy as np
import matplotlib.pyplot as plt
import sys
sys.path.append("/home/kesci/input")
import d2lzh1981 as d2l
print(torch.__version__)
1.3.0
def xyplot(x_vals, y_vals, name):
    # d2l.set_figsize(figsize=(5, 2.5))
    plt.plot(x_vals.detach().numpy(), y_vals.detach().numpy())
    plt.xlabel('x')
    plt.ylabel(name + '(x)')
x = torch.arange(-8.0, 8.0, 0.1, requires_grad=True)
y = x.relu()
xyplot(x, y, 'relu')

y.sum().backward()
xyplot(x, x.grad, 'grad of relu')

Sigmoid函数

sigmoid函数可以将元素的值变换到0和1之间:

\[
\text{sigmoid}(x) = \frac{1}{1 + \exp(-x)}.
\]

x.grad.zero_()
y = x.sigmoid()
xyplot(x, y, 'sigmoid')

依据链式法则,sigmoid函数的导数

\[
\text{sigmoid}'(x) = \text{sigmoid}(x)\left(1-\text{sigmoid}(x)\right).
\]

下面绘制了sigmoid函数的导数。当输入为0时,sigmoid函数的导数达到最大值0.25;当输入越偏离0时,sigmoid函数的导数越接近0。

y.sum().backward()
xyplot(x, x.grad, 'grad of sigmoid')

tanh函数

tanh(双曲正切)函数可以将元素的值变换到-1和1之间:

\[
\text{tanh}(x) = \frac{1 - \exp(-2x)}{1 + \exp(-2x)}.
\]

我们接着绘制tanh函数。当输入接近0时,tanh函数接近线性变换。虽然该函数的形状和sigmoid函数的形状很像,但tanh函数在坐标系的原点上对称。

y = x.tanh()
xyplot(x, y, 'tanh')

依据链式法则,tanh函数的导数

\[
\text{tanh}'(x) = 1 - \text{tanh}^2(x).
\]

下面绘制了tanh函数的导数。当输入为0时,tanh函数的导数达到最大值1;当输入越偏离0时,tanh函数的导数越接近0。

x.grad.zero_()
y.sum().backward()
xyplot(x, x.grad, 'grad of tanh')

关于激活函数的选择

ReLu函数是一个通用的激活函数,目前在大多数情况下使用。但是,ReLU函数只能在隐藏层中使用。

用于分类器时,sigmoid函数及其组合通常效果更好。由于梯度消失问题,有时要避免使用sigmoid和tanh函数。

在神经网络层数较多的时候,最好使用ReLu函数,ReLu函数比较简单计算量少,而sigmoid和tanh函数计算量大很多。

在选择激活函数的时候可以先选用ReLu函数如果效果不理想可以尝试其他激活函数。

多层感知机

多层感知机就是含有至少一个隐藏层的由全连接层组成的神经网络,且每个隐藏层的输出通过激活函数进行变换。多层感知机的层数和各隐藏层中隐藏单元个数都是超参数。以单隐藏层为例并沿用本节之前定义的符号,多层感知机按以下方式计算输出:

\[
\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}
\]

其中\(\phi\)表示激活函数。

多层感知机从零开始的实现

import torch
import numpy as np
import sys
sys.path.append("/home/kesci/input")
import d2lzh1981 as d2l
print(torch.__version__)
1.3.0

获取训练集

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size,root='/home/kesci/input/FashionMNIST2065')

定义模型参数

num_inputs, num_outputs, num_hiddens = 784, 10, 256 # w层, h层,输出层 

W1 = torch.tensor(np.random.normal(0, 0.01, (num_inputs, num_hiddens)), dtype=torch.float)
b1 = torch.zeros(num_hiddens, dtype=torch.float) # h = w * x + b
W2 = torch.tensor(np.random.normal(0, 0.01, (num_hiddens, num_outputs)), dtype=torch.float)
b2 = torch.zeros(num_outputs, dtype=torch.float) # output = h*w + b

params = [W1, b1, W2, b2]
for param in params:
    param.requires_grad_(requires_grad=True)

定义激活函数

def relu(X):
    return torch.max(input=X, other=torch.tensor(0.0))

定义网络

def net(X):
    X = X.view((-1, num_inputs))
    H = relu(torch.matmul(X, W1) + b1)
    return torch.matmul(H, W2) + b2

定义损失函数

loss = torch.nn.CrossEntropyLoss()

训练

num_epochs, lr = 5, 100.0
def train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size,
              params=None, lr=None, optimizer=None):
    for epoch in range(num_epochs):
        train_l_sum, train_acc_sum, n = 0.0, 0.0, 0
        for X, y in train_iter:
            y_hat = net(X)
            l = loss(y_hat, y).sum()

            # 梯度清零
            if optimizer is not None:
                optimizer.zero_grad()
            elif params is not None and params[0].grad is not None:
                for param in params:
                    param.grad.data.zero_()

            l.backward()
            if optimizer is None:
                d2l.sgd(params, lr, batch_size)
            else:
                optimizer.step()  # “softmax回归的简洁实现”一节将用到

            train_l_sum += l.item()
            train_acc_sum += (y_hat.argmax(dim=1) == y).sum().item()
            n += y.shape[0]
        test_acc = evaluate_accuracy(test_iter, net)
        print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f'
              % (epoch + 1, train_l_sum / n, train_acc_sum / n, test_acc))

d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size, params, lr)
epoch 1, loss 0.0031, train acc 0.708, test acc 0.762
epoch 2, loss 0.0019, train acc 0.822, test acc 0.803
epoch 3, loss 0.0017, train acc 0.844, test acc 0.830
epoch 4, loss 0.0015, train acc 0.857, test acc 0.822
epoch 5, loss 0.0015, train acc 0.864, test acc 0.837

多层感知机pytorch实现

import torch
from torch import nn
from torch.nn import init
import numpy as np
import sys
sys.path.append("/home/kesci/input")
import d2lzh1981 as d2l

print(torch.__version__)
1.3.0

初始化模型和各个参数

num_inputs, num_outputs, num_hiddens = 784, 10, 256

net = nn.Sequential(
        d2l.FlattenLayer(),
        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)

num_epochs = 5
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size, None, None, optimizer)
epoch 1, loss 0.0031, train acc 0.706, test acc 0.798
epoch 2, loss 0.0019, train acc 0.822, test acc 0.830
epoch 3, loss 0.0016, train acc 0.844, test acc 0.848
epoch 4, loss 0.0015, train acc 0.857, test acc 0.853
epoch 5, loss 0.0014, train acc 0.865, test acc 0.813

原文地址:https://www.cnblogs.com/hichens/p/12309264.html

时间: 2024-08-16 01:02:39

多层感知机的相关文章

多层感知机,非权值共享型卷积神经网络,权值共享型卷积神经网络之间的关系

前言:最近学习深度学习,有感写一点总结. 我们常常所说的神经网络,一般是指原始的多层感知机,简称MLP,它是在原始感知机堆叠多层而成的,MLP完全由全连接层组成(当然也有激活函数),即Caffe里的IP层.MLP的最大的缺点在于参数众多,比如说我们的网络层为1000--1000--500--20,那么它的总的参数为:1000*1000+1000*500+500*20. 参数过多不好训练,容易产生过拟合现象. 卷积神经网络,即CNN,它大大减少的网络参数的数目,通过1. 权值共享 2. 局部连接

DeepLearning tutorial(3)MLP多层感知机原理简介+代码详解

DeepLearning tutorial(3)MLP多层感知机原理简介+代码详解 @author:wepon @blog:http://blog.csdn.net/u012162613/article/details/43221829 本文介绍多层感知机算法,特别是详细解读其代码实现,基于python theano,代码来自:Multilayer Perceptron,如果你想详细了解多层感知机算法,可以参考:UFLDL教程,或者参考本文第一部分的算法简介. 经详细注释的代码:放在我的gith

记一下机器学习笔记 多层感知机的反向传播算法

<神经网络与机器学习>第4章前半段笔记以及其他地方看到的东西的混杂-第2.3章的内容比较古老预算先跳过. 不得不说幸亏反向传播的部分是<神机>里边人话比较多的部分,看的时候没有消化不良. 多层感知机 书里前三章的模型的局限都很明显,对于非线性可分问题苦手,甚至简单的异或都弄不了.于是多层感知机(也就是传说中的神经网络)就被发明了出来对付这个问题. 多层感知机就是由一系列的感知机,或者说神经元组成,每个神经元都接受若干的输入(树突)并产生一个输出(轴突). 这些神经元被分成若干层,每

基于theano的多层感知机的实现

1.引言 一个多层感知机(Multi-Layer Perceptron,MLP)可以看做是,在逻辑回归分类器的中间加了非线性转换的隐层,这种转换把数据映射到一个线性可分的空间.一个单隐层的MLP就可以达到全局最优. 2.模型 一个单隐层的MLP可以表示如下: 一个隐层的MLP是一个函数:$f:R^{D}\rightarrow R^{L}$,其中 $D$ 是输入向量 $x$ 的大小,$L$是输出向量 $f(x)$ 的大小: $f(x)=G(b^{(2)}+W^{(2)}(s(b^{(1)}+W^{

学习笔记TF026:多层感知机

隐含层,指除输入.输出层外,的中间层.输入.输出层对外可见.隐含层对外不可见.理论上,只要隐含层节点足够多,只有一个隐含层,神经网络可以拟合任意函数.隐含层越多,越容易拟合复杂函数.拟合复杂函数,所需隐含节点数,随隐含层数量增多指数下降. 过拟合,模型预测准确率在训练集上升,在测试集下降.泛化性不好,模型记忆当前数据特征,不具备推广能力.参数太多.Hinton教授团队,Dropout.随便丢弃部分输出数据节点.创造新随机样本,增大样本量,减少特征数量,防止过拟合.bagging方法,对特征新种采

多层感知机面临的问题

多层感知机 随着层数越多,所需的节点数目下降,但是随着层数的增多又会出现其他的问题: 过拟合 解决办法: DropOut 参数难以调试 尤其是梯度下降的参数使用Adagrad.Adam.Adadelta等自适应的方法可以降低调试参数的负担. 梯度弥散 使用Sigmoid在反向传播中梯度值会逐渐减少,经过多层的传递后会呈指数级的剧烈减少,因此梯度值在传递到前面几层时就变得非常小了这种情况下,根据训练数据的反馈来更新神经网络的参数将会非常缓慢 使用ReLU激活函数 特点: 单侧抑制性 相对宽阔的兴奋

MXNET:多层感知机

从零开始 前面了解了多层感知机的原理,我们来实现一个多层感知机. # -*- coding: utf-8 -*- from mxnet import init from mxnet import ndarray as nd from mxnet.gluon import loss as gloss import gb # 定义数据源 batch_size = 256 train_iter, test_iter = gb.load_data_fashion_mnist(batch_size) #

keras多层感知机MLP

肯定有人要说什么多层感知机,不就是几个隐藏层连接在一起的吗.话是这么说,但是我觉得我们首先要自己承认自己高级,不然怎么去说服(hu nong)别人呢 from keras.models import Sequential from keras.layers import Dense import numpy as np #设置随机种子,使得每次结果都是一致的 np.random.seed(7) import pandas as pd dataFrame = pd.read_csv("E:/数据集

动手深度学习10- pytorch多层感知机从零实现

多层感知机 定义模型的参数 定义激活函数 定义模型 定义损失函数 训练模型 小结 多层感知机 import torch import numpy as np import sys sys.path.append('..') import d2lzh_pytorch as d2l 我们仍然使用Fashion_MNIST数据集,使用多层感知机对图像进行分类 batch_size = 256 train_iter,test_iter = d2l.get_fahsion_mnist(batch_size

从头学pytorch(五) 多层感知机及其实现

多层感知机 上图所示的多层感知机中,输入和输出个数分别为4和3,中间的隐藏层中包含了5个隐藏单元(hidden unit).由于输入层不涉及计算,图3.3中的多层感知机的层数为2.由图3.3可见,隐藏层中的神经元和输入层中各个输入完全连接,输出层中的神经元和隐藏层中的各个神经元也完全连接.因此,多层感知机中的隐藏层和输出层都是全连接层. 具体来说,给定一个小批量样本\(\boldsymbol{X} \in \mathbb{R}^{n \times d}\),其批量大小为\(n\),输入个数为\(