【问题标题】:Save Interpolation output from Scipy保存 Scipy 的插值输出
【发布时间】:2023-04-02 13:56:01
【问题描述】:

我有一个问题,我需要使用例如插入 3D 函数。 SciPy,然后保存此插值的输出以供将来使用。也就是说,我不想每次都运行插值过程,因为生成要插值的 3D 函数对计算的要求很高(它来自 Biot-Savart 定律,所以很多数值积分也是如此)。

但是,我无法理解这是否可行,其次是如何实施。从我在其他一些帖子中看到的情况来看,这应该是可能的,但解决方案似乎对我不起作用。

我编写了以下测试代码,但在测试时收到以下错误:

TypeError: 'numpy.ndarray' 对象不可调用

此错误出现在函数loadInterpolation() 中以zeroVal 开头的代码行上。根据我之前阅读的内容,我希望allow_pickle=True 能够解决这个问题 .

import scipy
from scipy.interpolate import RegularGridInterpolator

def f(x,y,z):
    field = -x**2-y**2+z**2
    return field

def performSaveInterpolation():
    print(scipy.__version__)
    print('Performing Interpolation...')
    x = np.linspace(-1,1,100)
    y = np.linspace(-1,1,100)
    z = np.linspace(-1,1,100)
    xg, yg ,zg = np.meshgrid(x, y, z, indexing='ij', sparse=True)
    data = f(xg,yg,zg)
    my_interpolating_function = RegularGridInterpolator((x, y, z), data)
    zeroVal = my_interpolating_function([0,0,0])
    oneVal = my_interpolating_function([1,1,1])
    print('Interpolated function @ (0,0,0): ' + str(zeroVal))
    print('Interpolated function @ (1,1,1): ' + str(oneVal))
    np.save('interpolation.npy',my_interpolating_function,allow_pickle=True)
    return 0

def loadInterpolation():
    print('Loading Interpolation...')
    interpolationFunc = np.load('interpolation.npy',allow_pickle=True)
    zeroVal = interpolationFunc([0,0,0])
    oneVal = interpolationFunc([1,1,1])
    print('Interpolated function @ (0,0,0): ' + str(zeroVal))
    print('Interpolated function @ (1,1,1): ' + str(oneVal))
    return 0

performSaveInterpolation()
loadInterpolation()

【问题讨论】:

    标签: python numpy scipy interpolation pickle


    【解决方案1】:

    为什么不直接使用pickle?链接到问题:How-can-i-use-pickle-to-save-a-dict

    Pickle 应该能够序列化 任何可能类型的 python 对象。不仅是numpy数组(至尊numpy save函数only能够做到。它不能保存除np.arrays之外的其他对象类型,并且迭代函数不是numpy.ndarray类型,因此错误)

    像这样使用它:

    TLDR:

    import pickle
    
    with open('mypicklefile.pck', 'wb') as file_handle:
        pickle.dump(my_saved_object, file_handle)
    

    然后:

    with open('mypicklefile.pck', 'rb') as file_handle:
        my_loaded_object = pickle.load(file_handle)
    

    如果您需要一次序列化多个对象,例如您的函数,以及 zeroValoneVal 以避免每次都从函数中提取它们,您可以:

    解决方案 1

    对同一个文件进行多次序列化:

    with open('mypicklefile.pck', 'wb') as file_handle:
        pickle.dump(my_saved_object, file_handle)
        pickle.dump(my_saved_object2, file_handle)
        pickle.dump(my_saved_object3, file_handle)
    

    然后反序列化多次(顺序很重要!你必须“记住”哪个对象是哪个)

    with open('mypicklefile.pck', 'rb') as file_handle:
        my_loaded_object = pickle.load(file_handle)
        my_loaded_object2 = pickle.load(file_handle)
        my_loaded_object3 = pickle.load(file_handle)
    

    解决方案 2

    或者,(更好的解决方案 IMO)使用字典,每个对象都有一点元数据,因为它有一个名称(键):

    mydata = {"tiny_description": my_saved_object, "something_more" : my_saved_object2}
    
    with open('mypicklefile.pck', 'wb') as file_handle:
        pickle.dump(mydata , file_handle)
    
    with open('mypicklefile.pck', 'rb') as file_handle:
        temp_dict = pickle.load(file_handle)
        tiny_description = temp_dict["tiny_description"]
        something_more = emp_dict["something_more"]
    

    【讨论】:

    • 非常感谢您的回复!我确信这样的事情是解决方案。但是,如果这是一个愚蠢的问题,我很抱歉,但我以前没有使用过 pickle 功能。在您的示例中,如何保存插值的输出(例如 my_interpolating_function),在这种情况下是要保存然后重新加载的对象?我只能从你写的内容来看如何打开它。
    • @classAction68 在 python 中,everything 是一个对象。因此,使用转储,您将对象my_interpolated_function 序列化并写入您之前打开的文件中,并将该文件的句柄作为对象(file_handle)。然后,当您再次打开它时,使用另一个句柄来读取文件(在我的示例中,第二个句柄名称相同)您使用 load,其中 将句柄作为参数 并将反序列化的对象作为对象返回包含在文件中。因此,在我的示例中:my_loaded_object(理论上)完全my_interpolated_function 相同。
    • 对象的名称无关紧要。只有内容可以。例如你可以这样做:import numpy as np 然后foo = np 最后bar = foo.array([1,2,3]) 它会产生一个numpy.ndarray 就像使用 np 一样,因为 foo is np.
    • 非常感谢。我想我现在意识到“pickle.dump”是将它保存到我的磁盘的东西 - 这是我以前不理解的对象被保存到磁盘
    • 是的,完全正确。不用担心。祝您编码愉快!
    猜你喜欢
    • 2014-04-24
    • 1970-01-01
    • 2017-03-07
    • 1970-01-01
    • 2016-11-01
    • 2019-06-02
    • 2015-11-10
    • 2011-07-04
    • 2013-03-04
    相关资源
    最近更新 更多