Pytorch AttributeError: can't set attribute
I'm using pytorch lightining and I have this error but I'm non really understanding what is the problem. I create a Deep Learning pipeline to run with hyperparameters searching and I think that the problem is in.
I omitted some part of the code because I think they are irrelevant for this issue (due to stackoverflow restrictions). Thanks for the help!
class ProtBertBFDClassifier(pl.LightningModule):

    def __init__(self,hparams) -&gt; None:
        super(ProtBertBFDClassifier, self).__init__()
        self.hparams = hparams
        self.batch_size = self.hparams.batch_size

        self.model_name = pretrained_model_name
        
        self.dataset = Loc_dataset()

        self.metric_acc = Accuracy()

        # build model
        self.__build_model()

        # Loss criterion initialization.
        self.__build_loss()

        if self.hparams.nr_frozen_epochs &gt; 0:
            self.freeze_encoder()
        else:
            self._frozen = False
        self.nr_frozen_epochs = self.hparams.nr_frozen_epochs

    

    def __build_model(self) -&gt; None:
        &quot;&quot;&quot; Init BERT model + tokenizer + classification head.&quot;&quot;&quot;
        self.ProtBertBFD = BertModel.from_pretrained(self.model_name,gradient_checkpointing=self.hparams.gradient_checkpointing)
        self.encoder_features = 1024

        # Tokenizer
        self.tokenizer = BertTokenizer.from_pretrained(self.model_name, do_lower_case=False)

        # Label Encoder
        self.label_encoder = LabelEncoder(
            self.hparams.label_set.split(&quot;,&quot;), reserved_labels=[]
        )
        self.label_encoder.unknown_index = None

        # Classification head
        self.classification_head = nn.Sequential(
            nn.Linear(self.encoder_features*4, self.label_encoder.vocab_size),
            nn.Tanh(),
        )

    .....
    def predict(self, sample: dict) -&gt; dict:
        &quot;&quot;&quot; Predict function.
        :param sample: dictionary with the text we want to classify.
        Returns:
            Dictionary with the input text and the predicted label.
        &quot;&quot;&quot;
......
    
    
    def pool_strategy(self, features,
                      pool_cls=True, pool_max=True, pool_mean=True,
                      pool_mean_sqrt=True):
        token_embeddings = features['token_embeddings']
        cls_token = features['cls_token_embeddings']
        attention_mask = features['attention_mask']

        ## Pooling strategy
        output_vectors = []
        if pool_cls:
            output_vectors.append(cls_token)
        if pool_max:
            input_mask_expanded = attention_mask.unsqueeze(-1).expand(token_embeddings.size()).float()
            token_embeddings[input_mask_expanded == 0] = -1e9  # Set padding tokens to large negative value
            max_over_time = torch.max(token_embeddings, 1)[0]
            output_vectors.append(max_over_time)
        if pool_mean or pool_mean_sqrt:
            input_mask_expanded = attention_mask.unsqueeze(-1).expand(token_embeddings.size()).float()
            sum_embeddings = torch.sum(token_embeddings * input_mask_expanded, 1)

            #If tokens are weighted (by WordWeights layer), feature 'token_weights_sum' will be present
            if 'token_weights_sum' in features:
                sum_mask = features['token_weights_sum'].unsqueeze(-1).expand(sum_embeddings.size())
            else:
                sum_mask = input_mask_expanded.sum(1)

            sum_mask = torch.clamp(sum_mask, min=1e-9)

            if pool_mean:
                output_vectors.append(sum_embeddings / sum_mask)
            if pool_mean_sqrt:
                output_vectors.append(sum_embeddings / torch.sqrt(sum_mask))

        output_vector = torch.cat(output_vectors, 1)
        return output_vector
    
   ........

        inputs = self.tokenizer.batch_encode_plus(sample[&quot;seq&quot;],
                                                  add_special_tokens=True,
                                                  padding=True,
                                                  truncation=True,
                                                  max_length=self.hparams.max_length)

        if not prepare_target:
            return inputs, {}

        # Prepare target:
        try:
            targets = {&quot;labels&quot;: self.label_encoder.batch_encode(sample[&quot;label&quot;])}
            return inputs, targets
        except RuntimeError:
            print(sample[&quot;label&quot;])
            raise Exception(&quot;Label encoder found an unknown label.&quot;)

   
......

    def validation_step(self, batch: tuple, batch_nb: int, *args, **kwargs) -&gt; dict:
        &quot;&quot;&quot; Similar to the training step but with the model in eval mode.
        Returns:
            - dictionary passed to the validation_end function.
        &quot;&quot;&quot;
        inputs, targets = batch

        model_out = self.forward(**inputs)
        loss_val = self.loss(model_out, targets)

        y = targets[&quot;labels&quot;]
        y_hat = model_out[&quot;logits&quot;]
        
        labels_hat = torch.argmax(y_hat, dim=1)
        val_acc = self.metric_acc(labels_hat, y)
        
        output = OrderedDict({&quot;val_loss&quot;: loss_val, &quot;val_acc&quot;: val_acc,})

        return output
        
    
    def validation_epoch_end(self, outputs: list) -&gt; dict:
        &quot;&quot;&quot; Function that takes as input a list of dictionaries returned by the validation_step
        function and measures the model performance accross the entire validation set.
        
        Returns:
            - Dictionary with metrics to be added to the lightning logger.  
        &quot;&quot;&quot;

        val_loss_mean = torch.stack([x['val_loss'] for x in outputs]).mean()
        val_acc_mean = torch.stack([x['val_acc'] for x in outputs]).mean()

        tqdm_dict = {&quot;val_loss&quot;: val_loss_mean, &quot;val_acc&quot;: val_acc_mean}
        result = {
            &quot;progress_bar&quot;: tqdm_dict,
            &quot;log&quot;: tqdm_dict,
            &quot;val_loss&quot;: val_loss_mean,
        }
        return result
    
.......
        
    def test_epoch_end(self, outputs: list) -&gt; dict:
        &quot;&quot;&quot; Function that takes as input a list of dictionaries returned by the validation_step
        function and measures the model performance accross the entire validation set.
        
        Returns:
            - Dictionary with metrics to be added to the lightning logger.  
        &quot;&quot;&quot;
        test_loss_mean = torch.stack([x['test_loss'] for x in outputs]).mean()
        test_acc_mean = torch.stack([x['test_acc'] for x in outputs]).mean()

        tqdm_dict = {&quot;test_loss&quot;: test_loss_mean, &quot;test_acc&quot;: test_acc_mean}
        result = {
            &quot;progress_bar&quot;: tqdm_dict,
            &quot;log&quot;: tqdm_dict,
            &quot;test_loss&quot;: test_loss_mean,
        }
        return result

    def configure_optimizers(self):
        &quot;&quot;&quot; Sets different Learning rates for different parameter groups. &quot;&quot;&quot;
        parameters = [
            {&quot;params&quot;: self.classification_head.parameters()},
            {
                &quot;params&quot;: self.ProtBertBFD.parameters(),
                &quot;lr&quot;: self.hparams.encoder_learning_rate,
            },
        ]
        optimizer = optim.Adam(parameters, lr=self.hparams.learning_rate)
        return [optimizer], []


    def __retrieve_dataset(self, train=True, val=True, test=True):
        &quot;&quot;&quot; Retrieves task specific dataset &quot;&quot;&quot;
        if train:
            return self.dataset.load_dataset(hparams.train_csv)
        elif val:
            return self.dataset.load_dataset(hparams.dev_csv)
        elif test:
            return self.dataset.load_dataset(hparams.test_csv)
        else:
            print('Incorrect dataset split')

    def train_dataloader(self) -&gt; DataLoader:
        &quot;&quot;&quot; Function that loads the train set. &quot;&quot;&quot;
        self._train_dataset = self.__retrieve_dataset(val=False, test=False)
        return DataLoader(
            dataset=self._train_dataset,
            sampler=RandomSampler(self._train_dataset),
            batch_size=self.hparams.batch_size,
            collate_fn=self.prepare_sample,
            num_workers=self.hparams.loader_workers,
        )

    
....
    

    @classmethod
    def add_model_specific_args(
        cls, parser: HyperOptArgumentParser
    ) -&gt; HyperOptArgumentParser:
        &quot;&quot;&quot; Parser for Estimator specific arguments/hyperparameters. 
        :param parser: HyperOptArgumentParser obj
        Returns:
            - updated parser
        &quot;&quot;&quot;
        parser.opt_list(
            &quot;--max_length&quot;,
            default=1536,
            type=int,
            help=&quot;Maximum sequence length.&quot;,
        )
        parser.add_argument(
            &quot;--encoder_learning_rate&quot;,
            default=5e-06,
            type=float,
            help=&quot;Encoder specific learning rate.&quot;,
        )
        
     
        
        return parser
        
        

# these are project-wide arguments
parser = HyperOptArgumentParser(
    strategy=&quot;random_search&quot;,
    description=&quot;Minimalist ProtBERT Classifier&quot;,
    add_help=True,
)

# Early Stopping
parser.add_argument(
    &quot;--monitor&quot;, default=&quot;val_acc&quot;, type=str, help=&quot;Quantity to monitor.&quot;
)
parser.add_argument(
    &quot;--metric_mode&quot;,
    default=&quot;max&quot;,
    type=str,
    help=&quot;If we want to min/max the monitored quantity.&quot;,
    choices=[&quot;auto&quot;, &quot;min&quot;, &quot;max&quot;],
)
parser.add_argument(
    &quot;--patience&quot;,
    default=5,
    type=int,
    help=(
        &quot;Number of epochs with no improvement &quot;
        &quot;after which training will be stopped.&quot;
    ),
)



parser.add_argument(
    &quot;--accumulate_grad_batches&quot;,
    default=32,
    type=int,
    help=(
        &quot;Accumulated gradients runs K small batches of size N before &quot;
        &quot;doing a backwards pass.&quot;
    ),
)

# gpu/tpu args
parser.add_argument(&quot;--gpus&quot;, type=int, default=1, help=&quot;How many gpus&quot;)
parser.add_argument(&quot;--tpu_cores&quot;, type=int, default=None, help=&quot;How many tpus&quot;)
parser.add_argument(
    &quot;--val_percent_check&quot;,
    default=1.0,
    type=float,
    help=(
        &quot;If you don't want to use the entire dev set (for debugging or &quot;
        &quot;if it's huge), set how much of the dev set you want to use with this flag.&quot;
    ),
)


# each LightningModule defines arguments relevant to it
parser = ProtBertBFDClassifier.add_model_specific_args(parser)


hparams = parser.parse_known_args()[0]

&quot;&quot;&quot;
Main training routine specific for this project
:param hparams:
&quot;&quot;&quot;
seed_everything(hparams.seed)

# ------------------------
# 1 INIT LIGHTNING MODEL
# ------------------------
model = ProtBertBFDClassifier(hparams)


This is the error:

1 frames
&lt;ipython-input-26-561494d91469&gt; in __init__(self)
     10     def __init__(self) -&gt; None:
     11         super(ProtBertBFDClassifier, self).__init__()
---&gt; 12         self.hparams = parser.parse_known_args()[0]
     13         self.batch_size = self.hparams.batch_size
     14 

/usr/local/lib/python3.7/dist-packages/torch/nn/modules/module.py in __setattr__(self, name, value)
   1223                     buffers[name] = value
   1224                 else:
-&gt; 1225                     object.__setattr__(self, name, value)
   1226 
   1227     def __delattr__(self, name):

AttributeError: can't set attribute



pip install pytorch-lightning==1.2.10
