我有一个存储为2dnumpy数组的图像(可能是多个d数组)。
我可以在反映二维滑动窗口的数组上创建一个视图,但是当我重塑它,使每一行都是一个平坦的窗口(行是窗口,列是该窗口中的一个像素)时,python会生成一个完整的副本。它之所以这样做,是因为我使用了典型的步幅技巧,而新形状在内存中是不连续的。
我需要这个,因为我将整个大图像传递给sklearn分类器,它接受2d矩阵,其中没有批处理/部分拟合过程,并且完全扩展的副本对于内存来说太大了。
我的问题是:有没有一种方法可以在不复制视图的情况下做到这一点?
我相信答案要么是(1)关于我忽略的跨度或numpy内存管理,要么是(2) python的某种屏蔽内存结构,它可以模拟numpy数组,甚至可以模拟到包含cython的外部包,如sklearn。
这种在内存中对2d图像的移动窗口进行训练的任务很常见,但据我所知,唯一直接解决补丁问题的尝试是Vigra项目(http://ukoethe.github.io/vigra/)。
谢谢你的帮助。
>>> A=np.arange(9).reshape(3,3)
>>> print A
[[0 1 2]
[3 4 5]
[6 7 8]]
>>> xstep=1;ystep=1; xsize=2; ysize=2
>>> window_view = np.lib.stride_tricks.as_strided(A, ((A.shape[0] - xsize + 1) / xstep, (A.shape[1] - ysize + 1) / ystep, xsize, ysize),
... (A.strides[0] * xstep, A.strides[1] * ystep, A.strides[0], A.strides[1]))
>>> print window_view
[[[[0 1]
[3 4]]
[[1 2]
[4 5]]]
[[[3 4]
[6 7]]
[[4 5]
[7 8]]]]
>>>
>>> np.may_share_memory(A,window_view)
True
>>> B=window_view.reshape(-1,xsize*ysize)
>>> np.may_share_memory(A,B)
False发布于 2015-05-24 22:13:42
您的任务不可能只使用步长,但是NumPy支持一种类型的数组来完成这项工作。使用strides和masked_array,您可以为数据创建所需的视图。然而,并不是所有的NumPy函数都支持使用masked_array的操作,因此scikit learn也可能不能很好地使用这些操作。
让我们首先重新看一下我们在这里要做的事情。考虑一下示例中的输入数据。从根本上说,数据只是内存中的一个一维数组,如果我们考虑一下它的跨度,就会更简单。这个数组看起来只是二维的,因为我们已经定义了它的形状。使用strides,可以像这样定义形状:
from numpy.lib.stride_tricks import as_strided
base = np.arange(9)
isize = base.itemsize
A = as_strided(base, shape=(3, 3), strides=(3 * isize, isize))现在的目标是为base设置这样的步长,以便像在结束数组B中那样对数字进行排序。换句话说,我们要求整数a和b,以便
>>> as_strided(base, shape=(4, 4), strides=(a, b))
array([[0, 1, 3, 4],
[1, 2, 4, 5],
[3, 4, 6, 7],
[4, 5, 7, 8]])但这显然是不可能的。我们可以实现的最接近的视图是在base上滚动窗口
>>> C = as_strided(base, shape=(5, 5), strides=(isize, isize))
>>> C
array([[0, 1, 2, 3, 4],
[1, 2, 3, 4, 5],
[2, 3, 4, 5, 6],
[3, 4, 5, 6, 7],
[4, 5, 6, 7, 8]])但这里的不同之处在于,我们有额外的列和行,我们想要去掉它们。因此,我们实际上是在要求一个滚动窗口,它不是连续的,并且以规则的间隔跳跃。在这个示例中,我们希望每隔三个项目就从窗口中排除一次,并在两行之后跳过一个项目。
我们可以将其描述为masked_array
>>> mask = np.zeros((5, 5), dtype=bool)
>>> mask[2, :] = True
>>> mask[:, 2] = True
>>> D = np.ma.masked_array(C, mask=mask)这个数组包含我们想要的数据,并且它只是原始数据的一个视图。我们可以确认数据是相等的
>>> D.data[~D.mask].reshape(4, 4)
array([[0, 1, 3, 4],
[1, 2, 4, 5],
[3, 4, 6, 7],
[4, 5, 7, 8]])但正如我在一开始所说的,scikit-learn很可能不理解掩码数组。如果它简单地将其转换为数组,则数据将是错误的:
>>> np.array(D)
array([[0, 1, 2, 3, 4],
[1, 2, 3, 4, 5],
[2, 3, 4, 5, 6],
[3, 4, 5, 6, 7],
[4, 5, 6, 7, 8]])https://stackoverflow.com/questions/24816334
复制相似问题