Hello,
This is mainly a Python question even thought I use PyTorch. In PyTorch we can define tensors and then do mathematical operations on them. We can define our own tensors and overwrite its behaviour. I'm overwriting a bunch of mathematical operations like e.g. how two of my custom tensors are being added. Writing your own tensor in PyTorch is done as a wrapper class where the data is stil hold by a normal pytorch tensor. So any function you don't define can still be called with the usual implementation.
To achieve this, we have three functions: (this implementation is faulty I think)
from torch.utils._pytree import tree_map
def unwrap(t):
if isinstance(t, cls):
return t.elem, t.max_grad, t.min_grad
else:
return t
def wrap(t, max_grad=None, min_grad=None):
if isinstance(t, torch.Tensor) and not isinstance(t, cls):
return cls(t, max_grad=max_grad, min_grad=min_grad, verbose=cls.verbose)
else:
return t
def run_with_usual_semantic():
args_org = tree_map(unwrap, args)
args_ = (args_org[0][0], *args_org[1:])
kwargs_ = tree_map(unwrap, kwargs)
res = func(*args_, **kwargs_)
try:
res = tree_map(wrap, res, args_org[0][1], args_org[0][2])
except Exception as e:
print("Error:", e)
breakpoint()
return res
clsrepresents my own custom tensor subclass.t.elemrepresents thetorch.tensorelement that holds the actual datat.max_gradandt.min_gradare two additional optional tensors that I sometimes define when overwriting functions. The normal implementations of an functionof PyTorch does not know about these properties. If we call a function with the usual semantics i.e. the default implementation, we always call it witht.elem