-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathresnext29.py
127 lines (97 loc) · 4.04 KB
/
resnext29.py
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
import torch.nn as nn
import torch.nn.functional as F
from torch.nn import init
import math
__all__=['resnext29_8_64', 'resnext29_16_64']
class ResNeXtBottleneck(nn.Module):
expansion = 4
def __init__(self, inplanes, planes, cardinality, base_width, stride=1, downsample=None):
super(ResNeXtBottleneck, self).__init__()
D = int(math.floor(planes * (base_width/64.0)))#返回最大整数
C = cardinality
self.conv_reduce = nn.Conv2d(inplanes, D*C, kernel_size=1, stride=stride, padding=0, bias=False)
self.bn_reduce = nn.BatchNorm2d(D*C)
self.conv_conv = nn.Conv2d(D*C, D*C, kernel_size=3, stride=1, padding=1, groups=cardinality, bias=False)
self.bn = nn.BatchNorm2d(D*C)
self.conv_expand = nn.Conv2d(D*C, planes*4, kernel_size=1, stride=1, padding=0, bias=False)
self.bn_expand = nn.BatchNorm2d(planes*4)
self.downsample = downsample
def forward(self, x):
residual = x
bottleneck = self.conv_reduce(x)
bottleneck = F.relu(self.bn_reduce(bottleneck), inplace=True)
bottleneck = self.conv_conv(bottleneck)
bottleneck = F.relu(self.bn(bottleneck), inplace=True)
bottleneck = self.conv_expand(bottleneck)
bottleneck = self.bn_expand(bottleneck)
if self.downsample is not None:
residual = self.downsample(x)
return F.relu(residual + bottleneck, inplace=True)
class CifarResNeXt(nn.Module):
"""
ResNext optimized for the Cifar dataset, as specified in
https://arxiv.org/pdf/1611.05431.pdf
"""
def __init__(self, block, depth, cardinality, base_width, num_classes):
super(CifarResNeXt, self).__init__()
#Model type specifies number of layers for CIFAR-10 and CIFAR-100 model
assert (depth - 2) % 9 == 0, 'depth should be one of 29, 38, 47, 56, 101'
layer_blocks = (depth - 2) // 9
self.cardinality = cardinality
self.base_width = base_width
self.num_classes = num_classes
self.conv_1_3x3 = nn.Conv2d(3, 64, 3, 1, 1, bias=False)
self.bn_1 = nn.BatchNorm2d(64)
self.inplanes = 64
self.stage_1 = self._make_layer(block, 64 , layer_blocks, 1)
self.stage_2 = self._make_layer(block, 128, layer_blocks, 2)
self.stage_3 = self._make_layer(block, 256, layer_blocks, 2)
self.avgpool = nn.AvgPool2d(8)
self.classifier = nn.Linear(256*block.expansion, num_classes)
for m in self.modules():
if isinstance(m, nn.Conv2d):
n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
m.weight.data.normal_(0, math.sqrt(2. / n))
elif isinstance(m, nn.BatchNorm2d):
m.weight.data.fill_(1)
m.bias.data.zero_()
elif isinstance(m, nn.Linear):
init.kaiming_normal(m.weight)
m.bias.data.zero_()
def _make_layer(self, block, planes, blocks, stride=1):
downsample = None
if stride != 1 or self.inplanes != planes * block.expansion:
downsample = nn.Sequential(
nn.Conv2d(self.inplanes, planes * block.expansion,
kernel_size=1, stride=stride, bias=False),
nn.BatchNorm2d(planes * block.expansion),
)
layers = []
layers.append(block(self.inplanes, planes, self.cardinality, self.base_width, stride, downsample))
self.inplanes = planes * block.expansion
for i in range(1, blocks):
layers.append(block(self.inplanes, planes, self.cardinality, self.base_width))
return nn.Sequential(*layers)
def forward(self, x):
x = self.conv_1_3x3(x)
x = F.relu(self.bn_1(x), inplace=True)
x = self.stage_1(x)
x = self.stage_2(x)
x = self.stage_3(x)
x = self.avgpool(x)
x = x.view(x.size(0), -1)
return self.classifier(x)
def resnext29_16_64(num_classes=100):
"""Constructs a ResNeXt-29, 16*64d model for CIFAR-100 (by default)
Args:
num_classes (uint): number of classes
"""
model = CifarResNeXt(ResNeXtBottleneck, 29, 16, 64, num_classes)
return model
def resnext29_8_64(num_classes=100):
"""Constructs a ResNeXt-29, 8*64d model for CIFAR-100 (by default)
Args:
num_classes (uint): number of classes
"""
model = CifarResNeXt(ResNeXtBottleneck, 29, 8, 64, num_classes)
return model