awslabs / gluonts

Probabilistic time series modeling in Python
https://ts.gluon.ai
Apache License 2.0
4.61k stars 752 forks source link

Predictor objects do not serialize output transforms #1469

Open canerturkmen opened 3 years ago

canerturkmen commented 3 years ago

Description

Representable predictor objects do not serialize/deserialize the output transformation. See here. This prevents consistent serde as well as the ability to reuse existing predictor objects. Also see the discussion in #1458 .

lostella commented 3 years ago

Would this be just as easy as it's done here?

canerturkmen commented 3 years ago

that doesn't appear to be the case. In general output transforms are just Callables. For a simple function I get:

RuntimeError: Cannot serialize type builtins.function.
lostella commented 3 years ago

Yeah that’s an issue of course. In my opinion it should be fine to use whatever callable objects wherever they fit, as long as you’re willing to pay the price that it may not be serializable nicely. We could use for output transforms similar things like we use for the input, right? And have serialization rely on the @validated decorator

canerturkmen commented 3 years ago

OutputTransform is currently an alias for a certain Callable interface. It could become a serializable object of its own although seeing as it doesn't look like it's being used much I'm not sure if it's worth the effort.

lostella commented 3 years ago

It could become a serializable object of its own although seeing as it doesn't look like it's being used much I'm not sure if it's worth the effort.

What I mean is that one does not need to do much, in order to provide an object compatible with dump_json: just extend OutputTransform (to make type checking happy) and decorate the constructor:

In [11]: class MyOutputTransform(OutputTransform):
    ...:     @validated()
    ...:     def __init__(self, coeff: float):
    ...:         self.coeff = coeff
    ...:     def __call__(self, entry, x):
    ...:         return entry["target"] + coeff*x
    ...:

In [12]:

In [12]:

In [12]: output_transform = MyOutputTransform(42.0)

In [13]: encode(output_transform)
Out[13]:
{'__kind__': <Kind.Instance: 'instance'>,
 'class': '__main__.MyOutputTransform',
 'args': [],
 'kwargs': {'coeff': 42.0}}

In [14]: decode(encode(output_transform))
Out[14]: __main__.MyOutputTransform(coeff=42.0)

(These encode/decode functions are what is used internally for serde from/to json)