@@ -375,17 +375,31 @@ def list_obs_plate_vars(self):
375375 return {"name" : "" , "in" : [], "sites" : {}}
376376
377377 def on_load (self , model , ** kwargs ):
378- """Callback function run in :meth:`~scvi.model.base.BaseModelClass.load`.
379-
380- For some Pyro modules with AutoGuides, run one training step prior to loading state dict.
381- """
378+ """Callback function run in :meth:`~scvi.model.base.BaseModelClass.load`."""
382379 pyro .clear_param_store ()
383380 old_history = model .history_ .copy () if model .history_ is not None else None
384- model .train (max_steps = 1 , ** self .on_load_kwargs )
385381 model .history_ = old_history
386- if "pyro_param_store" in kwargs :
387- # For scArches shapes are changed, and we don't want to overwrite these changed shapes.
388- pyro .get_param_store ().set_state (kwargs ["pyro_param_store" ])
382+ if "pyro_param_store" in kwargs and kwargs ["pyro_param_store" ] is not None :
383+ store_state = kwargs ["pyro_param_store" ]
384+ # AutoGuide parameters are lazy — they only exist as nn.Module attributes
385+ # after the first forward call. Run one no-grad guide pass BEFORE restoring
386+ # the saved store so the CPU module always sees a device-neutral empty store.
387+ # Restoring first would expose CUDA constraint tensors (e.g. AffineTransform
388+ # bounds derived from CUDA buffers) that clash with the CPU batch tensors.
389+ if model .adata is not None :
390+ if hasattr (self .model , "n_obs" ):
391+ self .model .n_obs = model .adata .n_obs
392+ if hasattr (self .guide , "n_obs" ):
393+ self .guide .n_obs = model .adata .n_obs
394+ dl = model ._make_data_loader (model .adata , batch_size = 2 )
395+ batch = next (iter (dl ))
396+ args , guide_kwargs = self ._get_fn_args_from_batch (batch )
397+ with torch .no_grad ():
398+ self .guide (* args , ** guide_kwargs )
399+ # Restore the saved store after warmup. For scArches the saved store
400+ # carries old reference shapes — those are intentionally kept here.
401+ # load_state_dict + model.to_device() handle the final device placement.
402+ pyro .get_param_store ().set_state (store_state )
389403
390404 def create_predictive (
391405 self ,
0 commit comments