| 198 | |
| 199 | |
| 200 | class Model(nn.Module): |
| 201 | def __init__(self, n_parts=8): |
| 202 | super(Model, self).__init__() |
| 203 | self.n_parts = n_parts |
| 204 | |
| 205 | self.feat_conv = GoogLeNet() |
| 206 | self.conv_input_feat = nn.Conv2d(self.feat_conv.output_channels, 512, 1) |
| 207 | |
| 208 | # part net |
| 209 | self.conv_att = nn.Conv2d(512, self.n_parts, 1) |
| 210 | |
| 211 | for i in range(self.n_parts): |
| 212 | setattr(self, 'linear_feature{}'.format(i+1), nn.Linear(512, 64)) |
| 213 | |
| 214 | def forward(self, x): |
| 215 | feature = self.feat_conv(x) |
| 216 | feature = self.conv_input_feat(feature) |
| 217 | |
| 218 | att_weights = torch.sigmoid(self.conv_att(feature)) |
| 219 | |
| 220 | linear_feautres = [] |
| 221 | for i in range(self.n_parts): |
| 222 | masked_feature = feature * torch.unsqueeze(att_weights[:, i], 1) |
| 223 | pooled_feature = F.avg_pool2d(masked_feature, masked_feature.size()[2:4]) |
| 224 | linear_feautres.append( |
| 225 | getattr(self, 'linear_feature{}'.format(i+1))(pooled_feature.view(pooled_feature.size(0), -1)) |
| 226 | ) |
| 227 | |
| 228 | concat_features = torch.cat(linear_feautres, 1) |
| 229 | normed_feature = concat_features / torch.clamp(torch.norm(concat_features, 2, 1, keepdim=True), min=1e-6) |
| 230 | |
| 231 | return normed_feature |
| 232 | |
| 233 | |
| 234 | def load_reid_model(ckpt): |
no outgoing calls
no test coverage detected