深度学习实际4——用pytorch实现线性回归

感谢学习视频:https://www.bilibili.com/video/BV1Y7411d7Ys?p=5&vd_source=2314316d319741d0a2bc13b4ca76fae6

前面学到:
第一步: 确定我们的模型;
第二步:优化目标:定义损失函数(最终必须是一个标量值,这样才能去找怎样让它变得更小);
第三步:然后在 pytorch 进行优化时,需要用到前面学的SGD(随机梯度下降)【核心就是求出每一个权重损失关于权重的梯度】,然后用SGD对权重进行更新。
之前3节课实现了线性模型如何去训练、更新权重。本节主要内容是用 pytorch 提供的工具帮我们去实现一个简单的线性模型的过程
介绍 module 【如何构造自己的神经网络】;
loss 【如何构造损失函数】;
以及如何构造随机梯度下降的优化器。
之前也用到了pytorch的一些功能: Tensor 、 forward : 前馈,计算这组样本带来的损失、backward:反馈,求出最终的梯度。更新权重、权重梯度清零。。。
用pytorch框架写的神经网络代码看起来复杂,但它有很强的弹性,可通过扩展构造出更复杂的神经网络。
线性回归是最简单的只有一个神经元的神经网络。
在这里插入图片描述
pytorch写神经网络:
第一步:准备/构造数据集;
第二步:设计模型用来计算 y hat(y_pred);
第三步:构造损失函数和优化器(loss、optimizer),使用pytorch的API【封装功能】构造用来计算损失的对象、用来优化的对象;
第四步:训练的周期。

准备数据

在这里插入图片描述
模型是 y_hat = w * x + b

import torch
# 之前用两个列表保存数据
x_data = [1.0,2.0,3.0]
y_data = [2.0,4.0,6.0]

# 现在用 torch的 Tensor,用mini-batch的风格
x_data = torch.Tensor([[1.0], [2.0], [3.0]])
y_data = torch.Tensor([[2.0], [4.0], [6.0]])

在这里插入图片描述
mini-batch 就是一次性把三个样本结果都求出来。
numpy有一个广播机制【就是一个矩阵+一个列向量,本身两者是无法相加的,但广播机制会自动将1;2;3 扩充成与另一个矩阵相同的大小,这样就可以完成运算】
在这里插入图片描述
w和b自动广播成可运算的矩阵大小。在这里插入图片描述在这里插入图片描述

第二步定义模型

在这里插入图片描述
彷射模型实际上就是pytorch中的线性单元,一个线性单元就是w*x+b,需要确定权重形状【维度】是什么?偏置形状是什么?想知道w的大小,就要先知道x和y_hat的维度,然后将y_hat扔到loss函数中计算,最后得到loss。
换句话说,就是构造这样一个计算图,从x开始,经过权重参与的运算,最终经过损失函数到达loss,然后在 loss 调用 backward 对计算图进行反向传播。
这就是模型的设计,这里是比较简单的模型,就一个线性单元,x和y都是一维【列数就是维度】,注意loss 一定是一个标量,前面我们知道loss算出来有三个,所以我们要求平均。

class LinearModel(torch.nn.Module):
	def __init__(self):
		super(LinearModel, self).__init__()
		self.linear = torch.nn.Linear(1,1)
	def forward(self, x):
		y_pred = self.linear(x)
		return y_pred
		
model = LinearModel() # 用定义的模型时,实例化即可 model是可调用的

在这里插入图片描述
首先,把模型定义成一个类【模板】,所有模型都要继承自 Module 【因为Module 这个父类里有很多方法,它是将来模型训练过程中需要用到的】,继承下来后,这个类里需要至少两个函数:

  1. 构造函数 init【初始化对象时默认调用函数】
  2. forward 【前馈时执行的计算;必须叫这个名字
    这里没有backward,这是因为Module 构造的对象会自动地根据你的计算图帮你实现backward过程【这是Module里自动完成的】
    注:有时,要用的模块 pytorch 里没有定义,即没办法对它求导数,没有这种计算。这时候有两种方法:
    1.如果你的模块可以由基本的pytorch支持的运算来构成,可以把它封装成一个model、然后实例化model、然后调用它,它可以自动反向传播。
    2。 如果你觉得pytorch的计算图计算效率不高,可能在计算导数时,你有更高效的方法,你可以从Functions 里继承, Functions时pytorch 的一个类,这个类里是需要实现反向传播的,你可以自己构造自己的计算块,但你的计算快都可以用pytorch的计算模块构成。
    用Module是最简单的,因为不用人工设计反向传播的导数怎么去求。
    (1)构造函数: super就是父类,supper(LinearModel, self).init()是调用父类的构造。必须要有super(你定义类的名称,self)固定格式。
    self.linear = torch.nn.Linear(1,1)中torch.nn.Linear是pytorch 的一个类;Linear 也是继承Module的,所以它能自动反向传播;类后加括号【实际就是构造对象】;Linear这个的对象就包含了权重和偏置这两个Tensor,所以,就可直接用Linear来完成 权重*x+b 计算;linear是对象,这对象的类型是torch.nn模块中的Linear这个类, nn(Neural Network神经网络)
    y_pred = self.linear(x)——做的就是w乘x+b的计算,self.linear是前面建立的对象;对象后加括号:意味着实现了可调用的对象。
    model = LinearModel() 实例化,model是可调用的(collable);model(x):就是把x送到forward中返回y_hat。
    在这里插入图片描述
    在这里插入图片描述
    linear是由Linear 实例化的,里面有权重和偏置。
class  Foobar:        # 定义一个可调用的类
     def __init__(self):
         pass

     def __call__(self, *args, **kwargs):# 想让对象可调用,必须定义call这个函数;默认形式
         print("Hello" + str(args[0]))

foobar = Foobar()  # 定义变量foobar 让其实例化
foobar(1, 2, 3)

在这里插入图片描述

第三步构造损失函数

criterion = torch.nn.MSELoss(size_average =False)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

在这里插入图片描述
pytorch里有一个现成的类MSELoss【也是继承自Module】,实例化后,将来调用时就会计算(y_hat-y)^2。
构造 criterion 对象,需要的对象是 y_hat 和 y 求出loss。第一个参数是:是否求均值(可求可不求);第二个参数reduce:降维,是否要求和。
optimizer :优化器,不会构建计算图,optim 模块里有个类SGD,做实例化等一个参数:权重,model 有个成员函数 parameters 会检查 model 里的所有成员,如果成员里有相应的权重,它就把这些都加到最后训练的结果(参数集合)上。 lr 是设置的学习率。opimizer 知道要对哪些权重做优化,也知道学习率,用来对模型进行优化。

第四步

for epoch in range(100):
	y_pred = model(x_data)
	loss = criterion(y_pred, y_data)
	print(epoch, loss)

	optimizer.zero_grad()
	loss.backward()
	optimizer.step()

训练过程,:
(1)先在前馈算 y_hat
(2)用 criterion 算损失
(3)打印【注意 用 print 时loss自动用__str__()所以不会产生计算图】
(4)梯度归零
(5)反向传播
(6)更新 step()根据所有参数里所包含的梯度以及预先设置的学习率自动进行更新

test

# output weight and bias
print('w = ', model.linear.weight.item())
print('b = ', model.linear.bias.item())

# test model
x_test = torch.Tensor([[4.0]])
y_test = model(x_test)
print('y_pred = ', y_test.data)

打印 w 、b weight是一个矩阵,虽然只有一个值,需用item()
在这里插入图片描述
这是 optim 的不同优化器。

import torch

# 现在用 torch的 Tensor,用mini-batch的风格
x_data = torch.Tensor([[1.0], [2.0], [3.0]])
y_data = torch.Tensor([[2.0], [4.0], [6.0]])

class LinearModel(torch.nn.Module):
    def __init__(self):
        super(LinearModel, self).__init__()
        self.linear = torch.nn.Linear(1,1)
    def forward(self, x):
        y_pred = self.linear(x)
        return y_pred
model = LinearModel()
criterion = torch.nn.MSELoss(size_average =False)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
for epoch in range(100):
    y_pred = model(x_data)
    loss = criterion(y_pred, y_data)
    print(epoch, loss)

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
# output weight and bias
print('w = ', model.linear.weight.item())
print('b = ', model.linear.bias.item())

# test model
x_test = torch.Tensor([[4.0]])
y_test = model(x_test)
print('y_pred = ', y_test.data)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看到不同的优化器,效果不同。多尝试

猜你喜欢

转载自blog.csdn.net/qq_41175681/article/details/129619893
今日推荐