sppnet不讲了,懒得写。。。直接上代码

 1 from math import floor, ceil
 2 import torch
 3 import torch.nn as nn
 4 import torch.nn.functional as F
 5 
 6 class SpatialPyramidPooling2d(nn.Module):
 7     r"""apply spatial pyramid pooling over a 4d input(a mini-batch of 2d inputs 
 8     with additional channel dimension) as described in the paper
 9     'Spatial Pyramid Pooling in deep convolutional Networks for visual recognition'
10     Args:
11         num_level:
12         pool_type: max_pool, avg_pool, Default:max_pool
13     By the way, the target output size is num_grid:
14         num_grid = 0
15         for i in range num_level:
16             num_grid += (i + 1) * (i + 1)
17         num_grid = num_grid * channels # channels is the channel dimension of input data
18     examples:
19         >>> input = torch.randn((1,3,32,32), dtype=torch.float32)
20         >>> net = torch.nn.Sequential(nn.Conv2d(in_channels=3,out_channels=32,kernel_size=3,stride=1),\
21                                       nn.ReLU(),\
22                                       SpatialPyramidPooling2d(num_level=2,pool_type='avg_pool'),\
23                                       nn.Linear(32 * (1*1 + 2*2), 10))
24         >>> output = net(input)
25     """
26     
27     def __init__(self, num_level, pool_type='max_pool'):
28         super(SpatialPyramidPooling2d, self).__init__()
29         self.num_level = num_level
30         self.pool_type = pool_type
31 
32     def forward(self, x):
33         N, C, H, W = x.size()
34         for i in range(self.num_level):
35             level = i + 1
36             kernel_size = (ceil(H / level), ceil(W / level))
37             stride = (ceil(H / level), ceil(W / level))
38             padding = (floor((kernel_size[0] * level - H + 1) / 2), floor((kernel_size[1] * level - W + 1) / 2))
39 
40             if self.pool_type == 'max_pool':
41                 tensor = (F.max_pool2d(x, kernel_size=kernel_size, stride=stride, padding=padding)).view(N, -1)
42             else:
43                 tensor = (F.avg_pool2d(x, kernel_size=kernel_size, stride=stride, padding=padding)).view(N, -1)
44             
45             if i == 0:
46                 res = tensor
47             else:
48                 res = torch.cat((res, tensor), 1)
49         return res
50     def __repr__(self):
51         return self.__class__.__name__ + '(' \
52             + 'num_level = ' + str(self.num_level) \
53             + ', pool_type = ' + str(self.pool_type) + ')'
54     
55 
56 class SPPNet(nn.Module):
57     def __init__(self, num_level=3, pool_type='max_pool'):
58         super(SPPNet,self).__init__()
59         self.num_level = num_level
60         self.pool_type = pool_type
61         self.feature = nn.Sequential(nn.Conv2d(3,64,3),\
62                                     nn.ReLU(),\
63                                     nn.MaxPool2d(2),\
64                                     nn.Conv2d(64,64,3),\
65                                     nn.ReLU())
66         self.num_grid = self._cal_num_grids(num_level)
67         self.spp_layer = SpatialPyramidPooling2d(num_level)
68         self.linear = nn.Sequential(nn.Linear(self.num_grid * 64, 512),\
69                                     nn.Linear(512, 10))
70     def _cal_num_grids(self, level):
71         count = 0
72         for i in range(level):
73             count += (i + 1) * (i + 1)
74         return count
75 
76     def forward(self, x):
77         x = self.feature(x)
78         x = self.spp_layer(x)
79         print(x.size())
80         x = self.linear(x)
81         return x
82 
83 if __name__ == '__main__':
84     a = torch.rand((1,3,64,64))
85     net = SPPNet()
86     output = net(a)
87     print(output)