deep-learningpytorchplotlypth

torch cannot load a pth file containing plotly figures


I am running a bunch of DNN experiments using pytorch, and I am saving an instance of my ExperimentClass as a .pth file. The ExperimentClass has instance variables including a torch model, a dictionary of multiple plotly figure objects, dataframes, and other metadata related to experimental parameters.

However, when I try to load the .pth file using torch.load(full_model_path, weights_only=False), I get a cryptic ValueError related to some figure type that I never even use, but it's definitely occurring during the unpacking of the plotly figure objects.

ValueError: Invalid property specified for object of type plotly.graph_objs.layout.template.Data: 'heatmapgl'

Here is the full traceback:

loading model from experiment_plots/vLAYER/dnn_all_experiments_results.pth
Traceback (most recent call last):
  File "/Users/name/Desktop/name/research/nn-layer-weight-experiments/create_additional_training_plots.py", line 163, in <module>
    create_final_epoch_layer_plots(experiment_versions=experiment_versions, dnn_names=dnn_names)
  File "/Users/name/Desktop/name/research/nn-layer-weight-experiments/create_additional_training_plots.py", line 34, in create_final_epoch_layer_plots
    dnn_experiments = torch.load(full_model_path, weights_only=False)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/name/miniconda3/lib/python3.11/site-packages/torch/serialization.py", line 1471, in load
    return _load(
           ^^^^^^
  File "/Users/name/miniconda3/lib/python3.11/site-packages/torch/serialization.py", line 1964, in _load
    result = unpickler.load()
             ^^^^^^^^^^^^^^^^
  File "/Users/name/miniconda3/lib/python3.11/site-packages/plotly/graph_objs/_figure.py", line 641, in __init__
    super(Figure, self).__init__(data, layout, frames, skip_invalid, **kwargs)
  File "/Users/name/miniconda3/lib/python3.11/site-packages/plotly/basedatatypes.py", line 556, in __init__
    self._layout_obj = self._layout_validator.validate_coerce(
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/name/miniconda3/lib/python3.11/site-packages/_plotly_utils/basevalidators.py", line 2504, in validate_coerce
    v = self.data_class(v, skip_invalid=skip_invalid, _validate=_validate)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/name/miniconda3/lib/python3.11/site-packages/plotly/graph_objs/_layout.py", line 7124, in __init__
    self["template"] = _v
    ~~~~^^^^^^^^^^^^
  File "/Users/name/miniconda3/lib/python3.11/site-packages/plotly/basedatatypes.py", line 5898, in __setitem__
    super(BaseLayoutHierarchyType, self).__setitem__(prop, value)
  File "/Users/name/miniconda3/lib/python3.11/site-packages/plotly/basedatatypes.py", line 4852, in __setitem__
    self._set_compound_prop(prop, value)
  File "/Users/name/miniconda3/lib/python3.11/site-packages/plotly/basedatatypes.py", line 5263, in _set_compound_prop
    val = validator.validate_coerce(val, skip_invalid=self._skip_invalid)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/name/miniconda3/lib/python3.11/site-packages/_plotly_utils/basevalidators.py", line 2797, in validate_coerce
    return super(BaseTemplateValidator, self).validate_coerce(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/name/miniconda3/lib/python3.11/site-packages/_plotly_utils/basevalidators.py", line 2504, in validate_coerce
    v = self.data_class(v, skip_invalid=skip_invalid, _validate=_validate)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/name/miniconda3/lib/python3.11/site-packages/plotly/graph_objs/layout/_template.py", line 327, in __init__
    self["data"] = _v
    ~~~~^^^^^^^^
  File "/Users/name/miniconda3/lib/python3.11/site-packages/plotly/basedatatypes.py", line 4852, in __setitem__
    self._set_compound_prop(prop, value)
  File "/Users/name/miniconda3/lib/python3.11/site-packages/plotly/basedatatypes.py", line 5263, in _set_compound_prop
    val = validator.validate_coerce(val, skip_invalid=self._skip_invalid)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/name/miniconda3/lib/python3.11/site-packages/_plotly_utils/basevalidators.py", line 2504, in validate_coerce
    v = self.data_class(v, skip_invalid=skip_invalid, _validate=_validate)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/name/miniconda3/lib/python3.11/site-packages/plotly/graph_objs/layout/template/_data.py", line 1791, in __init__
    self._process_kwargs(**dict(arg, **kwargs))
  File "/Users/name/miniconda3/lib/python3.11/site-packages/plotly/basedatatypes.py", line 4378, in _process_kwargs
    raise err
ValueError: Invalid property specified for object of type plotly.graph_objs.layout.template.Data: 'heatmapgl'

What is also strange is that I ran a smaller version of my test experiments locally about a day ago, and all of the .pth files were able to be loaded without any errors. Has anyone else encountered this?


Solution

  • The following is a summary from the comments to the question:

    In earlier versions of plotly, its Data class had a heatmapgl property (see e.g. an earlier version of Data's source code here), while in the most recent versions, this property has been removed (see the current version of Data's source code here).

    The problem and its solution thus unfolded as follows:

    My personal experience and advice for avoiding such a problem (which, as we have seen, essentially boils down to the problem of unpickling/unserializing an instance of a class whose definition has changed between pickling/serializing and unpickling/unserializing) is as follows: I would try to save only instances of built-in Python classes (numbers, strings, tuples, lists, dicts, etc.) as well as PyTorch tensors in PyTorch checkpoints, and try to recreate other instances from values stored in these instances.