Loading... # hasattr,getattr,setattr原理及在深度学习中的使用 `用于记录python在深度学习中的使用` hasattr,getattr,setattr 均涉及类(class)示例对象的属性和方法 --- ## hasattr hasattr() 函数用来判断某个类实例对象是否包含指定名称的属性或方法。 无论是属性名还是方法名,都在 hasattr() 函数的匹配范围内。 ```python hasattr(obj, name) ``` - obj -- 指的是某个类的实例对象 - name -- 表示指定的属性名或方法名 - return -- True 或者 False ```python 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")) ``` **结果** ```python True True True False ``` ### 深度学习真实使用场景 RepVGGGBlock 训练时多个卷积,推理时重参数为一个3x3卷积 ```python 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() ##推理 ``` **结果** ```python train rep ``` ### 单卡训练和多卡训练权重的配套使用 如果是多卡训练,权重需要多个module.names 如果单卡训练则不用。 ```python self.names = self.model.module.names if hasattr(self.model, 'module') else self.model.names ``` ## getattr 返回对象属性值或方法值 ```python getattr(object, name, default) ``` - object -- 对象。 - name -- 属性名或者方法名。 - default --默认返回值,如果不提供该参数,在没有对应属性时,将触发 AttributeError。 ```python class A(object): bar = 1 a = A() getattr(a, 'bar') print(getattr(a, 'bar')) getattr(a, 'bar2',3) #若没有,3 则报错 print(getattr(a, 'bar2',3)) ``` **结果** ```python 1 3 ``` ## setattr 设置对象属性值或方法值,该属性不一定是存在的,即,可以新建 ```python setattr(object, name, value) ``` - object -- 对象。 - name -- 字符串,对象属性。 - value -- 属性值。 ```python 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) ``` **结果** ```python 1 5 10 ``` ## setattr 与 getattr 在深度学习中的使用 构建网络,规范化,减少代码量 ```python 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)) ``` **结果** ```python ['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 模块。 最后修改:2025 年 02 月 22 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏