【问题标题】:Numpy: vectorization for multiple valuesNumpy:多个值的矢量化
【发布时间】:2012-03-30 20:06:13
【问题描述】:

假设您有一个 RGB 图像并且想要处理每个像素:

import numpy as np
image = np.zeros((1024, 1024, 3))

def rgb_to_something(rgb):
    pass

vfunc = np.vectorize(rgb_to_something)
vfunc(image)

vfunc 现在应该获取每个 RGB 值。问题是 numpy 使 数组和函数在它应该得到的时候得到r0, g0, b0, r1, g1, b1, ... rgb0, rgb1, rgb2, ...。 这可以以某种方式完成吗?

http://docs.scipy.org/doc/numpy/reference/generated/numpy.vectorize.html

也许通过预先将 numpy 数组转换为一些特殊的数据类型?

例如(当然不行):

image = image.astype(np.float32)
import ctypes
RGB = ctypes.c_float * 3
image.astype(RGB)
ValueError: shape mismatch: objects cannot be broadcast to a single shape

更新: 这里的主要目的是效率。非矢量化版本可能看起来像这样:

import numpy as np
image = np.zeros((1024, 1024, 3))
shape = image.shape[0:2]
image = image.reshape((-1, 3))
def rgb_to_something((r, g, b)):
    return r + g + b
transformed_image = np.array([rgb_to_something(rgb) for rgb in image]).reshape(shape)

【问题讨论】:

  • 您能否将 3d 数组分成 3 个单独的 1d 数组(每个通道 1 个)并将其用作矢量化函数的参数?
  • 可以!但我必须说明它的效率。
  • 阵列分离比循环快很多,但 larsmans 解决方案仍然胜过它(我通过简单的测试得到了 2.7s、0.8s 和 0.3s)。但如果您想使用现有功能(例如来自 colorsys 模块),这仍然很有趣。
  • 我觉得你需要np.apply_over_axes

标签: python numpy vectorization


【解决方案1】:

解决此类问题的简单方法是将整个数组传递给函数,并在其中使用向量化的惯用语。具体来说,你的rgb_to_something也可以写成

def rgb_to_something(pixels):
    return pixels.sum(axis=1)

这比你的版本快大约 15 倍:

In [16]: %timeit np.array([old_rgb_to_something(rgb) for rgb in image]).reshape(shape)
1 loops, best of 3: 3.03 s per loop

In [19]: %timeit image.sum(axis=1).reshape(shape)
1 loops, best of 3: 192 ms per loop

np.vectorize 的问题在于它在应用于大型数组时必然会产生大量 Python 函数调用开销。

【讨论】:

  • 好的,这只是一个例子。没有内置在 numpy 中的更复杂的操作呢? (请纯 python,编写 C 扩展很好,但如果你只是想尝试一些东西,则很乏味)特别是你如何处理向量数组(rgb,velocity,...)。
  • 从我的示例中概括,您将使用沿 y 轴矢量化的表达式,即一次性处理大量短向量。如果您想为大量 a,b 对计算 f(a,b),那么您需要实现一个函数,该函数采用一对同样大的数组。
  • "提供vectorize函数主要是为了方便,而不是为了性能。实现本质上是一个for循环。" docs.scipy.org/doc/numpy/reference/generated/…
  • @endolith:是的。而且我可以从经验中看出,在 C 扩展的循环中调用 Python 函数来填充数组也不会提高性能,所以 np.vectorize 实际上不能做得更好。
【解决方案2】:

在某些情况下,您可以使用Numexpr。例如:

import numpy as np
import numexpr
rgb = np.random.rand(3,1000,1000)
r,g,b = rgb

在这种情况下,numexpr 甚至比“矢量化”的 numpy 表达式快 5 倍。但是,并不是所有的函数都可以这样写。

%timeit r*2+g*3/b
10 loops, best of 3: 20.8 ms per loop

%timeit numexpr.evaluate("(r*2+g*3) / b")
100 loops, best of 3: 4.2 ms per loop

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-30
    • 2018-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-27
    • 2020-04-06
    • 1970-01-01
    相关资源
    最近更新 更多