Spaces:
Runtime error
Runtime error
''' | |
Reference: | |
https://github.com/hshustc/CVPR19_Incremental_Learning/blob/master/cifar100-class-incremental/modified_linear.py | |
''' | |
import math | |
import torch | |
from torch import nn | |
from torch.nn import functional as F | |
class SimpleLinear(nn.Module): | |
''' | |
Reference: | |
https://github.com/pytorch/pytorch/blob/master/torch/nn/modules/linear.py | |
''' | |
def __init__(self, in_features, out_features, bias=True): | |
super(SimpleLinear, self).__init__() | |
self.in_features = in_features | |
self.out_features = out_features | |
self.weight = nn.Parameter(torch.Tensor(out_features, in_features)) | |
if bias: | |
self.bias = nn.Parameter(torch.Tensor(out_features)) | |
else: | |
self.register_parameter('bias', None) | |
self.reset_parameters() | |
def reset_parameters(self): | |
nn.init.kaiming_uniform_(self.weight, nonlinearity='linear') | |
nn.init.constant_(self.bias, 0) | |
def forward(self, input): | |
return {'logits': F.linear(input, self.weight, self.bias)} | |
class CosineLinear(nn.Module): | |
def __init__(self, in_features, out_features, nb_proxy=1, to_reduce=False, sigma=True): | |
super(CosineLinear, self).__init__() | |
self.in_features = in_features | |
self.out_features = out_features * nb_proxy | |
self.nb_proxy = nb_proxy | |
self.to_reduce = to_reduce | |
self.weight = nn.Parameter(torch.Tensor(self.out_features, in_features)) | |
if sigma: | |
self.sigma = nn.Parameter(torch.Tensor(1)) | |
else: | |
self.register_parameter('sigma', None) | |
self.reset_parameters() | |
def reset_parameters(self): | |
stdv = 1. / math.sqrt(self.weight.size(1)) | |
self.weight.data.uniform_(-stdv, stdv) | |
if self.sigma is not None: | |
self.sigma.data.fill_(1) | |
def forward(self, input): | |
out = F.linear(F.normalize(input, p=2, dim=1), F.normalize(self.weight, p=2, dim=1)) | |
if self.to_reduce: | |
# Reduce_proxy | |
out = reduce_proxies(out, self.nb_proxy) | |
if self.sigma is not None: | |
out = self.sigma * out | |
return {'logits': out} | |
class SplitCosineLinear(nn.Module): | |
def __init__(self, in_features, out_features1, out_features2, nb_proxy=1, sigma=True): | |
super(SplitCosineLinear, self).__init__() | |
self.in_features = in_features | |
self.out_features = (out_features1 + out_features2) * nb_proxy | |
self.nb_proxy = nb_proxy | |
self.fc1 = CosineLinear(in_features, out_features1, nb_proxy, False, False) | |
self.fc2 = CosineLinear(in_features, out_features2, nb_proxy, False, False) | |
if sigma: | |
self.sigma = nn.Parameter(torch.Tensor(1)) | |
self.sigma.data.fill_(1) | |
else: | |
self.register_parameter('sigma', None) | |
def forward(self, x): | |
out1 = self.fc1(x) | |
out2 = self.fc2(x) | |
out = torch.cat((out1['logits'], out2['logits']), dim=1) # concatenate along the channel | |
# Reduce_proxy | |
out = reduce_proxies(out, self.nb_proxy) | |
if self.sigma is not None: | |
out = self.sigma * out | |
return { | |
'old_scores': reduce_proxies(out1['logits'], self.nb_proxy), | |
'new_scores': reduce_proxies(out2['logits'], self.nb_proxy), | |
'logits': out | |
} | |
def reduce_proxies(out, nb_proxy): | |
if nb_proxy == 1: | |
return out | |
bs = out.shape[0] | |
nb_classes = out.shape[1] / nb_proxy | |
assert nb_classes.is_integer(), 'Shape error' | |
nb_classes = int(nb_classes) | |
simi_per_class = out.view(bs, nb_classes, nb_proxy) | |
attentions = F.softmax(simi_per_class, dim=-1) | |
return (attentions * simi_per_class).sum(-1) | |
''' | |
class CosineLinear(nn.Module): | |
def __init__(self, in_features, out_features, sigma=True): | |
super(CosineLinear, self).__init__() | |
self.in_features = in_features | |
self.out_features = out_features | |
self.weight = nn.Parameter(torch.Tensor(out_features, in_features)) | |
if sigma: | |
self.sigma = nn.Parameter(torch.Tensor(1)) | |
else: | |
self.register_parameter('sigma', None) | |
self.reset_parameters() | |
def reset_parameters(self): | |
stdv = 1. / math.sqrt(self.weight.size(1)) | |
self.weight.data.uniform_(-stdv, stdv) | |
if self.sigma is not None: | |
self.sigma.data.fill_(1) | |
def forward(self, input): | |
out = F.linear(F.normalize(input, p=2, dim=1), F.normalize(self.weight, p=2, dim=1)) | |
if self.sigma is not None: | |
out = self.sigma * out | |
return {'logits': out} | |
class SplitCosineLinear(nn.Module): | |
def __init__(self, in_features, out_features1, out_features2, sigma=True): | |
super(SplitCosineLinear, self).__init__() | |
self.in_features = in_features | |
self.out_features = out_features1 + out_features2 | |
self.fc1 = CosineLinear(in_features, out_features1, False) | |
self.fc2 = CosineLinear(in_features, out_features2, False) | |
if sigma: | |
self.sigma = nn.Parameter(torch.Tensor(1)) | |
self.sigma.data.fill_(1) | |
else: | |
self.register_parameter('sigma', None) | |
def forward(self, x): | |
out1 = self.fc1(x) | |
out2 = self.fc2(x) | |
out = torch.cat((out1['logits'], out2['logits']), dim=1) # concatenate along the channel | |
if self.sigma is not None: | |
out = self.sigma * out | |
return { | |
'old_scores': out1['logits'], | |
'new_scores': out2['logits'], | |
'logits': out | |
} | |
''' | |