Как десериализовать сохраненную модель PyTorch с закрытыми методами внутри класса? - PullRequest
2 голосов
/ 09 апреля 2020

Я использовал метод сохранения PyTorch для сериализации нескольких важных объектов. Среди них был один класс, ссылающийся на закрытый метод внутри __init__ того же класса. Теперь, после сериализации, я не могу десериализовать (открепить) файлы, потому что закрытый метод недоступен за пределами класса. Любая идея, как решить или обойти это? Мне нужно восстановить данные, сохраненные в атрибутах этого класса.

  File ".conda/envs/py37/lib/python3.7/site-packages/IPython/core/interactiveshell.py", line 3331, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-1-a5666d77c70f>", line 1, in <module>
    torch.load("snapshots/model.pth", map_location='cpu')
  File ".conda/envs/py37/lib/python3.7/site-packages/torch/serialization.py", line 529, in load
    return _legacy_load(opened_file, map_location, pickle_module, **pickle_load_args)
  File ".conda/envs/py37/lib/python3.7/site-packages/torch/serialization.py", line 702, in _legacy_load
    result = unpickler.load()
AttributeError: 'Trainer' object has no attribute '__iterator'
  • EDIT-1:

Здесь есть фрагмент кода, который сгенерирует проблема, с которой я сейчас сталкиваюсь.

import torch

class Test:
    def __init__(self):
        self.a = min
        self.b = max
        self.c = self.__private  # buggy

    def __private(self):
        return None

test = Test()

torch.save({"test": test}, "file.pkl")
torch.load("file.pkl")

Однако, если вы удалите атрибут private из метода, вы не получите никакой ошибки.

import torch

class Test:
    def __init__(self):
        self.a = min
        self.b = max
        self.c = self.private  # not buggy

    def private(self):
        return None

test = Test()

torch.save({"test": test}, "file.pkl")
torch.load("file.pkl")

Ответы [ 2 ]

1 голос
/ 17 апреля 2020

Этот вопрос похож на Python многопроцессорный - частный метод сопоставления , но не может быть помечен как дубликат из-за открытой награды.

Проблема возникает из этой открытой проблемы на Python баг-трекере: Объекты, ссылающиеся на имена с частными искажениями, не работают должным образом при выборе и связаны с тем, как pickle обрабатывает искажения имен. Подробнее об этом ответе: { ссылка }.

На данный момент единственным обходным решением не является использование частных методов в __init__.

0 голосов
/ 17 апреля 2020

Эта проблема возникает из-за искажения имени - где интерпретатор меняет имя переменной нижеуказанным способом, что затрудняет создание коллизий, когда класс расширяется позже. где

self.__private

было изменено на (self._className__privateMethodName)

self._Test__private

As искажение имени не применяется с dunder , где имя должно начинаться и заканчиваться двойным подчеркиванием.

Итак, чтобы избежать искажения имени добавьте еще два подчеркивания в конце.

Ниже фрагмент кода должен решить вашу проблему.

import torch

class Test:
    def __init__(self):
        self.a = min
        self.b = max
        self.c = self.__private__

    def __private__(self):
        return None

test = Test()

torch.save({"test": test}, "file.pkl")
torch.load("file.pkl")
...