Keras如何计算级联二维卷积

2024-10-01 11:34:56 发布

您现在位置:Python中文网/ 问答频道 /正文

当我有多个Conv2D层,只有通道,在Keras中级联时,最终的形状与最后阶段的(批、行、列、过滤器)相对应。如果所有层中的过滤器数量都是1,我可以毫无问题地计算输出,但是,当过滤器数量不是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将特征分组到一个组中的过程吗?对特征进行分组的数学过程是什么


Tags: 过滤器modeldefiltersla形状paddingdel
1条回答
网友
1楼 · 发布于 2024-10-01 11:34:56

最后我找到了解决办法

第一:过滤器中的DIM是(行、列、通道、过滤器)

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

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

# 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)

相关问题 更多 >