pickle/joblib AttributeError:模块'__main__'在pytest中没有属性'thing'
Posted
技术标签:
【中文标题】pickle/joblib AttributeError:模块\'__main__\'在pytest中没有属性\'thing\'【英文标题】:pickle/joblib AttributeError: module '__main__' has no attribute 'thing' in pytestpickle/joblib AttributeError:模块'__main__'在pytest中没有属性'thing' 【发布时间】:2019-04-10 04:04:52 【问题描述】:我已经建立了一个自定义的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
类是实现 BaseEstimator
和 TransformerMixin
的自定义 sklearn 步骤。
为了序列化这个对象,我使用
from sklearn.externals import joblib
joblib.dump(pipeline, 'data_pipeline.joblib')
但是当我反序列化时
pipeline = joblib.load('data_pipeline.joblib')
我收到AttributeError: module '__main__' has no attribute 'SelectColumnsTransfomer'
。
我已阅读其他类似问题并按照此博文here 中的说明进行操作,但无法解决问题。
我正在复制粘贴类,并将它们导入代码中。如果我创建了这个练习的简化版本,整个事情就可以了,问题发生是因为我正在使用 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
【问题讨论】:
joblib.load __main__ AttributeError的可能重复 【参考方案1】:好的,我发现了问题。我发现这个问题与我最初认为的 Python: pickling and dealing with "AttributeError: 'module' object has no attribute 'Thing'" 的博文中解释的问题无关。 您可以通过对对象进行酸洗和取消酸洗文件来轻松解决问题。我正在使用一个单独的脚本(一个 Jupyther 笔记本)来腌制,并使用一个普通的 [python 脚本来取消腌制。当我在同一个班级做所有事情时,它起作用了。
【讨论】:
“让你的对象拾取和解开文件”是什么意思?您能否在您的答案中也分享代码。 拾取和拆解必须由同一个对象在同一个脚本内完成。 您确定旧对象不只是重新使用吗?我不认为答案解决方案适用于 Python 实例。 这个答案看不懂。 今天我在寻找解决方案,所以要详细说明一下:“定义函数的模块必须是可导入的,并且必须具有函数名称作为属性”。如果函数是在 Jupyter Notebook 中定义的,则它是不可导入的,因此在可导入模块中定义它是使它能够工作的原因。【参考方案2】:当我尝试像这样保存 Pytorch 类时,我收到了同样的错误消息:
import torch.nn as nn
class custom(nn.Module):
def __init__(self):
super(custom, self).__init__()
print("Class loaded")
model = custom()
然后使用 Joblib 像这样转储这个模型:
from joblib import dump
dump(model, 'some_filepath.jobjib')
问题是我在Kaggle 内核中运行上面的代码。然后下载转储文件并尝试在本地使用此脚本加载它:
from joblib import load
model = load(model, 'some_filepath.jobjib')
我解决问题的方法是在我的计算机上本地运行所有这些代码 sn-ps,而不是创建类并将其转储到 Kaggle,而是将其加载到我的本地计算机上。想在此处添加此内容,因为 @DarioB 的 answer 上的 cmets 让我感到困惑,因为他们提到了一个不适用于我更简单的情况的“函数”。
【讨论】:
以上是关于pickle/joblib AttributeError:模块'__main__'在pytest中没有属性'thing'的主要内容,如果未能解决你的问题,请参考以下文章
在 Python 中导入历史标准普尔 500 指数数据 [关闭]
如何在 PyQt5 中返回 QlistWidget 中项目的值
Python:获取所有节点的度数,然后在networkx中绘制箱线图
gwpy 包给出错误 - AttributeError:模块“matplotlib.pyplot”在 Google Colab 中没有属性“FigureManagerBase”