Caffe 训练时caffe accuracy值不变 始终为1是什么原因

你的浏览器禁用了JavaScript, 请开启后刷新浏览器获得更好的体验!
Test net output #0: accuracy = 1
Test net output #1: loss = 0 (* 1 = 0 loss)
应该是过拟合了,你把基础学习率调小十倍试一下效果。
所以你的test集和train集是有重叠吗?
我也是被这个问题困扰了很久啊,我做图像分割的。name: &segnet&
name: &features&
type: &Data&
top: &features&
phase: TRAIN
transform_param {
data_param {
source: &project_shuo/lung_seg/train_db/features&
batch_size: 10
backend: LMDB
name: &labels&
type: &Data&
top: &labels&
phase: TRAIN
transform_param {
data_param {
source: &project_shuo/lung_seg/train_db/labels&
batch_size: 10
backend: LMDB
name: &features&
type: &Data&
top: &features&
phase: TEST
transform_param {
data_param {
source: &project_shuo/lung_seg/train_db/features&
batch_size: 10
backend: LMDB
name: &labels&
type: &Data&
top: &labels&
phase: TEST
transform_param {
data_param {
source: &project_shuo/lung_seg/train_db/labels&
batch_size: 10
backend: LMDB
name: &conv1&
type: &Convolution&
bottom: &features&
top: &conv1&
lr_mult: 1
decay_mult: 1
lr_mult: 2
decay_mult: 0
convolution_param {
num_output: 10
kernel_size: 7
name: &relu1&
type: &ReLU&
bottom: &conv1&
top: &conv1&
name: &conv2&
type: &Convolution&
bottom: &conv1&
top: &conv2&
lr_mult: 1
decay_mult: 1
lr_mult: 2
decay_mult: 0
convolution_param {
num_output: 1
kernel_size: 5
weight_filler {
type: &xavier&
bias_filler {
type: &constant&
name: &Sigmoid&
type: &Sigmoid&
bottom: &conv2&
top: &conv2&
name: &accuracy&
type: &Accuracy&
bottom: &conv2&
bottom: &labels&
top: &accuracy&
phase: TEST
name: &loss&
type: &SoftmaxWithLoss&
bottom: &conv2&
bottom: &labels&
top: &loss&
不知道怎么搞,数据集是从digits做的。运行的时候一直这样:
Waiting for data
I:03.79 data_layer.cpp:73] Restarting data prefetching from start.
I:03.78 data_layer.cpp:73] Restarting data prefetching from start.
I:11.74 solver.cpp:398]
Test net output #0: accuracy = 1
I:11.74 solver.cpp:398]
Test net output #1: loss = 0 (* 1 = 0 loss)
I:15.74 solver.cpp:219] Iteration 0 (-1.60881e-39 iter/s, 43.229s/50 iters), loss = 0
I:15.74 solver.cpp:238]
Train net output #0: loss = 0 (* 1 = 0 loss)
I:15.74 sgd_solver.cpp:105] Iteration 0, lr = 0.01
I:24.77 data_layer.cpp:73] Restarting data prefetching from start.
I:24.76 data_layer.cpp:73] Restarting data prefetching from start.
I:43.74 solver.cpp:331] Iteration 20, Testing net (#0)
I:13.79 data_layer.cpp:73] Restarting data prefetching from start.
I:13.78 data_layer.cpp:73] Restarting data prefetching from start.
I:20.74 solver.cpp:398]
Test net output #0: accuracy = 1
I:20.74 solver.cpp:398]
Test net output #1: loss = 0 (* 1 = 0 loss)
I:34.77 data_layer.cpp:73] Restarting data prefetching from start.
I:34.76 data_layer.cpp:73] Restarting data prefetching from start.
I:52.74 solver.cpp:331] Iteration 40, Testing net (#0)
I:23.79 data_layer.cpp:73] Restarting data prefetching from start.
I:23.78 data_layer.cpp:73] Restarting data prefetching from start.
I:30.74 solver.cpp:398]
Test net output #0: accuracy = 1
I:30.74 solver.cpp:398]
Test net output #1: loss = 0 (* 1 = 0 loss)
I:21.74 solver.cpp:219] Iteration 50 (0.163647 iter/s, 305.535s/50 iters), loss = 0
I:21.74 solver.cpp:238]
Train net output #0: loss = 0 (* 1 = 0 loss)
I:21.74 sgd_solver.cpp:105] Iteration 50, lr = 0.
I:44.77 data_layer.cpp:73] Restarting data prefetching from start.
I:44.76 data_layer.cpp:73] Restarting data prefetching from start.
I:02.74 solver.cpp:331] Iteration 60, Testing net (#0)
I:34.79 data_layer.cpp:73] Restarting data prefetching from start.
I:34.78 data_layer.cpp:73] Restarting data prefetching from start.
I:42.74 solver.cpp:398]
Test net output #0: accuracy = 1
I:42.74 solver.cpp:398]
Test net output #1: loss = 0 (* 1 = 0 loss)
请问楼主解决了吗
了吗,那个准确率一直是1的问题
一种可能是,你训练数据没有打散,即,负样本超级多后,大部分batch里全是负样本。
最好每个batch里即有负样本,又有一定比例的正样本.
顺便,还可以把训练了来的模型的参数值打出来看看,可能绝对直超大或0的值吧?
要回复问题请先或
浏览: 1012
关注: 5 人caffe 进行自己的imageNet训练分类:loss一直是87.3365,accuracy一直是0
时间: 14:30:11
&&&& 阅读:120
&&&& 评论:
&&&& 收藏:0
标签:&&&&&&&&&&&&&&&&&&&&&&&&&&&
caffe 进行自己的imageNet训练分类:
loss一直是87.3365,accuracy 一直是0,可能的原因是:
解决方法:&http://blog.csdn.net/jkfdqjjy/article/details/?locationNum=14知道了原因,解决时就能对症下药。总体上看,softmax输入的feature由两部分计算得到:一部分是输入数据,另部分是各层权重参数。&1、观察数据中是否有异常样本或异常label导致数据读取异常&2、调小初始化权重,以便使softmax输入的feature尽可能变小&3、降低学习率,这样就能减小权重参数的波动范围,从而减小权重变大的可能性。这条也是网上出现较多的方法。&4、如果有BN(batch normalization)层,finetune时最好不要冻结BN的参数,否则数据分布不一致时很容易使输出值变的很大。
http://blog.csdn.net/hyqsong/article/details/
标签的问题:&
imagelist中,图像分类的标签label一定要从0开始,
分类层的 num_output 和 标签的值域 不符合:
a. 要知道imagenet是进行1000类的分类任务,我自己的数据是一个二分类,就一定要把最后‘fc8’InnerProduct的分类层的num_output: 2原来是1000,这个设成自己label的类别总数就可以。&b. 但是注意同时要修改train.prototxt和deploy.prototxt两个网络配置文件中的num_output
可能是学习率太高了&
另外如果是最初的迭代的loss很小,然后突然变成87.3365?如果是这样,可以尝试一下调低学习率,我开始学习率是0.1,后来调成了0.001,反正就是调小,可以多试几次。
标签:&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&国之画&&&& &&
版权所有 京ICP备号-2
迷上了代码!4558人阅读
caffe学习(12)
今天才偶然发现,caffe在计算Accuravy时,利用的是最后一个全链接层的输出(不带有acitvation function),比如:alexnet的、caffenet的
下图是这两个网络训练配置文件(prototxt文件)计算Accuray的配置文件截图的截图(对于该部分,alexnet和caffenet是一致的)
最后一个全连接层
name: "fc8"
type: "InnerProduct"
bottom: "fc7"
top: "fc8"
lr_mult: 1
decay_mult: 1
lr_mult: 2
decay_mult: 0
num_output: 1000
weight_filler {
type: "gaussian"
type: "constant"
计算Accuracy
name: "accuracy"
type: "Accuracy"
bottom: "fc8"
bottom: "label"
top: "accuracy"
phase: TEST
可以看到,caffe中计算Accuracy时,是通过比较最后一个全连接层(神经元个数=类别数、但没有加入activation function)的输出和数据集的labels来得到的,计算过程在中实现
之前一直非常困惑,计算accuracy应该使用计算得到的labels与数据集真正的labels去做计算,为什么caffe的accuracy要将fc8接入Accuray层呢?通过简单查看的说明才发现,原来,在内部,实现了“利用fc8的输出得到数据集的预测labels”(数值最大的那个值得idnex就是样本的类别),那么,再与输入的数据集真实lebels作对比,就实现了accuray的计算!
实际上,如果仅仅是做预测,利用fc8的输出就够了(输出值最大的那个位置即为输入的label),该输出表示了输入的样本属于每一类的可能性大小,但并不是概率值;
如果为了使输出具有统计意义,需要加入softmax function,它只是使前面的全连接层的输出(fc8)具有了概率意义,并不改变这些输出之前的大小关系,因为softmax function本身就是增函数;
为了利用误差反向传播,还需要构造loss function,需要利用softmax function的输出,即需要利用输入样本属于每一类的概率值;
最后一个全连接层(fc8)的输出值位于区间[-∞,∞],它并不是概率值
fc8后面接的SoftmaxWithLoss层做的工作分2步
第一步:对fc8的输出计算softmax function(结果为概率值)
第二步:利用求得的概率值计算Loss值
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:239166次
积分:2651
积分:2651
排名:第12160名
原创:139篇
转载:10篇
评论:54条
(1)(1)(3)(1)(9)(2)(9)(9)(26)(85)(3)主题信息(必填)
主题描述(最多限制在50个字符)
申请人信息(必填)
申请信息已提交审核,请注意查收邮件,我们会尽快给您反馈。
如有疑问,请联系
擅长客户端及服务器端架构
你必须非常努力 才能看起来毫不费力
安卓开发工程师
本系列文章面向深度学习研发者,希望通过Image Caption Generation,一个有意思的具体任务,深入浅出地介绍深度学习的知识。本系列文章涉及到很多深度学习流行的模型,如CNN,RNN/LSTM,Attention等。本文为第13篇。
作者:李理
目前就职于环信,即时通讯云平台和全媒体智能客服平台,在环信从事智能客服和智能机器人相关工作,致力于用深度学习来提高智能机器人的性能。
相关文章:
6. 使用caffe在imagnet上训练AlexNet接下来我们介绍一下怎么用caffe训练ILSVRC2012。我们之前为了让大家理解卷积神经网络的细节原理,所以都是自己实现。但是在实际工作中,我们更倾向于使用成熟的框架来进行深度学习。caffe是一个老牌的深度学习框架,尤其是在计算机视觉领域很受欢迎。我们这里会简单的介绍一下怎么使用caffe训练ILSVRC2012,包括怎么用pycaffe使用训练好的模型,这在后面的Image Caption里会用到。6.1 ILSVRC2012和ImageNet介绍我们之前也多次提到这两个词,有时也不加区分的使用它们。这里我们稍微澄清一下它们的关系和区别。 首先ImangeNet是Stanford视觉实验室标注的一个图像数据库,有上万个分类和上千万的图片。截止到本文发表,最新的数据是“14,197,122 images, 21841 synsets indexed”。我们这个系列教程中多次涉及的课程cs231n就是stanford视觉实验室李飞飞教授开设的课程。 为了让学术界有个公开标准的图像分类【也包括Location】,Stanford视觉实验室从2010年开始就开始 ILSVRC(ImageNet Large Scale Visual Recognition Challenge) ,翻译成中文就是ImageNet大规模视觉竞赛。在2012年之前,最好的top5分类错误率在20%以上,而2012年AlexNet首次在比赛中使用了深层的卷积网络,取得了16%的错误率,一时让深度学习名声大噪。之后每年都有新的好成绩出现,2014年是GoogLeNet和VGG,而2015年是ResNet參差网络。目前最好系统的top5分类错误率在5%一下了。 ILSVRC年的比赛数据,是最流行的一个大规模分类数据,它包含1000个分类和100,000+训练数据。6.2 caffe简介caffe是berkeley视觉实验室开源的一个流行深度学习框架,更多细节读者可以参考一些官网资料。因为本文的目的也不是介绍各种工具,为了避免文字过于冗长,就不仔细介绍了,下面介绍训练步骤时简要的做一些解释。读者有了自己实现CNN的基础,理解怎么使用caffe应该不会太难。安装【包括cuda的支持】请参考官网,建议读者用Ubuntu的系统,安装比较简单,记得安装python的支持。6.3 获取ILSVRC2012数据最开始下载ILSVRC2012需要注册才能获得下载地址,现在已经完全开放,如果读者想训练ILSVRC2012,建议使用GPU,否则就得等几个月。另外机器要有比较大的硬盘空间来存放原始的数据【100多G】。如果读者不打算自己训练,也不影响,因为网上有很多训练好的模型,我们可以直接拿过来用,因此可以跳过本节。 下载地址: 这个比赛包括分类和定位,由于我们只做分类,所以只需要下载
138GB. MD5: 1d675b47dfa0da5fadfb00e
6.3GB. MD5: 29b22e3ddabcf34fc5622
13GB. MD5: fe64ceb247eaed23ab6d839
数据比较大,可能要下载一两天,用wget可以用-c选项支持断点续传。建议北京时间白天下载,对于美国来说是晚上,速度较快,最快可以到1MB/s。下载完了记得用md5检验一下下载完了解就行了。 训练数据是这样的目录结果:/path/to/imagenet/train/n26.JPEG 其中n就是代表一个类别,读者可以选择一些图片看看。 测试数据是:/path/to/imagenet/val/ILSVRC2012_val_.JPEG6.4 数据预处理1. 辅助数据下载首先要下载一下辅助的数据,进入caffe的根目录执行
$./data/ilsvrc12/get_ilsvrc_aux.sh 这个脚本会下载一些数据到data/ilsvrc12。包括train.txt val.txt和test.txt,这些文件包含图片路径【相对路径】和分类的对应关系2. 缩放图片由于图片的大小不一样,我们一般需要预先缩放图片。另外caffe使用leveldb来存储图片【为了统一管理和queue处理,上百G的图片不可能想mnist数据那样直接放到内存,我们只能把要训练的部分数据放到内存里,为了提供效率,那么需要队列这样的集中来prefetch图片到内存】,这都统一在脚本examples/imagenet/create_imagenet.sh里了。 我们需要修改一下这个脚本,主要是imagenet图片的位置,输出的目录。下面是我的配置,请参考后修改EXAMPLE=/bigdata/lili/imagenet
DATA=data/ilsvrc12
TOOLS=build/tools
TRAIN_DATA_ROOT=/bigdata/lili/imagenet/train/
VAL_DATA_ROOT=/bigdata/lili/imagenet/val/
# Set RESIZE=true to resize the images to 256x256. Leave as false if images have
# already been resized using another tool.
RESIZE=true然后在caffe的根目录运行这个脚本,注意这个脚本可能要运行好几个小时【我记不清楚了,反正第一天运行第二天才完成】6.5 计算图片的mean值就像batch normaliztion一样,我们一般需要把数据变成均值0的数据,计算mean就是这个用途。
./examples/imagenet/make_imagenet_mean.sh
这个脚本将生成data/ilsvrc12/imagenet_mean.binaryproto这个文件
注意:我使用这个脚本生成的mean文件训练时不收敛,不知道什么原因,去caffe的论坛发现别人也有碰到类似的问题,请参考 和。
我后来之后上网下载了一个mean文件就能训练了。需要的读者可以从这里下载:,解压后就有imagenet_mean.binaryproto,放到data/ilsvrc12/下就行了。6.6 修改配置文件1. models/bvlc_reference_caffenet/train_val.prototxt修改训练和测试的source: {
#source: "examples/imagenet/ilsvrc12_train_lmdb"
source: "/bigdata/lili/imagenet/ilsvrc12_train_lmdb"
batch_size: 32
backend: LMDB
#source: "examples/imagenet/ilsvrc12_val_lmdb"
source: "/bigdata/lili/imagenet/ilsvrc12_val_lmdb"
batch_size: 50
backend: LMDB
}2. models/bvlc_reference_caffenet/train_val.prototxt修改模型snapshot目录的位置:snapshot_prefix: "/bigdata/lili/imagenet/googlenetmodel/bvlc_googlenet"6.7 训练./build/tools/caffe train –solver=models/bvlc_reference_caffenet/solver.prototxt
如果是一个GPU,一般两三天也就收敛了,我最终得到的准确率在58%左右。7. 使用训练好的模型进行分类caffe代码里包含一个examples/00-classification.ipynb。我们用ipython notebook就可以像之前那样工作了。当然很可能我们是在某个GPU服务器上训练的数据,包括那些图片也放在上面,那么我们可以使用ipython的 –ip参数让ipython监听在非localhost上,这样我们使用笔记本也可以访问【这其实是ipython notebook好用之处,我们不需要在服务器上用vim编写代码或者在本地和服务器直接拷贝代码了,我们用这种方式就可以在本地笔记本开发python代码,而直接在服务器上调试和运行了】 ipython notebook –ip 这个机器的内网或者外网ip
启动后在终端会出现带token的链接:
这就在笔记本打开这个链接就行了。7.1 cell1初始化的代码,直接运行7.2 cell2设置caffe_root。直接运行应该就可以,如果有路径问题修改caffe_root为caffe的绝对路径肯定是不会有问题的。7.3 cell3下载模型,如果你训练了自己的模型,可以跳过这一步,否则这段代码会去下载网上已有的模型。注意模型上百M7.4 cell4定义和加载模型。如果你使用自己训练的模型,可以参考我的修改,否则不需要更改直接运行。model_weights = '/bigdata/lili/imagenet/models2/caffenet_train_iter_160000.caffemodel'7.5 cell5数据预处理对象caffe.io.Transformer
Our default CaffeNet is configured to take images in BGR format. Values are expected to start in the range [0, 255] and then have the mean ImageNet pixel value subtracted from them. In addition, the channel dimension is expected as the first (outermost) dimension. 默认的CaffeNet是使用BGR格式的图像【这和我们一般图像处理工具得到RBG是不一样的】。并且取值是0-255【另外一种表示方法就是0-1】,然后会减去RGB的平均值。另外Caffe的Blob是(N, C, H, W)的,我们从图像里得到的一般是(H, W, C)。 所以需要经过预处理把我们读到的数据转成Caffe需要的格式。Caffe提供了一个类caffe.io.Transformer,我们直接用这个类就可以方便的完成这些工作【当然你自己实现也是完全没有问题的,那么不需要这个类了】# load the mean ImageNet image (as distributed with Caffe) for subtraction
mu = np.load(caffe_root + 'python/caffe/imagenet/ilsvrc_2012_mean.npy')
mu = mu.mean(1).mean(1)
# average over pixels to obtain the mean (BGR) pixel values
print 'mean-subtracted values:', zip('BGR', mu)
# create transformer for the input called 'data'
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
transformer.set_transpose('data', (2,0,1))
# move image channels to outermost dimension
transformer.set_mean('data', mu)
# subtract the dataset-mean value in each channel
transformer.set_raw_scale('data', 255)
# rescale from [0, 1] to [0, 255]
transformer.set_channel_swap('data', (2,1,0))
# swap channels from RGB to BGR前面3行是读取mean文件。 第一行是读取mean文件,得到一个(3,256,256)的ndarray,代表BGR3个channel在每个像素点的平均值。 但是我们使用的时候是对每个channel减去同一个值域【不是每个位置减不同的值】,所以我们需要平均每个channel的256*256个值,这就可以用第二行代码mu=mu.mean(1).mean(1)来完成,这行代码的意思就是先对H求平均,得到一个(3,256)的ndarray,然后在对W求平均【注意这个时候H的维度下标从2变成1了】
其实用mu.mean(2).mean(1)也是等价的。总之就是对每个channel的256个值求平均。 第三行只是打印出来看看,我这里打印出来是:mean-subtracted values: [('B', 104.9), ('G', 116.67), ('R', 122.6)]接下来构造一个caffe.io.Transformer对象,它变化的数据是输入层net.blobs[‘data’].data,所以它变换的数据的shape是net.blobs[‘data’].data.shape 对caffe不熟悉的读者可以阅读一下caffe的官方文档。我们【下面】代码读入的图片是(N, H, W, C)的ndarray,如果一次读取一个图片,那么N就是1,H和W分别是图片的高度和宽度,而C就是3代表RGB 但是Caffe要求(N, C, H, W),所以需要下面这个transpose:transformer.set_transpose('data', (2,0,1)) 接下来这行transformer.set_mean(‘data’, mu) 告诉它要减去我们之前得到的BGR3个channel的均值 而transformer.set_raw_scale(‘data’, 255) 让它把0-1的范围缩放到0-255。最后因为我们读入的channel顺序是RGB,而caffe要求BGR,所以再加上最后这一行:transformer.set_channel_swap('data', (2,1,0)) 7.6 cell6这个cell显示了我们一次分类多个数据,其实也可以把batch改成1,这里只是为了演示可以一次分类多个,这会比一次分类一个加起来快。# set the size of the input (we can skip this if we're happy
with the default; we can also change it later, e.g., for different batch sizes)
net.blobs['data'].reshape(50,
# batch size
# 3-channel (BGR) images
# image size is 227x227注意,我们之前训练imagenet时会把图像缩放成227*227的,参考models/bvlc_reference_caffenet/train_val.prototxt: {
name: "data"
type: "Data"
top: "data"
top: "label"
phase: TRAIN
mirror: true
crop_size: 227
mean_file: "data/ilsvrc12/imagenet_mean.binaryproto"
}7.7 cell7接下来我们从example里读取一个图片,这是一只很可爱的猫。image = caffe.io.load_image(caffe_root + 'examples/images/cat.jpg')
transformed_image = transformer.preprocess('data', image)
plt.imshow(image)7.8 cell8我们用模型来预测:
net.blobs['data'].data[...] = transformed_image
output = net.forward()
output_prob = output['prob'][0]
print 'predicted class is:', output_prob.argmax()其实就是把data输入层放置成我们的这个图片,注意,我们之前定义的输入是(50,3,227,227),但是我们这里只传了一张(1,3,227,227)的图片,所以它会broadcasting成50个一样的图片,当然实际我们应该传人50个不同的图片。这里当然只是个演示。然后直接调用net.forward(),然后取出output[‘prob’][0],得到第一个图片的输出概率。这个prob在哪里定义的呢?感兴趣的读者可以打开models/bvlc_reference_caffenet/deploy.prototxt阅读。注意,我们训练和测试的时候用的是models/bvlc_reference_caffenet/train_val.prototxt,那个时候我们只关心loss(train phase)和accuracy(test phase)。而真正用来预测的时候,我们关心的是softmax的输出概率。如果模型训练的没有问题的话,这只猫的分类应该是:
predicted class is: 281
再往下面的内容这个系列教程不会用到,我们只要能够读取caffe的model,然后用它来预测就可以了,所以后面的cell就不一一介绍了,感兴趣的读者可以自行阅读。
8. ResNetResNet注意可以参考两篇论文:
和 。 有不少有用的链接,包括icml16上的tutorial和一些ResNet的实现代码。ResNet是Residual Network的缩写,翻译成中文就是残差网络。在介绍这种网络结构之前,我们来回顾一下之前的经验。 根据之前的经验,神经网络越深,效果越好。但是网络变深了之后就不好优化,模型训练时不容易收敛,当然我们可以用一些参数初始化和batch normalization的技术让我们可以训练较深的网络,比如十几层的VGG。 另外本文作者还提出了一个有意思的现象degradation问题——网络变得非常深以后,效果反而不如浅层的网络,甚至在训练数据上都不如(因此不是overfitting的问题)。【注:Inception v4那篇论文里作者似乎不太同意这个观点,他们没有用残差结构也能训练很深的网络,这说明本文作者参数没调好导致没收敛?但是他还是承认使用了残差结构确实可以加快训练的收敛速度】 作者在cifar10数据集行比较了,下图说明如果不用残差网络,深的网络效果反而不如浅的。
56层的网络效果反而不如20层的。作者在ImageNet上也发现同样的现象。我觉得可能原因是网络层数多,参数多,不使用ResNet比较难收敛。 为了解决训练收敛慢的问题,作者提出了残差结构的想法。 这个想法非常简单。比如一个网络(比如是两个卷积加relu)需要学习(拟合)一个H(x)函数,之前我们就是直接学习函数H(x)。而残差网络让它学习另外一个函数F(x)=H(x)-x。如下图所示: 图上在输入和第二个relu之间增加了一个x的直接连接。当然这里要求x的维度和F(x)是一样的,否则没法相加,这种情况一般会给x再乘以一个W使得Wx的维度和F(x)一样。就是这么一点点改动,作者通过实验验证效果就是比没有改动要好。
首先作者在ImageNet上训练了普通的34层的网络,然后又训练了加入残差的34层网络,另外使用了VGG18作为baseline,同时也训练了带残差的18层网络,实验对比如下: 可以看到,没有残差结果,34层的网络还不如18层。加了残差之后,34层的要比18层的好,当然18层的残差网络也比普通的18层VGG好。之后就是训练了著名的152层的网络,在ILSVRC15上top5的error讲到了3.57%不过15年的文章并没有怎么解释为什么加了这样的残差结构就能训练更深的网络,只是实验验证了想法而已。16年的文章做了更深入一些的分析,分析为什么加入残差结构能使得训练更深的网络变得可能。如上图(a)所示残差网络就是许多残差单元(Residual Units)组成的网络。每个残差单元都是这样的形式: 其中输入是 xl ,输出是 xl+1 (输出就是下一层l+1层的输入)。
在15年的文章里,h(xl)=xl而f是relu。这里我们先做一些简化,假设 h(xl)=xl以及 f(x)=x。
我们任意考察残差网络的第l层到第L层。 这里我们能发现这种结构很好的一些特性: 1. 任意更深的L层 xL 能表示成 xl 加上一个形如的残差之和。2. 第L层是输入加上残差。而普通的网络如果忽略BN和ReLU的话是如果我们用error对 xlxl 求梯度,会得到: 因为公式复杂那一项不会总是-1,因此error从L层 ?e/?xL 传到l层不会消失。所以这是可以训练深层网络的关键。 前面我们假设 h(xl)=xl,也就是通路是个identity mapping。如果我们稍微变化一下让 h(xl)=λlxl会是怎么样呢?
经过简单的推导,我们得到:
我们看到括号里不是1而是如果 λi&1 则容易梯度消失,反正会爆炸,总之就没法训练好了。出来Identity map也就是 h(x)=x ,作者对比很多其它的信息通路,结果发现效果都不好。原因就是通过Identity map,可以让任何两个层直接可以直接传到信息,也就是有一条直接的通路【说明:可以是说可能性,而不是一定会直接传递,这取决于数据的驱动让它是否这么做,就像我们后面会说LSTM相对与可以学习到更long distance的依赖一样】。基于之上的分析,作者提出了下图b的新结构: 图a是15年的工作,从第l层直接没有到l+1层的信息通路,因为这条通路要经过ReLU,不过可能ReLU至少在大于0时是完全可以通过的【不知道换成softmax会不会效果差很多,因为15年的文章没有用过做实验,也不好猜测】 而图b从l层到l+1层是有直接信息通路的,效果会更好。 大致的思路就讲到这里吧,如果要自己实现应该也很简单,有兴趣的读者可以自己实现一个ResNet在cifar数据上跑一跑。论文最好的结果是小于5%的错误率。上面的链接里也有很多现成的ResNet实现,读者可以参考。9. Inception结构主要是 、 、
这三篇论文。
第一篇就是inception v1,也就是GoogLeNet
第二篇是v2和v3
第三篇是v4
第一篇和ResNet一样,没有太多理论依据,只是实验,建议大致阅读一下,重点阅读第二篇。 首先是Inception这个词。《盗梦空间》?这个单词的意思是”起初“,”获得学位“。
这似乎和电影的情节没半毛钱关系,台湾翻译成《全面启动》就是这个单词的直接翻译,不过还是有些道理的。我不知道作者把这样的网络结构叫做Inception是什么意思。Inception结构的基本思想就是用小的filter组合来替代大的filter,从而减少参数和计算量,这样相同的计算资源也就能训练更深的网络,另外一个好处就是在一些终端设备占用的内存和cpu更少。我们看到,VGG都是使用3 3的filter,小的filter参数少,但是小的filter不能capture远距离的依赖,相当于损失了模型的表达能力。虽然我们设计网络是层次的,前面的层学习底层的特征,然后后面的层学习更高的特征。但是即使是底层特征,可能有些也没法用太小的filter来学到。所以最早的设计直觉是前面用比较大的filter比如7 7的,随着图片的变小和网络的加深,我们再使用更多更小的filter。我们可以看到7 7的计算量是3 3的5.4倍。inception的想法就是用多个小的filter来替代大的filter。 我们可以用两个3 3的filter stack起来替代一个5 5的filter,当然它们不是完全等价的,因为上层的3 3filter移动一步之后和之前是有重叠的部分的。 另外如上图,我们也可以用一些非对称的比如1 3和3 1的filter组合起来替代3 3的filter此外还有就是1 1的filter也是有用的,它可以起到”降维“压缩信息的作用,比如输入是(C1,H,W),用C2个1 1的filter后就变成了(C2,H,W)的图像。这种压缩的特点是卷积的局部的特性。大概的思路就是这样,细节就不罗嗦了,有兴趣的读者请参考论文。10. 总结通过上面的介绍,我们大致了解了Image Classification里最主流和state of the art的一些卷积网络结构,当然这只是视觉的一个任务,这里没有涉及到Location/Detection和Segmentation等其它任务,所以也没有设计R-CNN fast/faster R-CNN,YOLO SSD等。有兴趣的读者有了上面的基础应该是可以阅读相关的论文了解它们的原理。关于卷积神经网络的内容就介绍到这里,下一篇文章将会讲解RNN/LSTM的相关内容,敬请关注!

我要回帖

更多关于 caffe accuracy 不变 的文章

 

随机推荐