#python #pytorch #pickle
#python #pytorch #рассол
Вопрос:
Проблема
Я пытаюсь загрузить файл с помощью PyTorch, но состояния ошибки archive/data.pkl
не существует.
Код
import torch
cachefile = 'cacheddata.pth'
torch.load(cachefile)
Вывод
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-4-8edf1f27a4bd> in <module>
1 import torch
2 cachefile = 'cacheddata.pth'
----> 3 torch.load(cachefile)
~/opt/anaconda3/envs/matching/lib/python3.8/site-packages/torch/serialization.py in load(f, map_location, pickle_module, **pickle_load_args)
582 opened_file.seek(orig_position)
583 return torch.jit.load(opened_file)
--> 584 return _load(opened_zipfile, map_location, pickle_module, **pickle_load_args)
585 return _legacy_load(opened_file, map_location, pickle_module, **pickle_load_args)
586
~/opt/anaconda3/envs/matching/lib/python3.8/site-packages/torch/serialization.py in _load(zip_file, map_location, pickle_module, **pickle_load_args)
837
838 # Load the data (which may in turn use `persistent_load` to load tensors)
--> 839 data_file = io.BytesIO(zip_file.get_record('data.pkl'))
840 unpickler = pickle_module.Unpickler(data_file, **pickle_load_args)
841 unpickler.persistent_load = persistent_load
RuntimeError: [enforce fail at inline_container.cc:209] . file not found: archive/data.pkl
Гипотеза
Я предполагаю, что это как-то связано с pickle, из документов:
Этот процесс сохранения / загрузки использует наиболее интуитивно понятный синтаксис и требует наименьшего объема кода. Сохранение модели таким образом сохранит весь модуль, используя модуль pickle Python. Недостатком этого подхода является то, что сериализованные данные привязаны к определенным классам и точной структуре каталогов, используемой при сохранении модели. Причина этого в том, что pickle не сохраняет сам класс модели. Скорее, он сохраняет путь к файлу, содержащему класс, который используется во время загрузки. Из-за этого ваш код может по-разному ломаться при использовании в других проектах или после рефакторинга.
Версии
- Версия PyTorch: 1.6.0
- Версия Python: 3.8.0
Ответ №1:
Оказалось, что файл был каким-то образом поврежден. После повторной генерации он загрузился без проблем.
Комментарии:
1. У меня возникла эта проблема именно по этой причине: частой причиной этого может быть прерывание процесса обучения модели (Ctrl-C, прерывание планировщиком заданий из-за нехватки времени и т. Д.), Пока вы находитесь в процессе записи в файловую систему.
Ответ №2:
Я столкнулся с той же проблемой. Я напрямую загрузил модель ( .pt
), обученную с помощью графического процессора, из ноутбука на платформе GCP AI. Когда я загрузил его по локальной torch.load('models/model.pt', map_location=device)
сети, я получил эту ошибку:
RuntimeError: [enforce fail at inline_container.cc:145] . PytorchStreamReader failed reading zip archive: failed finding central directory`.
Я заметил, что размер загруженного файла намного меньше, чем ожидалось. Так же, как и @Ian, оказалось, что файл был поврежден при загрузке из ноутбука. Наконец, мне пришлось сначала перенести файл из записной книжки в корзину в облачном хранилище Google (GCS) вместо того, чтобы загружать его напрямую, а затем загрузить файл из GCS. Теперь это работает.
Ответ №3:
Я столкнулся с этой проблемой не для одного файла, а последовательно для любого файла, с которым я имел дело. Глядя на размер файла, вы могли бы сказать, что они были повреждены, в том смысле, что они были слишком маленькими и неполными, но почему они всегда создавались таким образом?
Я думаю, проблема заключалась в том, что я внес безвредную модификацию в простой класс, который я сохранял. Итак, как я создал класс Foo
, сохранил данные без изменений, но добавил некоторый метод, затем попытался сохранить более старый экземпляр, когда у меня было только более новое определение класса Foo
.
Вот пример того, что, я думаю, произошло, но он не воспроизводит его в точности:
class Foo(object):
def __init__(self):
self.contents = [1,2,3]
torch.save(Foo(), "foo1.pth")
foo1 = torch.load("foo1.pth") # saved with class version 1 of Foo
# some days later the code looks like this
class Foo(object):
def __init__(self):
self.contents = [1,2,3]
def __len__(self):
return len(self.contents)
foo1 = torch.load("foo1.pth") # still works
torch.save(foo1, "foo2.pth") # try to save version 1 object where class is no longer known
В первый раз я получил сообщение об ошибке PicklingError: Can't pickle <class '__main__.Foo'>: it's not the same object as __main__.Foo
, но при использовании функции автоматической загрузки Jupyter Notebook трудно сказать, что именно произошло.
Обычно старые классы могут быть загружены в новые определения классов без проблем.
В любом случае, что действительно произошло, мое решение состояло в том, чтобы загрузить старую версию и вручную скопировать поля данных в недавно созданную версию Foo
, например:
old = torch.load("foo1.pth")
new = Foo()
# new = old # this was the code that caused issues
new.contents = old.contents
torch.save(new, "foo2.pth")
Ответ №4:
В моем случае основной причиной этой ошибки был .pt
поврежден файл. Я начал загружать файл, когда файл все еще создавался.
Итак, чтобы избежать ошибки, скопируйте .pt
файл в другой каталог и загрузите .pt
файл из этого каталога.
Ответ №5:
В моем случае мой диск был заполнен.
Комментарии:
1. На самом деле, это была моя проблема!
2. Это было очень полезно, и из сообщения об ошибке не очевидно, что основной причиной был полный жесткий диск.