没有完全连接层的卷积神经网络分类器

Posted

技术标签:

【中文标题】没有完全连接层的卷积神经网络分类器【英文标题】:Convolution Neural Network classifier without Fully Connected Layers 【发布时间】:2017-04-04 20:20:49 【问题描述】:

我正在开展一个项目来检测以下类别汽车、卡车、公共汽车,然后提取相应的车牌。

这个问题是关于各个类的检测。我使用了传统方法,我将 HOG 特征与线性 SVM 一起使用,它可以工作,但准确度较低。我正在尝试研究 CNN 以进行基于深度学习的检测,该检测已显示出更高的准确性。 R-CNN 之类的论文非常精彩,我完全理解它是如何工作的。

最近YOLO 模型展示了一个非常快速的检测,这非常有趣。如果我猜对了,那么 YOLO 与DPM 大致相似。

一般来说,YOLO 有 24 个卷积层和 2 个全连接层。 NVIDIA DIGITS 基于这篇 YOLO 论文实现了一个 DetectNet。我感到困惑的是 NVIDIA 的 DetectNet 没有任何全连接层 (Caffe Model File)。取而代之的是,最后一个卷积层的输出通过一个降维卷积层传递,我认为这会输出一些对拥有对象的信心。

问题 1

但我不明白卷积层如何取代 FC-Layers 并学会预测对象?对此的详细解释将非常有帮助。

【问题讨论】:

detectnet 确实使用 FCN,请参阅 https://devblogs.nvidia.com/parallelforall/detectnet-deep-neural-network-object-detection-digits/ 内核空间大小1x1的卷积层和FC层的唯一区别是前者的权重是通道共享的,而后者的权重根本不共享。 【参考方案1】:

问题:你能否对图像进行卷积以使用全连接层进行分类

简单的答案:是的。我们不需要在 tensorflow 或 keras 中使用 Dense 层。但是……这到底是什么意思?这有多重要?让我们看一些使用 Denise 层进行 MNIST 分类的代码

import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import Conv2D, MaxPool2D, InputLayer, Reshape

# get some image data for classification
(xtrain,ytrain),(xtest,ytest) = tf.keras.datasets.mnist.load_data()
xtrain = np.reshape(xtrain,[-1,28,28,1]) / 255.0
ytrain = np.eye(10)[ytrain]
xtest = np.reshape(xtest,[-1,28,28,1]) / 255.0
ytest = np.eye(10)[ytest]

# make a convolution model with any dense or fully connected layers
model = tf.keras.models.Sequential([
    InputLayer([28,28,1]),
    Conv2D(filters=16, kernel_size=3, activation='tanh', padding='valid', kernel_initializer='he_normal'),
    Conv2D(filters=16, kernel_size=3, activation='tanh', padding='valid', kernel_initializer='he_normal'),
    MaxPool2D(pool_size=2),
    Conv2D(filters=24, kernel_size=3, activation='tanh', padding='valid', kernel_initializer='he_normal'),
    Conv2D(filters=24, kernel_size=3, activation='tanh', padding='valid', kernel_initializer='he_normal'),
    MaxPool2D(pool_size=2),
    Conv2D(filters=32, kernel_size=4, activation='tanh', padding='valid', kernel_initializer='he_normal'),
    Conv2D(filters=10, kernel_size=1, activation='softmax', padding='valid', kernel_initializer='he_normal'),
    Reshape([10])
    ])

model.summary()
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
_ = model.fit(x=xtrain,y=ytrain, validation_data=(xtest,ytest))

它会在 1 个 epoch 后用这个结果对 MNIST 进行分类

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 26, 26, 16)        160       
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 24, 24, 16)        2320      
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 12, 12, 16)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 10, 10, 24)        3480      
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 8, 8, 24)          5208      
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 4, 4, 24)          0         
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 1, 1, 32)          12320     
_________________________________________________________________
conv2d_5 (Conv2D)            (None, 1, 1, 10)          330       
_________________________________________________________________
reshape (Reshape)            (None, 10)                0         
=================================================================
Total params: 23,818
Trainable params: 23,818
Non-trainable params: 0
_________________________________________________________________

60000/60000 [==============================] - 28s 467us/sample - loss: 0.1709 - acc: 0.9543 - val_loss: 0.0553 - val_acc: 0.9838

准确度不是很好,但肯定远高于随机。从模型定义中我们可以看出,没有使用单个全连接层 (tf.keras.layers.Dense)。

但是,conv2d_4 层(即Conv2D(filters=32, kernel_size=4, ... 层)实际上执行的操作与Flatten() 后跟Dense(32, ...) 的操作相同。

然后conv2d_5Conv2D(filters=10, kernel_size=1, ... 正在有效地执行与Dense(10, ...) 相同的操作。关键区别在于,在上述模型中,这些操作使用了卷积框架。它看起来很酷,但是当 kernel_size 与整个高度 x 宽度相同时,它的计算与全连接层相同。

从技术上讲,答案是没有使用密集层。本着承认底层计算的精神,是的,最终层就像全连接层一样。

【讨论】:

以上是关于没有完全连接层的卷积神经网络分类器的主要内容,如果未能解决你的问题,请参考以下文章

卷积神经网络的一些细节思考(卷积池化层的作用)

CNN——卷积层

卷积神经网络(CNN)

初识卷积神经网络

神经网络的全连接层

使用卷积神经网络作为二元分类器