用于记录python在深度学习中的使用
hasattr,getattr,setattr 均涉及类(class)示例对象的属性和方法
hasattr() 函数用来判断某个类实例对象是否包含指定名称的属性或方法。
无论是属性名还是方法名,都在 hasattr() 函数的匹配范围内。
hasattr(obj, name)
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
训练时多个卷积,推理时重参数为一个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(object, name, default)
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(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
构建网络,规范化,减少代码量
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 模块。