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

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

使用nn模块

%matplotlib inline
import numpy as np
import torch
import torch.optim as optimtorch.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 nnlinear_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)**2return 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.6429Parameter 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 OrderedDictseq_model = nn.Sequential(OrderedDict([('hidden_linear', nn.Linear(1, 8)), #此时我们传入的格式是1*8('hidden_activation', nn.Tanh()),('output_linear', nn.Linear(8, 1))
]))seq_modelouts:
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 pltt_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.hqwc.cn/news/8648.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JMeter 后置处理器之JSON提取器

目录 前言&#xff1a; 测试环境 插件介绍 插件参数 插件使用示例 JSON-PATH表达式介绍 操作符 函数 过滤器操作符 JSON PATH示例 前言&#xff1a; JMeter是一个功能强大的性能测试工具&#xff0c;它提供了许多后置处理器来处理和提取测试结果。其中一个常用的后…

六大设计模式原则

1 单一职责原则 &#xff08;Single Responsibility Principle, SRP&#xff09;&#xff0c;有且仅有一个原因引起类的变更 顾名思义&#xff1a;一个类只负责一项职责 基本介绍 即对类来说&#xff0c;一个类应该只负责一项职责。如类 A 负责两个不同职责&#xff1a;职责 …

SpringBoot 整合Redis 实战篇

一、解决数据乱码问题&#x1f349; 在上篇文章中我们整合了redis&#xff0c;当我们存入一个对象时会发现redis中的数据存在乱码问题&#xff0c;这是jdk编码的问题 springboot整合redis时提供了两个模板工具类&#xff0c;StringRedisTemplate和RedisTemplate. 1.使用Red…

动态规划—兑换零钱(一)解析+代码

兑换零钱&#xff08;一&#xff09; 题目链接&#xff1a;兑换零钱&#xff08;一&#xff09; 题目描述&#xff1a; 题目既要求要刚好组成该钱数&#xff0c;又要求是组成该钱数的最少货币数。 面对不同面额的零钱&#xff0c;我们无法直接确定其所需数量&#xff0c;也不…

白盒测试扫盲

目录 前言&#xff1a; 什么是白盒测试 白盒测试中验证什么 如何执行白盒测试 步骤1&#xff1a;理解源代码 步骤2&#xff1a;创建测试用例并执行 白盒测试示例 白盒测试技术 白盒测试的类型 单元测试 测试内存泄漏 其他 白盒测试的优势 白盒测试的缺点 结束语…

Matlab把两个不同的x轴和y轴画在同一个图里

我们知道画两个y轴可以用yyaxis. 那么画两个x轴呢? 这时候可以用神奇的tiledlayout. % 创建两组数据 x1 0:0.1:40; y1 4.*cos(x1)./(x12); x2 1:0.2:20; y2 x2.^2./x2.^3;t tiledlayout(1,1); % 创建一个tiledlayout % 第一个坐标系 ax1 axes(t); % 创建坐标系, 指定t为…

网络安全之反序列化漏洞分析

简介 FastJson 是 alibaba 的一款开源 JSON 解析库&#xff0c;可用于将 Java 对象转换为其 JSON 表示形式&#xff0c;也可以用于将 JSON 字符串转换为等效的 Java 对象分别通过toJSONString和parseObject/parse来实现序列化和反序列化。 使用 对于序列化的方法toJSONStrin…

Tomcat 部署优化

目录 一.Tomcat介绍 二.了解Tomcat里面里面是放什么的 三. Tomcat&#xff1a;是一个特殊的服务 有两个领域 四.tomcat概述 五.再加上那个扩展java虚拟机&#xff08;JVM&#xff09; 调优 tomcat 优化分两种 六.Tomcat核心组件 ​编辑 容器&#xff1a;什么是容器 …

C/C++内存管理详解

去年的今日&#xff0c;博主第一次发文&#xff0c;那时初出茅庐&#xff0c;没什么经验。时隔一年&#xff0c;更加优质的博文献上&#xff0c;希望可以帮助到更多的人❤️❤️❤️ 文章目录 &#x1f4ac; 前言一、C/C内存分布二、C语言中动态内存管理方式三、C内存管理方式1…

密码学—Vigenere破解Python程序

文章目录 概要预备知识点学习整体流程技术名词解释技术细节小结代码 概要 破解Vigenere需要Kasiski测试法与重合指数法的理论基础 具体知识点细节看下面这两篇文章 预备知识点学习 下面两个是结合起来使用猜测密钥长度的&#xff0c;只有确认了密钥长度之后才可以进行破解。 …

旅游卡app软件开发解决方案

旅游业的不断发展&#xff0c;旅游卡作为一种便捷的旅游方式越来越受到人们的青睐。旅游卡可以帮助游客节省旅游开支&#xff0c;同时也能让游客更好地规划自己的旅游行程。针对这种情况&#xff0c;开发一款旅游卡app软件是非常必要的。本文将介绍旅游卡app软件开发的解决方案…

基于高校图书馆的用户画像、可视化、模型预测、推荐算法项目实现

需要本项目的可以私信博主获取源码及项目&#xff01;&#xff01;&#xff01; 本研究基于高校图书馆的借阅信息、馆藏图书信息、读者入馆信息、用户信息等多维度的数据表&#xff0c;首先将不同年份的数据拼接在一起&#xff0c;按照时间维度进行整合&#xff0c;并保证数据…