我想在pytorch中创建一个用于二进制图像分类的完全卷积网络,该网络可以采用动态输入图像大小,但是我在概念上不太了解将最终层从完全连接层更改为卷积层的想法。 Here和here 都指出,使用1x1卷积是可行的。
假设我有一个16x16x1的图像作为CNN的输入。经过几次卷积后,输出为16x16x32。如果使用完全连接的层,则可以通过创建16 * 16 * 32权重并将其提供给单个神经元来产生单个值输出。我不明白的是,如何通过应用1x1卷积来获得单个值输出。您不会以16x16x1的输出结束吗?
答案 0 :(得分:1)
检查此链接:http://cs231n.github.io/convolutional-networks/#convert
在这种情况下,您的卷积层应该是具有1个输出通道的16 x 16滤镜。这会将16 x 16 x 32输入转换为单个输出。
要测试的示例代码:
from keras.layers import Conv2D, Input
from keras.models import Model
import numpy as np
input = Input((16,16,32))
output = Conv2D(1, 16)(input)
model = Model(input, output)
print(model.summary()) # check the output shape
output = model.predict(np.zeros((1, 16, 16, 32))) # check on sample data
print(f'output is {np.squeeze(output)}')
这种完全卷积网络方法在使用基于补丁的方法进行分割任务中非常有用,因为您可以通过提供更大的图像部分来加快预测(推理)。
对于分类任务,通常在末尾有一个fc层。在这种情况下,将使用诸如AdaptiveAvgPool2d之类的层,以确保fc层无论输入图像大小如何都能看到恒定的输入要素大小。 https://pytorch.org/docs/stable/nn.html#adaptiveavgpool2d
请参阅以下关于Torchvision VGG的提取请求:https://github.com/pytorch/vision/pull/747
对于Keras,请使用GlobalAveragePooling2D。请参见示例“在一组新的类上微调InceptionV3”。 https://keras.io/applications/
答案 1 :(得分:0)
我希望你熟悉喀拉拉邦。现在看到您的图像是16 * 16 * 1。图像将传递到keras卷积层,但是首先我们必须创建模型。像model=Sequential()
这样,我们就能获得keras模型实例。现在,我们将为卷积层提供
model.add(Conv2D(20,(2,2),padding="same"))
现在我们在这里为图像添加20个滤镜。现在我们的图像变为16 * 16 * 20,以获得更多最佳功能,我们添加了更多的转化层,例如
model.add(Conv2D(32,(2,2),padding="same"))
现在我们将为您的图像添加32个滤镜,之后您的图像尺寸将为16 * 16 * 32
不要忘记在转换层之后进行激活。如果您是新手,则应该研究激活,优化和网络丢失。这些是神经网络的基本部分。
现在是时候转向完全连接的层了。首先,我们需要展平图像,因为在您的情况下,完全连接的图层仅适用于2d向量(no_of_ex,image_dim) 应用展平后的imgae尺寸将为(16 * 16 * 32)
model.add(Flatten())
使我们的图像变平之后,您的网络会将其分配给完全连接的层
model.add(Dense(32))
model.add(Activation("relu"))
model.add(Dense(8))
model.add(Activation("relu"))
model.add(Dense(2))
因为遇到二进制分类的问题,如果必须分类3个类,那么如果必须分类10个示例,那么最后一层将具有3个神经元。
model.add(Activation("softmax"))
model.compile(loss='binary_crossentropy',
optimizer=Adam(),
metrics=['accuracy'])
return model
在此之后,您必须适合此模型。
estimator=model()
estimator.fit(X_train,y_train)
完整代码:
def model (classes):
model=Sequential()
# conv2d set =====> Conv2d====>relu=====>MaxPooling
model.add(Conv2D(20,(5,5),padding="same"))
model.add(Activation("relu"))
model.add(Conv2D(32,(5,5),padding="same"))
model.add(Activation("relu"))
model.add(Flatten())
model.add(Dense(32))
model.add(Activation("relu"))
model.add(Dense(8))
model.add(Activation("relu"))
model.add(Dense(2))
#now adding Softmax Classifer because we want to classify 10 class
model.add(Dense(classes))
model.add(Activation("softmax"))
model.compile(loss='categorical_crossentropy',
optimizer=Adam(lr=0.0001, decay=1e-6),
metrics=['accuracy'])
return model