【python】hasattr,getattr,setattr原理及在深度学习中的使用


hasattr,getattr,setattr原理及在深度学习中的使用

用于记录python在深度学习中的使用

hasattr,getattr,setattr 均涉及类(class)示例对象的属性和方法


hasattr

hasattr() 函数用来判断某个类实例对象是否包含指定名称的属性或方法。
无论是属性名还是方法名,都在 hasattr() 函数的匹配范围内。

hasattr(obj, name)
  • obj – 指的是某个类的实例对象
  • name – 表示指定的属性名或方法名
  • return – True 或者 False
class HumanTest(object):
    def __init__(self):
        self.name = "张三"
        self.age = 20
 
    def say(self):
        print("I am SB!")
        
obj = HumanTest()
print(hasattr(obj, "name"))
print(hasattr(obj, "age"))
print(hasattr(obj, "say"))
print(hasattr(obj, "new_name"))

结果

True
True
True
False

深度学习真实使用场景 RepVGGGBlock

训练时多个卷积,推理时重参数为一个3x3卷积

class RepVGGBlock():
    def __init__(self,deploy=False):
        if deploy:
            self.rbr_reparam=1
    def forward(self):
        if hasattr(self,'rbr_reparam'):
            print("rep")
        else:
            print("train")
block1=RepVGGBlock()
block1.forward() ##训练

block2=RepVGGBlock(deploy=True) 
block2.forward() ##推理

结果

train
rep

单卡训练和多卡训练权重的配套使用

如果是多卡训练,权重需要多个module.names 如果单卡训练则不用。

self.names = self.model.module.names if hasattr(self.model, 'module') else self.model.names

getattr

返回对象属性值或方法值

getattr(object, name, default)
  • object – 对象。
  • name – 属性名或者方法名。
  • default --默认返回值,如果不提供该参数,在没有对应属性时,将触发 AttributeError。
class A(object):
    bar = 1

a = A()
getattr(a, 'bar') 
print(getattr(a, 'bar'))
getattr(a, 'bar2',3)  #若没有,3 则报错
print(getattr(a, 'bar2',3))

结果

1
3

setattr

设置对象属性值或方法值,该属性不一定是存在的,即,可以新建

setattr(object, name, value)
  • object – 对象。
  • name – 字符串,对象属性。
  • value – 属性值。
class A(object):
    bar = 1

a = A()
getattr(a, 'bar') 
print(a.bar)
setattr(a, 'bar',5)  
print(a.bar)
setattr(a, 'bar2',10)  
print(a.bar2)

结果

1
5
10

setattr 与 getattr 在深度学习中的使用

构建网络,规范化,减少代码量

import math
import torch.nn as nn
import torch
class example_model(nn.Module):
    def __init__(self):
        super().__init__()
        self.size=512
        self.log_size = int(math.log(self.size, 2))
        self.names = ['convblock%d'%i for i in range(self.log_size-1)] #根据2的幂次设置名字 

        conv = nn.Conv2d(in_channels=3,out_channels=64,kernel_size=3,padding=1)
        self.convblock0 = conv

        in_channel=64
        print(self.names)
        for i in range(self.log_size, 2, -1):
            out_channel = 2 ** (i - 1)
            conv = nn.Conv2d(in_channel, out_channel, 3, 1,1)
            setattr(self, self.names[self.log_size-i+1],conv)
            in_channel = out_channel



    def forward(self,x):
        for i in range(self.log_size-1):
            ecd = getattr(self, self.names[i])
            print(ecd)
        return "finish"

my_model = example_model()

import numpy as np
img = np.random.randn(1,3,112,112)
img=torch.from_numpy(img)

print(my_model(img))

结果

['convblock0', 'convblock1', 'convblock2', 'convblock3', 'convblock4', 'convblock5', 'convblock6', 'convblock7']
Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
Conv2d(64, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
Conv2d(256, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
Conv2d(128, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
Conv2d(64, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
Conv2d(32, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
Conv2d(16, 8, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
Conv2d(8, 4, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
finish

解释
setattr 将卷积层nn.conv 属性输入到self.names
推理时 getattr 取出卷积层
需要注意的是,这是最简单的例子,nn.conv 可以换成任意nn.module 模块。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RichardCV

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值