## 定义卷积块

```class BaseConv(nn.Module):
def __init__(self, in_channels, out_channels, k=1, s=1, p=None):
super().__init__()
self.in_channels = in_channels
self.out_channels = out_channels
self.conv = nn.Conv2d(in_channels, out_channels, k, s, autopad(k, p))
self.bn = nn.BatchNorm2d(out_channels)
self.act_fn = nn.ReLU(inplace=True)
def forward(self, x):
return self.act_fn(self.bn(self.conv(x)))```

```def autopad(k, p=None):
if p is None:
p = k // 2 if isinstance(k, int) else [x // 2 for x in k]
return p```

## 定义一个Bottleneck

```class Bottleneck(nn.Module):
def __init__(self, in_channels, out_channels, shortcut=True):
super(Bottleneck, self).__init__()
self.conv1 = BaseConv(in_channels, out_channels, k=1, s=1)
self.conv2 = BaseConv(out_channels, out_channels, k=3, s=1)
self.add = shortcut and in_channels == out_channels
def forward(self, x):
"""
|_________________|
"""
return x + self.conv2(self.conv1(x)) if self.add else self.conv2(self.conv1(x))```

## 攥写yaml配置文件

```# define own model
backbone:
[[-1, 1, BaseConv, [32, 3, 1]],  # out_channles=32, k=3, s=1
[-1, 1, BaseConv, [64, 1, 1]],
[-1, 2, Bottleneck, [64]]
]```

```import yaml
# 获得yaml文件名字
yaml_file = Path('Model.yaml').name
with open(yaml_file,errors='ignore') as f:
print(yaml_)```

{‘backbone’: [[-1, 1, ‘BaseConv’, [32, 3, 1]], [-1, 1, ‘BaseConv’, [64, 1, 1]], [-1, 2, ‘Bottleneck’, [64]]]}

```class Model(nn.Module):
def __init__(self, cfg='./Model.yaml', ch=3, ):
super().__init__()
self.yaml = cfg
import yaml
yaml_file = Path(cfg).name
with open(yaml_file, errors='ignore')as f:
ch = self.yaml["ch"] = self.yaml["ch"] = 3
self.backbone = parse_model(deepcopy(self.yaml), ch=[ch])
def forward(self, x):
output = self.backbone(x)
return output```

## 传入参数

```def parse_model(yaml_cfg, ch):
"""
:param yaml_cfg: yaml file
:param ch: init in_channels default is 3
:return: model
"""
layer, out_channels = [], ch[-1]
for i, (f, number, Module_name, args) in enumerate(yaml_cfg['backbone']):
"""
f:上一层输出通道
number:该模块有几层，就是该模块要重复几次
Mdule_name：卷积层名字
args:参数，包含输出通道数，k,s,p等
"""
# 通过eval，将str类型转自己定义的BaseConv
m = eval(Module_name) if isinstance(Module_name, str) else Module_name
for j, a in enumerate(args):
# 通过eval，将str转int,获得输出通道数
args[j] = eval(a) if isinstance(a, str) else a
# 更新通道
# args[0]是输出通道
if m in [BaseConv, Bottleneck]:
in_channels, out_channels = ch[f], args[0]
args = [in_channels, out_channels, *args[1:]]  # args=[in_channels, out_channels, k, s, p]
# 将参数传入模型
model_ = nn.Sequential(*[m(*args) for _ in range(number)]) if number > 1 else m(*args)
# 更新通道列表，每次获取输出通道
ch.append(out_channels)
layer.append(model_)
return nn.Sequential(*layer)```

```# 这行代码是通过列表用来存放每层内容以及输出通道数
layer, out_channels = [], ch[-1]```

`for i, (f, number, Module_name, args) in enumerate(yaml_cfg['backbone']):`

`m = eval(Module_name) if isinstance(Module_name, str) else Module_name`

```>>> b = eval(a) if isinstance(a,str) else a
>>> b
123
>>> type(b)
<class 'int'>```

```>>> a="BaseConv"
>>> b = eval(a) if isinstance(a,str) else a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
NameError: name 'BaseConv' is not defined```

`<class 'models.BaseConv'>`

```for j, a in enumerate(args):
# 通过eval，将str转int,获得输出通道数
args[j] = eval(a) if isinstance(a, str) else a```

```# 更新通道
# args[0]是输出通道
if m in [BaseConv, Bottleneck]:
in_channels, out_channels = ch[f], args[0]
args = [in_channels, out_channels, *args[1:]]  # args=[in_channels, out_channels, k, s, p]```

#### 将参数传入模型

`model_ = nn.Sequential(*[m(*args) for _ in range(number)]) if number > 1 else m(*args)`

` BaseConv(    (conv): Conv2d(3, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))    (bn): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)    (act_fn): ReLU(inplace=True)  )`

```# 更新通道列表，每次获取输出通道
ch.append(out_channels)
layer.append(model_)```

```Model(
(backbone): Sequential(
(0): BaseConv(
(conv): Conv2d(3, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(act_fn): ReLU(inplace=True)
)
(1): BaseConv(
(conv): Conv2d(32, 64, kernel_size=(1, 1), stride=(1, 1))
(bn): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(act_fn): ReLU(inplace=True)
)
(2): Sequential(
(0): Bottleneck(
(conv1): BaseConv(
(conv): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1))
(bn): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(act_fn): ReLU(inplace=True)
)
(conv2): BaseConv(
(conv): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(act_fn): ReLU(inplace=True)
)
)
(1): Bottleneck(
(conv1): BaseConv(
(conv): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1))
(bn): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(act_fn): ReLU(inplace=True)
)
(conv2): BaseConv(
(conv): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(act_fn): ReLU(inplace=True)
)
)
)
)
)```

```from copy import deepcopy
from models import BaseConv, Bottleneck
import torch.nn as nn
import os
path = os.getcwd()
from pathlib import Path
import torch
def parse_model(yaml_cfg, ch):
"""
:param yaml_cfg: yaml file
:param ch: init in_channels default is 3
:return: model
"""
layer, out_channels = [], ch[-1]
for i, (f, number, Module_name, args) in enumerate(yaml_cfg['backbone']):
"""
f:上一层输出通道
number:该模块有几层，就是该模块要重复几次
Mdule_name：卷积层名字
args:参数，包含输出通道数，k,s,p等
"""
# 通过eval，将str类型转自己定义的BaseConv
m = eval(Module_name) if isinstance(Module_name, str) else Module_name
for j, a in enumerate(args):
# 通过eval，将str转int,获得输出通道数
args[j] = eval(a) if isinstance(a, str) else a
# 更新通道
# args[0]是输出通道
if m in [BaseConv, Bottleneck]:
in_channels, out_channels = ch[f], args[0]
args = [in_channels, out_channels, *args[1:]]  # args=[in_channels, out_channels, k, s, p]
# 将参数传入模型
model_ = nn.Sequential(*[m(*args) for _ in range(number)]) if number > 1 else m(*args)
# 更新通道列表，每次获取输出通道
ch.append(out_channels)
layer.append(model_)
return nn.Sequential(*layer)
class Model(nn.Module):
def __init__(self, cfg='./Model.yaml', ch=3, ):
super().__init__()
self.yaml = cfg
import yaml
yaml_file = Path(cfg).name
with open(yaml_file, errors='ignore')as f:
ch = self.yaml["ch"] = self.yaml["ch"] = 3
self.backbone = parse_model(deepcopy(self.yaml), ch=[ch])
def forward(self, x):
output = self.backbone(x)
return output
if __name__ == "__main__":
cfg = path + '/Model.yaml'
model = Model()
model.eval()
print(model)
x = torch.ones(1, 3, 512, 512)
output = model(x)
torch.save(model, "model.pth")