pickle / joblib AttributeError: модуль '__main__' не имеет атрибута 'thing' в pytest

Я создал собственный конвейер sklearn, как показано ниже:

pipeline = make_pipeline(
    SelectColumnsTransfomer(features_to_use),
    ToDummiesTransformer('feature_0', prefix='feat_0', drop_first=True,  dtype=bool), # Dummify customer_type
    ToDummiesTransformer('feature_1', prefix='feat_1'), # Dummify the feature
    ToDummiesTransformer('feature_2', prefix='feat_2'), # Dummify 
    ToDummiesTransformer('feature_3', prefix='feat_3'), # Dummify
)
pipeline.fit(df)

Классы SelectColumnsTransfomer и ToDummiesTransformer - это настраиваемые шаги sklearn, реализующие BaseEstimator и TransformerMixin. Чтобы сериализовать этот объект, я использую

from sklearn.externals import joblib
joblib.dump(pipeline, 'data_pipeline.joblib')

но когда я выполняю десериализацию с помощью

pipeline = joblib.load('data_pipeline.joblib') 

Я получаю AttributeError: module '__main__' has no attribute 'SelectColumnsTransfomer'.

Я прочитал другие похожие вопросы и выполнил инструкции в этом блоге здесь, но проблему решить не удалось. Я копирую, вставляю классы и импортирую их в код. Если я создам упрощенную версию этого упражнения, все работает, проблема возникает из-за того, что я запускаю некоторые тесты с pytest, и когда я запускаю pytest, кажется, что он не видит мои пользовательские классы, на самом деле есть эта другая часть ошибки self = <sklearn.externals.joblib.numpy_pickle.NumpyUnpickler object at 0x7f821508a588>, module = '__main__', name = 'SelectColumnsTransfomer', которая намекает мне, что NumpyUnpickler не видит SelectColumnsTransfomer, даже если в тесте он был импортирован.

Мой тестовый код

import pytest
from app.pipeline import * # the pipeline objects 
                          # SelectColumnsTransfomer and ToDummiesTransformer 
                          # are here!


@pytest.fixture(scope="module")
def clf():
    pipeline = joblib.load("persistence/data_pipeline.joblib")
    return clf

def test_fake(clf):
    assert True

person DarioB    schedule 06.11.2018    source источник
comment
Возможный дубликат joblib.load __main__ AttributeError   -  person BenP    schedule 05.11.2019


Ответы (1)


Хорошо, я обнаружил проблему. Я обнаружил, что проблема не имеет ничего общего с проблемой, описанной в блоге здесь Python: обработка и обработка« AttributeError: объект 'module' не имеет атрибута 'Thing' », как я изначально думал. Вы можете легко решить эту проблему, если ваш объект будет травить и распаковывать файл. Я использовал отдельный сценарий (записную книжку Jupyther) для маринования и простой скрипт [python для удаления. Когда я все делал в одном классе, это сработало.

person DarioB    schedule 07.11.2018
comment
Что вы имеете в виду, когда ваш объект выбирает и распаковывает файл? Можете ли вы также поделиться кодом в своем ответе. - person HakunaMaData; 06.01.2019
comment
Сбор и распаковка должны выполняться одним и тем же объектом и в одном сценарии. - person DarioB; 06.01.2019
comment
Вы уверены, что старый объект нельзя использовать повторно? Я не думаю, что решение ответа работает на экземплярах Python. - person BenP; 05.11.2019
comment
этот ответ непонятен. - person 3nomis; 22.11.2019
comment
это означает, что один и тот же класс / объект нужно мариновать и расшаривать, иначе это не сработает. - person DarioB; 23.11.2019
comment
Чтобы уточнить это, поскольку сегодня я искал решение: модуль, в котором определена функция, должен быть импортируемым, и он должен иметь имя функции в качестве атрибута. Если функция была определена в Jupyter Notebook, ее нельзя импортировать, поэтому ее определение в импортируемом модуле позволяет ей работать. - person Lucy; 20.01.2021