python 无法加载模型,因为无法将PosixPath

wlp8pajw  于 2023-04-04  发布在  Python
关注(0)|答案(8)|浏览(300)

我正在设置一个脚本,我需要使用fast-ai包中的一些函数。事实是,我在Windows上,当我定义我的路径时,来自fast-ai的名为load_learner的函数无法加载模型。
我尝试将函数更改为包:
state = pickle.load(open(str(path) + '/' + str(fname), 'rb'))
而不是:
state = pickle.load(open(path/fname, 'rb'))
但我得到了这个错误:

File "lib\site-packages\fastai\basic_train.py", line 462, in load_learner
    state = pickle.load(open(path/fname, 'rb'))
  File "\lib\pathlib.py", line 1006, in __new__
    % (cls.__name__,))
NotImplementedError: cannot instantiate 'PosixPath' on your system

我的路径定义为:

folder_path = './models/model1'
fname = 'model.pkl'

我把这个函数叫做:model = load_learner(folder_path, fname)
如何在此函数中使用Windows路径?

更新1

发布的答案仅在Linux上是正确的。我在Windows上仍然有这个问题。我没有找到一种方法来通过Windows上的PosixPath。我找到的唯一解决方案是从我的模块中更改内部包,但它不是解决这种问题的安全方法。
先谢谢你了。

nimxete2

nimxete21#

PosixPath重定向到WindowsPath

import pathlib
temp = pathlib.PosixPath
pathlib.PosixPath = pathlib.WindowsPath

我也在加载fastai模型,这个技巧很有效。

rekjcdws

rekjcdws2#

根据我自己的问题,我找到了一种方法:

from pathlib import Path

folder_path = Path('./models/model1')

更新1

这个解决方案只适用于Linux,在Windows上我仍然得到一个错误。

93ze6v8z

93ze6v8z3#

在Windows上工作时,您可以临时将pathlib.PosixPath设置为WindowsPath。重要的是恢复到原始值,特别是在加载pickle期间出现异常时。
一个简单的方法是执行try / finally

posix_backup = pathlib.PosixPath
try:
    pathlib.PosixPath = pathlib.WindowsPath
    learn_inf = load_learner(EXPORT_PATH)
finally:
    pathlib.PosixPath = posix_backup

如果你经常这样做,你可以让流程更流畅,如下所示:
1.定义一个可以临时执行更改的函数
1.在with块中使用它
您可以将其添加到某个地方(如果使用Jupyter,则可以将其添加到脚本或专用单元格的顶部)。

from contextlib import contextmanager
import pathlib

@contextmanager
def set_posix_windows():
    posix_backup = pathlib.PosixPath
    try:
        pathlib.PosixPath = pathlib.WindowsPath
        yield
    finally:
        pathlib.PosixPath = posix_backup

然后,就像这样使用它:

EXPORT_PATH = pathlib.Path("model.pkl")

with set_posix_windows():
    learn_inf = load_learner(EXPORT_PATH)

......同时,检查sophros的答案:https://stackoverflow.com/a/62836990/1603480

hjqgdpho

hjqgdpho4#

根据提供的错误信息,您使用的是pathlib。因此您不需要在这里使用+ '/' +str(path) + '/' + str(fname)
/作为路径分隔符在Linux/Unix上工作:

state = pickle.load(open(path / fname, 'rb'))

在Windows上使用.joinpath()

state = pickle.load(open(path.joinpath(fname), 'rb'))

如果您不打算使用pathlib,请使用os.path.join()。它会自动为您的操作系统选择正确的格式。

snvhrwxg

snvhrwxg5#

这里的问题与Python根据操作系统处理路径的方式的差异有关:

  • PosixPath-在Linux / Unix上
  • WindowsPath-在Windows上

当在一个操作系统上使用pickle持久化对象时(比如Linux -就像在本例中一样),有关类型/类的信息也会持久化(这里:PosixPath)。
现在,当pickle文件被加载时,Python假设它将能够基于它先前持久化的类型信息重新创建对象。在这种情况下,它试图重新创建PosixPath类型的对象,该对象被pathlib库阻止并且不能在Windows上示例化。在Windows上应该使用WindowsPath,但是pickle模块不能很好地处理这种依赖于操作系统的逻辑,因此它无助地抛出错误。
理论上,你可以干预pathlib的代码来删除操作系统检查,但没有简单的解决方法,而是避免对依赖于操作系统的对象进行pickle(例如,将路径存储为字符串-就像os.path一样-肯定会解决这个问题)。
There is also another possibility-为path对象使用一个独立于平台的PurePosixPath类。

wtzytmuj

wtzytmuj6#

对于posix路径错误:当你在colab/gradient上训练你的模型并下载它,然后在Windows上进行推理。
PosixPath重定向到WindowsPath

import pathlib

temp = pathlib.PosixPath
pathlib.PosixPath = pathlib.WindowsPath
omqzjyyz

omqzjyyz7#

我正在做同样的工作-将fastai模型部署为Web服务器,遇到了同样的问题,这就是我所做的......在导出模型时,使用joblib或pickle来pickle模型,而不是使用learn.export(),并在服务器中使用以下代码。

__model = pickle.load(open(os.path.join('./artifacts/saved_model.pkl'), 'rb'))

通过这样做,它能够解决路径问题,但由于模型是使用GPU训练的,因此它会给出错误,要求将存储Map到CPU

tez616oj

tez616oj8#

在windows上使用此方法在本地使用fastai:

import pathlib
temp = pathlib.PosixPath
pathlib.PosixPath = pathlib.WindowsPath

相关问题