Python lazy evaluation numpy ndarray



我有一个大型 2D 数组,我想声明一次,偶尔只根据参数更改一些值,而不遍历整个数组。

为了构建这个数组,我用 dtype=object 子类化了 numpy ndarray 类,并分配给我想要更改函数的元素,例如:

def f(parameter):
     return parameter**2
for i in range(np.shape(A)[0]):
    A[i,i]=f
    for j in range(np.shape(A)[0]):
        A[i,j]=1.

然后,我覆盖了 __getitem__ 方法,以便它返回具有给定参数的函数的计算(如果它是可调用的),否则返回值本身。

    def __getitem__(self, key):
        value = super(numpy.ndarray, self).__getitem__(key)
        if callable(value):
            return value(*self.args)
        else:
            return value

以前self.args提供给 myclass 实例的地方。

但是,我需要在最后使用浮点数组,并且我不能简单地使用这种技术将此数组转换为dtype=float数组。我还尝试使用 numpy 视图,这对 dtype=object 也不起作用。

你有更好的选择吗?我应该覆盖视图方法而不是 getitem 吗?

编辑 我将来可能不得不使用 Cython,所以如果你有一个涉及例如 C 指针的解决方案,我很感兴趣。

在这种情况下,将转换函数绑定到数组的每个索引是没有意义的。

相反,更有效的方法是将转换定义为函数,以及它所应用的数组的子集。 这是一个基本的实现,

import numpy as np
class LazyEvaluation(object):
    def __init__(self):
        self.transforms = []
    def add_transform(self, function, selection=slice(None), args={}):
        self.transforms.append( (function, selection, args))
    def __call__(self, x):
        y = x.copy() 
        for function, selection, args in self.transforms:
            y[selection] = function(y[selection], **args)
        return y

可以按如下方式使用:

x = np.ones((6, 6))*2
le = LazyEvaluation()
le.add_transform(lambda x: 0, [[3], [0]]) # equivalent to x[3,0]
le.add_transform(lambda x: x**2, (slice(4), slice(4,6)))  # equivalent to x[4,4:6]
le.add_transform(lambda x: -1,  np.diag_indices(x.shape[0], x.ndim), ) # setting the diagonal 
result =  le(x)
print(result)

哪个打印,

array([[-1.,  2.,  2.,  2.,  4.,  4.],
       [ 2., -1.,  2.,  2.,  4.,  4.],
       [ 2.,  2., -1.,  2.,  4.,  4.],
       [ 0.,  2.,  2., -1.,  4.,  4.],
       [ 2.,  2.,  2.,  2., -1.,  2.],
       [ 2.,  2.,  2.,  2.,  2., -1.]])

通过这种方式,您可以轻松支持所有高级 Numpy 索引(逐元素访问、切片、花哨索引等),同时将数据保存在具有本机数据类型(floatint 等)的数组中,这比使用 dtype='object' 更有效。

相关内容

  • 没有找到相关文章

最新更新