'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) -> 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 > 0:
self.freeze_encoder()
else:
self._frozen = False
self.nr_frozen_epochs = self.hparams.nr_frozen_epochs
def __build_model(self) -> None:
""" Init BERT model + tokenizer + classification head."""
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(","), 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) -> dict:
""" Predict function.
:param sample: dictionary with the text we want to classify.
Returns:
Dictionary with the input text and the predicted label.
"""
......
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["seq"],
add_special_tokens=True,
padding=True,
truncation=True,
max_length=self.hparams.max_length)
if not prepare_target:
return inputs, {}
# Prepare target:
try:
targets = {"labels": self.label_encoder.batch_encode(sample["label"])}
return inputs, targets
except RuntimeError:
print(sample["label"])
raise Exception("Label encoder found an unknown label.")
......
def validation_step(self, batch: tuple, batch_nb: int, *args, **kwargs) -> dict:
""" Similar to the training step but with the model in eval mode.
Returns:
- dictionary passed to the validation_end function.
"""
inputs, targets = batch
model_out = self.forward(**inputs)
loss_val = self.loss(model_out, targets)
y = targets["labels"]
y_hat = model_out["logits"]
labels_hat = torch.argmax(y_hat, dim=1)
val_acc = self.metric_acc(labels_hat, y)
output = OrderedDict({"val_loss": loss_val, "val_acc": val_acc,})
return output
def validation_epoch_end(self, outputs: list) -> dict:
""" 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.
"""
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 = {"val_loss": val_loss_mean, "val_acc": val_acc_mean}
result = {
"progress_bar": tqdm_dict,
"log": tqdm_dict,
"val_loss": val_loss_mean,
}
return result
.......
def test_epoch_end(self, outputs: list) -> dict:
""" 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.
"""
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 = {"test_loss": test_loss_mean, "test_acc": test_acc_mean}
result = {
"progress_bar": tqdm_dict,
"log": tqdm_dict,
"test_loss": test_loss_mean,
}
return result
def configure_optimizers(self):
""" Sets different Learning rates for different parameter groups. """
parameters = [
{"params": self.classification_head.parameters()},
{
"params": self.ProtBertBFD.parameters(),
"lr": 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):
""" Retrieves task specific dataset """
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) -> DataLoader:
""" Function that loads the train set. """
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
) -> HyperOptArgumentParser:
""" Parser for Estimator specific arguments/hyperparameters.
:param parser: HyperOptArgumentParser obj
Returns:
- updated parser
"""
parser.opt_list(
"--max_length",
default=1536,
type=int,
help="Maximum sequence length.",
)
parser.add_argument(
"--encoder_learning_rate",
default=5e-06,
type=float,
help="Encoder specific learning rate.",
)
return parser
# these are project-wide arguments
parser = HyperOptArgumentParser(
strategy="random_search",
description="Minimalist ProtBERT Classifier",
add_help=True,
)
# Early Stopping
parser.add_argument(
"--monitor", default="val_acc", type=str, help="Quantity to monitor."
)
parser.add_argument(
"--metric_mode",
default="max",
type=str,
help="If we want to min/max the monitored quantity.",
choices=["auto", "min", "max"],
)
parser.add_argument(
"--patience",
default=5,
type=int,
help=(
"Number of epochs with no improvement "
"after which training will be stopped."
),
)
parser.add_argument(
"--accumulate_grad_batches",
default=32,
type=int,
help=(
"Accumulated gradients runs K small batches of size N before "
"doing a backwards pass."
),
)
# gpu/tpu args
parser.add_argument("--gpus", type=int, default=1, help="How many gpus")
parser.add_argument("--tpu_cores", type=int, default=None, help="How many tpus")
parser.add_argument(
"--val_percent_check",
default=1.0,
type=float,
help=(
"If you don't want to use the entire dev set (for debugging or "
"if it's huge), set how much of the dev set you want to use with this flag."
),
)
# each LightningModule defines arguments relevant to it
parser = ProtBertBFDClassifier.add_model_specific_args(parser)
hparams = parser.parse_known_args()[0]
"""
Main training routine specific for this project
:param hparams:
"""
seed_everything(hparams.seed)
# ------------------------
# 1 INIT LIGHTNING MODEL
# ------------------------
model = ProtBertBFDClassifier(hparams)
This is the error:
1 frames
<ipython-input-26-561494d91469> in __init__(self)
10 def __init__(self) -> None:
11 super(ProtBertBFDClassifier, self).__init__()
---> 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:
-> 1225 object.__setattr__(self, name, value)
1226
1227 def __delattr__(self, name):
AttributeError: can't set attribute
Solution 1:[1]
pip install pytorch-lightning==1.2.10
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Bandar Alrooqi |