【问题标题】:How Keras calculates convolutions 2d in cascadedKeras 如何在级联中计算 2d 卷积
【发布时间】:2020-06-28 15:41:20
【问题描述】:

当我有多个 Conv2D 层,只有通道,在 Keras 中级联时,最终形状对应于最后阶段的(批次、行、列、过滤器)。如果过滤器的数量在所有层中都是 1,我可以毫无问题地计算输出,但是,当过滤器的数量不是一个时会发生什么?例如,在这段代码中,我有 3 个带有 2,2 和 1 个过滤器的 Conv2D 层。我在第二层计算结果:

# 1ª etapa
padding = "same"
i_s = (16,32,32) # Batch y tamaño de la imagen de entrada

# 1ª Etapa
f_s_1 = (9,9) # Tamaño del filtro 1
filters_1 = 2 # Número de filtros 1
strides_1 = (1,1) # Strides 1

# 2ª Etapa
f_s_2 = (9,9) # Tamaño del filtro 2 
filters_2 = 2 # Número de filtros 2
strides_2 = (1,1) # Strides 2

# 3ª Etapa
f_s_3 = (9,9) # Tamaño del filtro 2 
filters_3 = 1 # Número de filtros 2
strides_3 = (1,1) # Strides 2

# Matriz de imágenes
I = np.random.random(i_s).astype(np.float32)
If = np.copy(I)
I.shape = (i_s[0],i_s[1],i_s[2],1)

# Convolución 2D mediante keras
model = Sequential()
k_s = (i_s[1],i_s[2],1)
model.add(Conv2D(filters_1, f_s_1, input_shape=k_s, strides=strides_1, padding=padding))
model.add(Conv2D(filters_2, f_s_2, strides=strides_2, padding=padding))
# Calculo la salida en la segunda etapa
reference = model.predict(I)[:,:,:,:] # Convolución de referencia
model.add(Conv2D(filters_3, f_s_3, strides=strides_3, padding=padding))

形状结果是 (16,32,32,2) 但我认为输出形状会是 (16,32,32,4) 因为 2过滤器和 2 个过滤器是 4 个功能......不是吗?

过滤器形状是(k_h,k_w,前一层的过滤器,实际层的过滤器)。我也不明白这个形状。 前一层过滤器的维度是多少。我用这段代码捕获了过滤器:

# Se coge el filtro de la capa de convolución de keras
filters = model.get_weights()
filters_stg1 = filters[0][:,:,:,:]
filters_stg2 = filters[2][:,:,:,:]
filters_stg3 = filters[4][:,:,:,:]

Shapes of the filters. I don't understand the third dim

我正在阅读关于体积上的卷积...这是使用 Keras 将特征分组为一个的过程吗?对特征进行分组的数学过程是什么?

【问题讨论】:

    标签: python tensorflow keras conv-neural-network


    【解决方案1】:

    我终于找到了解决办法。

    首先:过滤器中的暗淡是(行、列、通道、过滤器)

    第二:当 2 个或更多 conv 2d 级联时,Keras 使用卷积对体积计算前一阶段的每个滤波器输​​出。这意味着前一阶段的每个滤波器输​​出与实际层中的滤波器的卷积之和。通过这种方式,可以实现输出与最后一层具有相同数量的过滤器。

    下一个代码实现了这个特性。测试给出 E-16 的 mse 错误。

    # 1ª etapa
    padding = "same"
    i_s = (16,32,32) # Batch y tamaño de la imagen de entrada
    
    # 1ª Etapa
    f_s_1 = (15,15) # Tamaño del filtro 1
    filters_1 = 32 # Número de filtros 1
    strides_1 = (1,1) # Strides 1
    # 2ª Etapa
    f_s_2 = (15,10) # Tamaño del filtro 2 
    filters_2 = 16 # Número de filtros 2
    strides_2 = (1,1) # Strides 2
    # 3ª Etapa
    f_s_3 = (9,9) # Tamaño del filtro 3
    filters_3 = 5 # Número de filtros 3
    strides_3 = (1,1) # Strides 3
    
    # Matriz de imágenes
    I = np.random.random(i_s).astype(np.float32)
    If = np.copy(I)
    I.shape = (i_s[0],i_s[1],i_s[2],1)
    
    # Convolución 2D mediante keras
    model = Sequential()
    k_s = (i_s[1],i_s[2],1)
    
    # Calculo la salida en la primera etapa
    model.add(Conv2D(filters_1, f_s_1, input_shape=k_s, strides=strides_1, padding=padding))
    # reference_1 = model.predict(I)[:,:,:,:]
    
    # Calculo la salida en la segunda etapa
    model.add(Conv2D(filters_2, f_s_2, strides=strides_2, padding=padding))
    reference_2 = model.predict(I)[:,:,:,:]
    
    # Calculo la salida en la tercera etapa
    model.add(Conv2D(filters_3, f_s_3, strides=strides_3, padding=padding))
    
    
    # Se coge el filtro de la capa de convolución de keras
    filters = model.get_weights()
    filters_stg1 = filters[0][:,:,:,:].reshape((np.prod(f_s_1),filters_1))
    filters_stg2 = filters[2][:,:,:,:]#.reshape((np.prod(f_s_2),filters_2))
    filters_stg3 = filters[4][:,:,:,:]#.reshape((np.prod(f_s_2),filters_2))
    
    # First stage Ouput
    If = pad_signal(If, f_s_1, strides_1)
    msk, r_shape = conv2d_mask(i_s, f_s_1, strides=strides_1, padding=padding)
    result_1 = np.matmul(If.flatten()[msk], filters_stg1).reshape(r_shape+(filters_1,))
    
    acum = 0
    stg = np.zeros(r_shape+(filters_2,))
    channels = []
    msk_2, r_shape = conv2d_mask(i_s, f_s_2, strides=strides_2, padding=padding)
    for i in range(filters_2):
        for j in range(filters_1):
            channel = result_1[:,:,:,j]
            filter = filters_stg2[:,:,j,i].reshape((np.prod(f_s_2),1))
            If = pad_signal(channel, f_s_2, strides_2)
            acum += np.matmul(If.flatten()[msk_2], filter).reshape(r_shape)
        stg[:,:,:,i] = acum
        acum = 0
    
    # - reference: Convolución con Keras
    # - result   : Convolución con FPGA
    # Se comprueba que el resultado es correcto con error medio cuadrático producido
    mse = (np.square(reference_2 - stg)).mean(axis=None)
    txt = "Test CORRECTO"
    if mse > 1e-10:
        txt = "Test INCORRECTO"
    print(txt)
    

    【讨论】:

    • 嗨 Diego,您能否更详细地解释一下您的代码。 pad_signal 和 conv2d_mask 有什么作用?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-26
    • 2017-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多