我将图像存储为 2d numpy 数组(可能是多维)。
我可以在那个反射(reflect)二维滑动窗口的数组上创建一个 View ,但是当我 reshape 它以使每一行都是一个扁平化的窗口(行是窗口,列是该窗口中的一个像素)时,python 会制作一个完整的副本。这样做是因为我使用的是典型的步幅技巧,并且新形状在内存中不连续。
我需要这个,因为我将整个大图像传递给 sklearn 分类器,它接受二维矩阵,其中没有批处理/部分拟合过程,并且完整的扩展副本对于内存来说太大了。
我的问题:有没有办法在不完全复制 View 的情况下做到这一点?
我相信答案要么是 (1) 我忽略的关于 strides 或 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
最佳答案
您的任务仅使用步幅是不可能的,但 NumPy 确实支持
一种完成这项工作的数组。大步向前,masked_array
您可以为您的数据创建所需的 View 。然而,并非所有
NumPy 函数支持对 masked_array
的操作,所以它是
可能 scikit-learn 也不能很好地处理这些。
让我们首先重新审视一下我们在这里尝试做的事情。 考虑示例的输入数据。基本上数据是 只是内存中的一维数组,如果我们考虑一下就更简单了 的进步。该数组似乎只是二维的,因为我们 定义了它的形状。使用步幅,可以定义形状 像这样:
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]])
但这显然是不可能的。我们可以达到的最接近的 View
这是在 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]])
关于python - Numpy View Reshape Without Copy(二维移动/滑动窗口、步幅、屏蔽内存结构),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24816334/