深度学习——卷积神经网络 (Convolutional Neural Networks / CNN)_神经网络indicts存的什么_loveliuzz的博客-程序员秘密

技术标签: 深度学习  

一、卷积神经网络的概述



1、卷积神经网络与普通神经网络非常相似,它们都由具有可学习的权重w和偏置常量(biases)的神经元组成。每个神经元都接收一些输入,并做一些点积计算,输出是每个分类的分数,普通神经网络里的一些计算技巧到这里依旧适用。普通神经网络把输入层和隐含层进行“全连接(Full Connected)的设计。从计算的角度来讲,相对较小的图像从整幅图像中计算特征是可行的。但是,如果是更大的图像(如 96x96 的图像),要通过这种全联通网络的这种方法来学习整幅图像上的特征,将变得非常耗时。

2、卷积层解决这类问题一种简单方法是对隐藏单元和输入单元间连接加以限制每个隐单元仅仅只能连接输入单元的一部分卷积神经网络与普通神经网络的区别在于,卷积神经网络包含了一个由卷积层和子采样层构成的特征抽取器在卷积神经网络的卷积层中,一个神经元只与部分邻层神经元连接。在CNN的一个卷积层中,通常包含若干个特征平面(featureMap),每个特征平面由一些矩形排列的的神经元组成,同一特征平面的神经元共享权值,这里共享的权值就是卷积核。卷积核一般以随机小数矩阵的形式初始化,在网络的训练过程中卷积核将学习得到合理的权值。共享权值(卷积核)带来的直接好处是减少网络各层之间的连接,同时又降低了过拟合的风险

子采样也叫做池化(pooling),通常有均值子采样(mean pooling)和最大值子采样(max pooling)两种形式。子采样可以看作一种特殊的卷积过程。卷积和子采样大大简化了模型复杂度,减少了模型的参数。卷积神经网络的基本结构如图所示:


卷积神经网络由三部分构成:第一部分是输入层,第二部分由n个卷积层和池化层的组合组成,第三部分由一个全连结的多层感知机分类器构成。


二、卷积神经网络的结构分析

(一)卷积神经网络的输入层——input layer

卷积神经网络默认输入是图像,可以把特定的性质编码入网络结构,使前馈函数更加有效率,并减少了大量参数。


虽然每个输出单元只是连接输入的一部分,但是值的计算方法是没有变的,都是权重和输入的点积,然后加上偏置,这点与普通神经网络是一样的。





(二)卷积神经网络的卷积层——CONV  layer

1、卷积操作(与数学中定义的卷积有所不同,卷积神经网络中将互相关操作成为卷积)

卷积操作看成是提取特征的方式,该方式与位置无关。这隐含的原理是:图像的一部分的统计特性与其他部分是一样的。味着在这一部分学习的特征也能用在另一部分上,对于这个图像上的所有位置,都能使用同样的学习特征。更直观一些,当从一个大尺寸图像中随机选取一小块,并且从这个小块样本中学习到了一些特征,这时可以把从这个小块样本中学习到的特征作为探测器,应用到这个图像的任意地方中去

特别是,我们可以用小块样本中所学习到的特征跟原本的大尺寸图像作卷积,从而对这个大尺寸图像上的任一位置获得一个不同特征的激活值

 如下图所示,展示了一个3的卷积核在5×5的图像上做卷积的过程。每个卷积都是一种特征提取方式,就像一个筛子,将图像中符合条件(激活值越大越符合条件)的部分筛选出来



2、卷积神经网络中的一些基本概念


(1)、过滤器/卷积核:   filter,定义用符号 f 来表示:

去检测图像的复杂边缘,过滤器filter中的数字可以对应深度学习的参数,如:w。


假设输入图像大小为:n*n过滤器大小为:f*f,则输出图像大小为:(n-f+1)*(n-f+1)

(2)补零填充值:   zero  padding  ,定义用符号 p 来表示:

valid卷积:无填充(no padding),假设输入图像大小为:n*n过滤器大小为:f*f,输出图像大小为:(n-f+1)*(n-f+1)

same卷积:填充后输出图像大小与输入图像大小相同。假设输入图像大小为:n*n过滤器大小为:f*f,输出图像大小可表示  为:(n+2p-f+1)*(n+2p-f+1),由于输出大小与输入大小相同,输出大小也可表示为:n*n,则得到下面的等式:

n = n+2p-f+1,计算求得 p = (f-1)/2 。即:当填充为 p = (f-1)/2时,会得到same卷积。

(3)步长:stride,定义用符号 s表示:


(4)多卷积核

只有1个卷积核的情况下,特征提取是不充分的。我们可以添加多个卷积核,比如32个卷积核,可以学习32种特征。在有多个卷积核时,如下图所示:


 上图右,不同颜色表明不同的卷积核每个卷积核都会将图像生成为另一幅图像。比如两个卷积核就可以将生成两幅图像,这两幅图像可以看做是一张图像的不同的通道

下图展示了在四个通道上的卷积操作,有两个卷积核生成两个通道。其中需要注意的是,四个通道上与卷积核的通道一 一对应,先将w1忽略,只看w0,那么在w0的某位置(i,j)处的值,是由四个通道上(i,j)处的卷积结果相加然后再取激活函数值得到的。

 所以,在 由4个通道卷积得到2个通道 的过程中, 参数的数目为4×2×2×2个 ,其中 4表示4个通道

第一个2表示生成2个通道,最后的2×2表示卷积核大小

结论:

输入图像大小为:n*n*nc,其中 nc 表示图像的通道数,过滤器维度为:f*f*nc,在无填充(no padding)以及步长s=1时,输出图像大小为:(n-f+1)*(n-f+1)*nc'  ,nc'表示:过滤器的个数



(三)卷积神经网络的ReLU激励层——ReLU  layer






(四)单层卷积网络举例:



(五)卷积神经网络的池化层——pooling  layer

除了卷积层,在卷积神经网络里面通常也使用池化层来减少模型的大小,提高计算速度,同时提高所提取特征的鲁棒性。在通过卷积获得了特征 (features) 之后,下一步我们希望利用这些特征去做分类。理论上讲,人们可以用所有提取得到的特征去训练分类器,例如 softmax 分类器,但这样做面临计算量的挑战。例如:对于一个 96X96 像素的图像,假设已经学习得到了400个定义在8X8输入上的特征,每一个特征和图像卷积都会得到一个 (96 − 8 + 1) × (96 − 8 + 1) = 7921 维卷积特征,由于有 400 个特征,每个样例 (example) 都会得到一个 7921 × 400 = 3,168,400 维的卷积特征向量。学习一个拥有超过 3 百万特征输入的分类器十分不便,且容易出现过拟合 (over-fitting)。

       为了解决这个问题,首先回忆一下,我们之所以决定使用卷积后的特征是因为图像具有一种“静态性”的属性,这也就意味着在一个图像区域有用的特征极有可能在另一个区域同样适用。因此,为了描述大的图像,一个很自然的想法就是对不同位置的特征进行聚合统计,例如,人们可以计算图像一个区域上的某个特定特征的平均值 (或最大值)。这些概要统计特征不仅具有低得多的维度 (相比使用所有提取得到的特征),同时还会改善结果(不容易过拟合)。这种聚合的操作就叫做池化 (pooling),有时也称为平均池化或者最大池化(取决于计算池化的方法)。




池化(pool)下采样(down samples),目的是为了减少特征图。池化操作对每个深度切片独立,规模一般为 2*2,相对于卷积层进行卷积运算,池化层进行的运算一般有以下几种: 
1、 最大池化(Max Pooling)取4个点的最大值。这是最常用的池化方法。 

最大值子采样的卷积核中各权重值中只有一个为1,其余均为0,卷积核中为1的位置对应inputX被卷积核覆盖部分值最大的位置。卷积核在原图inputX上的滑动步长为2。最大值子采样的效果是把原图缩减至原来的1/4,并保留每个2*2区域的最强输入


2、 均值池化(Mean Pooling)取4个点的均值

均值子采样的卷积核中每个权重都是0.25,卷积核在原图inputX上的滑动的步长为2。均值子采样的效果相当于把原图模糊缩减至原来的1/4


3、池化层的总结

(1)最大池化层、效率很高,实际中经常使用。它有一组超参数过滤器大小 f 和步长 s

但并没有参数需要学习,不用梯度下降,一旦确定 f 和 s 之后,它是一个固定的运算。

(2)池化操作将保存深度大小不变如果池化层的输入单元大小不是二的整数倍,

一般采取边缘补零(zero-padding)的方式补成2的倍数,然后再池化。


(六)卷积神经网络的全连接层(Fully-connected layer)



三、卷积神经网络训练算法及dropout正则化








四、数据增强(Data augmentation

增加训练数据,则能够提升算法的准确率,因为这样可以避免过拟合,而避免过拟合就可以增大网络结构。当训练数据有限的时候,可以通过一些变换来从已有的训练数据集中生成一些新的数据,来扩大训练数据。数据增强的方法有:

1、水平翻转


2、随机裁剪

如原始图像大小为256*256,随机裁剪出一些图像224*224的图像。如下图,红色方框内为随机裁剪出的224*224的图片。AlexNet训练时,左上、右上、左下、右下、中间做了5次裁剪然后翻转,得到10张裁剪的图片。防止大网络过拟合(underubstantialoverfitting)。


3、fancy PCA


4、样本不均衡——Labelshuffle

样本不均衡即有些类别图像特别多,有些特别少。类别不平衡数据的处理:Labelshuffle,由海康威视提出。由于场景数据集不均匀的类别分布,给模型训练带来了困难。海康威视提出了Label Shuffling的类别平衡策略

在Class-Aware Sampling方法中,定义了2种列表,一是类别列表,一是每个类别的图像列表,对于80类的分类问题来说,就需要事先定义80个列表,很不方便。对此进行了改进,只需要原始的图像列表就可以完成同样的均匀采样任务。以图中的例子来说,步骤如下:(1)首先对原始的图像列表,按照标签顺序进行排序(2)然后计算每个类别的样本数量,并得到样本最多的那个类别的样本数。根据这个最多的样本数,对每类随机都产生一个随机排列的列表(3)然后用每个类别的列表中的数对各自类别的样本数求余,得到一个索引值,从该类的图像中提取图像,生成该类的图像随机列表(4)然后把所有类别的随机列表连在一起,做个Random Shuffling,得到最后的图像列表,用这个列表进行训练。每个列表,到达最后一张图像的时候,然后再重新做一遍这些步骤,得到一个新的列表,接着训练。

Label Shuffling方法的优点在于,只需要原始图像列表,所有操作都是在内存中在线完成,非常易于实现。 


import random

category=80

f=open('scene_train_20170904.txt')  #按照label从小到大排序
#f=open('scene_validation_20170908.txt')
dicts={}
for line in f:
    line=line.strip('\n')
    image=line.split()[0]
    label=int(line.split()[-1])
    dicts[image]=label
dicts=sorted(dicts.items(),key=lambda item:item[1])
f.close()

counts={}   #统计每一类label的数目
new_dicts=[]
for i in range(category):
    counts[i]=0
for line in dicts:
    line=list(line)
    line.append(counts[line[1]])
    #print line
    counts[line[1]]+=1
    new_dicts.append(line)
#print counts

#for line in new_dicts:
#    print line

tab=[]  #把原列表按照每一类分成各个block并形成新列表
origin_index=0
for i in range(category):
    block = []
    for j in range(counts[i]):
        block.append(new_dicts[origin_index])
        origin_index+=1
    #print block
    tab.append(block)
#print tab

nums=[] #找到数目最多的label类别
for key in counts:
    nums.append(counts[key])
nums.sort(reverse=True)
#print nums

lists=[]    #形成随机label序列
for i in range(nums[0]):
    lists.append(i)
#print lists
all_index=[]
for i in range(category):
    random.shuffle(lists)
    #print lists
    lists_res=[j%counts[i] for j in lists]
    all_index.append(lists_res)
    #print lists_res
#print all_index

#f=open('train_shuffle_labels.txt','w') #按照随机序列提取图像生成最后的标签
#f=open('val_shuffle_labels.txt','w')
f=open('train_shuffle_labels.lst','w')
#f=open('val_shuffle_labels.lst','w')
shuffle_labels=[]
index=0
for line in all_index:
    for i in line:
        shuffle_labels.append(tab[index][i])
    index+=1
#print shuffle_labels
random.shuffle(shuffle_labels)
id=0
for line in shuffle_labels:
    #print line
    #f.write(line[0]+' '+str(line[1]))
    f.write(str(id)+'\t'+str(line[1])+'\t'+line[0])
    f.write('\n')
    id+=1
f.close()

5、其他数据增强的方法

平移变换旋转/仿射变换;高斯噪声、模糊处理。

对颜色的数据增强:图像亮度、饱和度、对比度变化。

注意: 训练和测试要 协调一致

       (1) 训练的时候,我们通常都需要做数据增强,在测试的时候,我们通常很少去做数据增强。这其中似乎有些不协调,因为你训练和测试之间有些不一致。实验发现训练的最后几个迭代,移除数据增强,和传统一样测试,可以提升一点性能

       (2) 如果训练的时候一直使用尺度和长宽比增强数据增强,在测试的时候也同样做这个变化,随机取32个裁剪图片来测试,也可以在最后的模型上提升一点性能 就是多尺度的训练,多尺度的测试

         (3)训练过程的中间结果,加入做测试,可以一定程度上降低过拟合。


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/loveliuzz/article/details/79062350

智能推荐

使用ESP8266播放音乐_esp8266扬声器_James.OuYang的博客-程序员秘密

使用工具:NodeMCU开发板、Arduino IDE1.安装Arduino IDE 1.8.10,点击下载,根据提示安装完成。2.下载ESP8266支持包,点击下载,双击等待完成。3.打开Arduino IDE>工具>开发板即可看到对ESP8266相关的支持,如下图:4.添加SPIFFS环境,点击下载,解压复制ESP8266FS到Arduino IDE安装目录to...

logging模块详解_这个异常不抛出的博客-程序员秘密

简单将日志打印到屏幕:[python] view plain copy import logging  logging.debug('debug message')  logging.info('info message')  logging.warning('warning message')  logging.error('err

HttpClient实现登录功能_httpclient 登录_Mr. 码农的博客-程序员秘密

在很多APP里面,用户注册、登录的功能是必不可少的,登录功能的原理就是将本地的数据POST到服务器端,服务器接收到数据之后返回一个Json。客户端获取到返回的Json数据并对其解析,其中有个加密的标识符进行判断,如果是肯定的标识符则可以登录,如果是失败的标识符则提示错误信息。 首先给一个登录的按钮增加一个点击事件,点击按钮的时候弹出一个正在登录的对话框,然后执行线程:mDialog = ne

Linux驱动开发(从零开始编写一个驱动程序)_学习&笔记的博客-程序员秘密

1、系统整体工作原理(1)应用层->API->设备驱动->硬件(2)API:open、read、write、close等(3)驱动源码中提供真正的open、read、write、close等函数实体2、file_operations结构体(用来挂接实体函数地址)(1)元素主要是函数指针,用来挂接实体函数地址(2)每个设备驱动都需要一个该结构体类型的变量(3)设备驱动向内核注册时提供该结构体类型的变量3、注册字符设备驱动驱动向内核注册函数register

小程序ios时间处理_小程序苹果时间处理了_davico_tao的博客-程序员秘密

wpy小程序处理ios时间问题微信小程序展示时间会出现NAN,原因是ios对-不处理:处理方法百度有在newDate之前 replace(/-/g, ‘/’)还可以直接判断是否为ios,然后统一处理代码片.// 处理时间const formatTime = date => { date = new Date(date) const year = date.getFullYear(); const month = date.getMonth() + 1; co

Mac os中pycharm配置anaconda环境的方法(帮新手避坑)_macbook pycharm设置环境_哈哈小火锅的博客-程序员秘密

Mac os中pycharm配置anaconda环境的方法(帮新手避坑)第一步打开PyCharm,进入System preferences(偏好设置)中找到python Interpreter第二步,点击右上角的齿轮,并选择add…出现如下窗口,我们应该选择System Interpreter 而不是Virtualenv Environment或condas Environment:第三步,点击右上角进入添加,找到如下,anaconda目录下python.app文件夹然后继续往下找到MacOS

随便推点

sql:谓词_Cytues的博客-程序员秘密

谓词就是返回值为真值的函数。1.like谓词:字符串的部分一致查询取ddd开头的字符串:select *from SampleLikewhere strcol like 'ddd%';%代表0字符以上的任意字符串,是通配符其中的一种2.between谓词:范围查找选取销售单价为100-1000的商品:select product_name, sale_price...

tomcat中部署好的项目,内网和localhost可以访问,但是外网不能访问(Windows 2008 R2中)_tomcat 项目不对外_hsj1213522415的博客-程序员秘密

在Windows 2008 R2用tomcat搭建环境能够运行web项目,在本地用localhost或者内网可以访问网站,但是外网均无法访问网站,发现有两种可能性致使这种情况发生:1.防火墙屏蔽80端口,需要在防火墙中允许外网对80端口的访问,但是这对服务器来说极不安全:具体

dw写html怎么自动缩进,DW中文首行缩进实现技巧_朱晓光指数投资的博客-程序员秘密

方法1:预格式化标签<PRE><PRE>是HTML语言中控制版式的一个标签,但现在的网页设计人员好像不是很常用它。在HTML语言规范中,被<PRE></PRE>标签包含的文字将按输入时的格式显示。对于加上<PRE>标签的文字,浏览器将以等宽字体预先显示格式化的文本,而不会合并文字之间的空格距离和进行行两端对齐。在格式化中文段落,尤其是诗词时,<PRE>的作用就显得很重要了。首先打开原始文档,在欲复...

ndk-build使用说明_ndk-build arm64_csfchh的博客-程序员秘密

ndk-build是上一代android ndk开发编译工具,尽管现在官方推荐使用CMake,AS默认的工具也切换成了后者,但是仍有必要对ndk-build有一定了解,以求:知道ndk-build如何使用;知道如何从ndk-build项目切换到CMake;还是先回顾一下NDK开发的步骤:在java类文件中编写native接口;借助AS代码提示自动生成或者使用javah命令生成.h头文件;新建c/cpp文件引入头文件并实现接口函数;配置编译选项编译成so文件(ndk-build或CMake

python中pack的用法_Python中struct.pack()和struct.unpack()用法详细说明_weixin_39890332的博客-程序员秘密

python中的struct主要是用来处理C结构数据的,读入时先转换为Python的字符串类型,然后再转换为Python的结构化类型,比如元组(tuple)啥的~。一般输入的渠道来源于文件或者网络的二进制流。1.struct.pack()和struct.unpack()在转化过程中,主要用到了一个格式化字符串(format strings),用来规定转化的方法和格式。下面来谈谈主要的方法:1.1 ...

在线二维码生成工具html源码_酷爱码的博客-程序员秘密

源码介绍:上传源码到服务器以后了,打开域名即可使用,源码仅供参考学习。