【2023.07.24-7.25】pytorch basics:autograd, optimization, save and load model

1.autograd

1)计算图是一个DAG有向无环图。

正向传播:autograd包含两个步骤,首先计算tensor结果,维护操作的.grad_fn。

反向传播:显示的调用backward函数后,包含三个步骤:首先用.grad_fn计算梯度值;然后所有requires_grad属性为True的结点的梯度(即结点的.grad属性)被累积更新;最终利用链式法则,反向传播。

2)backward(gradient,retain_graph)

(1)gradient:

对于标量结点,参数可选,此时参数被默认为torch.Tensor([1])。

对于非标量结点,则必需要gradient。且gradient尺寸需要和输出尺寸相同,

import torch
z = torch.matmul(x, w)+b
loss = torch.nn.functional.binary_cross_entropy_with_logits(z, y)
loss.backward()

(2)retain_graph:一个计算图只能调用一次backward函数。如果需要对同一张图多次调用,则需要backward(retain_graph=True).并且多次调用的梯度会累计。

3)取消gradient tracking

为了固定网络参数或加速计算省去后向传播,所以会不记录部分tensor梯度。

通过以下两种方式设置。用z_det=z.detach()定义的tensor或with torch.no_grad() 语句被包裹的结点。

z=torch.matmul(x,a)+b
z_det=z.detach()
with torch.no_grad():
    z_det2=torch.matmul(x,a)+b

4)查看梯度和grad_fn

(1)结点梯度:print(x.grad)

(2)梯度函数:如果是直接创建tensor,则.grad_fn=None.如果是y=x+x,则.grad_fn=AddBackward

2.optimization

1) hyperparam

number of epochs:迭代模型的次数

batch size:每次迭代需要的样本数

learning rate:每个epoch更新模型的程度。值越小,模型学习速度越慢。值越大,模型容易出现不可预测的行为。

2)optimization loop

training loop:在训练集上迭代,目标是使模型收敛

validation loop:在验证集上迭代,验证模型效果。

3)优化器

优化算法被封装在优化器对象中。在初始化优化器时,我们把需要优化的模型参数、超参数作为初始化时的参数传给优化器。

optimizer=torch.optim.SGD(model.parameters(),lr=learning_rate)

在每个批次之间,为了防止模型梯度叠加,使用optimizer.zero_grad()清零梯度

在使用loss.backward()更新梯度后,使用optim.step()使用梯度更新模型参数

4)training loop和validation loop的实现

def train_loop(dataloader,model,optimizer,loss_fn)
    model.train()
    size=len(dataloader.dataset)
    for batch,(X,y) in enumerate(dataloader):
        pred=model(X)
        loss=loss_fn(pred,y)
        loss.backward()
        optim.step()
        optim.zero_grad()

    if batch%100==0:
        loss,current=loss.item(),(batch+1)*len(X)
        print(f"train loss:{loss:>7f} [{current position:>5d}/{size:5d}]"))
#每个loss是在每个batch上计算,test_loop中loss需要求和因为需要求多个loss的平均,但train_loop是每100个batch才打印
#因为loss_fn的返回值是一个标量,pred才是和输出相同维度的。


def test_loop(dataloader,model,loss_fn)
    model.eval()
    test_loss,correct=0,0 #因为test_loop函数被多次调用,且两个变量累加。所以需要清零。
    size=len(dataloader.dataset)
    num_batches=len(dataloader)
    with torch.no_grad(): #节约资源不用再计算梯度
        for (X,y) in dataloader:
            pred=model(X)
            loss=loss_fn(pred,y)
            test_loss+=loss.item()
            correct+=(pred.argmax(1)==y).type(torch.float).sum().item()
            #一个样本的预测标签为每一行中的最大值,即pred.argmax(1),列为种类、行为为一个batch中的样本。
    correct/=size
    test_loss/=num_batches #在多个batch上的平均
    print(f"correctness:"crrect/batch_size,"train loss:"loss)

epochs=10
loss_fn=nn.CrossEntropyLoss()
for i in range(epochs):
    print(f"Epoch"i+1"-------------")
    train_loop(training_dataloader,model,optimizer,loss_fn)
    test_loop(testing_dataloader,model,loss_fn)
print("done")

3. save and load model

1)只是用于推理:只保存模型权重

#save model weights
torch.save(model.state_dict(),'model_weight.pth')
#load model weights
model.load_state_dict(torch.load('model_weights.pth'))
#pytorch load save函数可以保存任何文件,保存的时候只保存了state_dict,则取出的时候也调用load_state_dict


2)需要继续训练模型:保存整个模型

state = {
    'epoch': epoch,
    'state_dict': model.state_dict(),
    'optimizer': optimizer.state_dict(),
    ...
}
#save model including optimizer,epoch,score
torch.save(state,filepath)

#load model including optimizer,epoch,score
model=torch.load(state,filepath)

------------

1.model.tran() model.eval()作用

由于之前model = NeuralNetwork(),因此model是自定义类NeuralNetwork的实例。而NeuralNetwork是nn.Module的子类。nn.Module中包含属性.train();.eval()

表示模型在不同的状态下。在model.train()下模型会根据不同批的结果,更新梯度。但在model.eval()下不会,会关闭BN,dropout。具体解释dropout参照deep learning 7.12:deeplearningbook.org/contents/regularization.html, 解释BN参照deep learning 8.1.3:deeplearningbook.org/contents/optimization.html

2.model(X)

等价于调用__call__(),该函数调用model.forward(X)+hooks。

3.optimizer.zero_grad()

为什么清零模型梯度需要通过调用optimizer的属性呢?当把模型所有参数都在定义优化器时,给了同一个优化器,则optimizer.zero_grad()效果等于model.zero_grad().除非一个模型使用了多个优化器优化。

4.dataloader类

将dataset和决定如何从数据集中获取样本的sampler结合在一起。

.num_workers定义cpu加载数据需要子进程的数量。会尽可能均匀的将batch_size个样本平均分配给num_workers。num_workers数量越大,对内存消耗越大,模型能使用的内存越少;num_workers数量太小时,Gpu必须等待cpu加载数据。结合IO、内存使用情况。所以num_worker数量需要结合batch_size数量选择,最好和训练速度匹配。当num_workers数量为0时,只由主进程加载数据。

.dataset:获取定义dataloader的数据集。

5.为什么要设计batch和epoch

epoch数量是神经网络在整个数据集上训练的次数。

batch是把整个数据集分块的块数。batch的存在是由于一次把整个数据集太大,不能整个输入给模型。

7 tensor.type(dtype)

tensor的数据类型的强制转换。torch.float,torch.double等

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值