第一章 动手学深度学习( PyTorch)笔记 ------ 线性神经网络(二)


本文仅作为个人学习笔记用,如有错误请指正,欢迎大家讨论学习。本博客内容来自动手学深度学习


一、线性回归的简洁实现

在过去的几年里,出于对深度学习强烈的兴趣, 许多公司、学者和业余爱好者开发了各种成熟的开源框架。 这些框架可以自动化基于梯度的学习算法中重复性的工作。 实际上,由于数据迭代器、损失函数、优化器和神经网络层很常用, 现代深度学习库也为我们实现了这些组件。

1.数据集

想跑代码的同学,可以先下载好Pycharm以及Anaconda,以及相应环境,可以用电脑配置允许下的较新版本。

导包

import numpy as np
import torch
from torch.utils import data
from d2l import torch as d2l
from torch import nn

创建数据集

Tensor(张量)是包含单一数据类型元素的多维数组,它是 PyTorch 中数据存储和运算的基本单元,类似于 NumPy 的numpy.ndarray
代码定义了两个PyTorch张量(tensors),true_w 是模型的真实权重,包含两个元素 [2, -3.4];true_b 是模型的真实偏置,值为 4.2。这些值通常用于生成或评估模型的性能。
该函数根据给定的真实权重true_w和偏置 true_b 生成了一个包含1000个样本的数据集。数据集分为特征 features 和标签 labels 两部分。

true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = d2l.synthetic_data(true_w, true_b, 1000)  # 库函数生成人工数据集

读取数据集

我们可以调用框架中现有的API来读取数据。 我们将featureslabels作为API的参数传递,并通过数据迭代器指定batch_size。 此外,布尔值is_train表示是否希望数据迭代器对象在每个迭代周期内打乱数据。
使用data_iter的方式是为了验证是否正常工作,让我们读取并打印第一个小批量样本。 这里我们使用iter构造Python迭代器,并使用next从迭代器中获取第一项。

def load_array(data_arrays, batch_size, is_train=True):
    """构造一个Pytorch数据迭代器"""
    dataset = data.TensorDataset(*data_arrays)  # dataset相当于Pytorch的Dataset。一个星号*,表示对list解开入参。
    return data.DataLoader(dataset, batch_size, shuffle=is_train)  # 返回的是从dataset中随机挑选出batch_size个样本出来


batch_size = 10
data_iter = load_array((features, labels), batch_size)  # 返回的数据的迭代器
print(next(iter(data_iter)))  # iter(data_iter) 是一个迭代器对象,next是取迭代器里面的元素

定义模型

在PyTorch中,nn.Sequential 是一个容器,它允许你将多个神经网络层按顺序堆叠起来。net = nn.Sequential(nn.Linear(2, 1)) 创建了一个简单的神经网络模型 net,该模型仅包含一个线性层(也称为全连接层或密集层)。

具体来说,nn.Linear(2, 1) 定义了一个线性层,它接受输入特征的数量为2(即输入向量的维度是2),并输出一个单一的特征(即输出向量的维度是1)。这种层通常用于线性回归任务,其中你需要预测一个连续的值,但也可以作为更复杂神经网络中的一部分。

nn.Linear(2, 1)包裹在 nn.Sequential 中是为了方便管理模型的架构,尽管在这个例子中只包含一个层,但在构建更复杂的模型时,你可以通过简单地添加更多的层到nn.Sequential容器中来扩展模型。

# 使用框架的预定义好的层
# nn是神经网络的缩写
net = nn.Sequential(nn.Linear(2, 1))

初始化模型参数

在使用net之前,我们需要初始化模型参数。 如在线性回归模型中的权重和偏置。 深度学习框架通常有预定义的方法来初始化参数。 在这里,我们指定每个权重参数应该从均值为0、标准差为0.01的正态分布中随机采样, 偏置参数将初始化为零。
正如我们在构造nn.Linear时指定输入和输出尺寸一样, 现在我们能直接访问参数以设定它们的初始值。 我们通过net[0]选择网络中的第一个图层, 然后使用weight.databias.data方法访问参数。

net[0].weight.data.normal_(0, 0.01)  # 使用正态分布替换掉weight变量里面的数据值
net[0].bias.data.fill_(0)  # 偏差bias变量里面的值设置为0
print(net[0])

定义损失函数

计算均方误差使用的是MSELoss类,也称为平方 L 2 L_2 L2范数。 默认情况下,它返回所有样本损失的平均值。

# 计算均方误差使用的是MSELoss类,也称为平方L2范数
loss = nn.MSELoss()  # L1是算术差,L2是平方差

定义优化算法

小批量随机梯度下降算法是一种优化神经网络的标准工具, PyTorch在optim模块中实现了该算法的许多变种。 当我们实例化一个SGD实例时,我们要指定优化的参数 (可通过net.parameters()从我们的模型中获得)以及优化算法所需的超参数字典。 小批量随机梯度下降只需要设置lr值,这里设置为0.03。

# 实例化SGD实例
trainer = torch.optim.SGD(net.parameters(), lr=0.03)

训练

通过深度学习框架的高级API来实现我们的模型只需要相对较少的代码。 我们不必单独分配参数、不必定义我们的损失函数,也不必手动实现小批量随机梯度下降。 当我们需要更复杂的模型时,高级API的优势将大大增加。 当我们有了所有的基本组件,训练过程代码与我们从零开始实现时所做的非常相似。

回顾一下:在每个迭代周期里,我们将完整遍历一次数据集train_data, 不停地从中获取一个小批量的输入和相应的标签。 对于每一个小批量,我们会进行以下步骤:

1.通过调用net(X)生成预测并计算损失 l l l(前向传播)。

2.通过进行反向传播来计算梯度。

3.通过调用优化器来更新模型参数。

为了更好的衡量训练效果,我们计算每个迭代周期后的损失,并打印它来监控训练过程。

# 训练过程代码与从零开始时所做的非常相似
num_epochs = 3
for epoch in range(num_epochs):
    for X, y in data_iter:  # 从DataLoader里面一次一次把所有数据拿出来
        #         print("X:",X)
        #         print("y:",y)
        l = loss(net(X), y)  # net(X) 为计算出来的线性回归的预测值
        trainer.zero_grad()  # 梯度清零
        l.backward()
        trainer.step()  # SGD优化器优化模型
    l = loss(net(features), labels)
    print(f'epoch{epoch + 1},loss{l:f}')

二、所有代码及运行结果

import numpy as np
import torch
from torch.utils import data
from d2l import torch as d2l
from torch import nn

true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = d2l.synthetic_data(true_w, true_b, 1000)  # 库函数生成人工数据集


# 调用框架现有的API来读取数据
def load_array(data_arrays, batch_size, is_train=True):
    """构造一个Pytorch数据迭代器"""
    dataset = data.TensorDataset(*data_arrays)  # dataset相当于Pytorch的Dataset。一个星号*,表示对list解开入参。
    return data.DataLoader(dataset, batch_size, shuffle=is_train)  # 返回的是从dataset中随机挑选出batch_size个样本出来


batch_size = 10
data_iter = load_array((features, labels), batch_size)  # 返回的数据的迭代器
print(next(iter(data_iter)))  # iter(data_iter) 是一个迭代器对象,next是取迭代器里面的元素

# 使用框架的预定义好的层
# nn是神经网络的缩写
net = nn.Sequential(nn.Linear(2, 1))

# 初始化模型参数
net[0].weight.data.normal_(0, 0.01)  # 使用正态分布替换掉weight变量里面的数据值
net[0].bias.data.fill_(0)  # 偏差bias变量里面的值设置为0
print(net[0])

# 计算均方误差使用的是MSELoss类,也称为平方L2范数
loss = nn.MSELoss()  # L1是算术差,L2是平方差

# 实例化SGD实例
trainer = torch.optim.SGD(net.parameters(), lr=0.03)

# 训练过程代码与从零开始时所做的非常相似
num_epochs = 3
for epoch in range(num_epochs):
    for X, y in data_iter:  # 从DataLoader里面一次一次把所有数据拿出来
        #         print("X:",X)
        #         print("y:",y)
        l = loss(net(X), y)  # net(X) 为计算出来的线性回归的预测值
        trainer.zero_grad()  # 梯度清零
        l.backward()
        trainer.step()  # SGD优化器优化模型
    l = loss(net(features), labels)
    print(f'epoch{epoch + 1},loss{l:f}')

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值