【问题标题】:Vectorization with numpy使用 numpy 进行矢量化
【发布时间】:2017-06-27 09:50:41
【问题描述】:

我正在尝试创建一个高斯模糊矩阵。我正在从http://www.labri.fr/perso/nrougier/teaching/numpy/numpy.html 修改代码

dev_data 具有 784 行像素特征,我想与相关像素周围的邻居以及像素本身进行模糊处理。当我们沿着外边缘(第 1 行,-1 行,第 1 列,-1 列)时,丢弃任何超出边界的邻居。我不太确定如何进行这种丢弃。

代码:

# Initialize a new feature array with the same shape as the original data.
blurred_dev_data = np.zeros(dev_data.shape)

#we will reshape the 784 feature-long rows into 28x28 matrices
for i in range(dev_data.shape[0]):
    reshaped_dev_data = np.reshape(dev_data[i], (28,28))
    #the purpose of the reshape is to use the average of the 8 pixels + the pixel itself to blur
    for idx, pixel in enumerate(reshaped_dev_data):
        pixel = np.mean(reshaped_dev_data[idx-1:idx-1,idx-1:idx-1] + reshaped_dev_data[idx-1:idx-1,idx:idx] + reshaped_dev_data[idx-1:idx-1,idx+1:] +
             reshaped_dev_data[idx:idx,idx-1:idx-1] + reshaped_dev_data[idx:idx,idx:idx] + reshaped_dev_data[idx:idx,idx+1:] +
             reshaped_dev_data[idx+1:  ,idx-1:idx-1] + reshaped_dev_data[idx+1:  ,idx:idx] + reshaped_dev_data[idx+1:  ,idx+1:])
    blurred_dev_data[i,:] = reshaped_dev_data.ravel()

我收到一个索引错误:

ValueError: operands could not be broadcast together with shapes (0,0) (0,27)

这不是索引错误,所以我不太确定我在这里做错了什么/如何解决它。

【问题讨论】:

  • reshaped_dev_data[idx-1:idx-1,idx-1:idx-1] 编辑为reshaped_dev_data[idx-1,idx-1] 等等。
  • 谢谢。现在我得到了我所期待的越界错误。你知道忽略越界索引的好方法吗?
  • 我建议使用高斯模糊滤镜 - docs.scipy.org/doc/scipy-0.14.0/reference/generated/…

标签: python numpy vectorization


【解决方案1】:

试试这个:

pixel = np.mean(reshaped_dev_data[idx-1:idx+1, idx-1:idx+1])

另外,阅读slicing


所以我进一步查看了你的代码,你做错了一些事情:

  • 这不是高斯核。
  • 在一个循环中多次重新计算reshaped_dev_data
  • 循环错误的东西。
  • 试图在第 9 行更改 pixel。这很糟糕,因为:
    • 您正在循环的对象的突变通常是不好的
    • 反正不会变异! pixel 就像一个“价值”持有者。更改它不会更改您正在循环的数组。
  • 未编写矢量化代码!

这是一种天真的、非矢量化的做法:

def conv(arr, i, j):
    return np.mean(arr[i-1:i+1, j-1:j+1])

blurred_dev_data = np.zeros_like(dev_data)
reshaped_dev_data = dev_data.reshape(28, 28)

for i, row in enumerate(reshaped_dev_data):
    for j, pixel in enumerate(row):
        blurred_dev_data[i, j] = conv(reshaped_dev_data, i, j)

请注意,我们正在进行卷积。所以我们可以简单地使用内置库对平均内核执行卷积。


关于你的 cmets,

def conv(arr, i, j):
    # Ensure the boundaries are not exceeded
    a = max(i-1, 0)
    b = min(i+1, 28)
    c = min(j-1, 0)
    d = max(i+1, 28)

    return np.mean(arr[a:b, c:d])

blurred_dev_data = np.zeros_like(dev_data)

for n, data in enumerate(dev_data):
    reshaped = data.reshape(28, 28)
    blurred = np.zeros_like(reshaped)

    for i, row in enumerate(reshaped):
        for j, pixel in enumerate(row):
            blurred[i, j] = conv(reshaped, i, j)

    blurred_dev_data[n] = blurred.ravel()

请注意,我修改了conv,因为我忘记确保没有超出界限。

注意:使用现有的库(例如 SciPy 或 OpenCV)执行 2D 卷积(或者在本例中为均值滤波器)要快得多。

【讨论】:

  • 感谢您的帮助。你能告诉我如何使用 .ravel() 来汇总 blurred_dev_data 中的行吗?我将您的第 5 行更改为 for i in range(dev_data.shape[0]): reshaped_dev_data = np.reshape(dev_data[i], (28,28)),因为我需要重塑 dev_data 的每一行。
  • @FredericBastiat 您的意思是将 28x28 矩阵展平为 764 长度的向量吗?那就是vector = matrix.ravel()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 2015-08-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多