李沐深度学习-线性回归简洁实现

import torch
from matplotlib import pyplot as plt
import numpy as np
import torch.utils.data as Data
import torch.nn as nn
from torch.nn import init
import sys
import torch.optim as optim

sys.path.append("/home/eilab2023/yml/project/limu/")
from d2lzh_pytorch import *

'''
----------------------------------生成数据集----------------------------------------------------
'''
# 1.生成数据集
num_inputs = 2
num_examples = 1000
true_w = [2, -3.4]
true_b = 4.2
features = torch.tensor(np.random.normal(0, 1, size=(num_examples, num_inputs)), dtype=torch.float)
labels = true_w[0] * features[:, 0] + true_w[1] * features[:, 1] + true_b  # 是个张量
labels += torch.tensor(np.random.normal(0, 0.01, size=labels.size()), dtype=torch.float)
'''
---------------------------------读取数据-------------------------------------------
'''
# 2.读取数据
# 使用pytorch内置data读取数据
batch_size = 10
# 将训练数据的特征和标签组合
dataset = Data.TensorDataset(features, labels)
# 随机读取小批量
data_iter = Data.DataLoader(dataset, batch_size, shuffle=True)
'''
---------------------------------模型定义,分两种---------------------------------------------------
'''
# 3.模型定义
'''
torch.nn 仅支持一个batch大写啊哦的样本输入而不支持单个样本输入
定义方式一 定义类
'''


class LinearNet(nn.Module):
    def __init__(self, n_feature):
        super(LinearNet, self).__init__()
        self.linear = nn.Linear(n_feature, 1)  # n个特征输入,1个输出,全连接层

    # 定义前向传播
    def forward(self, x):
        x = self.linear(x)
        return x


net = LinearNet(num_inputs)  # 传入的参数参与到初始函数作用 net(x)中的参数参与到forward函数作用

'''
定义方式二 使用nn.Sequential搭建网络,Sequential是一个有序容器,网络层将按照在传入Sequential的顺序依次添加进计算图中
'''
# 写法一
net1 = nn.Sequential(
    nn.Linear(num_inputs, 1)  # 创建了一个网络层,num_inputs个特征输入,1个输出
    # 此处还可以传入其他层
)
# 写法二
net2 = nn.Sequential()
net2.add_module('linear', nn.Linear(num_inputs, 1))
# net2.add_module...
# 写法三
from collections import OrderedDict

net3 = nn.Sequential(
    OrderedDict([('linear', nn.Linear(num_inputs, 1))])
)

# 可以通过net.parameters() 查看模型所有的可学习参数,该函数返回生成器,里面包含的是权重,偏置
'''
--------------------------------------初始化权重和偏差-----------------------------------------------------------
'''
# 4.初始化模型参数
'''
使用net之前需要预先将模型权重和偏差进行初始化,初始化一般会对其正态分布初始化  可以使用nn模块中的init模块里的normal_方法初始化
当net的定义使用的是自定义类时,网络层的权重访问方式为   net.linear.weight   一个特征对应一个权重
当net的定义方式使用的是Sequential模块,网络层权重访问方式是 net[0].weight   
'''
init.normal_(net.linear.weight, mean=0, std=0.01)  # 初始化网络层权重
init.constant_(net.linear.bias, val=0)  # 设置偏置项
'''
--------------------------------------定义损失函数--------------------------------------------------
损失函数pytorch提供了各种调用函数
'''
# 5.定义损失函数
loss = nn.MSELoss()
'''
--------------------------------------定义优化算法--------------------------------------------------
torch.optim模块中提供了很多优化算法:SGD,Adam,RMSProp等优化算法
'''
# 6.定义优化算法
'''
统一设置学习率
'''
optimizer = optim.SGD(net.parameters(), lr=0.01)  # net.parameters()拥有网络层的所有可更新的参数,这里的是权重和偏置
'''
为不同网络层设置学习率,finetune经常使用
optimizer_f = optim.SGD([
    # 如果对某个参数不指定学习率,就是用最外层的默认学习率
    {'params': net.netname1.parameters()},  # lr=0.03
    {'params': net.netname2.parameters(), 'lr': 0.01}
], lr=0.03)
'''

'''
动态设置学习率,不固定设置它,方法有两种:
1.修改optimizer.param_groups中对应的学习率
2.新建优化器(推荐做法,但不适合应用于Adam算法)
# 调整学习率
for param_groups in optimizer.param_groups:
    param_groups['lr'] *= 0.1  # 学习率变为之前的0.1倍
'''

'''
------------------------------------------训练模型----------------------------------------------
通过调用optim实例的step迭代更新模型参数:权重和偏置   
'''
num_epochs = 10
epoch_list = []
loss_list = []
for epoch in range(1, num_epochs + 1):
    epoch_list.append(epoch)
    for X, y in data_iter:  # 生成器返回的是一个个小批量的特征及其对应的标签
        y_hat = net(X)  # 传入了小批量的样本特征,得到预测y
        ll = loss(y_hat, y.view(y_hat.size()))  # 得到损失  保证y和y_hat同型
        optimizer.zero_grad()  # 放在反向传播之前,第一次反向传播前没有梯度,所以清零与不清零没区别
        ll.backward()  # 反向传播计算l对w,b的梯度,得到小量的参数梯度累计值W,B
        optimizer.step()  # 使用SGD优化算法对参数w,b进行了梯度下降或者说参数更新
    # print('epoch %d, loss: %f' % (epoch, ll.item()))
    loss_list.append(ll.item())
# 比较学习到的模型参数和真实的参数之间的差距
dense = net.linear
print(true_w, dense.weight)
print(true_b, dense.bias)
plt.plot(epoch_list, loss_list)
plt.savefig('路径')

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值