保存 Scipy 的插值输出

Save Interpolation output from Scipy

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

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

我写了下面的测试代码,但是在测试的时候出现如下错误:

TypeError: 'numpy.ndarray' object is not callable

此错误发生在函数 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()

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

Pickle 应该能够序列化 任何可能类型 的 python 对象。不仅 numpy 数组(至于 numpy save 函数是 只有 能够做到。它不能保存除 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"]