主要目标

有的时候想看一下设置了优化器和学习率之后是否按照我设置的样子去进行更新,所以想查看一下网络参数中的及各相关变量:

  • 更新前的值
  • 优化器中的学习率
  • 计算出loss之后的梯度值
  • 更新后的值

有了这几个值,可能在之后我调试网络结构的过程当中能确保代码没有问题,或者检查中间的结果

实验代码1:查看梯度以及参数更新的问题

import torch 
import torch.nn as nn
import numpy as np
import torch.optim as optim
from torchsummary import summary
import os
from torch.utils.data.dataset import Dataset
from torch.utils.data import DataLoader
from tqdm import tqdm


# 设置一下数据集   数据集的构成是随机两个整数,形成一个加法的效果 input1 + input2 = label
class TrainDataset(Dataset):
    def __init__(self):
        super(TrainDataset, self).__init__()
        self.data = []
        for i in range(1,1000):
            for j in range(1,1000):
                self.data.append([i,j])
    def __getitem__(self, index):
        input_data = self.data[index]
        label = input_data[0] + input_data[1]
        return torch.Tensor(input_data),torch.Tensor([label])
    def __len__(self):
        return len(self.data)

class TestNet(nn.Module):
    def __init__(self):
        super(TestNet, self).__init__()
        self.net1 = nn.Linear(2,1)

    def forward(self, x):
        x = self.net1(x)
        return x

def train():
    traindataset = TrainDataset()
    traindataloader = DataLoader(dataset = traindataset,batch_size=1,shuffle=False)
    testnet = TestNet().cuda()
    myloss = nn.MSELoss().cuda()
    optimizer = optim.SGD(testnet.parameters(), lr=0.001 )
    for epoch in range(100):
        for data,label in traindataloader :
            print("\n=====迭代开始=====")
            data = data.cuda()
            label = label.cuda()
            output = testnet(data)
            print("输入数据:",data)
            print("输出数据:",output)
            print("标签:",label)
            loss = myloss(output,label)
            optimizer.zero_grad()
            for name, parms in testnet.named_parameters():	
                print('-->name:', name)
                print('-->para:', parms)
                print('-->grad_requirs:',parms.requires_grad)
                print('-->grad_value:',parms.grad)
                print("===")
            loss.backward()
            optimizer.step()
            print("=============更新之后===========")
            for name, parms in testnet.named_parameters():	
                print('-->name:', name)
                print('-->para:', parms)
                print('-->grad_requirs:',parms.requires_grad)
                print('-->grad_value:',parms.grad)
                print("===")
            print(optimizer)
            input("=====迭代结束=====")



if __name__ == '__main__':

    os.environ["CUDA_VISIBLE_DEVICES"] = "{}".format(3)
    train()

代码结果1

结果说明

网络前传公式
pytorch网络每次运行的结果差的多_pytorch网络每次运行的结果差的多
MSEloss的计算公式
pytorch网络每次运行的结果差的多_迭代_02
针对几个参数的偏导数可以用如下的方式计算:
pytorch网络每次运行的结果差的多_pytorch网络每次运行的结果差的多_03

pytorch网络每次运行的结果差的多_python_04

pytorch网络每次运行的结果差的多_迭代_05

运行一下代码换几个输入输出梯度就不一样了,这里主要是因为输入是两个1所以导致剃度一样。

数据更新
pytorch网络每次运行的结果差的多_pytorch_06

pytorch网络每次运行的结果差的多_深度学习_07

实验代码2:不同优化器的验证(Adam)

将实验1中的优化器换为如下的代码

optimizer = optim.Adam(testnet.parameters(), lr=0.001, betas=(0.9, 0.99))

代码结果2

验证一下梯度loss求导公式没变所以针对梯度我们就不验证了

验证一下Adam的更新

pytorch网络每次运行的结果差的多_迭代_08

算一下实际用于更新的梯度
pytorch网络每次运行的结果差的多_深度学习_09
我们验证一个pytorch网络每次运行的结果差的多_深度学习_10
pytorch网络每次运行的结果差的多_pytorch_11
会发现第一轮的时候最终更新的幅度一定是等于学习率的,这个结论我们等会在实验代码三种再使用一次

pytorch网络每次运行的结果差的多_深度学习_12

实验代码3:优化器对不同层不同参数设置不一样的学习率

比较具体的可以参考之后的一片博客

将实验1中的优化器换为如下的代码

optimizer = optim.Adam(
            [
                {'params': testnet.net1.weight,'lr': 1e-2},
                {'params': testnet.net1.bias, 'lr': 1e-1}
            ]
        )

代码结果3

使用一下实验二的结果Adam优化器第一轮的更新幅度就等于学习率

pytorch网络每次运行的结果差的多_pytorch网络每次运行的结果差的多_13

补充说明

好像只能对一个具体的层进行参数的学习率设置,而不能再细化下去对每个层的不同位置的参数进行学习率的精细调整