So I am doing a classification problem with BCEwithlogits loss, therefore, it expects my integer targets to be float. However, I defined torch.from_numpy(df[FOLDS.class_col_name].values).float()
and subsequently return {"y": torch.FloatTensor(target)}
and the error is IndexError: slice() cannot be applied to a 0-dim tensor.
Once I use {"y": target}
it started to work. Why is this the case, I manually checked that target
is a float tensor, why cannot I call FloatTensor
again on it?
from typing import Dict, Union
import albumentations
import cv2
import pandas as pd
import torch
class CustomDataset(torch.utils.data.Dataset):
"""Dataset class for the {insert competition/project name} dataset."""
def __init__(
self,
df: pd.DataFrame,
transforms: albumentations.core.composition.Compose = None,
mode: str = "train",
):
"""Constructor for the dataset class.
Args:
df (pd.DataFrame): Dataframe for either train, valid or test.
transforms (albumentations.core.composition.Compose): albumentations transforms to apply to the images.
mode (str, optional): Defaults to "train". One of ['train', 'valid', 'test', 'gradcam']
"""
# "image_path" is hardcoded, as that is always defined in prepare_data.
self.image_path = df["image_path"].values
self.image_ids = df[FOLDS.image_col_name].values
self.df = df
self.targets = (
torch.from_numpy(df[FOLDS.class_col_name].values).float()
if mode != "test"
else None
)
self.transforms = transforms
self.mode = mode
def __len__(self) -> int:
"""Return the length of the dataset."""
return len(self.df)
def __getitem__(
self, index: int
) -> Union[
Dict[str, torch.FloatTensor],
Dict[str, Union[torch.FloatTensor, torch.LongTensor]],
]:
"""Implements the getitem method: https://www.geeksforgeeks.org/__getitem__-and-__setitem__-in-python/
Be careful of Targets:
BCEWithLogitsLoss expects a target.float()
CrossEntropyLoss expects a target.long()
Args:
index (int): index of the dataset.
Returns:
Dict[str, torch.FloatTensor]:{"X": image_tensor}
Dict[str, Union[torch.FloatTensor, torch.LongTensor]]: {"y": target_tensor} If BCEwithLogitsLoss then FloatTensor, else LongTensor
"""
image_path = self.image_path[index]
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# needed for gradcam.
original_image = cv2.resize(
image, (TRANSFORMS.image_size, TRANSFORMS.image_size)
).copy()
# Get target for all modes except for test.
target = self.targets[index] if self.mode != "test" else None
if self.transforms:
image = self.transforms(image=image)["image"]
if self.mode in ["train", "valid"]:
if CRITERION.train_criterion_name == "BCEWithLogitsLoss":
return {
"X": torch.FloatTensor(image),
"y": target,
}
return {
"X": torch.FloatTensor(image),
"y": torch.LongTensor(target),
}
elif self.mode == "test":
return {"X": torch.FloatTensor(image)}
elif self.mode == "gradcam":
return {
"X": torch.FloatTensor(image),
"y": target,
"original_image": torch.FloatTensor(original_image),
"image_id": self.image_ids[index],
}
return None