I’ve tried a similar collate_fn before, but doesn’t seem to work if my ds_train is a list that contains tensors.
This is the error meassage I got:
TypeError: expected np.ndarray (got list)
class ChannelDataset(Dataset):

    def __init__(self, df, input_labels, target_label): # input df is a dataframe
        toArray = lambda x: np.atleast_1d(x)  # convert scalar to array
        toTensor = lambda x: torch.from_numpy(x)  # convert array to tensor
        toFloat = lambda x: x.float() if x.dtype == torch.float64 else x  # convert double to float

        self.df = df.applymap(toArray).applymap(toTensor).applymap(toFloat)

        self.inputs = self.df[input_labels].values
        self.target = self.df[target_label].values

    def __len__(self):
        return len(self.df)

    def __getitem__(self, index):
        inputs = list(self.inputs[index]) # have problem with using torch.cat()
        target = list(self.target[index])[0]

        return inputs, target


class Trainer:
    def _step(self, data_batch, optimizer=None):

        inputs_batch, target_batch = data_batch
        pred_batch = self.model(*inputs_batch)
        loss = self._criterion(pred_batch, target_batch)

        if optimizer is not None:
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

        return loss.item(), len(target_batch)   
   
 
    def fit(self, df_train, df_val, df_test, batch_size=1, print_freq=1, max_epochs=1000, min_epochs=0, earlystopping=False, patience=0):

        self.df_train = df_train
        self.df_val = df_val

        # Convert dataframes to datasets
        ds_train = ChannelDataset(df_train, self.input_labels, self.target_label)
        ds_val = ChannelDataset(df_val, self.input_labels, self.target_label)
        ds_test = ChannelDataset(df_test, self.input_labels, self.target_label)

        # Convert datasets to dataloaders
        trainloader = DataLoader(ds_train, batch_size=batch_size, shuffle=True, collate_fn=lambda batch: [(torch.from_numpy(dp_train[0]), torch.tensor(dp_train[1])) for dp_train in batch])
        valloader = DataLoader(ds_val, batch_size=batch_size, shuffle=False, collate_fn=lambda batch: [(torch.from_numpy(dp[0]), torch.tensor(dp[1])) for dp in batch])
        testloader = DataLoader(ds_test, batch_size=batch_size, shuffle=False, collate_fn=lambda batch: [(torch.from_numpy(dp[0]), torch.tensor(dp[1])) for dp in batch])#collate_fn = my_collate,

        # Initialize loss_history
        if self.loss_history is None:
            self.loss_history = {'train': [], 'val': [], 'test': []}

        while keep_going:  # In each epoch
            # Set model to train mode
            self.model.train()

            # Loop over trainloader
            losses, nums = zip(*[self._step(data_batch, self._optimizer) for data_batch in trainloader])
            train_loss = np.sum(np.multiply(losses, nums)) / np.sum(nums)

            # Set model to eval mode
            self.model.eval()

            # Loop over valloader
            with torch.no_grad():
                losses, nums = zip(*[self._step(data_batch) for data_batch in valloader])
            val_loss = np.sum(np.multiply(losses, nums)) / np.sum(nums)

            # Loop over testloader
            with torch.no_grad():
                losses, nums = zip(*[self._step(data_batch) for data_batch in testloader])
            test_loss = np.sum(np.multiply(losses, nums)) / np.sum(nums)

            # Append losses
            self.loss_history['train'].append(train_loss)
            self.loss_history['val'].append(val_loss)
            self.loss_history['test'].append(test_loss)