动手学深度学习V2每日笔记(PyTorch神经网络基础)

本文主要参考沐神的视频教程 https://www.bilibili.com/video/BV1AK4y1P7vsp=1&vd_source=c7bfc6ce0ea0cbe43aa288ba2713e56d
文档教程 https://zh-v2.d2l.ai/

本文的主要内容对沐神提供的代码中个人不太理解的内容进行笔记记录,内容不会特别严谨仅供参考。

1.函数目录

1.1 torch

torch.nn位置
Module2.1
init2.2
Parameter2.3
torch.rand0-1均匀分布抽取值
torch.randn0-1正态分布抽取值
torch.save3.1
torch.load3.1

2. 层和块

2.1自定义块

2.1.1 torch.nn.Module

nn.Module是PyTorch中神经网络的基本构建块。它是所有神经网络模块的基类,包含了神经网络中所有层的定义以及前向传播的方法。通过继承nn.Module,我们可以轻松地构建自己的神经网络模型。

  • nn.Module的作用
  1. 封装网络层:nn.Module封装了网络的各层及其参数,这使得我们可以像操作对象一样方便地操作神经网络。
  2. 管理参数:nn.Module自动管理所有子模块的参数。通过调用parameters()方法,可以很方便地获取模型的所有参数。
  3. 定义前向传播:通过重写forward()方法,可以定义网络的前向传播过程。
    该类常用的方法
序号函数作用
1init()构造函数,用于定义网络层和初始化。
2forward()前向传播函数,定义数据如何通过网络进行传播。需要在子类中重写此方法
3parameters()返回模型的所有参数,通常用于优化器。
4named_parameters()与parameters()类似,但会返回参数名和参数。
5state_dict()返回包含模型所有参数和缓存的字典。常用于模型的保存和加载。
6eval()将模块设置为评估模式。在评估模式下,BatchNorm和Dropout等层的行为会有所不同。
7train()将模块设置为训练模式。这是默认模式,但在使用eval()后需要切换回训练模式时使用
8children()返回子模块的迭代器。
9named_children()返回子模块的迭代器,包含子模块名称
10modules()返回所有模块(包括子模块)的迭代器。
11named_modules()返回所有模块(包括子模块)的迭代器,包含模块名称。
12apply

2.1.2 使用Module定义模型

import torch
from torch import nn
from torch.nn import functional as F

class MLP(nn.Module):
    def __init__(self):
        super(MLP, self).__init__()
        self.l1 = nn.Linear(4, 8)
        self.l2 = nn.Linear(8, 1)

    def forward(self, x):
        return  self.l2(F.relu(self.l1(x)))

2.1.3 参数访问

nn.Module类通过定义的属性名称来访问各个层,例如 net.l1 或 net.l2。

net = MLP()
X = torch.rand(size=(2, 4))
print(net(X))
# 1.参数访问
print(net.l2.state_dict())

2.1.4 目标参数

# 2. 目标参数
print(type(net.l2.bias))
print(net.l2.bias)
print(net.l2.bias.data)
print(net.l2.bias.grad)
函数功能
net.l2.bias访问l2中的bias,bais包含值、梯度和额外信息
net.l2.bias.data访问l2中bias的值
net.l2.bias.grad访问l2中bias的梯度

2.1.5 一次性访问所有参数

named_parameters() 是 PyTorch 中 nn.Module 类的一个方法,用于返回模型中所有参数的迭代器,其中每个参数都有其对应的名称。

print(*[(name, param.shape) for name, param in net.l1.named_parameters()])
print(*[(name, param.shape) for name, param in net.named_parameters()])

2.2 参数初始化

2.2.1 nn.init

torch.nn.init 模块是 PyTorch 中用于初始化神经网络模型参数的工具。参数初始化在深度学习中非常重要,因为它会影响模型的收敛速度和最终性能。torch.nn.init 提供了多种常用的初始化方法,帮助用户在创建神经网络时对参数进行合理初始化。

方法功能示例
nn.init.uniform_将参数张量的元素初始化为从均匀分布 U(a, b) 中抽取的值。nn.init.uniform_(tensor, a=0.0, b=1.0)
nn.init.constant_将参数张量的元素初始化为常数值。nn.init.constant_(tensor, val)
nn.init.normal_将参数张量的元素初始化为从正态分布 N(mean, std) 中抽取的值nn.init.normal_(tensor, mean=0.0, std=1.0)
nn.init.xavier_uniform_使用 Xavier 初始化方法,将参数张量的元素初始化为从均匀分布中抽取的值。nn.init.xavier_uniform_(tensor, gain=1.0)
nn.init.xavier_normal_使用 Xavier 初始化方法,将参数张量的元素初始化为从正态分布中抽取的值。nn.init.xavier_normal_(tensor, gain=1.0)
nn.init.kaiming_uniform_使用 Kaiming 初始化方法,将参数张量的元素初始化为从均匀分布中抽取的值,适用于 ReLU 激活函数。nn.init.kaiming_uniform_(tensor, a=0, mode=‘fan_in’, nonlinearity=‘leaky_relu’)
nn.init.kaiming_normal_使用 Kaiming 初始化方法,将参数张量的元素初始化为从正态分布中抽取的值,适用于 ReLU 激活函数。nn.init.kaiming_normal_(tensor, a=0, mode=‘fan_in’, nonlinearity=‘leaky_relu’)
nn.init.orthogonal_使用正交初始化方法,将参数张量的元素初始化为正交矩阵。nn.init.orthogonal_(tensor, gain=1.0)
nn.init.sparse_将参数张量初始化为稀疏矩阵,非零条目从正态分布中抽取。nn.init.sparse_(tensor, sparsity, std=0.01)
w = torch.empty(size=(2, 3))
print(w)
q = nn.init.constant_(w, 2.)
print(q)

tensor([[0., 0., 0.],
[0., 0., 0.]])
tensor([[2., 2., 2.],
[2., 2., 2.]])

2.2.2 内置初始化

# 4. 参数初始化
def init_normal(m):
    if type(m)==nn.Linear:
        nn.init.normal_(m.weight, mean=0, std=0.01)
        nn.init.constant_(m.bias, val=0)

net.apply(init_normal)
print(net.l2.weight.data, net.l2.bias.data)
#某些应用块使用不用的初始化
def init_xavier(m):
    if type(m) == nn.Linear:
        nn.init.xavier_normal_(m.weight)

def init_42(m):
    if type(m) == nn.Linear:
        nn.init.constant_(m.weight, 42.)
net.l2.apply(init_42)
net.l1.apply(init_xavier)
print(net.l1.weight.data)
print(net.l2.weight.data)

2.3 自定义层

2.3.1 不带参数的层

class CenteredLayer(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self, x):
        return x - x.mean()
layer = CenteredLayer()
print(layer(torch.FloatTensor([1, 2, 3, 4, 5])))

将层作为组件添加到模型中

net1 = nn.Sequential(nn.Linear(8, 128), CenteredLayer())
Y = net1(torch.rand(size=(4,8)))
print(Y.mean())

2.3.2 nn.Parameter()

torch.nn.Parameter 类在 PyTorch 中的作用是将普通的张量转换为模型参数,以便这些参数可以被 nn.Module 类的实例自动识别和管理。使用 nn.Parameter 可以确保这些参数会出现在 model.parameters() 的输出中,并且在调用 backward() 时这些参数的梯度会被自动计算。

  • 主要作用
  • 区分普通张量和模型参数:nn.Parameter 可以让 PyTorch 自动识别哪些张量是模型的参数,从而在优化过程中正确处理它们。
  • 自动注册为模块参数:当在 nn.Module 的子类中定义一个 nn.Parameter,该参数会自动被注册为模型的参数。

2.3.3 带参数的层

class myLinear(nn.Module):
    def __init__(self, in_units, out_nuits):
        super().__init__()
        self.weight = nn.Parameter(torch.rand(size=(in_units, out_nuits)))
        self.bais = nn.Parameter(torch.rand(out_nuits))

    def forward(self, x):
        linear = torch.matmul(x, self.weight) + self.bais
        return F.relu(linear)

linear = myLinear(5,3)
print(linear.weight)

我们可以使用自定的层直接进行前向计算

print(linear(torch.rand(size=(2, 5))))

tensor([[1.1681, 1.0715, 0.6788],
[1.6209, 2.4351, 1.7599]], grad_fn=)
可以使用自定义层构建模型

net2 = nn.Sequential(nn.Linear(64,8), myLinear(8,1))
print(net2(torch.rand(size=(2, 64))))

3. 读写文件

3.1加载和保存张量

3.1.1 torch.save()

torch.save() 函数将一个对象保存到文件中。这个对象可以是一个张量、一个模型的状态字典或者任何支持序列化的 Python 对象。

3.1.2 torch.load()

torch.load() 函数从文件中加载一个对象。它通常用于加载之前保存的张量、模型的状态字典或者任何支持序列化的 Python 对象。

# 1.保存张量
x =torch.arange(4)
torch.save(x, 'x-file')
x1 = torch.load('x-file')
print(x1)
# 2.保存张量列表
y = torch.zeros(4)
torch.save([x,y], 'x-file')
x2, y2 = torch.load('x-file')
print(x2, y2)
# 3.保存字典
mydict = {
    'x': x,
    'y':y
}
torch.save(mydict, 'mydict')
mydict1 = torch.load('mydict')
print(mydict1)

3.2 加载和保存模型参数

class MLP(nn.Module):
    def __init__(self):
        super().__init__()
        self.hidden = nn.Linear(20, 256)
        self.output = nn.Linear(256, 10)

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

net3 = MLP()
X = torch.randn(size=(2, 20))
Y = net3(X)
print(Y.shape)
# 将模型参数存储在mlp.params文件中
torch.save(net3.state_dict(), 'mlp.params')
# 定义模型
clone = MLP()
# 加载参数
clone.load_state_dict(torch.load('mlp.params'))
clone.eval()

Y_clone = clone(X)
print(Y_clone==Y)
  • 13
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值