pytorch 优化器优化模型参数的数据分析

一直有一个疑问,我们生成一个模型,这个模型的参数传递给了优化器,优化器在优化的时候,模型的参数会有变化,这之间的关联到底是怎样的呢?如果想改变模型的参数,只能通过优化器更新吗?如果在优化器外面更新了,这个时候的参数会在模型中、优化器中同时起作用吗?答案是会的,因为我们传递给优化器的模型参数包括了模型参数的地址,我们在这个地址上进行更改,则全局都会同步产生变化。

其实我要解决的一个问题就是,我想在优化器对模型进行更新的情况下,我自己也对模型增加一个更新。下面是我的代码:

    class Net(nn.Module):
        def __init__(self):
            super(Net, self).__init__()
            self.linear1 = nn.Linear(6,2)
            self.conv1 = nn.Conv2d(2,2,3)
            self.par = Parameter( torch.Tensor(4,2) )

        def forward(self, input):
            # prob = self.linear1(input)
            # return prob
            pass

    net = Net()#生成模型,则参数也一同产生了
    params = [{'params':value} for _, value in net.named_parameters() ] #将模型的可更新参数按照字典的形式存起来,一个模型参数对应一个字典,将字典放到列表中
    optim = torch.optim.SGD( params, lr = 0.00035 )#将模型参数送给优化器
    print('第一次遍历:')
    for para in optim.param_groups:#看传递给优化器的模型参数的值和地址是不是内存共享的
        if para['params'][0].size() == torch.Size([2, 6]):
            print(id(para['params'][0]))
            print(para['params'][0])

    for key, value in net.named_parameters():#直接在模型中查看模型的参数的内存地址和值
        if value.size() == torch.Size([2,6]):
            print(id(value))
            print(value)
    print('weight',id(net.linear1.weight))#直接在模型中查看模型的参数的内存地址和值
    print('data',id(net.linear1.weight.data))#直接在模型中查看模型的参数值
    print(net.linear1.weight)

    x = torch.randn(2,6)
    net.linear1.weight.data.add(0.1) #这一步相当于在优化器以外对模型参数进行更改

    print('第二次遍历:')
    for para in optim.param_groups:#看看在优化器外改了模型参数,优化器中的模型参数值是否也会同步产生变化,答案是会产生变化
        if para['params'][0].size() == torch.Size([2, 6]):
            print(id(para['params'][0]))
            print(para['params'][0])
    for key, value in net.named_parameters():#看看在优化器外改了模型参数,是否起作用,结果是会起作用
        if value.size() == torch.Size([2,6]):
            print(id(value))
            print(value)
    print('weight',id(net.linear1.weight))#直接查看模型参数的地址
    print('data',id(net.linear1.weight.data))#查看模型参数的值
    print(net.linear1.weight)#看看模型参数变没变

程序运行结果为:

第一次遍历:
140487128355032
Parameter containing:
tensor([[ 0.2104, -0.1802, -0.0791,  0.1916, -0.3843,  0.2448],
        [-0.0840,  0.2077,  0.0568, -0.0500,  0.1132,  0.0201]],
       requires_grad=True)
140487128355032
Parameter containing:
tensor([[ 0.2104, -0.1802, -0.0791,  0.1916, -0.3843,  0.2448],
        [-0.0840,  0.2077,  0.0568, -0.0500,  0.1132,  0.0201]],
       requires_grad=True)
weight 140487128355032
data 140487128356904
Parameter containing:
tensor([[ 0.2104, -0.1802, -0.0791,  0.1916, -0.3843,  0.2448],
        [-0.0840,  0.2077,  0.0568, -0.0500,  0.1132,  0.0201]],
       requires_grad=True)
第二次遍历:
140487128355032
Parameter containing:
tensor([[ 0.2104, -0.1802, -0.0791,  0.1916, -0.3843,  0.2448],
        [-0.0840,  0.2077,  0.0568, -0.0500,  0.1132,  0.0201]],
       requires_grad=True)
140487128355032
Parameter containing:
tensor([[ 0.2104, -0.1802, -0.0791,  0.1916, -0.3843,  0.2448],
        [-0.0840,  0.2077,  0.0568, -0.0500,  0.1132,  0.0201]],
       requires_grad=True)
weight 140487128355032
data 140487128357048
Parameter containing:
tensor([[ 0.2104, -0.1802, -0.0791,  0.1916, -0.3843,  0.2448],
        [-0.0840,  0.2077,  0.0568, -0.0500,  0.1132,  0.0201]],
       requires_grad=True)

实验结果表明,往params这个字典中传递模型参数,以及将params传递给优化器的时候,传递的都是内存地址,因此只要在这个地址上进行数据更新,则全局都会进行更新,那么如何更新模型中的某个参数呢?如下所示,我要在每次进行forward()之前,将线性分类层的每个向量都进行标准化,则可以进行下面的操作:

self.encoder.module.classifier.weight.data.copy_(F.normalize( self.encoder.module.classifier.weight.data ,dim=1))

这里要注意一下,如果是将2048维的特征向量,分类乘1000份,则分类层的tensor的尺寸是[1000,2048],而不是[2048,1000],这块要注意一下。

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值