Hello, I am trying to train a custom database that I created and my labels are in the following format: 10988, 10995,10995, etc.
So, I’m getting the next error
Engine run is terminating due to exception: y_pred contains less classes than y. Number of predicted classes is 12 and element in y has invalid class = 10999..
So, if I check the documentations
if y.max() + 1 > num_classes:
raise ValueError(
"y_pred contains less classes than y. Number of predicted classes is {}"
" and element in y has invalid class = {}.".format(num_classes, y.max().item() + 1)
)
What I think is that pytorch wants my labels to be in the format 0,1,2,3,4,5,6,7,8,9,10,11
Is there a way I can fix this without changing my database’s labels?
Thanks in advance
vfdev-5
(vfdev-5)
January 7, 2021, 8:26am
2
Hi @Tanya_Boone
Yes, you have to map the labels to a contiguous format like 0,1,2,3,4,5,6,7,8,9,10,11
The error appears when you compute metrics, so you can perform the mapping with output_transform
for the metric:
from ignite.metrics import Precision
labels_mapping = {
10988: 0,
10995: 1,
...
}
def ot_map_labels(output):
y_pred, y = output
new_y = labels_mapping[y]
return y_pred, y
precision = Precision(output_transform=ot_map_labels)
Hope this helps
1 Like
Thank you. Just one more question . If I have this type of training
def update_fn(engine, batch):
model.train()
x = convert_tensor(batch[0], device=device, non_blocking=True)
y = convert_tensor(batch[1], device=device, non_blocking=True)
y_pred = model(x)
# Compute loss
loss = criterion(y_pred, y)
optimizer.zero_grad()
if use_amp:
with amp.scale_loss(loss, optimizer, loss_id=0) as scaled_loss:
scaled_loss.backward()
else:
loss.backward()
optimizer.step()
return {
"batchloss": loss.item(),
}
Where should I call the function precision? and also I think the function ot_map_labels should return y_pred and new_y?
What I did is…
Define mapping
define function ot_map_labels
inside update_fn before loss I call precision function, but I didn’t work
Thanks for your help!
vfdev-5
(vfdev-5)
January 7, 2021, 10:23am
4
OK, I see.
Personally, I’d perform the mapping inside Dataset
before the training/validation code:
train_dataset = ... # your training dataset
val_dataset = ... # your validation dataset etc
class TransformedDataset(torch.utils.data.Dataset):
def __init__(self, dataset, transform_fn):
self.dataset = dataset
self.transform_fn = transform_fn
def __len__(self):
return len(self.dataset)
def __getitem__(self, index):
dp = self.dataset[index]
return self.transform_fn(dp)
from functools import partial
labels_mapping = {
10988: 0,
10995: 1,
...
}
def map_targets_fn(dp, target_mapping):
x, y = dp
new_y = target_mapping[y]
return x, new_y
train_dataset = TransformedDataset(train_dataset, partial(map_targets_fn, target_mapping=labels_mapping))
val_dataset = TransformedDataset(val_dataset, partial(map_targets_fn, target_mapping=labels_mapping))
# same code as before without any change to metrics
HTH
1 Like
Thanks! I am trying to do it the same way but I get this error
File "D:/CapsuleNet/CIFAR10/vgg_m_marine.py", line 134, in map_targets_fn
new_y = target_mapping[y]
KeyError: tensor(10988)
vfdev-5
(vfdev-5)
January 7, 2021, 12:11pm
6
Seems like y
is a tensor coming from your dataset. Maybe, the following would work:
new_y = target_mapping[y.item()]
1 Like
Apparently it worked. Thank you so much for your support!
1 Like