# 【深度学习】:《PyTorch入门到项目实战》第六天:多层感知机(含代码)

简介: 上一章中介绍了如何使用softmax回归来进行多分类问题,对于一些基本线性模型基本介绍完毕,下面正式进入深度神经网络的学习。先介绍一个比较基础的模型,多层感知机,它是神经网络的最基础模型。首先我们来看看感知机
  • ✨本文收录于【深度学习】:《PyTorch入门到项目实战》专栏,此专栏主要记录如何使用PyTorch实现深度学习笔记,尽量坚持每周持续更新,欢迎大家订阅!
  • 🌸个人主页:JoJo的数据分析历险记
  • 📝个人介绍:小编大四统计在读,目前保研到统计学top3高校继续攻读统计研究生
  • 💌如果文章对你有帮助,欢迎✌关注、👍点赞、✌收藏、👍订阅专栏

参考资料:本专栏主要以沐神《动手学深度学习》为学习资料,记录自己的学习笔记,能力有限,如有错误,欢迎大家指正。同时沐神上传了的教学视频和教材,大家可以前往学习。

请添加图片描述

写在前面

上一章中介绍了如何使用softmax回归来进行多分类问题,对于一些基本线性模型基本介绍完毕,下面正式进入深度神经网络的学习。先介绍一个比较基础的模型,多层感知机,它是神经网络的最基础模型。首先我们来看看感知机✍ # 🍓1.感知机 感知机是一个非常简单的处理二分类的模型,首先我们来看看一个简单的例子 对于给定输入$x$,权重$w$,和偏移$b$,感知机输出结果为: $$ f(x) = \begin{cases}1,\quad wx+b>0 \\-1,\quad wx+b<0 \end{cases} $$ 从这个可以看出如果$y_i(wx_i+b)>0$,则分类正确,否则分类错误。因此感知机训练过程为: $$ if\quad y_i(wx_i+b)\leq 0\\ w := w+y_ix_i\\ b := b+y_i $$ 其中等价于一个梯度下降,其中损失函数为: $$ L=max[0,-y(wx+b)] $$ 因此感知机的基本思想是找到一个超平面来将两个类别分隔开来,如下图所示 ```python # 导入相关库 import torch from torch import nn import matplotlib.pyplot as plt import seaborn as sns from torchvision import datasets,transforms from torch.utils import data %matplotlib inline ``` ```python # 创建x,y x = torch.tensor([[0.5,0.25],[0.2,0.5],[0.3,1.1],[0.4,1.1]]) y = torch.tensor([1,1,0,0]) sns.set(style="white") sns.relplot(x[:,0],x[:,1],hue=y) plt.plot([0,1],[1,0],'r') ``` ​ ![png](https://ucc.alicdn.com/images/user-upload-01/img_convert/0870b50e0bd32125ed900fa0466b45af.png#pic_center) ​ 上面给出的平面将0,1两类完全分隔开来。但是感知机有一个问题是,解决不了`异或问题(XOR)`,下面我们来介绍一下异或问题 # 🍅2.异或问题 异或问题,当两个相同时,返回正类,不同时,返回负类,具体如下所示 ```python # 创建x,y x = torch.tensor([[1,1],[-1,1],[-1,-1],[1,-1]]) y = torch.tensor([1,0,1,0]) sns.set(style="white") sns.relplot(x[:,0],x[:,1],hue=y) ``` ![请添加图片描述](https://ucc.alicdn.com/images/user-upload-01/a0892745392446028cf9240de0b3fbd6.png#pic_center) ​ 可以看出,在这种情况下,无论如何我们没办法找到一个超平面将其分开,这是一组线性不可分的数据,在这种情况下,==感知机解决不了异或问题==,因此,神经网络的研究暂缓发展。多年之后,提出了多层感知机,自此开起了神经网络的新发展 # 🍒3多层感知机 多层感知机通过在网络中==加入一个或多个隐藏层==来克服线性模型的限制,是一个简单的神经网络,也是深度学习的重要基础,具体如下图所示 ![image-20220522173029007](https://ucc.alicdn.com/images/user-upload-01/img_convert/6f59b2537b5e11e57659f4e65337ffce.png#pic_center) 这是一个具有一个隐藏层的多层感知机,其中输入有4个特征,输出有三个特征,隐藏层有五个隐藏单元,每一层的权重和偏差维度如下: $$ W^{[1]}_{5\times 4}, b^{[1]}_{5\times 1}\\ W^{[2]}_{3\times 5}, b^{[2]}_{3\times 1}\\ ...\\ W^{[l]}_{n_{l+1}\times n_{l}}, b^{[l]}_{n_{l+1}} $$ 其中,$n_l$表示第n层神经元的数量。具体计算过程如下: $$ Z^{[1]} = W^{[1]}X+b^{[1]}\\ A^{[1]} = \sigma(Z^{[1]})\\ Z^{[2]} = W^{[2]}A^{[2]} + b^{[2]}\\ A^{[2]} = \sigma(Z^{[1]}) $$ 其中$\sigma()$表示激活函数 ==每一层的输出是下一个层的输入,直到生成最后的输出== # 🍑4. 激活函数 如果只是做线性计算的话,那可以转换成一个没有隐藏层的神经网络,因此需要引入激活函数,注意:激活函数必须是非线性的。将激活函数的输出来作为下一层的输入。常用的激活函数可以分为以下几类: - sigmoid: $$ y = \frac{1}{1+e^{-z}} $$ - tanh $$ \operatorname{tanh}(x) = \frac{1 - \exp(-2x)}{1 + \exp(-2x)} $$ - Relu $$ y = max(0,x) $$ ## 🍐4.1 sigmoid函数 在`logistic回归`中,我们就运用了`sigmoid函数`,它能够将输入转换到`0-1`之间,呈现出S曲线。在处理二分类问题时,==可以考虑使用sigmoid函数用于输出层。== 具体图形如下 ```python # sigmoid 函数 x = torch.arange(-8.0, 8.0, 0.01, requires_grad=True) y = torch.sigmoid(x) plt.ylabel("y = sigmoid(X)")#y标签 plt.grid(True)#显示网格 plt.plot(x.detach(), y.detach()) ``` ​ ![png](https://ucc.alicdn.com/images/user-upload-01/img_convert/c8bed6d78025e3205ffae8eb519bea5a.png#pic_center) ​ 可以看出,当接近0时,变化最大,说明此时导数值最大,对`sigmoid函数`求导,可得它的导数图如下: ```python y.backward(torch.ones_like(x),retain_graph=True) plt.plot(x.detach(), x.grad) ``` ​ ![png](https://ucc.alicdn.com/images/user-upload-01/img_convert/b36e68897ce9e9af7bb0fc0910e10bf4.png#pic_center) ​ ## 🍏4.2 Relu激活函数 最受欢迎的激活函数是修正线性单元(Rectified linear unit,ReLU), 因为它实现简单,同时在各种预测任务中表现良好。 ReLU提供了一种非常简单的非线性变换。 给定元素\(x\),ReLU函数被定义为该元素与\(0\)的最大值。==因此往往在隐藏层中,我们使用Relu激活函数==。其图形如下 ```python x = torch.arange(-8.0, 8.0, 0.1, requires_grad=True) y = torch.relu(x) plt.ylabel("y = Relu(X)")#y标签 plt.grid(True)#显示网格 plt.plot(x.detach(), y.detach()) ``` ​ ![png](https://ucc.alicdn.com/images/user-upload-01/img_convert/e36bed094e1a3d8ef6820e7155acf549.png#pic_center) ​ 可以看出,当输入值为负数,其导数为0,输入值为正时,其导数为1,虽然在0处不可导,但是这种情况一般不会出现,因为输入往往不会为0,下面我们绘制Relu函数的导数 ```python y.backward(torch.ones_like(x),retain_graph=True) plt.plot(x.detach(), x.grad) ``` ​ ![png](https://ucc.alicdn.com/images/user-upload-01/img_convert/d780c18ceb30dfabd55d900e7f5b2146.png#pic_center) ​ 使用ReLU的原因是,它求导表现得特别好:要么让参数消失,要么让参数通过。 这使得优化表现得更好,==并且ReLU减轻了困扰以往神经网络的梯度消失问题==,当然还有一些Relu函数的变形 ## 🍎4.3 tanh函数 `tanh函数`与`sigmoid函数`类似,将输入压缩到`(-1,1)`之间。其图形如下 ```python # tanh(x) y = torch.tanh(x) plt.ylabel('y=tanh(x)') plt.grid(True) plt.plot(x.detach(), y.detach()) ``` ​ ![png](https://ucc.alicdn.com/images/user-upload-01/img_convert/f01445de969ab0d8ee782c2b66d0f6a1.png#pic_center) ​ 可以看出图形结果和`sigmoid函数`形状基本一致,唯一有区别的是`tanh`是关于原点对称的,下面对其进行求导,得到以下结果 ```python # 清除以前的梯度 y.backward(torch.ones_like(x),retain_graph=True) plt.plot(x.detach(), x.grad) plt.grid(True) ``` ​ ![png](https://ucc.alicdn.com/images/user-upload-01/img_convert/610fe463d92b420bd199199985e18234.png#pic_center) ​ 求导的结果也和sigmoid函数结果类似。 # 🥭5.模型训练 - **数据集导入** ```python trans = transforms.ToTensor() train = datasets.MNIST(root='./data',download=True,train=True,transform=trans) test = datasets.MNIST(root='./data',download=True,train=False,transform=trans) # 分批次加载数据集 batch_size = 64 df_train = data.DataLoader(train, batch_size, shuffle=True, ) df_test = data.DataLoader(test, batch_size, shuffle=True, ) X, y = next(iter(df_train)) ``` - **参数初始化** ```python num_in,num_out, num_hid = 784,10,64 W1 = nn.Parameter( torch.randn(num_in,num_hid,requires_grad=True)) b1 = nn.Parameter( torch.zeros(num_hid,requires_grad = True)) W2 = nn.Parameter(torch.randn(num_hid,num_out,requires_grad=True)) b2 = nn.Parameter( torch.zeros(num_out)) params = [W1,b1,W2,b2] ``` - **定义使用的激活函数** ```python def relu(X): a = torch.zeros_like(X) return torch.max(X, a) ``` - **计算模型** ```python def net(X): X = X.reshape((-1, num_in)) H = relu(X@W1 + b1) # 这里“@”代表矩阵乘法 return (H@W2 + b2) ``` - **损失函数** ```python loss = nn.CrossEntropyLoss(reduction='none') ``` ```python # SGD优化器 optimizer = torch.optim.SGD(params=params, lr=1) ``` - **模型训练** ```python for epoch in range(1000): optimizer.zero_grad() hypothesis = net(X) cost = loss(hypothesis, y) cost.mean().backward() optimizer.step() if epoch % 100 == 0: print(epoch, cost.mean().item()) ``` 0 79.99055480957031 100 0.4515937864780426 200 0.30940207839012146 300 0.25154954195022583 400 0.2046610414981842 500 0.18980586528778076 600 0.1860966980457306 700 0.1445973813533783 800 0.13446013629436493 900 0.09926929324865341 # 🍍6.简洁代码实现 ```python ''' 定义模型 ''' net = nn.Sequential(nn.Flatten(), nn.Linear(784, 64), nn.ReLU(), nn.Linear(64, 10)) ''' 初始化权重 ''' def init_weights(m): if type(m) == nn.Linear: nn.init.normal_(m.weight, std=0.01) net.apply(init_weights) ''' 损失函数 ''' loss = nn.CrossEntropyLoss() ''' SGD优化器 ''' trainer = torch.optim.SGD(net.parameters(), lr=0.1) ''' 模型训练 ''' for epoch in range(1000): trainer.zero_grad() hypothesis = net(X) cost = loss(hypothesis, y) cost.backward() trainer.step() if epoch % 100 == 0: print(epoch, cost.item()) ``` 0 2.2971670627593994 100 0.5922114849090576 200 0.07867014408111572 300 0.028783854097127914 400 0.016159456223249435 500 0.010870776139199734 600 0.008055186830461025 700 0.006334712728857994 800 0.0051856981590390205 900 0.004369326401501894 本章的介绍到此介绍,如果文章对你有帮助,请多多点赞、收藏、评论、关注支持!!
相关文章
|
1月前
|
机器学习/深度学习 人工智能 PyTorch
PyTorch深度学习 ? 带你从入门到精通!!!
🌟 蒋星熠Jaxonic,深度学习探索者。三年深耕PyTorch,从基础到部署,分享模型构建、GPU加速、TorchScript优化及PyTorch 2.0新特性,助力AI开发者高效进阶。
PyTorch深度学习 ? 带你从入门到精通!!!
|
4月前
|
机器学习/深度学习 算法 定位技术
Baumer工业相机堡盟工业相机如何通过YoloV8深度学习模型实现裂缝的检测识别(C#代码UI界面版)
本项目基于YOLOv8模型与C#界面,结合Baumer工业相机,实现裂缝的高效检测识别。支持图像、视频及摄像头输入,具备高精度与实时性,适用于桥梁、路面、隧道等多种工业场景。
517 27
|
6月前
|
机器学习/深度学习 PyTorch API
PyTorch量化感知训练技术:模型压缩与高精度边缘部署实践
本文深入探讨神经网络模型量化技术,重点讲解训练后量化(PTQ)与量化感知训练(QAT)两种主流方法。PTQ通过校准数据集确定量化参数,快速实现模型压缩,但精度损失较大;QAT在训练中引入伪量化操作,使模型适应低精度环境,显著提升量化后性能。文章结合PyTorch实现细节,介绍Eager模式、FX图模式及PyTorch 2导出量化等工具,并分享大语言模型Int4/Int8混合精度实践。最后总结量化最佳策略,包括逐通道量化、混合精度设置及目标硬件适配,助力高效部署深度学习模型。
957 21
PyTorch量化感知训练技术:模型压缩与高精度边缘部署实践
|
2月前
|
机器学习/深度学习 存储 PyTorch
Neural ODE原理与PyTorch实现:深度学习模型的自适应深度调节
Neural ODE将神经网络与微分方程结合,用连续思维建模数据演化,突破传统离散层的限制,实现自适应深度与高效连续学习。
145 3
Neural ODE原理与PyTorch实现:深度学习模型的自适应深度调节
|
8月前
|
机器学习/深度学习 JavaScript PyTorch
9个主流GAN损失函数的数学原理和Pytorch代码实现:从经典模型到现代变体
生成对抗网络(GAN)的训练效果高度依赖于损失函数的选择。本文介绍了经典GAN损失函数理论,并用PyTorch实现多种变体,包括原始GAN、LS-GAN、WGAN及WGAN-GP等。通过分析其原理与优劣,如LS-GAN提升训练稳定性、WGAN-GP改善图像质量,展示了不同场景下损失函数的设计思路。代码实现覆盖生成器与判别器的核心逻辑,为实际应用提供了重要参考。未来可探索组合优化与自适应设计以提升性能。
676 7
9个主流GAN损失函数的数学原理和Pytorch代码实现:从经典模型到现代变体
|
3月前
|
PyTorch 算法框架/工具 异构计算
PyTorch 2.0性能优化实战:4种常见代码错误严重拖慢模型
我们将深入探讨图中断(graph breaks)和多图问题对性能的负面影响,并分析PyTorch模型开发中应当避免的常见错误模式。
246 9
|
2月前
|
机器学习/深度学习 数据采集 编解码
基于深度学习分类的时相关MIMO信道的递归CSI量化(Matlab代码实现)
基于深度学习分类的时相关MIMO信道的递归CSI量化(Matlab代码实现)
130 1
|
2月前
|
机器学习/深度学习 算法 vr&ar
【深度学习】基于最小误差法的胸片分割系统(Matlab代码实现)
【深度学习】基于最小误差法的胸片分割系统(Matlab代码实现)
|
5月前
|
机器学习/深度学习 存储 PyTorch
PyTorch + MLFlow 实战:从零构建可追踪的深度学习模型训练系统
本文通过使用 Kaggle 数据集训练情感分析模型的实例,详细演示了如何将 PyTorch 与 MLFlow 进行深度集成,实现完整的实验跟踪、模型记录和结果可复现性管理。文章将系统性地介绍训练代码的核心组件,展示指标和工件的记录方法,并提供 MLFlow UI 的详细界面截图。
252 2
PyTorch + MLFlow 实战:从零构建可追踪的深度学习模型训练系统
|
4月前
|
机器学习/深度学习 数据可视化 PyTorch
Flow Matching生成模型:从理论基础到Pytorch代码实现
本文将系统阐述Flow Matching的完整实现过程,包括数学理论推导、模型架构设计、训练流程构建以及速度场学习等关键组件。通过本文的学习,读者将掌握Flow Matching的核心原理,获得一个完整的PyTorch实现,并对生成模型在噪声调度和分数函数之外的发展方向有更深入的理解。
1807 0
Flow Matching生成模型:从理论基础到Pytorch代码实现

热门文章

最新文章

推荐镜像

更多