我想在pytorch中创建一个完全卷积网络用于二进制图像分类,它可以采用动态输入图像大小,但我从概念上并不完全理解将最终层从完全连接层更改为卷积层的想法。 Here和here 都声明这可以通过使用1x1卷积来实现。
假设我有一个16x16x1图像作为CNN的输入。经过几次卷积后,输出为16x16x32。如果使用完全连接的层,我可以通过创建16 * 16 * 32权重并将其馈送到单个神经元来生成单个值输出。我不明白的是你如何通过应用1x1卷积获得单个值输出。难道你不会得到16x16x1输出?
检查此链接:http://cs231n.github.io/convolutional-networks/#convert
在这种情况下,您的卷积层应为16 x 16滤波器,具有1个输出通道。这会将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/
我希望你和keras比较熟悉。现在看你的图像是16 * 16 * 1。图像将传递到keras convoloutional图层,但首先我们必须创建模型。像model=Sequential()
这样我们能够得到keras模型实例。现在我们将使用我们的参数给我们的convoloutional层
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 diminsion将是(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个类而不是最后一层将有3个神经元如果你必须分类10个例子而不是你的最后一个密集层将有10个神经元。
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