What is the recommended strategy for loading legacy PyTorch checkpoints after the torch.load weights_only default changed to True?
0 reputation · 27 Apr 2024, 10:49 UTC
0 reputation · 27 Apr 2024, 10:49 UTC
Determine a safe, version‑agnostic method for loading existing PyTorch checkpoints that were saved with the legacy torch.load behavior (weights_only=False) while the default has shifted to weights_only=True in recent releases.
Constraints include preserving the ability to load trusted checkpoints that contain non‑tensor Python objects (e.g., custom optimizer state, loss classes) without exposing the loading process to arbitrary code execution, and ensuring that the chosen approach works across the range of PyTorch versions where the weights_only default and the allowlist API have evolved.
Should teams resave their trusted checkpoints once with weights_only=True to avoid future breakage, or should they maintain the original files and rely on torch.serialization.add_safe_globals to whitelist the required classes? How should nested container objects (such as lists or dicts holding custom types) be handled when building an allowlist? What verification steps can confirm that a checkpoint loads correctly under the new default without silently dropping state?
32275 reputation · 27 Apr 2024, 15:16 UTC
The recommended strategy for loading trusted legacy checkpoints containing custom Python objects is to use torch.serialization.add_safe_globals() to whitelist the specific classes required for reconstruction. This allows you to maintain the security benefits of the weights_only=True default while restoring the ability to load complex state dictionaries.
weights_only=True. If the checkpoint contains custom objects, PyTorch will raise a RuntimeError explicitly naming the classes that are not in the safe list.add_safe_globals API to register these classes before calling torch.load():
import torch
from my_module import CustomOptimizerState
torch.serialization.add_safe_globals([CustomOptimizerState])
checkpoint = torch.load("legacy_model.pt")
state_dict against a known-good legacy load (using weights_only=False in a controlled environment) to ensure no metadata was silently dropped.Nested Containers: You do not need to whitelist standard Python containers like list or dict; the restricted unpickler handles these natively. You only need to whitelist the leaf custom types contained within those structures.
Resaving vs. Whitelisting: While add_safe_globals solves the immediate loading issue, the most robust long-term strategy is to resave trusted checkpoints using a weights-only compatible format, such as safetensors. This removes the dependency on pickle entirely and eliminates the need for version-specific allowlists.
Caution: Never set weights_only=False for checkpoints sourced from untrusted third parties, as this exposes the system to arbitrary code execution via pickle.
Assumptions: This guidance assumes the use of PyTorch 2.x versions where the weights_only parameter and add_safe_globals API are available. If you are using an older version, these parameters will not exist, and torch.load will behave as weights_only=False by default.
Diagnostic Detail Needed: To refine this recommendation, please specify if your checkpoints contain torch.nn.Module subclasses saved as entire objects (via torch.save(model)) rather than state dictionaries (via torch.save(model.state_dict())), as the latter is significantly easier to secure.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.