莫烦pytorch 关系拟合(回归)

思路:首先建立一个数据集用来拟合函数,要拟合函数我们就需要建立一个神经网络,建立好神经网络后,我们再通过训练网络来减小神经网络拟合函数的误差,最后再可视化拟合过程。

建立数据集
我们创建一个一元二次函数:y=a*x^2 + b, 我们给y数据加上一点噪声来更加真实的展示它。

import torch
import matplotlib.pyplot as plt #可视化函数库

x = torch.unsqueeze(torch.linspace(-1,1,100), dim=1)
y = x.pow(2) + 0.2*torch.rand(x.size())

plt.scatter(x.data.numpy(), y.data.numpy())
plt.show()

函数剖析:

torch.linspace(start, end, steps=100, out=None) → Tensor

返回start和end之间长度为steps的一维张量 参数:
#start(float) — 点集的起始值
#end(float) — 点集的最终值
#steps(int) — 在start和end间的采样数,即返回多少个数
#out(Tensor, 可选的) — 结果张量

torch.squeeze(input, dim=None, out=None)

将输入张量形状中的1去除并返回。如果输入是形如((A \times 1\times B \times 1 \times C \times 1 \times D) ),那么输出形状就为: ((A \times B \times C \times D) )

当给定dim时,那么挤压操作只在给定维度上。例如,输入形状为:((A \times 1 \times B) ),squeeze(input, 0)将会保持张量不变,只有用squeeze(input, 1),形状会变成((A \times B))。
注意:返回张量与输入张量共享内存,所以改变其中一个的内容会改变另一个。

参数:
#input(Tensor) — 输入张量
#dim(int, 可选的) — 如果给定,则input只会在给定维度挤压
#out(Tensor, 可选的) — 输出张量

torch.unsqueeze(input, dim, out=None)

返回一个新的张量,对输入的制定位置插入维度1
注意:返回张量与输入张量共享内存,所以改变其中一个的内容会改变另一个。
如果dim为负,则将会被转化( dim+input.dim()+1 )
参数:
tensor(Tensor) — 输入张量
dim(int) — 插入维度的索引
out(Tensor, 可选的) — 结果张量

>>> x = torch.Tensor([1, 2, 3, 4])
>>> torch.unsqueeze(x, 0)
 1  2  3  4
[torch.FloatTensor of size 1x4]
>>> torch.unsqueeze(x, 1)
 1
 2
 3
 4
[torch.FloatTensor of size 4x1]
torch.rand(x.size())
>>> torch.unsqueeze(x,1)
tensor([[[[[[0., 0.],
            [0., 0.]]]]],




        [[[[[0., 0.],
            [0., 0.]]]]]])
>>> x.size()
torch.Size([2, 1, 1, 2, 2])
>>> torch.rand(x.size())
tensor([[[[[0.5035, 0.9477],
           [0.2464, 0.4020]]]],



        [[[[0.3719, 0.5475],
           [0.8418, 0.4617]]]]])

建立神经网络

我们先定义所有层的属性(__ init__()),然后再一层层搭建(forward(x))层与层的关系链接。

import torch
import torch.nn.functional as F #激励函数在此库

class Net(torch.nn.Module): 
	def __init__(self, n_feature, n_hidden, n_output):
		super(Net, self).__init__() #继承__init__功能
		self.hidden = torch.nn.Linear(n_feature, n_hidden)
		self.predict = torch.nn.Linear(n_hidden, n_output)
	def forward(self, x):
		x = F.relu(self.hidden(x))
		x = self.predict(x)
		return x
net = Net(n_feature=1, n_hidden=10, n_output=1)
print(net)

输出:

Net (
  (hidden): Linear (1 -> 10)
  (predict): Linear (10 -> 1)
)

class torch.nn.Module
所有神经网络模块的基类。
Modules还可以包含其他模块,允许将它们嵌套在树结构中。

训练网络

#optimizer是训练的工具
optimiizer = torch.optim.SGD(net.parameters(), lr=0.2) #传入net的所有参数,学习率
loss_func = torch.nn.MSELoss() #预测值和真实值的误差计算公式(均方差)

for i in range(100):
	prediction = net(x) #喂数据
	loss = loss_func(prediction, y) #计算预测值与真实值误差
	optimizer.zero_grad() #清空上一步的残余更新参数值
	loss.backward() #误差反向传播,计算参数更新值
	optimizer.step() #将参数更新值施加到net 的 parameters上

如何使用optimizer
要使用torch.optim,你必须构造一个optimizer对象。这个对象能保存当前的参数状态并且基于计算梯度更新参数
构建
要构造一个Optimizer,你必须给它一个包含参数(必须都是Variable对象)进行优化。然后,您可以指定optimizer的参 数选项,比如学习率,权重衰减等。
例子:

optimizer = optim.SGD(model.parameters(), lr=0.02,momentum=0.9)
optimizer = optim.Adam([var1, var2], lr=0.0001)

当我们想指定每一层的学习率时,这是非常有用的:

optim.SGD([
            {'params': model.base.parameters()},
            {'params': model.classifier.parameters(), 'lr': 1e-3}
            ], lr=1e-2, momentum=0.9)

这意味着model.base参数将使用默认的学习速率1e-2,model.classifier参数将使用学习速率1e-3,并且0.9的momentum将会被用于所有的参数。

进行单次优化

optimizer.step()

这是大多数optimizer所支持的简化版本。一旦梯度被如backward()之类的函数计算好后,我们就可以调用该函数。

for input, target in dataset:
    optimizer.zero_grad()
    output = model(input)
    loss = loss_fn(output, target)
    loss.backward()
    optimizer.step()

optimizer.step(closure)
一些优化算法例如Conjugate Gradient和LBFGS需要重复多次计算函数,因此你需要传入一个闭包去允许它们重新计算你的模型。这个闭包会清空梯度,计算损失,然后返回。

for input, target in dataset:
	def closure():
		optimizer.zero_grad()
		output = model(input)
		loss = loss_func(output, target)
		loss.backward()
		return loss
	optimizer.step(closure)

可视化训练过程

import matplotlib.pyplot as plt

plt.ion() #打开交互模式
plt.show()

for t in range(200):
	...
	loss.backward()
	optimizer.step()

	if t%5 == 0:
		plt.cla() #Clear axis

matplotlib的显示模式默认为阻塞(block)模式。什么是阻塞模式?就是在plt.show()之后暂停,并不会继续执行下去。如果要继续执行程序,就要关闭图片。那如何展示动态图或多个窗口呢?这就要使用plt.ion()这个函数,使matplotlib的显示模式转换为交互(interactive)模式。即使在脚本中遇到plt.show(),代码还是会继续执行。

完整代码:

import torch
from torch.autograd import Variable
import torch.nn.functional as F
import matplotlib.pyplot as plt

x = torch.unsqueeze(torch.linspace(-1, 1, 100), dim=1)
#把一维数据变为二维数据
y = x.pow(3) + 0.2*x.pow(2) + torch.rand(x.size())
x, y = Variable(x), Variable(y)

#plt.scatter(x.data.numpy(), y.data.numpy())
#plt.show()
#打印散点图

class Net(torch.nn.Module):
    def __init__(self, n_features, n_hidden, n_output):
        super(Net, self).__init__()#首先找到Net的父类(比如是类A),然后把类Net的对象self转换为类A的对象,然后“被转换”的类A对象调用自己的__init__函数
        self.hidden = torch.nn.Linear(n_features, n_hidden)#对于输入数据进行线性变化:$$y = xA^T+b$$
        self.predict = torch.nn.Linear(n_hidden, n_output)

    def forward(self, x):
        x  = F.relu(self.hidden(x))
        x = self.predict(x)
        return x

net = Net(1, 10, 1)
print(net)

optimizer = torch.optim.SGD(net.parameters(), lr=0.2)
#优化神经网络
loss_func = torch.nn.MSELoss()#损失函数
#均方误差
plt.show()
plt.show()
for t in range(10000):

    prediction = net(x)

    loss = loss_func(prediction, y)
    #预测值在前,真实值在后

    optimizer.zero_grad()
    #先让梯度为0(初始化)
    loss.backward()
    #一次反向传递过程
    optimizer.step()
    #以学习效率0.5优化梯度
    if t % 5 == 0:
        plt.cla()
        plt.scatter(x.data.numpy(), y.data.numpy())
        plt.plot(x.data.numpy(), prediction.data.numpy(), 'r-', lw=5)
        plt.text(0.5, 0, 'Loss=%.4f' % loss.data.numpy(), fontdict={'size': 20, 'color': 'red'})
        plt.pause(0.1)

plt.ioff()
plt.show()

torch.nn有两个参数
#data(Tensor) - paramter tensor
#requires_grad(bool, optional) - 如果需要计算梯度, 可以参考从向后排除子图

torch.nn.MSELoss()

拓展链接:
MSELoss()与CrossEntropyLoss() 区别

pytorch的nn.MSELoss损失函数

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PyTorch拟合通常发生在模型训练时,模型在训练集上表现良好,但在测试集或新的数据上表现不佳。这种现象可能是由于模型过于复杂、数据集过小、训练次数过多等原因造成的。 下面是一些减轻PyTorch拟合的常见方法: 1. 更多的数据:增加训练集数据量可以减少过拟合的风险。如果无法获得更多的真实数据,可以考虑使用数据增强技术来扩充训练集,如随机裁剪、翻转、旋转等。 2. 简化模型:过于复杂的模型容易记住训练集中的噪声,从而导致过拟合。可以通过减少模型的层数、节点数或使用正则化技术(如L1、L2正则化)来简化模型。 3. 正则化:正则化是通过在损失函数中添加一个正则化项来限制模型参数的大小。常见的正则化技术包括L1正则化和L2正则化。它们有助于防止模型对训练数据过拟合。 4. 早停法:通过监控模型在验证集上的性能,在性能不再提升时停止训练,可以防止模型过度拟合训练集。 5. Dropout:Dropout是一种正则化技术,通过在训练过程中随机丢弃一部分节点的输出来减少模型复杂度。这样可以防止某些特定的节点过拟合训练数据。 6. 批标准化:批标准化是一种在深度神经网络中常用的正则化技术,通过对每个批次的输入进行标准化来减少内部协变量偏移,有助于提高模型的泛化性能。 以上是一些常见的方法来减轻PyTorch模型的过拟合问题。根据具体情况选择合适的方法,可以有效提高模型的泛化能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值