Cannot load encoder on CPU with model trained on GPU

I trained a ULMFiT text model on a GPU, saved the model and the encoder. When I try

learn = text_classifier_learner(data_clas, AWD_LSTM, drop_mult=0.5)
learn.load_encoder()

on a CPU-only machine I get the first error message attached. When I follow the suggestion and instead call

learn.load_encoder(language_model_encoder_name, device=‘cpu’)

I get the same message (second attached message).

Any ideas?

Alex


RuntimeError Traceback (most recent call last)
in
----> 1 learn.load_encoder(language_model_encoder_name, device=‘cpu’)

~/anaconda3/lib/python3.7/site-packages/fastai/text/learner.py in load_encoder(self, name, device)
67 if device is None: device = self.data.device
68 if hasattr(encoder, ‘module’): encoder = encoder.module
—> 69 encoder.load_state_dict(torch.load(self.path/self.model_dir/f’{name}.pth’))
70 encoder.load_state_dict(torch.load(self.path/self.model_dir/f’{name}.pth’, map_location=device))
71 self.freeze()

~/anaconda3/lib/python3.7/site-packages/torch/serialization.py in load(f, map_location, pickle_module, **pickle_load_args)
385 f = f.open(‘rb’)
386 try:
–> 387 return _load(f, map_location, pickle_module, **pickle_load_args)
388 finally:
389 if new_fd:

~/anaconda3/lib/python3.7/site-packages/torch/serialization.py in _load(f, map_location, pickle_module, **pickle_load_args)
572 unpickler = pickle_module.Unpickler(f, **pickle_load_args)
573 unpickler.persistent_load = persistent_load
–> 574 result = unpickler.load()
575
576 deserialized_storage_keys = pickle_module.load(f, **pickle_load_args)

~/anaconda3/lib/python3.7/site-packages/torch/serialization.py in persistent_load(saved_id)
535 obj = data_type(size)
536 obj._torch_load_uninitialized = True
–> 537 deserialized_objects[root_key] = restore_location(obj, location)
538 storage = deserialized_objects[root_key]
539 if view_metadata is not None:

~/anaconda3/lib/python3.7/site-packages/torch/serialization.py in default_restore_location(storage, location)
117 def default_restore_location(storage, location):
118 for _, _, fn in _package_registry:
–> 119 result = fn(storage, location)
120 if result is not None:
121 return result

~/anaconda3/lib/python3.7/site-packages/torch/serialization.py in _cuda_deserialize(obj, location)
93 def _cuda_deserialize(obj, location):
94 if location.startswith(‘cuda’):
—> 95 device = validate_cuda_device(location)
96 if getattr(obj, “_torch_load_uninitialized”, False):
97 storage_type = getattr(torch.cuda, type(obj).name)

~/anaconda3/lib/python3.7/site-packages/torch/serialization.py in validate_cuda_device(location)
77
78 if not torch.cuda.is_available():
—> 79 raise RuntimeError('Attempting to deserialize object on a CUDA ’
80 'device but torch.cuda.is_available() is False. ’
81 'If you are running on a CPU-only machine, ’

RuntimeError: Attempting to deserialize object on a CUDA device but torch.cuda.is_available() is False. If you are running on a CPU-only machine, please use torch.load with map_location=‘cpu’ to map your storages to the CPU.

With ‘cpu’ specified as device:


RuntimeError Traceback (most recent call last)
in
----> 1 learn.load_encoder(language_model_encoder_name, device=‘cpu’)

~/anaconda3/lib/python3.7/site-packages/fastai/text/learner.py in load_encoder(self, name, device)
67 if device is None: device = self.data.device
68 if hasattr(encoder, ‘module’): encoder = encoder.module
—> 69 encoder.load_state_dict(torch.load(self.path/self.model_dir/f’{name}.pth’))
70 encoder.load_state_dict(torch.load(self.path/self.model_dir/f’{name}.pth’, map_location=device))
71 self.freeze()

~/anaconda3/lib/python3.7/site-packages/torch/serialization.py in load(f, map_location, pickle_module, **pickle_load_args)
385 f = f.open(‘rb’)
386 try:
–> 387 return _load(f, map_location, pickle_module, **pickle_load_args)
388 finally:
389 if new_fd:

~/anaconda3/lib/python3.7/site-packages/torch/serialization.py in _load(f, map_location, pickle_module, **pickle_load_args)
572 unpickler = pickle_module.Unpickler(f, **pickle_load_args)
573 unpickler.persistent_load = persistent_load
–> 574 result = unpickler.load()
575
576 deserialized_storage_keys = pickle_module.load(f, **pickle_load_args)

~/anaconda3/lib/python3.7/site-packages/torch/serialization.py in persistent_load(saved_id)
535 obj = data_type(size)
536 obj._torch_load_uninitialized = True
–> 537 deserialized_objects[root_key] = restore_location(obj, location)
538 storage = deserialized_objects[root_key]
539 if view_metadata is not None:

~/anaconda3/lib/python3.7/site-packages/torch/serialization.py in default_restore_location(storage, location)
117 def default_restore_location(storage, location):
118 for _, _, fn in _package_registry:
–> 119 result = fn(storage, location)
120 if result is not None:
121 return result

~/anaconda3/lib/python3.7/site-packages/torch/serialization.py in _cuda_deserialize(obj, location)
93 def _cuda_deserialize(obj, location):
94 if location.startswith(‘cuda’):
—> 95 device = validate_cuda_device(location)
96 if getattr(obj, “_torch_load_uninitialized”, False):
97 storage_type = getattr(torch.cuda, type(obj).name)

~/anaconda3/lib/python3.7/site-packages/torch/serialization.py in validate_cuda_device(location)
77
78 if not torch.cuda.is_available():
—> 79 raise RuntimeError('Attempting to deserialize object on a CUDA ’
80 'device but torch.cuda.is_available() is False. ’
81 'If you are running on a CPU-only machine, ’

RuntimeError: Attempting to deserialize object on a CUDA device but torch.cuda.is_available() is False. If you are running on a CPU-only machine, please use torch.load with map_location=‘cpu’ to map your storages to the CPU.

Seems like this might have been a bug: https://github.com/fastai/fastai/issues/2175. Looks like it is fixed in master but not in the latest release yet. You can install from github rather than PyPi to get the latest code

Thanks so much for your response Drew. That did the trick. I had been running predictions on the GPU in the mean time so this makes my life much easier.

As a side note, I did have to retrain my models with the new version due to some breaking changes to fastai relating to tensor sizes in the hidden layers. I did see that there are workarounds to retraining, but it was easier in this case to just retrain.