深度学习在计算机视觉领域四大基本任务中的应用,包括分类、定位检测、语义分割、和实例分割。首先从图像分类开始学习,利用Caffe搭建深度学习网络,在实际数据集上进行测试。
CNN模型
补充:为什引入非线性激励函数?为什么Relu比sigmoid和tanh效果要好?
第一个问题:为什么引入非线性激励函数?
如果不用激励函数(其实相当于激励函数是f(x) = x),在这种情况下你每一层输出都是上层输入的线性函数,很容易验证,无论你神经网络有多少层,输出都是输入的线性组合,与没有隐藏层效果相当,这种情况就是最原始的感知机(Perceptron)了。
正因为上面的原因,我们决定引入非线性函数作为激励函数,这样深层神经网络就有意义了(不再是输入的线性组合,可以逼近任意函数)。最早的想法是sigmoid函数或者tanh函数,输出有界,很容易充当下一层输入(以及一些人的生物解释balabala)。
第二个问题:为什么引入Relu呢?
第一,采用sigmoid等函数,算激活函数时(指数运算),计算量大,反向传播求误差梯度时,求导涉及除法,计算量相对大,而采用Relu激活函数,整个过程的计算量节省很多。
第二,对于深层网络,sigmoid函数反向传播时,很容易就会出现梯度消失的情况(在sigmoid接近饱和区时,变换太缓慢,导数趋于0,这种情况会造成信息丢失,参见 @Haofeng Li 答案的第三点),从而无法完成深层网络的训练。
第三,Relu会使一部分神经元的输出为0,这样就造成了网络的稀疏性,并且减少了参数的相互依存关系,缓解了过拟合问题的发生(以及一些人的生物解释balabala)。
当然现在也有一些对relu的改进,比如prelu,random relu等,在不同的数据集上会有一些训练速度上或者准确率上的改进,具体的大家可以找相关的paper看。
多加一句,现在主流的做法,会在做完relu之后,加一步batch normalization,尽可能保证每一层网络的输入具有相同的分布[1]。而最新的paper[2],他们在加入bypass connection之后,发现改变batch normalization的位置会有更好的效果。大家有兴趣可以看下。
常用网络结构
lenet
alexnet
vgg
resnet
caffe安装及使用
安装平台是mac os x10.13.3 利用anaconda带的python环境,此外,mac安装需要Homebrew,安装Homebrew,会自动创建目录 /usr/local/Cellar,我们可以把所有相关的安装依赖包都保存到此路径下,便于管理和使用。
1 | # Homebrew 安装 |
下载Anaconda2-4.2.0-MacOSX-x86_64.pkg并安装在/usr/local/Cellar/anaconda目录下,安装依赖包
1 | brew install -vd snappy leveled flags glow szip lmdb |
如果使用Anaconda python,openCV需要做如下的修改
1 | brew edit opencv |
继续安装依赖
1 | brew install --build-from-source --with-python -vd protobuf |
修改环境变量
1 | # added by Anaconda2 4.2.0 installer |
下载caffe并生成配置文件
1 | git clone https://github.com/BVLC/caffe.git |
修改配置文件中的内容,下面的配置文件是基于我自己电脑的参数进行的修改
1 | ## Refer to http://caffe.berkeleyvision.org/installation.html |
进行编译
1 | make all |
在jupyter notebook中使用
1 | import caffe |
import caffe如果出现问题,一般是protobuf安装有问题,原因不明确。
解决办法:将anaconda里面默认的先 pip uninstall protobuf 然后打开Anaconda Navigator控制器 在root里面 安装protobuf(利用默认的channel,清华镜像的channel只有3.2版本),新的版本为3.4.1,随后import成功。
使用自带模型
训练cifar训练集,进入到caffe根目录获取训练数据
1 | ./data/cifar10/get_cifar10.sh |
开始训练1
./examples/cifar10/train_quick.sh
在运行之前需要在./examples/cifar10/目录中修改cifar10_quick_solver_lr1.prototxt和cifar10_quick_solver.prototxt这两个文件中solver_mode为CPU(根据实际配置),训练后会得到:
1 | cifar10_quick_iter_5000.caffemodel.h5 |
此时,我们就训练得到了模型,用于后面的分类。下面我们使用模型来分类数据(注意examples前面两个空格):
1 | python python/classify.py --model_def examples/cifar10/cifar10_quick.prototxt --pretrained_model examples/cifar10/cifar10_quick_iter_5000.caffemodel.h5 --center_only examples/images/cat.jpg foo |
默认的classify脚本不会直接输出结果,而是会把结果输入到foo文件里,不太直观,这里我在网上找了一个修改版,添加了一些参数,可以输出概率最高的分类。替换python/classify.py,下载地址:http://download.csdn.net/detail/caisenchuan/9513196 ,但是原始程序有一点点问题以及dataframe升级后排序函数有些变化,因此里面的代码做如下改变:
1 | if args.print_results: |
这个脚本添加了两个参数,可以指定labels_file,然后可以直接把分类结果输出来:
1 | python python/classify.py --print_results --model_def examples/cifar10/cifar10_quick.prototxt --pretrained_model examples/cifar10/cifar10_quick_iter_5000.caffemodel.h5 --labels_file data/cifar10/cifar10_words.txt --center_only examples/images/cat.jpg foo |
可以根据自己的需求进行修改分类函数。