11 从0开始学PyTorch | PyTorch使用nn模块、手工实现神经网络

news2024/12/25 9:33:16

上一小节对神经网络有了基本的了解,这一小节就看一下如何用代码来实现一个神经网络。
我们所用的案例还是那个温度转换的案例,只不过需要我们把之前的线性模型替换成神经网络模型,并重新训练以找到适合神经网络的权重。
依照我们的经验,前面有一些前置步骤,一部分大部分代码我们都学过了,包括了引用相关的包,设置notebook的显示规范,初始化数据,分割训练集和验证集以及对数据进行标准化。

使用nn模块

%matplotlib inline
import numpy as np
import torch
import torch.optim as optim

torch.set_printoptions(edgeitems=2, linewidth=75)

t_c = [0.5,  14.0, 15.0, 28.0, 11.0,  8.0,  3.0, -4.0,  6.0, 13.0, 21.0]
t_u = [35.7, 55.9, 58.2, 81.9, 56.3, 48.9, 33.9, 21.8, 48.4, 60.4, 68.4]
t_c = torch.tensor(t_c).unsqueeze(1) #这个地方跟之前有些区别,我们给数据进行了升维,目的是把数据转化成单个的样本,如果这里不太明白不要紧,后面会讲
t_u = torch.tensor(t_u).unsqueeze(1) 

t_u.shape
outs:
torch.Size([11, 1])

n_samples = t_u.shape[0]
n_val = int(0.2 * n_samples)

shuffled_indices = torch.randperm(n_samples)

train_indices = shuffled_indices[:-n_val]
val_indices = shuffled_indices[-n_val:]

train_indices, val_indices
outs:
(tensor([5, 6, 1, 4, 9, 0, 3, 2, 8]), tensor([ 7, 10]))
#训练集数据获取
t_u_train = t_u[train_indices]
t_c_train = t_c[train_indices]
#验证集数据获取
t_u_val = t_u[val_indices]
t_c_val = t_c[val_indices]

# 某种很简单的数据标准化
t_un_train = 0.1 * t_u_train
t_un_val = 0.1 * t_u_val

在PyTorch中,提供了一个torch.nn模块,里面提供了各种创建神经网络的功能。

#加载nn模块
import torch.nn as nn

linear_model = nn.Linear(1, 1) # 这里我们使用的仍然是nn模块里面的线性模型,传入的参数1,1分别为输入tensor的大小和输出tensor的大小,还有一个默认的参数‘带有偏置’
linear_model(t_un_val)#调用模型
outs:tensor([[2.4104],
        [5.8570]], grad_fn=<AddmmBackward0>)

这里用到的linear模型和我们以前自己构建的线性模型并没有什么区别,可以输出此时的权重和偏置看一下

linear_model.weight
Parameter containing:
tensor([[0.1007]], requires_grad=True)

linear_model.bias
Parameter containing:
tensor([-0.6234], requires_grad=True)

批量训练

前面我们看到了如何做好一个调包侠,使用nn模块里面的模型来进行训练。
如我们前面说的,我们可以以batch的形式来训练模型,PyTorch里的nn.Module及其子类也都设计好了,可以同时接收多个样本。批量输入样本有利于最大化利用计算资源。

在我们传入参数的时候,模块期望输入的第0维是每个批次的样本数量。

比如像下面这样

x = torch.ones(10, 1) #初始化10 * 1 tensor,表示10个样本,每个样本尺寸是1
linear_model(x)
outs:
tensor([[0.6814],
        [0.6814],
        [0.6814],
        [0.6814],
        [0.6814],
        [0.6814],
        [0.6814],
        [0.6814],
        [0.6814],
        [0.6814]], grad_fn=<AddmmBackward>)

从上面初始化的数据,我们从模型得到的结果都是一样的,如果像我们前面搞图像的输入时候,每个批次三张图像,那么我们初始化的数据应该就是一个3 * 3 * 256 * 256的tensor。

就像我们开头的代码里缩写的

t_c = torch.tensor(t_c).unsqueeze(1)

我们用了unsqueeze方法给数据进行升维,升维完成之后就成了一个11 * 1的tensor。
接下来我们继续构建训练步骤,加入优化器。

optimizer = optim.SGD(
    linear_model.parameters(), # 这里我们又省了一步,原来是自己攒了一个params,现在也不需要了,直接调用方法
    lr=1e-2)

list(linear_model.parameters()) #查看当前参数
outs:
[Parameter containing:
 tensor([[0.1007]], requires_grad=True), Parameter containing:
 tensor([-0.6234], requires_grad=True)]

写成一个完整的循环

#传入的参数:迭代次数,优化器,模型,损失函数,训练特征数据,验证特征数据,训练结果数据,验证结果数据
def training_loop(n_epochs, optimizer, model, loss_fn, t_u_train, t_u_val,
                  t_c_train, t_c_val): #这里注意,直接定义了一个model参数,把模型作为参数传入,因此我们可以替换不同的模型
    for epoch in range(1, n_epochs + 1):
        t_p_train = model(t_u_train)  #训练
        loss_train = loss_fn(t_p_train, t_c_train)

        t_p_val = model(t_u_val) #验证
        loss_val = loss_fn(t_p_val, t_c_val)
        
        optimizer.zero_grad() #梯度归零,防止上一轮迭代的梯度数据混入
        loss_train.backward() #反向传播
        optimizer.step() #优化器迭代参数

        if epoch == 1 or epoch % 1000 == 0: #第一轮训练或者每1000轮训练输出一次结果
            print(f"Epoch {epoch}, Training loss {loss_train.item():.4f},"
                  f" Validation loss {loss_val.item():.4f}")

接下来就开始训练了

def loss_fn(t_p, t_c):
    squared_diffs = (t_p - t_c)**2
    return squared_diffs.mean()

linear_model = nn.Linear(1, 1) 
optimizer = optim.SGD(linear_model.parameters(), lr=1e-2)

training_loop(
    n_epochs = 3000, 
    optimizer = optimizer,
    model = linear_model,
    loss_fn = loss_fn,
    t_u_train = t_un_train,
    t_u_val = t_un_val, 
    t_c_train = t_c_train,
    t_c_val = t_c_val)

print()
print(linear_model.weight)
print(linear_model.bias)

outs:
Epoch 1, Training loss 244.1249, Validation loss 78.6624
Epoch 1000, Training loss 4.5626, Validation loss 2.7117
Epoch 2000, Training loss 2.8499, Validation loss 3.3772
Epoch 3000, Training loss 2.7084, Validation loss 4.6429

Parameter containing:
tensor([[5.5946]], requires_grad=True)
Parameter containing:
tensor([-18.4819], requires_grad=True)

神经网络

看到这里,怎么搞来搞去还是一个线性模型,怎么还没有出现神经网络,到底在搞什么?快把它搞成一个神经网络!

要搞成神经网络,像我们前一节讲的,似乎已经很简单了,就是在线性单元的后面再叠加一个激活函数单元。PyTorch提供了一个nn.Sequential来连接模型,下面的代码中组合了三个单元,第一个线性单元输入tensor大小为1,输出tensor大小13,后面接一个tanh激活函数,然后再进入到一个新的线性单元,这个新单元的输入tensor大小为13,输出tensor大小为1。这里需要注意的一点是,后一个模块的输入大小必须与前一个模块的输出大小一致。

seq_model = nn.Sequential(
            nn.Linear(1, 13), 
            nn.Tanh(),
            nn.Linear(13, 1)) 
seq_model

对于Sequential也可以接收OrderedDict数据结构,从而让我们为每一个模块定义一个名字。

from collections import OrderedDict

seq_model = nn.Sequential(OrderedDict([
    ('hidden_linear', nn.Linear(1, 8)), #此时我们传入的格式是1*8
    ('hidden_activation', nn.Tanh()),
    ('output_linear', nn.Linear(8, 1))
]))

seq_model

outs:
Sequential(
  (hidden_linear): Linear(in_features=1, out_features=8, bias=True)
  (hidden_activation): Tanh()
  (output_linear): Linear(in_features=8, out_features=1, bias=True)
)

既然我们能够加入激活函数和输出层,我们就可以用我们搭建的这个超级mini神经网络来训练了。

optimizer = optim.SGD(seq_model.parameters(), lr=1e-3) 
training_loop(
    n_epochs = 5000, 
    optimizer = optimizer,
    model = seq_model,
    loss_fn = nn.MSELoss(), #这里直接调用了nn模块下面的损失函数,nn模块提供了很多常见的损失函数,不再需要手动编写
    t_u_train = t_un_train,
    t_u_val = t_un_val, 
    t_c_train = t_c_train,
    t_c_val = t_c_val)
    
print('output', seq_model(t_un_val))
print('answer', t_c_val)
print('hidden', seq_model.hidden_linear.weight.grad) #我们可以把我们前面定义的命名作为一个模块来访问

outs:
Epoch 1, Training loss 206.6782, Validation loss 66.7875
Epoch 1000, Training loss 4.4289, Validation loss 2.6821
Epoch 2000, Training loss 3.9474, Validation loss 6.9495
Epoch 3000, Training loss 2.5048, Validation loss 5.1201
Epoch 4000, Training loss 2.0997, Validation loss 4.5748
Epoch 5000, Training loss 1.9665, Validation loss 4.5594
output tensor([[-1.5225],
        [12.1985]], grad_fn=<AddmmBackward0>)
answer tensor([[-4.],
        [11.]])
hidden tensor([[ 5.4156e+00],
        [ 2.9012e-01],
        [ 2.4442e-01],
        [-6.7246e+00],
        [-6.8313e+00],
        [-1.9907e-03],
        [-6.1124e+00],
        [ 1.5848e-01]])

我们这就完成了用神经网络来训练,so easy ! 从上面输出的结果,我们可以看到,使用神经网络我们获取了更低的损失,训练了5000轮之后在训练集上的损失只有1.966,不过在测试集上看起来并没有太大的区别,这似乎有点像我们前面说的过拟合,不过还不严重,属于可以接受的范围。

最后画个图,看看神经网络模拟出来的结果有什么不同

from matplotlib import pyplot as plt

t_range = torch.arange(20., 90.).unsqueeze(1)

fig = plt.figure(dpi=600)
plt.xlabel("Fahrenheit")
plt.ylabel("Celsius")
plt.plot(t_u.numpy(), t_c.numpy(), 'o')
plt.plot(t_range.numpy(), seq_model(0.1 * t_range).detach().numpy(), 'c-')
plt.plot(t_u.numpy(), seq_model(0.1 * t_u).detach().numpy(), 'kx')

image.png

可以看到,比起之前的直线来说,我们这次获得了一条更加优雅的曲线,这个曲线对数据的拟合程度更好,当然,在这个例子中这并没有起到什么大的作用,因为我们摄氏和华氏温度的转换原本就是一条直线。

今天这节以代码为主,需要消化一下。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/715546.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PyTorch 神经网络模型可视化(Netron)

文章目录 PyTorch 神经网络模型可视化&#xff08;Netron&#xff09;ONNXtorch.savetorch.jit.scripttorch.jit.trace PyTorch 神经网络模型可视化&#xff08;Netron&#xff09; Netron 是一个用于可视化深度学习模型的工具&#xff0c;可以帮助我们更好地理解模型的结构和…

scanf大家都用过,但是scanf的多组输入!及scanf的两种输入方法你了解过嘛?看完这篇文章保证你彻底认识scanf!

☕ hello宝子们大家好啊 ,欢迎来到鸽芷咕的个人频道。 &#x1f3ac; 鸽芷咕&#xff1a; 个人主页 &#x1f525; 个人专栏: 《快速入门C语言》 《C语言初阶篇》 文章目录 前言&#x1f4ac; scanf( ) 函数的介绍&#x1f4ac; scanf( )的俩种用法&#x1f331;示例一:⛳️输入…

【备战秋招】每日一题:华东师范大学保研机试-2022-Minimum_Sum

为了更好的阅读体检&#xff0c;可以查看我的算法学习博客在线评测链接:P1053 题目内容 你有一个序列,,...,,然后给你一些区间[l,r].对于每一个区间,你需要找到下式的最小值,对于所有可能的x 输入格式 第一行一个整数代表序列长度。 接下来一行有N个正整数,用空格隔开。 …

Ansys Speos | 2023R2 新功能介绍

Speos 2023R2 新功能集中在优化、交互设计、GPU的更新&#xff0c;Speos将提供嵌入界面的优化工具&#xff0c;简化Speos和optiSLang的联合优化&#xff0c;交互式实时预览提供无限方案探索&#xff0c;Block Recording块记录更加整洁清晰&#xff0c;GPU对Rayfile光源的支持满…

第九届“互联网+”大赛产业赛道百度命题正式公布!57道命题,等你揭榜!

2023年6月28日&#xff0c;中国国际“互联网”大学生创新创业大赛组委会正式发布了《关于公布第九届中国国际“互联网”大学生创新创业大赛产业命题赛道入选命题的通知》&#xff0c;百度共有五十七道命题成功入围产业赛道&#xff0c;入围数居全国前列。 中国国际“互联网”大…

InsCode Stable Diffusion 美图活动投稿

本地部署可以使用B站大佬秋叶的整合包 CSDN亦提供了Stable Diffusion 模型在线使用地址&#xff1a;https://inscode.csdn.net/inscode/Stable-Diffusion 模型相关版本和参数配置&#xff1a; 模型&#xff1a;cetusversion4.WRgK.safetensors [b42b09ff12] VAE&#xff1a;y…

Vivado_Cordic IP核使用详解

本文介绍Vivado中CORDIC V6.0的使用方法。 参考资料&#xff1a;pg105 文章目录 IP核配置CORDIC算法Vector RotationPolar to Rectangular Vector translationSin and CosSinh and CoshArcTanArcTanhSquare Root IP核配置 Configuration Options选项卡 Configuration Paramet…

银河麒麟服务器v10 sp1 安装 redis

1、下载redis安装包 https://download.redis.io/releases/ 本文下载redis-7.0.11.tar.gz包&#xff0c;请按照自己需求下载相应文件。 2、将下载后的.tar.gz压缩包上传到到服务器自定义文件夹下 本人上传为系统的下载文件夹下&#xff0c;可以直接上传至指定目录下&#xff…

Linux发行版Gentoo被发现有漏洞,在SQL注入方面存在安全风险

近日有消息表明&#xff0c;Gentoo Linux发行版中存在漏洞CVE-2023-28424&#xff0c;并且极有可能被黑客利用该漏洞进行SQL注入攻击。 据悉&#xff0c;研究人员从 GentooLinux的Soko搜索组件中找到了这个漏洞&#xff0c;并且该漏洞的CVSS风险评分为 9.1&#xff0c;属于特别…

两数相加问题

给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff0c;这两个数都不会以 0 …

Linux 进程虚拟地址空间与虚拟内存

Linux 进程虚拟地址空间与虚拟内存 本文主要介绍Linux进程虚拟地址空间和虚拟内存的概念&#xff0c;学习可用物理内存中的页帧与所有的进程虚拟地址空间中的页之间的关联&#xff1a; 逆向映射&#xff08;reverse mapping&#xff09; 技术有助于从虚拟内存页追踪到对应的物…

ASS字幕 中的阴影 如何去除,三秒解决

有些外挂的ass字幕&#xff0c;总是自带一层浓浓的 阴影&#xff0c;看着就很不舒服&#xff0c;如下截图 解决方法&#xff1a; 鼠标右键&#xff0c;用记事本打开ass字幕文件&#xff0c;然后搜索关键字 ScaledBorderAndShadow&#xff0c;将其后面的 yes 改为 no&#xff0…

JSP在线小说系统用eclipse定制开发mysql数据库BS模式java编程jdbc

一、源码特点 JSP 在线小说系统是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,eclipse开发&#xff0c;数据库为Mysql5.0&#xff0c;使用ja…

C. Insert Zero and Invert Prefix - 构造+思维

分析&#xff1a; 数组b的最后一个元素永远不可能使1&#xff0c;因为即使在最后一个位置操作&#xff0c;也只会把前n-1个元素反转&#xff0c;最后一个元素只能为0.然后可以发现只要a[i]0就可以直接输出0&#xff0c;当a[i]1时一连串的1只需要最后一个1的位置改变成1的字串长…

微信小程序基础语法

微信小程序 文章目录 微信小程序[toc]一、初识微信小程序1.什么是微信小程序2.小程序可以做什么3.小程序与普通网页开发的区别 二、开发准备1.注册小程序开发账号2.安装开发者工具3.登陆我们的开发者工具 三、小程序构成1.小程序的基本组成结构2.小程序的页面组成结构3.小程序组…

OSI(开放系统互连参考模型)知识点详细介绍!!

开放系统互连参考模型分七层&#xff0c;从低到高是物理层&#xff0c;数据链路层&#xff0c;网络层&#xff0c;传输层&#xff0c;会话层&#xff0c;表示层和应用层 一.物理层&#xff08;Physical Layer&#xff09; 物理层位于 OSI/RM 参考模型的最底层&#xff0c;为数…

6.18、Java初级异常

1. 异常概述 1.1 什么是生活的异常 男主角小明每天开车上班&#xff0c;正常车程 1 小时。但是&#xff0c;可能会出现意外&#xff0c;出现意外&#xff0c;即为异常情况。我们会做相应的处理。如果不处理&#xff0c;到不了公司。 处理完了&#xff0c;就可以正常开车去公司…

浪涌保护器的标准和应用领域综合方案

浪涌保护器是一种用于防止电力系统或电子设备受到雷击或其他暂态过电压的损坏的装置。根据国家标准GB/T 18802.11-20201&#xff0c;低压电涌保护器 (SPD) 应符合IEC 61643-11:2011的性能要求和试验方法。浪涌保护器的产品参数包括&#xff1a;额定工作电压、最大连续工作电压、…

【kubernetes系列】kubernetes之kube-proxy的工作模式

概述 从kubernetes最早开始&#xff0c;kube-proxy到现在总共支持三种模式&#xff0c;在v1.8之前我们使用的是iptables 以及 userspace两种模式&#xff0c;iptables 模式从 v1.2 版本开始引入并作为kube-proxy 默认的操作模式。在kubernetes 1.8之后引入了ipvs模式&#xff…

!!!已解决: Linux操作系统登录,输入正确账号密码显示却显示:Sorry, that didn‘t work. Please try again.

&#xff01;&#xff01;&#xff01;已解决&#xff1a; Linux操作系统登录&#xff0c;明明输入密码正确却显示&#xff1a;Sorry, that didn’t work. Please try again. 先给大家复现一下我的问题&#xff1a; 为什么出现这个问题&#xff1f;&#xff1f;&#xff1f; …