Why cannot I call FloatTensor on a float tensor?

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

I cannot reproduce the issue using:

torch.FloatTensor(torch.randn(10))

but in any case you shouldn’t use torch.FloatTensor as its usage is deprecated and undocumented due to its unintuitive behavior.
E.g. passing a scalar to it will return a FloatTensor with scalar elements using uninitialized memory, while passing a list would return a FloatTensor which contains the passed values:

torch.FloatTensor(10)
> tensor([-1.3895e+28,  3.0778e-41, -1.3954e+28,  3.0778e-41,  4.9870e-17,
           4.5729e-41, -6.7316e+36,  3.0778e-41,  1.4013e-45,  0.0000e+00])
torch.FloatTensor([10])
> tensor([10.])

Use the factory methods (torch.randn, torch.empty etc.) or transform the dtypes via to() or the direct call e.g. tensor.float().

@ptrblck Thanks, so the better way to ensure the correctness of the dtypes is to just say something like:

return {"y": torch.as_tensor(target, dtype=...)

Yes, as_tensor would probably work. If the input is a numpy array, you could also use torch.from_numpy.