【总结】Caffe QA
1.caffe读入彩色图像和灰度单通道图像问题
在caffe中,若读入的图像为三通道,则需要进行通道维度转换:
1 transformer.set_transpose('data', (2,0,1)) #改变维度的顺序,由原始图片(28,28,3)变为(3,28,28)
若读入的图像为灰度单通道图,则需要把上面代码注释,并
1 im=caffe.io.load_image(img,False) #添加False参数
2.caffe的权值初始化问题
Q:想要用A网络训练的卷积层的 net.params初始化另一个我要训练的B网络,怎么做?
A:这个有点像微调(fine_tuning),但与微调又不一样。微调是用别的训练集训练出来的权值应用到当前的训练集上,两次训练用的同一个网络,只是数据不同而已。你这是用的两个不同的网络,所以不能用微调。在训练阶段权值的初始化,caffe是利用FillerParameter参数进行设置,初始化的方式有常量初始化(constant)、高斯分布初始化(gaussian)、positive_unitball初始化、均匀分布初始化(uniform)、xavier初始化、msra初始化、双线性初始化(bilinear)这么几种,并不支持任意修改,权值只有在训练完成后才能修改。因此你要实现的这个功能,现有的caffe版本办不到,只能自己扩展。
3.caffemodel中的参数及特征的抽取(详细转http://www.cnblogs.com/denny402/p/5686257.html)caffemodel中的参数及特征的抽取
1 import caffe 2 import numpy as np 3 root='/home/xxx/' #根目录 4 deploy=root + 'mnist/deploy.prototxt' #deploy文件 5 caffe_model=root + 'mnist/lenet_iter_9380.caffemodel' #训练好的 caffemodel 6 net = caffe.Net(deploy,caffe_model,caffe.TEST) #加载model和network 7 8 [(k,v[0].data.shape) for k,v in net.params.items()] #查看各层参数规模 9 w1=net.params['Convolution1'][0].data #提取参数w 10 b1=net.params['Convolution1'][1].data #提取参数b 11 12 net.forward() #运行测试 13 14 [(k,v.data.shape) for k,v in net.blobs.items()] #查看各层数据规模 15 fea=net.blobs['InnerProduct1'].data #提取某层数据(特征)
fea=net.blobs['InnerProduct1'].data
这行语句就是抽取第一个全连接层的特征,把fea这个变量保存起来就行。
numpy.save().
4.caffe训练中出现Data layer prefetch queue empty
问题描述:blocking_queue.cpp:50] Data layer prefetch queue empty
原因: CPU数据读入慢于GPU计算,导致GPU处于空闲,使得计算速度下降,迭代时间间隔扩大。nvidia-smi显示为:GPU功率不断大幅度变化,GPU电压不稳定。
可能诱因:服务器同时在进行其他工作,如大规模读写数据(频繁使用IO),数据无法读入;CPU同时进行其他工作,负载极重,无法正常读取数据;CPU内存爆表,所有程序速度变慢。
解决办法:
1) 把图片转为lmdb,可以加快数据读取速度,提高IO效率;
2) 在1的基础上,可以使用prefetch参数对数据进行预取
data_param {
source: “./data/ilsvrc12/ilsvrc12_train_lmdb”
batch_size: 32
backend: LMDB
prefetch: 20
}
注意:直接读入图片的是使用ImageDataLayer
使用LMDB格式的数据是用DataLayer
3) 简单粗暴,换一台CPU性能更好的电脑,可以匹配上GPU计算性能。
5.深度学习CV中,如果想让训练输入的图片尺寸不同,batchsize要怎么设置?
要让batchsize大于1,图片只能裁剪、拉伸或者边缘填充到相同的大小,否则只能设置batchsize为1.SPPNet中可以不考虑图片尺寸,只是为了在全连接部分可以接受任意大小的图片,不同的batch可以使用不同的图片尺寸,但是每个batch的输入为4D tensor,所以同一个batch的所有图片还是要相同尺寸的。
实际上,caffe等实现中,为了计算的方便,GPU,CUDA等比较适合固定尺寸的输入,所以训练的时候输入是固定了尺度了的。
6.取自一位大佬的对话,觉得学到的东西好多,记录下来
Q:loss下不去,一般采用什么方法解决? A:分2种情况: 1:训练过程自始至终,loss都没有下降过; 2:训练过程中loss下降到某个位置后就不再下降了. 2种情况各有各的解决办法 Q:多任务的时候会存在局部极小,跷跷板式的问题,任务lossA,lossB下去了,lossC又起来了,为了加快loss下降,加层有效还是加outputnum有效 A:都试试咯,,, 我遇到loss降不下去时(甚至新设计好一个网络还没有训练之前):先用训练集里非常小的一部份,比如每个类别10张图片,用这个很小的数据集训练网络,正常的网络应该很快就能收敛(其实是过拟合),如果很小的数据集网络很快收敛说明网络基本是正常的.. Q:嗯,对啊,good idea A:先用训练集里很小的一部份数据去训练网络(比如每个类别10张图片),正常的网络应该很快就能收敛(其实是过拟合),如果很小的数据集网络都不收敛,说明:1,网络本身有问题;2,数据预处理不行;3学习率太大了。 小样本的目的是要快速确定网络是否正常...如果大样本跑一天下来才发现网络本身有问题,,,这时间浪费得不值。 Q:是的,这个方法不错 A:如果小样本收敛,大样本不收敛,,,,就先增加网络的复杂度了,这个最简单所以先往这方面考虑 Q:一般网络训练的瓶颈是loaddatas还是forward&backword?时间瓶颈 A:如果GPU的显存容量够大,一次都把整个训练集都装进去了,loaddatas就不是什么瓶颈了.... 网络模型结构定下来了,forward&backword的计算量也基本定了的吧?所以这个时候就看loaddatas的咯... 现在的框架基本都是多线程的,,,一个线程处理训练,一个线程管数据IO,而且DL的机子都是多CPU,多核心的,,loaddatas似乎也算不上什么瓶颈了.. 把思路放到学习率,batchsize上可能收获更大些,对训练速度... A:我现在小样本训练到测试都OK了,换成大样本就不行了 Q:还有每个任务的权重很重要啊 A:如果是你自己设计的网络,小样本收敛,大样本难收敛,还可以试试增加网络模型的复杂度,,,就是增加网络的拟合能力 Q:现在的问题是,已经很慢了,再增加网络复杂度会更慢 我这个网其实也不算很大啊,也就8个卷积层,5个pool层 A:如果是别人的网络模型,别人训练收敛,你训练难收敛,那就得费心思了 如果是你的网络对正在使用的训练集数据量的拟合能力不够,增加网络模型复杂度是必须的,,, Q:我用一个网络训练了1整天,我现在想换一个网络结构,还是沿用前面那个网络的大部分层的权值数据,省得全部重新训练,怎么搞 A:先别换,要换也要把现在训练的这个网络和训练进度保存起来,也许过几天会对它有新的想法.... 我一般换网络就重新训练..
7.池化层的反向传播过程?
按照前向传播的分类,反向传播也需要分成两类
MAC (max pooling)
-
如果只看输出矩阵中的一个点y,则有 y = max( x1 , x2, x3, ... );
-
所以对x求导后有(可以理解成分段函数的求导)
AVG (average pooling)
-
如果只看输出矩阵中的一个点y,则有 y = ( x1 , x2, x3, ... ,xn )/n;
-
所以对x求导后有
1 max 2*2 kernel,stride=2 average 2*2 kernel,stride=2 2 3 --> Forward --> --> Forward --> 4 1 2 1 2 5 4 2 max_pool 4 4 2 average_pool 2.25 6 7 <-- Backward <-- <-- Backward <-- 8 0 0 2.25 2.25 9 4 4 0 2.25 2.25 2.25
8.next