from torch import nn class LinearClassifier(nn.Module): """Linear layer to train on top of frozen features""" def __init__( self, dim: int, num_labels: int = 1000, use_dropout_in_head: bool = False, dropout_rate: float = 0.3, large_head: bool = True, use_bn: bool = False, log_softmax: bool = False, ): super(LinearClassifier, self).__init__() self.num_labels = num_labels self.large_head = large_head self.use_bn = use_bn self.log_softmax = log_softmax self.use_dropout_in_head = use_dropout_in_head if self.use_dropout_in_head: self.dropout = nn.Dropout(dropout_rate) if self.use_bn: self.bn = nn.BatchNorm1d(dim) if self.large_head: self.linear = nn.Linear(dim, 128) self.linear.weight.data.normal_(mean=0.0, std=0.01) self.linear.bias.data.zero_() self.relu = nn.ReLU() self.dropout2 = nn.Dropout(dropout_rate) if self.use_bn: self.bn2 = nn.BatchNorm1d(128) self.linear2 = nn.Linear(128, num_labels) self.linear2.weight.data.normal_(mean=0.0, std=0.01) self.linear2.bias.data.zero_() else: self.linear = nn.Linear(dim, num_labels) self.linear.weight.data.normal_(mean=0.0, std=0.01) self.linear.bias.data.zero_() def forward(self, x): # flatten x = x.view(x.size(0), -1) # dropout if self.use_dropout_in_head: x = self.dropout(x) if self.use_bn: x = self.bn(x) # 1. linear layer x = self.linear(x) # smaller version of head if self.large_head: x = self.relu(x) x = self.dropout2(x) if self.use_bn: x = self.bn2(x) # 2. linear layer x = self.linear2(x) # output if self.log_softmax: return nn.LogSoftmax(dim=1)(x) else: return x