File size: 6,063 Bytes
3bbb319
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# 教程 10: 权重初始化

在训练过程中,适当的初始化策略有利于加快训练速度或获得更⾼的性能。 [MMCV](https://github.com/open-mmlab/mmcv/blob/master/mmcv/cnn/utils/weight_init.py) 提供了一些常⽤的初始化模块的⽅法,如 `nn.Conv2d`。 MMdetection 中的模型初始化主要使⽤ `init_cfg`。⽤⼾可以通过以下两个步骤来初始化模型:

1.`model_cfg` 中为模型或其组件定义 `init_cfg`,但⼦组件的 `init_cfg` 优先级更⾼,会覆盖⽗模块的 `init_cfg`2. 像往常一样构建模型,然后显式调⽤ `model.init_weights()` ⽅法,此时模型参数将会被按照配置文件写法进行初始化。

MMdetection 初始化工作流的高层 API 调用流程是:

model_cfg(init_cfg) -> build_from_cfg -> model -> init_weight() -> initialize(self, self.init_cfg) -> children's init_weight()

### 描述

它的数据类型是 dict 或者 list\[dict\],包含了下列键值:

- `type` (str),包含 `INTIALIZERS` 中的初始化器名称,后面跟着初始化器的参数。
- `layer`(str 或 list\[str\]),包含 Pytorch 或 MMCV 中基本层的名称,以及将被初始化的可学习参数,例如 `'Conv2d'`,`'DeformConv2d'`。
- `override` (dict 或 list\[dict\]),包含不继承⾃ `BaseModule` 且其初始化配置与 `layer` 键中的其他层不同的⼦模块。 `type` 中定义的初始化器将适⽤于 `layer` 中定义的所有层,因此如果⼦模块不是 `BaseModule` 的派⽣类但可以与 `layer` 中的层相同的⽅式初始化,则不需要使⽤ `override`。`override` 包含了:
  - `type` 后跟初始化器的参数;
  - `name` 用以指⽰将被初始化的⼦模块。

### 初始化参数

从 `mmcv.runner.BaseModule` 或 `mmdet.models` 继承一个新模型。这里我们用 FooModel 来举个例子。

```python
import torch.nn as nn
from mmcv.runner import BaseModule

class FooModel(BaseModule)
	def __init__(self,
                 arg1,
                 arg2,
                 init_cfg=None):
    	super(FooModel, self).__init__(init_cfg)
		...
```

- 直接在代码中使⽤ `init_cfg` 初始化模型

  ```python
  import torch.nn as nn
  from mmcv.runner import BaseModule
  # or directly inherit mmdet models

  class FooModel(BaseModule)
  	def __init__(self,
                  arg1,
                  arg2,
                  init_cfg=XXX):
    		super(FooModel, self).__init__(init_cfg)
    	    ...
  ```

-`mmcv.Sequential``mmcv.ModuleList` 代码中直接使⽤ `init_cfg` 初始化模型

  ```python
  from mmcv.runner import BaseModule, ModuleList

  class FooModel(BaseModule)
  	def __init__(self,
                	arg1,
                	arg2,
                	init_cfg=None):
    		super(FooModel, self).__init__(init_cfg)
        	...
        	self.conv1 = ModuleList(init_cfg=XXX)
  ```

- 使⽤配置⽂件中的 `init_cfg` 初始化模型

  ```python
  model = dict(
  	...
    	model = dict(
        	type='FooModel',
        	arg1=XXX,
        	arg2=XXX,
        	init_cfg=XXX),
            ...
  ```

### init_cfg 的使用

1. 用 `layer` 键初始化模型

   如果我们只定义了 `layer`, 它只会在 `layer` 键中初始化网络层。

   注意: `layer` 键对应的值是 Pytorch 的带有 weights 和 bias 属性的类名(因此不⽀持 `MultiheadAttention` 层)。

- 定义⽤于初始化具有相同配置的模块的 `layer` 键。

  ```python
  init_cfg = dict(type='Constant', layer=['Conv1d', 'Conv2d', 'Linear'], val=1)
  # ⽤相同的配置初始化整个模块
  ```

- 定义⽤于初始化具有不同配置的层的 `layer` 键。

  ```python
  init_cfg = [dict(type='Constant', layer='Conv1d', val=1),
              dict(type='Constant', layer='Conv2d', val=2),
              dict(type='Constant', layer='Linear', val=3)]
  # nn.Conv1d 将被初始化为 dict(type='Constant', val=1)
  # nn.Conv2d 将被初始化为 dict(type='Constant', val=2)
  # nn.Linear 将被初始化为 dict(type='Constant', val=3)
  ```

2. 使⽤ `override` 键初始化模型

- 当使⽤属性名初始化某些特定部分时,我们可以使⽤ `override` 键, `override` 中的值将忽略 init_cfg 中的值。

  ```python
  # layers:
  # self.feat = nn.Conv1d(3, 1, 3)
  # self.reg = nn.Conv2d(3, 3, 3)
  # self.cls = nn.Linear(1,2)

  init_cfg = dict(type='Constant',
                  layer=['Conv1d','Conv2d'], val=1, bias=2,
                  override=dict(type='Constant', name='reg', val=3, bias=4))
  # self.feat and self.cls 将被初始化为 dict(type='Constant', val=1, bias=2)
  # 叫 'reg' 的模块将被初始化为 dict(type='Constant', val=3, bias=4)
  ```

- 如果 init_cfg 中的 `layer` 为 None,则只会初始化 override 中有 name 的⼦模块,⽽ override 中的 type 和其他参数可以省略。

  ```python
  # layers:
  # self.feat = nn.Conv1d(3, 1, 3)
  # self.reg = nn.Conv2d(3, 3, 3)
  # self.cls = nn.Linear(1,2)

  init_cfg = dict(type='Constant', val=1, bias=2, 	override=dict(name='reg'))

  # self.feat and self.cls 将被 Pytorch 初始化
  # 叫 'reg' 的模块将被 dict(type='Constant', val=1, bias=2) 初始化
  ```

- 如果我们不定义 `layer` 或 `override` 键,它不会初始化任何东西。

- 无效的使用

  ```python
  # override 没有 name 键的话是无效的
  init_cfg = dict(type='Constant', layer=['Conv1d','Conv2d'], val=1, bias=2,
              	override=dict(type='Constant', val=3, bias=4))

  # override 有 name 键和其他参数但是没有 type 键也是无效的
  init_cfg = dict(type='Constant', layer=['Conv1d','Conv2d'], val=1, bias=2,
                  override=dict(name='reg', val=3, bias=4))
  ```

3. 使⽤预训练模型初始化模型

   ```python
   init_cfg = dict(type='Pretrained',
                checkpoint='torchvision://resnet50')
   ```

更多细节可以参考 [MMCV](https://mmcv.readthedocs.io/en/latest/cnn.html#weight-initialization) 的文档和 MMCV [PR #780](https://github.com/open-mmlab/mmcv/pull/780)