Skip to content

Commit 36e7db6

Browse files
authored
Network Cleanup (#81)
* removed old supported_tasks dictionary from heads, added some docstrings and some small fixes * removed old supported_tasks attribute and updated doc strings in base backbone and base head components * removed old supported_tasks attribute from network backbones * put time series backbones in separate files, add doc strings and refactored search space arguments * split image networks into separate files, add doc strings and refactor search space * fix typo * add an intial simple backbone test similar to the network head test * fix flake8 * fixed imports in backbones and heads * added new network backbone and head tests * enabled tests for adding custom backbones and heads, added required properties to base head and base backbone
1 parent ddc0f3d commit 36e7db6

15 files changed

+832
-555
lines changed
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
from typing import Any, Dict, List, Optional, Tuple
2+
3+
import ConfigSpace as CS
4+
from ConfigSpace.configuration_space import ConfigurationSpace
5+
from ConfigSpace.hyperparameters import (
6+
CategoricalHyperparameter,
7+
UniformIntegerHyperparameter
8+
)
9+
10+
from torch import nn
11+
12+
from autoPyTorch.pipeline.components.setup.network_backbone.base_network_backbone import NetworkBackboneComponent
13+
from autoPyTorch.pipeline.components.setup.network_backbone.utils import _activations
14+
15+
16+
class ConvNetImageBackbone(NetworkBackboneComponent):
17+
"""
18+
Standard Convolutional Neural Network backbone for images
19+
"""
20+
21+
def __init__(self, **kwargs: Any):
22+
super().__init__(**kwargs)
23+
self.bn_args = {"eps": 1e-5, "momentum": 0.1}
24+
25+
def _get_layer_size(self, w: int, h: int) -> Tuple[int, int]:
26+
cw = ((w - self.config["conv_kernel_size"] + 2 * self.config["conv_kernel_padding"])
27+
// self.config["conv_kernel_stride"]) + 1
28+
ch = ((h - self.config["conv_kernel_size"] + 2 * self.config["conv_kernel_padding"])
29+
// self.config["conv_kernel_stride"]) + 1
30+
cw, ch = cw // self.config["pool_size"], ch // self.config["pool_size"]
31+
return cw, ch
32+
33+
def _add_layer(self, layers: List[nn.Module], in_filters: int, out_filters: int) -> None:
34+
layers.append(nn.Conv2d(in_filters, out_filters,
35+
kernel_size=self.config["conv_kernel_size"],
36+
stride=self.config["conv_kernel_stride"],
37+
padding=self.config["conv_kernel_padding"]))
38+
layers.append(nn.BatchNorm2d(out_filters, **self.bn_args))
39+
layers.append(_activations[self.config["activation"]]())
40+
layers.append(nn.MaxPool2d(kernel_size=self.config["pool_size"], stride=self.config["pool_size"]))
41+
42+
def build_backbone(self, input_shape: Tuple[int, ...]) -> nn.Module:
43+
channels, iw, ih = input_shape
44+
layers: List[nn.Module] = []
45+
init_filter = self.config["conv_init_filters"]
46+
self._add_layer(layers, channels, init_filter)
47+
48+
cw, ch = self._get_layer_size(iw, ih)
49+
for i in range(2, self.config["num_layers"] + 1):
50+
cw, ch = self._get_layer_size(cw, ch)
51+
if cw == 0 or ch == 0:
52+
break
53+
self._add_layer(layers, init_filter, init_filter * 2)
54+
init_filter *= 2
55+
backbone = nn.Sequential(*layers)
56+
self.backbone = backbone
57+
return backbone
58+
59+
@staticmethod
60+
def get_properties(dataset_properties: Optional[Dict[str, str]] = None) -> Dict[str, Any]:
61+
return {
62+
'shortname': 'ConvNetImageBackbone',
63+
'name': 'ConvNetImageBackbone',
64+
'handles_tabular': False,
65+
'handles_image': True,
66+
'handles_time_series': False,
67+
}
68+
69+
@staticmethod
70+
def get_hyperparameter_search_space(dataset_properties: Optional[Dict] = None,
71+
num_layers: Tuple[Tuple, int] = ((2, 8), 4),
72+
num_init_filters: Tuple[Tuple, int] = ((16, 64), 32),
73+
activation: Tuple[Tuple, str] = (tuple(_activations.keys()),
74+
list(_activations.keys())[0]),
75+
kernel_size: Tuple[Tuple, int] = ((3, 5), 3),
76+
stride: Tuple[Tuple, int] = ((1, 3), 1),
77+
padding: Tuple[Tuple, int] = ((2, 3), 2),
78+
pool_size: Tuple[Tuple, int] = ((2, 3), 2)
79+
) -> ConfigurationSpace:
80+
cs = CS.ConfigurationSpace()
81+
82+
min_num_layers, max_num_layers = num_layers[0]
83+
cs.add_hyperparameter(UniformIntegerHyperparameter('num_layers',
84+
lower=min_num_layers,
85+
upper=max_num_layers,
86+
default_value=num_layers[1]))
87+
88+
cs.add_hyperparameter(CategoricalHyperparameter('activation',
89+
choices=activation[0],
90+
default_value=activation[1]))
91+
92+
min_init_filters, max_init_filters = num_init_filters[0]
93+
cs.add_hyperparameter(UniformIntegerHyperparameter('conv_init_filters',
94+
lower=min_init_filters,
95+
upper=max_init_filters,
96+
default_value=num_init_filters[1]))
97+
98+
min_kernel_size, max_kernel_size = kernel_size[0]
99+
cs.add_hyperparameter(UniformIntegerHyperparameter('conv_kernel_size',
100+
lower=min_kernel_size,
101+
upper=max_kernel_size,
102+
default_value=kernel_size[1]))
103+
104+
min_stride, max_stride = stride[0]
105+
cs.add_hyperparameter(UniformIntegerHyperparameter('conv_kernel_stride',
106+
lower=min_stride,
107+
upper=max_stride,
108+
default_value=stride[1]))
109+
110+
min_padding, max_padding = padding[0]
111+
cs.add_hyperparameter(UniformIntegerHyperparameter('conv_kernel_padding',
112+
lower=min_padding,
113+
upper=max_padding,
114+
default_value=padding[1]))
115+
116+
min_pool_size, max_pool_size = pool_size[0]
117+
cs.add_hyperparameter(UniformIntegerHyperparameter('pool_size',
118+
lower=min_pool_size,
119+
upper=max_pool_size,
120+
default_value=pool_size[1]))
121+
122+
return cs

autoPyTorch/pipeline/components/setup/network_backbone/image.py renamed to autoPyTorch/pipeline/components/setup/network_backbone/DenseNetImageBackone.py

Lines changed: 35 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import logging
21
import math
32
from collections import OrderedDict
4-
from typing import Any, Dict, List, Optional, Tuple
3+
from typing import Any, Dict, Optional, Tuple
54

65
import ConfigSpace as CS
76
from ConfigSpace.configuration_space import ConfigurationSpace
@@ -16,103 +15,7 @@
1615
from torch.nn import functional as F
1716

1817
from autoPyTorch.pipeline.components.setup.network_backbone.base_network_backbone import NetworkBackboneComponent
19-
20-
_activations: Dict[str, nn.Module] = {
21-
"relu": nn.ReLU,
22-
"tanh": nn.Tanh,
23-
"sigmoid": nn.Sigmoid
24-
}
25-
26-
27-
class ConvNetImageBackbone(NetworkBackboneComponent):
28-
supported_tasks = {"image_classification", "image_regression"}
29-
30-
def __init__(self, **kwargs: Any):
31-
super().__init__(**kwargs)
32-
self.bn_args = {"eps": 1e-5, "momentum": 0.1}
33-
34-
def _get_layer_size(self, w: int, h: int) -> Tuple[int, int]:
35-
cw = ((w - self.config["conv_kernel_size"] + 2 * self.config["conv_kernel_padding"])
36-
// self.config["conv_kernel_stride"]) + 1
37-
ch = ((h - self.config["conv_kernel_size"] + 2 * self.config["conv_kernel_padding"])
38-
// self.config["conv_kernel_stride"]) + 1
39-
cw, ch = cw // self.config["pool_size"], ch // self.config["pool_size"]
40-
return cw, ch
41-
42-
def _add_layer(self, layers: List[nn.Module], in_filters: int, out_filters: int) -> None:
43-
layers.append(nn.Conv2d(in_filters, out_filters,
44-
kernel_size=self.config["conv_kernel_size"],
45-
stride=self.config["conv_kernel_stride"],
46-
padding=self.config["conv_kernel_padding"]))
47-
layers.append(nn.BatchNorm2d(out_filters, **self.bn_args))
48-
layers.append(_activations[self.config["activation"]]())
49-
layers.append(nn.MaxPool2d(kernel_size=self.config["pool_size"], stride=self.config["pool_size"]))
50-
51-
def build_backbone(self, input_shape: Tuple[int, ...]) -> nn.Module:
52-
channels, iw, ih = input_shape
53-
layers: List[nn.Module] = []
54-
init_filter = self.config["conv_init_filters"]
55-
self._add_layer(layers, channels, init_filter)
56-
57-
cw, ch = self._get_layer_size(iw, ih)
58-
for i in range(2, self.config["num_layers"] + 1):
59-
cw, ch = self._get_layer_size(cw, ch)
60-
if cw == 0 or ch == 0:
61-
logging.info("> reduce network size due to too small layers.")
62-
break
63-
self._add_layer(layers, init_filter, init_filter * 2)
64-
init_filter *= 2
65-
backbone = nn.Sequential(*layers)
66-
self.backbone = backbone
67-
return backbone
68-
69-
@staticmethod
70-
def get_properties(dataset_properties: Optional[Dict[str, str]] = None) -> Dict[str, Any]:
71-
return {
72-
'shortname': 'ConvNetImageBackbone',
73-
'name': 'ConvNetImageBackbone',
74-
'handles_tabular': False,
75-
'handles_image': True,
76-
'handles_time_series': False,
77-
}
78-
79-
@staticmethod
80-
def get_hyperparameter_search_space(dataset_properties: Optional[Dict[str, str]] = None,
81-
min_num_layers: int = 2,
82-
max_num_layers: int = 5,
83-
min_init_filters: int = 16,
84-
max_init_filters: int = 64,
85-
min_kernel_size: int = 2,
86-
max_kernel_size: int = 5,
87-
min_stride: int = 1,
88-
max_stride: int = 3,
89-
min_padding: int = 2,
90-
max_padding: int = 3,
91-
min_pool_size: int = 2,
92-
max_pool_size: int = 3) -> ConfigurationSpace:
93-
cs = CS.ConfigurationSpace()
94-
95-
cs.add_hyperparameter(UniformIntegerHyperparameter('num_layers',
96-
lower=min_num_layers,
97-
upper=max_num_layers))
98-
cs.add_hyperparameter(CategoricalHyperparameter('activation',
99-
choices=list(_activations.keys())))
100-
cs.add_hyperparameter(UniformIntegerHyperparameter('conv_init_filters',
101-
lower=min_init_filters,
102-
upper=max_init_filters))
103-
cs.add_hyperparameter(UniformIntegerHyperparameter('conv_kernel_size',
104-
lower=min_kernel_size,
105-
upper=max_kernel_size))
106-
cs.add_hyperparameter(UniformIntegerHyperparameter('conv_kernel_stride',
107-
lower=min_stride,
108-
upper=max_stride))
109-
cs.add_hyperparameter(UniformIntegerHyperparameter('conv_kernel_padding',
110-
lower=min_padding,
111-
upper=max_padding))
112-
cs.add_hyperparameter(UniformIntegerHyperparameter('pool_size',
113-
lower=min_pool_size,
114-
upper=max_pool_size))
115-
return cs
18+
from autoPyTorch.pipeline.components.setup.network_backbone.utils import _activations
11619

11720

11821
class _DenseLayer(nn.Sequential):
@@ -177,7 +80,9 @@ def __init__(self,
17780

17881

17982
class DenseNetBackbone(NetworkBackboneComponent):
180-
supported_tasks = {"image_classification", "image_regression"}
83+
"""
84+
Dense Net Backbone for images (see https://arxiv.org/pdf/1608.06993.pdf)
85+
"""
18186

18287
def __init__(self, **kwargs: Any):
18388
super().__init__(**kwargs)
@@ -247,39 +152,55 @@ def get_properties(dataset_properties: Optional[Dict[str, str]] = None) -> Dict[
247152
}
248153

249154
@staticmethod
250-
def get_hyperparameter_search_space(dataset_properties: Optional[Dict[str, str]] = None,
251-
min_growth_rate: int = 12,
252-
max_growth_rate: int = 40,
253-
min_num_blocks: int = 3,
254-
max_num_blocks: int = 4,
255-
min_num_layers: int = 4,
256-
max_num_layers: int = 64) -> ConfigurationSpace:
155+
def get_hyperparameter_search_space(dataset_properties: Optional[Dict] = None,
156+
num_blocks: Tuple[Tuple, int] = ((3, 4), 3),
157+
num_layers: Tuple[Tuple, int] = ((4, 64), 16),
158+
growth_rate: Tuple[Tuple, int] = ((12, 40), 20),
159+
activation: Tuple[Tuple, str] = (tuple(_activations.keys()),
160+
list(_activations.keys())[0]),
161+
use_dropout: Tuple[Tuple, bool] = ((True, False), False),
162+
dropout: Tuple[Tuple, float] = ((0, 0.5), 0.2)
163+
) -> ConfigurationSpace:
257164
cs = CS.ConfigurationSpace()
165+
166+
min_growth_rate, max_growth_rate = growth_rate[0]
258167
growth_rate_hp = UniformIntegerHyperparameter('growth_rate',
259168
lower=min_growth_rate,
260-
upper=max_growth_rate)
169+
upper=max_growth_rate,
170+
default_value=growth_rate[1])
261171
cs.add_hyperparameter(growth_rate_hp)
262172

173+
min_num_blocks, max_num_blocks = num_blocks[0]
263174
blocks_hp = UniformIntegerHyperparameter('blocks',
264175
lower=min_num_blocks,
265-
upper=max_num_blocks)
176+
upper=max_num_blocks,
177+
default_value=num_blocks[1])
266178
cs.add_hyperparameter(blocks_hp)
267179

268180
activation_hp = CategoricalHyperparameter('activation',
269-
choices=list(_activations.keys()))
181+
choices=activation[0],
182+
default_value=activation[1])
270183
cs.add_hyperparameter(activation_hp)
271184

272-
use_dropout = CategoricalHyperparameter('use_dropout', choices=[True, False])
185+
use_dropout = CategoricalHyperparameter('use_dropout',
186+
choices=use_dropout[0],
187+
default_value=use_dropout[1])
188+
189+
min_dropout, max_dropout = dropout[0]
273190
dropout = UniformFloatHyperparameter('dropout',
274-
lower=0.0,
275-
upper=1.0)
191+
lower=min_dropout,
192+
upper=max_dropout,
193+
default_value=dropout[1])
194+
276195
cs.add_hyperparameters([use_dropout, dropout])
277196
cs.add_condition(CS.EqualsCondition(dropout, use_dropout, True))
278197

279198
for i in range(1, max_num_blocks + 1):
199+
min_num_layers, max_num_layers = num_layers[0]
280200
layer_hp = UniformIntegerHyperparameter('layer_in_block_%d' % i,
281201
lower=min_num_layers,
282-
upper=max_num_layers)
202+
upper=max_num_layers,
203+
default_value=num_layers[1])
283204
cs.add_hyperparameter(layer_hp)
284205

285206
if i > min_num_blocks:

0 commit comments

Comments
 (0)