CNN 入门讲解:什么是全连接层(Fully …

论坛 期权论坛 爱问     
holy4884   2022-5-24 08:36   7671   20
新年第一更
祝大家新年快乐万事如意
这个时候还愿意点进来,新的一年肯定要起飞了

这情人节和新年连着过啊
这对情侣意味着什么,意味着要带情人去见家长了
当然对一些情侣意味着,情人节过不好,估计年也过不好

对于那些没用男女朋友的,不要心急,不要灰心
好好学习,好好生活,站直走路背影要美
总有一个人愿意跨过所有时间来到你身边
可能ta步履蹒跚,衣衫不整
但你一定要以最帅/美的姿态迎接ta

那些过年没回家的
也不要失望
心中有方向
哪怕整个世界阻拦你
你都会回家的

我来教大家放个烟花








----------------------------------------- _φ_(..) 正文开始--------------------------------------------
微信公号:follow_bobo
首发于专栏卷积神经网络(CNN)入门讲解
时隔一个月,我又来更新啦
啦啦啦
可能有很多小伙伴已经不满了
你怎么更新这么慢啊
其实不是的,其实我很多已经写好了
但是出于神秘原因,不能发
为什么不能发,以后你们就知道了

--------------------------------------好吧,正文现在才开始-----------------------------------------------------

上一期我们讲到激活函数(Activation Function),假设我们经过一个Relu之后的输出如下
Relu:





然后开始到达全连接层
啊啊啊,终于开始进入CNN的末尾了
已经推到敌军老家了,准备开始攻打水晶了
大家坚持住,黎明前,最黑暗


以上图为例,我们仔细看上图全连接层的结构,全连接层中的每一层是由许多神经元组成的(1x 4096)的平铺结构,上图不明显,我们看下图


注:上图和我们要做的下面运算无联系
并且不考虑激活函数和bias

当我第一次看到这个全连接层,我的第一个问题是:

它是怎么样把3x3x5的输出,转换成1x4096的形式



很简单,可以理解为在中间做了一个卷积



从上图我们可以看出,我们用一个3x3x5的filter 去卷积激活函数的输出,得到的结果就是一个fully connected layer 的一个神经元的输出,这个输出就是一个值
因为我们有4096个神经元
我们实际就是用一个3x3x5x4096的卷积层去卷积激活函数的输出
以VGG-16再举个例子吧
再VGG-16全连接层中
对224x224x3的输入,最后一层卷积可得输出为7x7x512,如后层是一层含4096个神经元的FC,则可用卷积核为7x7x512x4096的全局卷积来实现这一全连接运算过程。

很多人看到这,可能就恍然大悟
哦,我懂了,就是做个卷积呗

你不懂

敲黑板了
麻烦后排吃东西的同学叫下前排玩游戏的同学去把第一排的同学吵醒
我要说重点了!!!!!!!!!!!

这一步卷积一个非常重要的作用
就是把分布式特征representation映射到样本标记空间
什么,听不懂
那我说人话
就是它把特征representation整合到一起,输出为一个值

这样做,有一个什么好处?
就是大大减少特征位置对分类带来的影响

来,让我来举个简单的例子



这个例子可能过于简单了点
可是我懒得画了,大家将就着看吧
从上图我们可以看出,猫在不同的位置,输出的feature值相同,但是位置不同
对于电脑来说,特征值相同,但是特征值位置不同,那分类结果也可能不一样
而这时全连接层filter的作用就相当于
喵在哪我不管
我只要喵
于是我让filter去把这个喵找到
实际就是把feature map 整合成一个值
这个值大
哦,有喵
这个值小
那就可能没喵
和这个喵在哪关系不大了有没有
鲁棒性有大大增强了有没有
喵喵喵

因为空间结构特性被忽略了,所以全连接层不适合用于在方位上找Pattern的任务,比如segmentation

ok, 我们突然发现全连接层有两层1x4096fully connected layer平铺结构(有些网络结构有一层的,或者二层以上的)
好吧也不是突然发现,我只是想增加一点戏剧效果



但是大部分是两层以上呢
这是为啥子呢

泰勒公式都知道吧
意思就是用多项式函数去拟合光滑函数
我们这里的全连接层中一层的一个神经元就可以看成一个多项式

我们用许多神经元去拟合数据分布
但是只用一层fully connected layer 有时候没法解决非线性问题
而如果有两层或以上fully connected layer就可以很好地解决非线性问题了

说了这么多,我猜你应该懂的
听不懂?
那我换个方式给你讲

我们都知道,全连接层之前的作用是提取特征
全理解层的作用是分类
我们现在的任务是去区别一图片是不是猫


哈哈哈,猫猫好可爱
我先撸一把先

撸完了,回来啦(嗯,怎么好像哪里不对)

假设这个神经网络模型已经训练完了
全连接层已经知道


当我们得到以上特征,我就可以判断这个东东是猫了

因为全连接层的作用主要就是实现分类(Classification)
从下图,我们可以看出



红色的神经元表示这个特征被找到了(激活了)
同一层的其他神经元,要么猫的特征不明显,要么没找到
当我们把这些找到的特征组合在一起,发现最符合要求的是猫
ok,我认为这是猫了
那我们现在往前走一层
那们现在要对子特征分类,也就是对猫头,猫尾巴,猫腿等进行分类
比如我们现在要把猫头找出来


猫头有这么些个特征
于是我们下一步的任务
就是把猫头的这么些子特征找到,比如眼睛啊,耳朵啊


道理和区别猫一样
当我们找到这些特征,神经元就被激活了(上图红色圆圈)
这细节特征又是怎么来的?
就是从前面的卷积层,下采样层来的

至此,关于全连接层的信息就简单介绍完了

全连接层参数特多(可占整个网络参数80%左右),近期一些性能优异的网络模型如ResNet和GoogLeNet等均用全局平均池化(global average pooling,GAP)取代全连接层来融合学到的深度特征
需要指出的是,用GAP替代FC的网络通常有较好的预测性能
于是还出现了
以后会慢慢介绍的
----------------------------------------------------------------------------------------------
说实话,说的有点简单
但是我不能摆公式啊
不能摆计算啊
所以
大家就将就着看吧
有问题在下面留言

-------------------------------------------------------------------
新年快乐啦
有人说以前的文风太浮夸
现在我严谨一些
不知道大家喜欢不
喜欢的
点个赞
问题汇总简答(持续更新):
(1)全连接层对模型的影响?
      首先我们明白全连接层的组成如下:



二层全连接层结构

     那么全连接层对模型影响参数就是三个:

  • 全接解层的总层数(长度)
  • 单个全连接层的神经元数(宽度)
  • 激活函数
首先我们要明白激活函数的作用是:
增加模型的非线性表达能力
更详细了解请去:

如果全连接层宽度不变,增加长度:
优点:神经元个数增加,模型复杂度提升;全连接层数加深,模型非线性表达能力提高。理论上都可以提高模型的学习能力。
如果全连接层长度不变,增加宽度:
优点:神经元个数增加,模型复杂度提升。理论上可以提高模型的学习能力。
难度长度和宽度都是越多越好?
肯定不是
(1)缺点:学习能力太好容易造成过拟合。
(2)缺点:运算时间增加,效率变低。
那么怎么判断模型学习能力如何?
看Training Curve 以及 Validation Curve,在其他条件理想的情况下,如果Training Accuracy 高, Validation Accuracy 低,也就是过拟合 了,可以尝试去减少层数或者参数。如果Training Accuracy 低,说明模型学的不好,可以尝试增加参数或者层数。至于是增加长度和宽度,这个又要根据实际情况来考虑了。
PS:很多时候我们设计一个网络模型,不光考虑准确率,也常常得在Accuracy/Efficiency 里寻找一个好的平衡点。

麻烦大家给我点个赞,就是那种让我看起来,写的还不错的样子!
拜托了!!o(^`)o
分享到 :
0 人收藏

20 个回复

倒序浏览
2#
iodws  1级新秀 | 2022-5-24 08:36:50 发帖IP地址来自 中国
厉害了。可不可以写些目标检测方面的专栏?
3#
xgix8  1级新秀 | 2022-5-24 08:37:26 发帖IP地址来自 北京
厉害了,我之前也一直没想明白卷积层到全连接层是怎么转换的。谢谢解惑啊!
不过文中“很简单,可以理解为在中间做了一个卷积”这个又让我很疑惑。
这个“做了一个卷积”只是为了理解。还是真实的代码实现?如果是要做卷积,kernel是什么?是不是全是1?因为看起来只是为了后面做个sum操作。没必要再学习一次?
4#
36n4v  1级新秀 | 2022-5-24 08:37:49 发帖IP地址来自 中国
有些地方错的有些离谱了吧,首先你给的是LeNet的架构图,可以看到S4输出的特征图大小是5·5,一共16个,而C5是一个卷积层,共120个卷积核,而LeNet的卷积层的卷积核大小都是5·5,所以经过C5的卷积处理输出的尺寸正好是120·1·1,这是一个很自然的flatten的过程,而后面紧跟着的全连接层的神经元个数是84而不是4096。AlexNet的全连接层的神经元个数都是4096,但是这也是因为AlexNet中全连接层之前的输出尺寸是256·4·4,一共是4096个像素,把这些像素平铺之后就是一个一维向量,就是一个平铺的操作。在MXNet中这一点就更明显了,在softmax之前会要求做一个flatten。
5#
n03uh  1级新秀 | 2022-5-24 08:38:23 发帖IP地址来自 广东
抱歉,我没说清楚,我举的例子和这些Alexnet ,mxnet 没有关系,全部是我自己编的,那个图只是为了让读者感受一下到全连接层的变化,谢谢提议
6#
blackeye05  1级新秀 | 2022-5-24 08:38:38 发帖IP地址来自 北京
你说的这个不对,我更新了一个例子:
以VGG-16为例,对224x224x3的输入,最后一层卷积可得输出为7x7x512,如后层是一层含4096个神经元的FC,则可用卷积核为7x7x512x4096的全局卷积来实现这一全连接运算过程
7#
cq7k3  1级新秀 | 2022-5-24 08:38:52 发帖IP地址来自 北京
都和你说了和mxnet 没有关系
8#
fcfze  1级新秀 | 2022-5-24 08:39:16 发帖IP地址来自 北京
这个结构是我自己随便写的
9#
whtwhtwht53  1级新秀 | 2022-5-24 08:39:54 发帖IP地址来自 北京
我看了一下caffe里关于全连接层的实现,里面是这样写的:
  // num_output:输出个数,对应VGG-16也就是4096
  const int num_output = this->layer_param_.inner_product_param().num_output();
  bias_term_ = this->layer_param_.inner_product_param().bias_term();
  transpose_ = this->layer_param_.inner_product_param().transpose();
  N_ = num_output;
  const int axis = bottom[0]->CanonicalAxisIndex(
      this->layer_param_.inner_product_param().axis());
  // 从下面这段注释中可以看到,从axis开始的像素会被flattened成一个K_维的向量,
  // 这里也说了,如果输入的尺寸是(batch_size, channel, height, weight),那么
  // 一共会做batch_size次内积,每次做内积的是权值矩阵和一个channel*height*weight维的向量
  // Dimensions starting from "axis" are "flattened" into a single
  // length K_ vector. For example, if bottom[0]'s shape is (N, C, H, W),
  // and axis == 1, N inner products with dimension CHW are performed.
  // K_指的是输入全连接层的像素总数
  K_ = bottom[0]->count(axis);
  // Check if we need to set up the weights
  if (this->blobs_.size() > 0) {
    LOG(INFO) << "Skipping parameter initialization";
  } else {
    if (bias_term_) {
      this->blobs_.resize(2);
    } else {
      this->blobs_.resize(1);
    }
    // Initialize the weights
    // 从这里开始初始化全连接层的权值矩阵了
    vector<int> weight_shape(2);
    if (transpose_) {
      weight_shape[0] = K_;
      weight_shape[1] = N_;
    } else {
      weight_shape[0] = N_;
      weight_shape[1] = K_;
    }
    // 很明显的,全连接层的矩阵是一个K_*N_或者N_*K_的矩阵对应到你说的VGG-16的例子,最后一个max-pooling层输出的是一个512*7*7(乘积是25088)的特征图,那么如果是caffe,这个特征图进入全连接层之后就会被flatten成一个25088维的向量,同时这个全连接层会初始化一个25088*4096的权值矩阵,这两个进行矩阵乘积运算,最后输出一个4096的一维向量。我大概知道你说的全局卷积是什么意思,核心思想应该是一致的,你可能指的是fully convolution?如果是fully convolution,那么你这种说法就没什么错误,但是毕竟你的专栏是面对小白,把全连接转为卷积运算可能会让人摸不着头脑,当然这是从我的角度。我个人觉得直接说把一个多维的Tensor直接平摊成一个一维的vector,然后送到全连接里会更加容易让人理解,尤其是小白,毕竟框架就是这么实现的。
10#
吴宇  管理员  伦敦金丝雀码头交易员 | 2022-5-24 08:40:17 发帖IP地址来自 北京海淀
我理解你的意思,但是全连接转换为全卷积的过程对小白不友好,上面就有一个评论里说他不明白。而且框架实现(这里指caffe)也不是用全卷积的方式,而是直接flatten,然后矩阵相乘
11#
t8ji6  1级新秀 | 2022-5-24 08:40:43 发帖IP地址来自 北京朝阳
这位小哥厉害了,人家caffe 实现的方法核心明明就是卷积啊。
因为我前面说了什么是卷积,在这里为了方便理解,把全连接理解为卷积不是更方便,cs231官方文档里也是这么理解的呀
12#
ff66e  1级新秀 | 2022-5-24 08:41:22 发帖IP地址来自 北京
好吧,反正caffe里卷积也是拿矩阵相乘实现的,你的文章你做主,至于哪个更容易理解,见仁见智吧,反正机器学习这种东西,一千个人一千种理解方式
13#
o2r76  1级新秀 | 2022-5-24 08:41:40 发帖IP地址来自 北京
具体的实现方式肯定和硬件有关,但是和理论不冲突
14#
s0tb5  1级新秀 | 2022-5-24 08:42:19 发帖IP地址来自 北京丰台
第1个Dense那里替换成ksize=(上层特征图W,上层特征图H),同时不要用same,改valid,第2个Dense用ksize=(1,1),也用valid,这样就可以了,最后加个flat,再加个dense做为out就可以了
15#
_w85o  1级新秀 | 2022-5-24 08:42:55 发帖IP地址来自 北京
全连接层就是全连接的卷积层
16#
mq4r_  1级新秀 | 2022-5-24 08:43:01 发帖IP地址来自 北京
所谓的4096个神经元,在运算中是指4096个filter吗?
17#
63yk3  1级新秀 | 2022-5-24 08:43:30 发帖IP地址来自 中国
一个神经元里面的Filter 的个数是输入的feature map 的个数
18#
rocky217  1级新秀 | 2022-5-24 08:43:48 发帖IP地址来自 中国
哦哦,feature map就是上面最简单的那个例子的 5*3*3 的5吗?
19#
y2z_1b  1级新秀 | 2022-5-24 08:44:37 发帖IP地址来自 北京
对,5个feature map
20#
b0bm8  1级新秀 | 2022-5-24 08:45:17 发帖IP地址来自 中国
越说越糊涂,不如不说
21#
fnn8  1级新秀 | 2022-5-24 08:45:23 发帖IP地址来自 北京海淀
你哪里没看懂呢,全连接层其实是个很大的概念,我挑了一些简单的方面为了让初学者有个大概得映像
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:25
帖子:14
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP