【问题标题】:How are filter strides implemented (coding wise) in CNNs?如何在 CNN 中实现过滤器步幅(编码方式)?
【发布时间】:2017-06-03 21:49:15
【问题描述】:

我试图弄清楚 CNN 中的步幅是如何编码的,但我似乎无法有效地实现它——脚本需要很长时间才能完成计算,否则我会遇到错误

from PIL import Image

img = Image.open('C:\sample_pic.jpeg').convert("RGB") #800 x600 dimensions
pixels =np.array(img)  # However PIL inverts height and width so #600 X800
print(pixels.shape)    # (600L, 800L, 3L)

理想情况下,我不想展平图像,但是当正确使用 1 的步幅时,我无法弄清楚如何将 600 x 800 x 3 的图像与 2x3x3 的滤镜相乘。因此,我尝试将阵列展平,因为我觉得这样会更容易。

   flat = pixels.flatten()
   filter1= np.array([1,1,0],) 
   pixels2 = np.array([])

for i in range(0, len(flat),2):
   pixels2 =np.append(pixels2,np.sum((flat[i:i+3] * filter1)))

所以我尝试将每个像素的 RGB 值与过滤器相乘,然后取和然后滑动 2。我试图可视化 CNN 的第一个卷积层。 在这里,我无法弄清楚如何告诉循环仅在 i+3 个元素可用时进行迭代。我认为这就是我收到以下错误的原因

ValueError: operands could not be broadcast together with shapes (2,) (3,)

还有一种计算速度更快的方法可以将过滤器值与图像的像素值相乘,因为我的笔记本电脑需要很长时间来计算。 (英特尔 i-7 3610QM @2.30 Geforce 650M GT 2GB)

编辑:为清晰起见进行编辑。如果可以将 600x800x3 数组与 2x3x3 的过滤器相乘,那么我想使用 1 的步幅。 我希望过滤器看起来像这样,

[[[1,1,0]
[1,1,0]
[1,1,0]]


[[1,1,0]
[1,1,0]
[1,1,0]]]

2 行,每行 3 列,每列有三个值 [1,1,0]

原始图像为 600 行(高度)、800 列(宽度)和 3 个值(RGB 值)。

如有任何混淆,我们深表歉意。

我正在使用的图片:

【问题讨论】:

  • 输出数组的形状是什么?
  • 嗨,理想情况下,我想要一个可以重塑为图片尺寸自然尺寸的输出。因此,如果可能的话,我希望能够将每个维度重塑为 350(最小值)。
  • 修改您的循环代码以使其与2x3x3 形状的过滤器一起工作,因为这似乎是最终目的地?你说-"RGB values of each pixel with the filter,"。使用多维过滤器,有多种方法可以解释过滤操作。因此,循环代码将有助于演示您的想法。
  • 您是否尝试将(2, 2, 3)(600, 800, 3) 进行卷积?您想为每个颜色平面单独执行此操作,生成(599, 799, 3) 输出,还是一起生成(599, 799) 输出?还是您的意思是步幅为 2,给 (300, 400, 3)(300, 400)
  • 对不起,造成混乱。当图像未展平时,我希望步幅为 1。我想要一个3维的输出。所以我假设(599,799,3)将是如果我使用步幅为 1 和过滤器(2,3,3)的输出。谢谢。

标签: python-2.7 numpy python-imaging-library conv-neural-network


【解决方案1】:

这是一种使用 Scipy's 2D convolution 并结合 stride 的方法 -

from scipy.signal import convolve2d as conv2

def filter_images3D(img3D, filter3D, stride=1):
    M1,N1 = img3D.shape[:2]
    M2,N2 = filter3D.shape[:2]
    O1,O2 = (M1-M2+stride)//stride, (N1-N2+stride)//stride

    n = img3D.shape[-1]
    out = np.empty((O1,O2,n))
    for i in range(n):
        out[...,i] = conv2(img3D[...,i],filter3D[...,i],'valid')[::stride,::stride]
    return out

【讨论】:

  • 可悲的是,这不是 stride 对卷积的意义。步幅意味着conv(img, filter)[::stride],但显然你想在不计算被丢弃的值的情况下这样做
  • @Eric 没错,之前错过了。已更新。
  • 谢谢,我要先阅读有关 convolve2d(从未使用过)的信息,然后再玩弄代码。
【解决方案2】:

不是最佳解决方案,因为它会在stack 中产生一个副本,1。但是:

from scipy.signal import convolve2d

res = np.stack([
    convolve2d(pixels[...,i], filter[...,i], mode='valid')
    for i in range(3)
], axis=-1)

或消除幻数3

res = np.stack([
    convolve2d(plane, filterp, mode='valid')
    for plane, filterp in zip(np.rollaxis(pixels, -1), np.rollaxis(filter, -1))
], axis=-1)

1 - 实际上,由于 convolve2d 没有 out 参数,因此别无选择

【讨论】:

  • 谢谢。我不知道convolve2d。这将需要一些时间,因为我将阅读有关第一个 convolve2d 的内容,但我会使用您提供的代码,看看我是否有任何问题。谢谢。
  • 所以我在测试代码时遇到了几个问题:'Traceback (most recent call last): File "C:\Python27\PIL_Image.py", line 38, in <module> assert res.shape == (599, 799, 3) AssertionError 当我检查我得到的 res 形状时,我认为这不是什么大问题(599,798, 3)。但是,当我尝试使用 im = Image.fromarray(res) 将其转换回图像格式时,我似乎遇到了错误,TypeError: Cannot handle this data type。任何线索为什么我可能会赌这个错误?
  • @moondra:我将您的过滤器形状误读为 (2, 2, 3),而不是 (2, 3, 3)。是的,这种说法是垃圾。您的问题可能是 res 具有 dtype float,而 Image.fromarray 可能期待 uint8
  • 哦,是的,我忘了。谢谢。
  • stack(...,axis = -1) 将 N 个形状 (a, b, c, ...) 的数组转换为一个形状为 (a, b, c, ..., N) 的数组 - 将 N 放在第 -1 位。范围是3,因为len('rgb') == 3
猜你喜欢
  • 2018-02-14
  • 1970-01-01
  • 1970-01-01
  • 2021-11-05
  • 2018-10-08
  • 2020-10-01
  • 2019-05-17
  • 2020-03-19
  • 2021-12-31
相关资源
最近更新 更多