1.4学习日志

本文介绍了多层感知机的概念,与感知机和Softmax回归的区别,强调了激活函数如sigmoid、Tanh和ReLU的重要性。讨论了模型的训练过程,包括参数初始化、隐藏层和多层结构的影响,以及如何通过超参数调整提高模型性能。还提供了从零开始实现多层感知机的示例,包括简洁版本的代码。
摘要由CSDN通过智能技术生成

12多层感知机

1.感知机

同线性回归的区别是,线性回归输出为实数,这里输出离散的类

同Softmax回归区别是,输出Softmax是个多分类,可以多个输出,这里是二分类模型

如果y[<w,x>+b]<=0,表示分类错误,因此需要对w,b进行更新直到当前的w,b保证所有样本分类正确,才停止对参数的更新。

等价于使用批量大小为1的梯度下降意思就是每次拿一个样本来算梯度。

max(0,-y<w,x>),max和0是对应上面的if语句,如果分类正确,那么y<w,x>为正,-y<w,x>为负,max=0,梯度(导数)为常数,不去做更新;如果分类错误,那么y<w,x>为负,-y<w,x>为正,max=-y<w,x>,这时候就有梯度(导数)了,就去更新。


理解下来:原本一只狗一只猫的分类权重是红线,又来一只狗之后,需要对权重进行更新,然后下移成黑线,保证分类的正确性,再次增加样本同理

收敛定理:

 中间的绿色区域就是分类余量分界面ρ,分界面ρ满足w^2+b^2<=1,保证收敛的意思就是保证找到最优解

感知机存在的问题

感知机不能拟合XOR函数,原因是感知机只能产生一条分界线,无法将两者分隔开

 2.多层感知机

解决XOR问题 :

先分出一个类,再分出另一个类 ,两个综合判断出结果

隐藏层

h是隐藏层对于输入层作为输出,o是输出层对于隐藏层作为输出,如果缺少非线性的激活函数σ,可以得到以下等价替换,最后输入层和输出层的结果仍是线性关系,失去了多层感知机的作用

激活函数

1.sigmoid激活函数

sigmoid是一个soft版本的激活函数, 这样就不会出现在0处难以求导的问题

 2.Tanh激活函数

将输入投影到(-1,1)

3.ReLU激活函数(用的最多)

实质就是ReLU(x)=max(x,0)

多类分类

多类分类相较于Softmax()只是加了一层隐藏层

有k个输出单元,w2是m*k的张量

多隐藏层

多层感知机的隐藏层大小(即每个隐藏层中的神经元数量)是一个超参数,可以根据具体任务和数据的特点进行选择。

  1. 模型复杂性: 较大的隐藏层大小可以使模型具有更强的表示能力,但也可能增加过拟合的风险。选择一个适度的隐藏层大小,以平衡模型的复杂性和泛化能力。

  2. 数据规模: 对于较大的数据集,通常可以使用更大的隐藏层,因为模型有更多的信息来学习。对于较小的数据集,可能需要选择相对较小的隐藏层以避免过拟合。

  3. 任务复杂性: 复杂的任务可能需要更大的隐藏层来捕捉数据中的更多复杂模式。简单的任务可能只需要较小的隐藏层。

  4. 超参数调优: 可以通过使用交叉验证或验证集来调整隐藏层大小。尝试不同的大小并评估它们在验证集上的性能,以找到最佳配置。

 

3.多层感知机从零开始实现 

参数的初始化

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

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

num_inputs,num_outputs,num_hiddens = 784,10,256
#通常指定隐藏层的宽度为2的次幂,计算上会高效

W1 = nn.Parameter(torch.randn(num_inputs,num_hiddens,requires_grad=True)*0.01)
#* 0.01: 将随机初始化的张量的所有元素乘以 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]

权重张量大小就是和当前“输入”和“输出”相关,偏差张量大小只和当前“输出”相关 

为什么w权重需要随机生成?

如果隐藏层的权重矩阵中所有的权重都初始化为相同的值,那么每个隐藏单元将计算出相同的输出。在进行反向传播时,所有权重都会受到相同的梯度更新,导致权重在训练过程中保持对称,这可能阻碍模型的学习能力。通过使用随机初始化,我们可以破坏对称性,使每个隐藏单元计算出不同的输出,从而促使模型学习更丰富的特征表示。

为什么偏差b不用随机生成?

偏置(bias)的初始化通常可以选择为零,因为偏置的主要作用是对输入数据引入一个平移(平移变换),使得模型更灵活地适应数据。将偏置初始化为零是一种常见的做法,这样可以使模型在初始阶段更容易拟合训练数据。

实现ReLU激活函数 

def relu(X):
    a = torch.zeros_like(X)
    return torch.max(X,a)
#a是一个同X相同矩阵大小全为零的矩阵

实现模型

def net(X):
    X = X.reshape(-1,num_inputs)#因为需要忽略空间结构,将二维图像转换为一个长度为num_inputs的向量
    H = relu(X@W1 + b1)
    return(H@W2 + b2)

损失函数

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.plt.show()

 

对比下来,多层感知机模型更大数据拟合性更好,损失相较于softmax有一些下降,精确度没有发生较大改变

同时可以在一些测试数据上应用这个模型

d2l.predict_ch3(net,test_iter)
d2l.plt.show()

4.多层感知机的简洁实现

import torch
from torch import nn
from d2l import torch as d2l
'''模型建立'''
net = nn.Sequential(nn.Flatten(),
                    nn.Linear(784,256),
                    nn.ReLU(),
                    nn.Linear(256,10))
#两个全连接层(线性层),第一个是隐藏层,第二个是输出层

def init_weights(m):
    if type(m)==nn.Linear:
        nn.init.normal_(m.weight,std=0.01)
        #正态分布进行权重初始化,均值为 0,标准差为 0.01

net.apply(init_weights)
#调用 apply 方法,将 init_weights 函数应用于神经网络模型 net 中的每个模块,模型中所有线性层的权重都会被初始化。

'''训练过程'''
batch_size,lr,num_epochs = 256,0.1,10
loss = nn.CrossEntropyLoss()
trainer = torch.optim.SGD(net.parameters(),lr=lr)
# 创建了一个随机梯度下降(SGD)优化器,用于更新模型参数,net.parameters()返回模型中所有可优化参数

train_iter,test_iter = d2l.load_data_fashion_mnist(batch_size)
d2l.train_ch3(net,train_iter,test_iter,loss,num_epochs,trainer)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值