code: def to_device(
      data: _Data,
      device: torch.device,
      warned_types: Optional[Set[Type]] = None,
  ) -> TorchData:
      """
      Accept np.ndarray, torch.Tensor, list, or dictionary. Recursively convert any ndarrays to
      tensors and call .to() on any tensors or data types that have custom serialization logic
      defined via a callable to() attribute.
  
      If the data cannot be moved to device, log a warning (only once per type) and return the
      original data.
      """
      # Never print errors recursively.
      if warned_types is None:
          warned_types = set()
  
      if isinstance(data, dict):
          return {k: to_device(v, device, warned_types) for k, v in data.items()}  # type: ignore
      elif isinstance(data, list):
          return [to_device(d, device, warned_types) for d in data]  # type: ignore
      elif isinstance(data, tuple):
          return tuple(to_device(d, device, warned_types) for d in data)  # type: ignore
      elif isinstance(data, np.ndarray):
          # Torch supports floats, complex floats, ints, uints, and bools as tensors.
          # Those correspond to numpy dtype kinds: "f", "c", "i", "u", and "b", respectively.
          # Do not attempt to convert any other kinds to tensors.
          if data.dtype.kind in "fciub":
              return torch.from_numpy(data).to(device)
      elif hasattr(data, "to") and callable(data.to):  # type: ignore
          return data.to(device)  # type: ignore
  
      if type(data) not in warned_types:
          warned_types.add(type(data))
          logger.warning(
              f"Was not able to move data item of type '{type(data).__name__}' to device."
          )
  
      return data
  
file_path: determined/harness/determined/pytorch/_data.py
imports: import logging
  from typing import Any, Callable, Dict, Iterator, List, Optional, Sequence, Set, Type, TypeVar, Union, cast
  import numpy
  import torch
  from packaging import version
  from torch.utils.data import BatchSampler, Dataset, RandomSampler, Sampler, SequentialSampler, _utils
  from determined.pytorch import samplers
label_desc: Use image node_id 4 for calling a global function with example usage: to_device(data, device, warned_types) and returns: data, unknown, unknown, tuple, torch, data