首页 > 网络安全频道 > 系统安全 > 正文
实践介绍深度学习和Caffe与Python
2016-11-02     我来说两句       作者:黑帽网
   我要投稿

 实践介绍深度学习和Caffe与Python

作者:

Adil Moujahid

译者:

gashero

日期:

2016-10-28

地址:

http://adilmoujahid.com/posts/2016/06/introduction-deep-learning-python-caffe/

标题原文:

A Practical Introduction to Deep Learning with Caffe and Python

目录

  • 1   问题定义
  • 2   分类:使用传统机器学习vs深度学习
  • 3   深度学习快速教程
    • 3.1   人工神经网络ANN
      • 3.1.1   人工神经网络vs生物神经网络
      • 3.1.2   前馈神经网络
      • 3.1.3   激活函数
      • 3.1.4   训练ANN
    • 3.2   卷积神经网络(CNN或ConvNet)
      • 3.2.1   卷积层
      • 3.2.2   汇集层
      • 3.2.3   CNN架构
  • 4   使用CNN构建猫狗分类器
    • 4.1   获取猫狗数据
    • 4.2   机器设置
    • 4.3   Caffe概览
    • 4.4   数据准备
    • 4.5   模型定义
    • 4.6   Solver定义
    • 4.7   模型训练
      • 4.7.1   绘制学习曲线
    • 4.8   在新数据上的预测
  • 5   使用Transfer Learning构建猫狗分类器
    • 5.1   什么是Transfer Learning
    • 5.2   使用Transfer Learning训练猫狗分类器
      • 5.2.1   下载bvlc_reference_caffenet模型
      • 5.2.2   模型定义
      • 5.2.3   Solver定义
      • 5.2.4   通过传输学习训练模型
      • 5.2.5   绘制学习曲线
      • 5.2.6   在新数据上的预测
  • 6   总结

深度学习是机器学习的大趋势。在计算机视觉、自动语音识别、自然语言处理上有很多成功案例。

本文的目的是给你个上手简介。基于构建一个猫狗图片分类,使用深度学习算法,叫做卷积神经网络CNN和Kaggle数据集( https://www.kaggle.com/c/dogs-vs-cats )。

本文分为两个部分。第一部分是代码概念,第二部分是上手入门。

在第4节上手入门,我们会构建一个猫狗图片分类器使用一个CNN。在第二部分(第5节),我们会用更高级的技术来训练CNN,叫做Transfer Learning。我们会使用一些Python代码和流行的开源深度学习框架Caffe来构建分类器。我们的分类器会实现97%的准确度。

本文末尾,你会理解CNN的原理,并熟悉构建这些网络的步骤。

本文的代码在 https://github.com/adilmoujahid/deeplearning-cats-dogs-tutorial 。

1   问题定义

本入门使用Kaggle的数据集。包含了25000张图片,有猫和狗。

目标是构建机器学习算法来检测新的图片。

机器学习中,这类问题叫 分类(classification) 。

2   分类:使用传统机器学习vs深度学习

机器学习来进行分类有两个阶段:

  1. 训练阶段:训练一个机器学习算法,使用有对应标签的数据集
  2. 预测阶段:使用训练过的模型来预测(predict)新图片的标签

图片分类的训练阶段有两个主要步骤:

  1. 特征提取(Feature Extraction):使用领域知识来提取新的特征,用于机器学习算法,HoG和SIFT是图片分类的例子
  2. 模型训练:使用干净的数据集,包括图片的特征和对应的标签来训练机器学习模型

在预测阶段,我们使用相同的特征提取器来处理新图片,并传入这些特征到训练过的机器学习算法来预测标签。

 

传统机器学习和深度学习算法的区别是特征工程(Feature Engineering)。传统机器学习算法,需要手工设计特征。相对的在深度学习中,特征的设计由算法自动完成。特征工程很困难,消耗时间和领域知识。深度学习的优势是无需特征工程就能做到更好的准确率。

 

3   深度学习快速教程

深度学习是很多处理层构成的人工神经网络(ANN=Artificial Neural Networks)。ANN存在了几十年,但是对训练深度架构的ANN是从Geoffrey Hinton开始的,在2000年中期。除了算法创新,GPU的强大计算能力和大量的数据集都帮助了深度学习的迅速成长。

3.1   人工神经网络ANN

ANN是一系列模仿生物神经网络的模型。

3.1.1   人工神经网络vs生物神经网络

生物神经网络是大脑的核心。一个神经元(neuron)由细胞体、树突(dendrite)、轴突(axon)构成。会处理和传输信息到其他神经元,通过发射电信号。每个神经元从树突接受输入信号并通过轴突产生输出信号。轴突的分支输出,通过突触(synapse)连接到其他神经元的树突。

一个神经元工作的基本模型:每个突触有个强度,是可以被学习和控制的。树突将输入信号带入神经元做求和,如果求和结果高于一定的阈值,神经元就被点亮,通过轴突发送脉冲出去。

人工神经元受到了生物神经元的启发,尝试模拟模型来解释如上计算模式。一个人工神经元拥有数量有限的输入,且没有输入都有一个权重,以及一个激活函数(也叫传输函数)。神经元的输出是激活函数应用了输入权重再求和的结果。人工神经元回想连接,构成了ANN。

 

3.1.2   前馈神经网络

前馈神经网络是ANN最简单的形式。

这个网络由3种类型的层:输入层、隐藏层、输出层。这些网络中,数据从输入层通过隐藏层到达输出层。

下面的例子是全连接前馈神经网络(Fully-Connected FeedForward Neural Network)的例子,有两个隐藏层。全连接意味着每个结点都连接到下一层的所有结点。

注意:隐藏层的数量以及大小是仅有的自由参数。更大和更深的隐藏层,理论上就可以得到更加复杂的模式。

 

3.1.3   激活函数

激活函数将输入权重的和转换为人工神经元。这些函数应该是非线性的,来编码复杂的数据模式。最流行的激活函数是Sigmoid、Tanh和ReLU。ReLU是深度学习中最流行的激活函数。

 

3.1.4   训练ANN

训练阶段就是学习网络的权重,我们需要两个元素来训练一个ANN:

  1. 训练数据:训练数据由图片和对应的标签组成
  2. 损失函数:测量预测准确率

一旦我们有了这两个,训练ANN使用的算法叫 backpropagation(反向传播) ,和梯度下降(gradient descent)或者是他的导数。反向传播的细节,推荐 https://mattmazur.com/2015/03/17/a-step-by-step-backpropagation-example/ 。

3.2   卷积神经网络(CNN或ConvNet)

CNN是一种特殊类型的前馈网络。这些模型设计用于模拟视觉皮层(visual cortex)。CNN在视觉识别任务中的效果很好。CNN拥有一些特殊的层叫做卷积层(Convolutional Layer)和汇集层(Pooling Layer),允许网络编码图像属性。

 

3.2.1   卷积层

这个层由一系列可学习的图片空间过滤器组成,计算输入图像和过滤器的点积。过滤器应该扩展为全深度的输入图像。例如,如果我们想要使用5x5大小的过滤器到32x32的彩色图像,那么过滤器应该拥有深度3(5x5x3)来覆盖所有3个颜色通道。这些过滤器会在看到特定图像结构时激活。

 

3.2.2   汇集层

汇集(Pooling)是一种非线性降采样(down-sampling)。汇集层的目标是逐步降低网络计算参数的空间大小,也有避免过拟合(overfitting)。有多种方法实现汇集,但max pooling最常用。汇集通常使用2x2过滤器,通过一个最大2步到每个深度切片。一个汇集层的大小为2x2包含2个缩小输入图像到1/4的原始大小。

 

如上max pooling示例将每个角落中最大的数字作为结果。

3.2.3   CNN架构

最简单的CNN架构,拥有一个输入层(图像),跟着一系列的卷积层和汇集层,最后以全连接层结束。卷积层通常跟着一层ReLU激活函数。

卷积、汇集、ReLU层作为可学习的特征提取器,而全连接层作为机器学习的分类器。此外,靠前的层编码通用的图像模式,后面的层编码图像模式的细节。

注意,不是所有的卷积层和全连接层都拥有权重。这些权重在训练阶段是可学习的。

 

4   使用CNN构建猫狗分类器

本章使用CNN实现一个猫狗分类器。我们会使用Kaggle的数据集。要实现CNN,我们将会使用Caffe框架和一些Python代码。

4.1   获取猫狗数据

要获取数据,需要从 https://www.kaggle.com/c/dogs-vs-cats/data 下载两个数据集, train.zip 和 test1.zip 。前者是训练数据,后者是未标注的测试数据。我们还可以上传我们的预测结果到Kaggle来获得预测模型的分数。

4.2   机器设置

要训练一个CNN,我们需要有强大GPU的电脑。

本文档里,作者使用了AWS EC2的g2.2xlarge实例。这个实例有高性能的nVidia GPU,有1536个CUDA核心和4GB显存,15GB内存和8个CPU核心。机器的价格是$0.65/h。

如果你对AWS不熟悉,这里有设置的文档 http://cs231n.github.io/aws-tutorial/ 。

注意:文章推荐的AMI已经失效,所以作者准备了一个AMI(ami-64d31209),包含了所有必要的软件。也创建了新的指南 https://github.com/adilmoujahid/deeplearning-cats-dogs-tutorial/blob/master/aws-ec2-setup.md 用以安装Caffe和 Anaconda 到AWS EC2和Ubuntu机器。

在设置AWS实例后,我们连接和clone代码,包含Python代码和Caffe配置。从你的终端执行:

git clone https://github.com/adilmoujahid/deeplearning-cats-dogs-tutorial.git

然后,创建一个input目录用于存储训练和测试数据:

cd deeplearning-cats-dogs-tutorial

mkdir input

4.3   Caffe概览

Caffe是BVLC=Berkeley Vision and Learning Center开发的框架,以C++编写,有Python和Matlab绑定。

使用Caffe训练CNN有4个步骤:

  1. 数据准备:清理图片并存储到Caffe可用的格式,我们使用Python会处理图片预处理和存储
  2. 模型定义:选择CNN架构并定义其参数到配置文件.prototxt
  3. Solver定义:Solver对应的是模型优化器,我们定义Solver参数到.prototxt
  4. 模型训练:用Caffe的命令训练一个模型,训练后,我们会得到模型.caffemodel

在训练阶段后,我们使用.caffemodel模型来预测新的数据。我们用Python搞定。

4.4   数据准备

先拷贝 train.zip 和 test1.zip 到AWS EC2实例的input目录。可以用scp命令,然后解压:

unzip ~/deeplearning-cats-dogs-tutorial/input/train.zip

unzip ~/deeplearning-cats-dogs-tutorial/input/test1.zip

rm ~/deeplearning-cats-dogs-tutorial/input/*.zip

然后运行 create_lmdb.py

cd ~/deeplearning-cats-dogs-tutorial/code

python create_lmdb.py

create_lmdb.py 会做如下事情:

  1. 运行直方图均衡化(histogram equalization)到所有训练图片,这会调整图片的对比度
  2. 调整图片大小到227x227格式
  3. 分割训练数据为两部分:一部分(5/6的图片)用于训练,另一部分(1/6)用于验证,验证集用于计算模型的准确度
  4. 存储训练和验证数据到2个LMDB数据库, train_lmdb 用于训练, validation_lmdb 用于模型验证

如下是代码重要部分:

def transform_img(img, img_width=IMAGE_WIDTH, img_height=IMAGE_HEIGHT):

 

    #Histogram Equalization

    img[:, :, 0] = cv2.equalizeHist(img[:, :, 0])

    img[:, :, 1] = cv2.equalizeHist(img[:, :, 1])

    img[:, :, 2] = cv2.equalizeHist(img[:, :, 2])

 

    #Image Resizing

    img = cv2.resize(img, (img_width, img_height), interpolation = cv2.INTER_CUBIC)

 

    return img

transform_img() 接受彩色图像输入,做直方图均衡化3个颜色通道,并调整图像大小。

 

def make_datum(img, label):

 

    return caffe_pb2.Datum(

        channels=3,

        width=IMAGE_WIDTH,

        height=IMAGE_HEIGHT,

        label=label,

        data=np.rollaxis(img, 2).tostring())

make_datum() 接受图像和标签输入,并返回 Datum 对象包含了图像机器标签。

in_db = lmdb.open(train_lmdb, map_size=int(1e12))

with in_db.begin(write=True) as in_txn:

    for in_idx, img_path in enumerate(train_data):

        if in_idx %  6 == 0:

            continue

        img = cv2.imread(img_path, cv2.IMREAD_COLOR)

        img = transform_img(img, img_width=IMAGE_WIDTH, img_height=IMAGE_HEIGHT)

        if 'cat' in img_path:

            label = 0

        else:

            label = 1

        datum = make_datum(img, label)

        in_txn.put('{:0>5d}'.format(in_idx), datum.SerializeToString())

        print '{:0>5d}'.format(in_idx) + ':' + img_path

in_db.close()

如上代码接受训练图片,转换和存储到 train_lmdb 。用于验证和存储的代码差不多,就不写了。

生成训练数据的平均图像:

我们执行如下命令来生成训练数据的平均图像。我们让输入图像减去平均图像后来确保每个特征像素都是0均值(zero mean)的。这是有监督机器学习的常用预处理步骤:

/home/ubuntu/caffe/build/tools/compute_image_mean \

    -backend=lmdb /home/ubuntu/deeplearning-cats-dogs-tutorial/input/train_lmdb \

    /home/ubuntu/deeplearning-cats-dogs-tutorial/input/mean.binaryproto

4.5   模型定义

在确定了CNN架构后,我们需要在.prototxt文件train_val中定义其参数。Caffe自带了流行的CNN模型,例如Alexnet和GoogleNet。本文中我们使用 bvlc_reference_caffenet 模型,属于AlexNet的修改。在复制 train_val 后我们命名为 caffenet_train_val_1.prototxt 。如果你想克隆本文的代码,你应该用相同的名字 deeplearning-cats-dogs-tutorial/caffe_models/caffe_model_1/ 。

我们需要修改原始的 bvlc_reference_caffenet 的prototxt文件:

  1. 改变输入数据路径和平均图像:24、40、50行
  2. 改变输出数量从1000到2:373行,就是输出有几个类

我们可以打印出架构,通过如下命令。模型架构图像会存储在 deeplearning-cats-dogs-tutorial/caffe_models/caffe_model_1/caffe_model_1.png

python /home/ubuntu/caffe/python/draw_net.py \

    /home/ubuntu/deeplearning-cats-dogs-tutorial/caffe_models/caffe_model_1/caffenet_train_val_1.prototxt \

    /home/ubuntu/deeplearning-cats-dogs-tutorial/caffe_models/caffe_model_1/caffe_model_1.png

4.6   Solver定义

Solver是模型优化的主管。我们定义Solver参数在一个.prototxt文件中。你可以在 deeplearning-cats-dogs-tutorial/caffe_models/caffe_model_1/solver_1.prototxt 。

Solver会在每1000次迭代就使用验证集计算模型精度。优化流程会运行最大40000次迭代,并每5000次迭代生成一个快照模型。

base_lr 、 lr_policy 、 gamma 、 momentum 、 weight_decay 是超参数(hyperparameter),我们需要调整以便获得模型更好的收敛(convergence)。

作者选择了 lr_policy : stepsize: 2500 、 base_lr: 0.001 、 gamma: 0.1 。在这个配置下,我们开始的学习率为0.001,然后调低学习率通过系数10,在每2500次迭代。

还有其他的优化策略。对细节的解释,建议 http://caffe.berkeleyvision.org/tutorial/solver.html 。

4.7   模型训练

在定义好模型和Sovler后,通过如下命令开始训练:

/home/ubuntu/caffe/build/tools/caffe train \

    --solver /home/ubuntu/deeplearning-cats-dogs-tutorial/caffe_models/caffe_model_1/solver_1.prototxt 2>&1 \

    | tee /home/ubuntu/deeplearning-cats-dogs-tutorial/caffe_models/caffe_model_1/model_1_train.log

训练产生的日志会存放到 deeplearning-cats-dogs-tutorial/caffe_models/caffe_model_1/model_1_train.log 。

在训练时,我们需要监控损失(loss)和模型精度。可以在任何时候停止这个过程,通过Ctrl+C。Caffe会在训练模型每5000个迭代时产生一个快照,并存储到 caffe_model_1 目录。

快照拥有.caffemodel扩展名。例如10000次迭代的快照叫做 caffe_model_1_iter_10000.caffemodel 。

4.7.1   绘制学习曲线

学习曲线是显示训练和测试损失的功能。对于训练/验证损失和精度很有用。

我们可以通过学习曲线来了解模型和验证何时到达90%,以及在3000次迭代后就不再改进了:

python /home/ubuntu/deeplearning-cats-dogs-tutorial/caffe_models/code/plot_learning_curve.py \

    /home/ubuntu/deeplearning-cats-dogs-tutorial/caffe_models/caffe_models/caffe_model_1/model_1_train.log \

    /home/ubuntu/deeplearning-cats-dogs-tutorial/caffe_models/caffe_models/caffe_model_1/caffe_model_1_learning_curve.png

 

4.8   在新数据上的预测

现在我们拥有了训练过的模型,我们可以用它来预测新的数据(从test1而来)。 deeplearning-cats-dogs-tutorial/code/make_predictions_1.py 就是预测代码。需要4个文件来运行:

  1. 测试图片:使用test1图片
  2. 平均图片:如上4.4节得到的
  3. 模型结构图: deeplearning-cats-dogs-tutorial/caffe_models/caffe_model_1/caffenet_deploy_1.prototxt 结构类似于 caffenet_train_va1_1.prototxt ,但是有少量修改,需要删除数据层,添加输入层并改变最后一层从SoftmaxWithLost为Softmax
  4. 训练模型权重:这个文件是训练阶段计算得到的,使用 caffe_model_1_iter_10000.caffemodel

要运行这个Python代码,我们需要执行如下命令。预测会存储到 deeplearning-cats-dogs-tutorial/caffe_models/caffe_model_1/submission_mode_1.csv 。

cd /home/ubuntu/deeplearning-cats-dogs-tutorial/code

python make_predictions_1.py

如下解释重要的代码部分:

#Read mean image

mean_blob = caffe_pb2.BlobProto()

with open('/home/ubuntu/deeplearning-cats-dogs-tutorial/input/mean.binaryproto') as f:

    mean_blob.ParseFromString(f.read())

mean_array = np.asarray(mean_blob.data, dtype=np.float32).reshape(

    (mean_blob.channels, mean_blob.height, mean_blob.width))

 

 

#Read model architecture and trained model's weights

net = caffe.Net('/home/ubuntu/deeplearning-cats-dogs-tutorial/caffe_models/caffe_model_1/caffenet_deploy_1.prototxt',

                '/home/ubuntu/deeplearning-cats-dogs-tutorial/caffe_models/caffe_model_1/caffe_model_1_iter_10000.caffemodel',

                caffe.TEST)

 

#Define image transformers

transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})

transformer.set_mean('data', mean_array)

transformer.set_transpose('data', (2,0,1))

如上代码存储平均图像为 mean_array ,通过读取部署文件和训练模型定义模型叫做 net ,然后定义变换,应用到测试图像。

img = cv2.imread(img_path, cv2.IMREAD_COLOR)

img = transform_img(img, img_width=IMAGE_WIDTH, img_height=IMAGE_HEIGHT)

 

net.blobs['data'].data[...] = transformer.preprocess('data', img)

out = net.forward()

pred_probas = out['prob']

print pred_probas.argmax()

如上代码读取图像,应用与训练阶段相似的图像处理步骤,计算每个类的概率并打印最大概率的类,0=猫,1=狗。

之后提交预测结果到Kaggle,给出精度为0.89691。

5   使用Transfer Learning构建猫狗分类器

本节使用一个强大而实用的技术叫做Transfer Learning来构建我们的猫狗分类器。

5.1   什么是Transfer Learning

CNN需要大量的数据集和大量的计算时间来训练。一些网络可能需要2-3周,以及多个GPU来训练。传输学习则是解决这两个问题的办法。与其从头训练网络,传输学习使用已经训练的模型和不同的数据集,并适应更多要解决的问题。

传输学习的两个策略:

  1. 把训练出的模型作为特征提取器:在这个策略里,我们是你出最后的全连接层,冻结剩余层的权重,并训练在剩余层的输出上做分类器
  2. Fine-Tune训练过的模型:继续调优训练过的模型到新的数据集,持续做反向传播,我们可以同时在整个网络做调优或者冻结一部分的层

传输学习的细节解释,参见 http://cs231n.github.io/transfer-learning/ 。

5.2   使用Transfer Learning训练猫狗分类器

Caffe自带了版本库给研究者和机器学习实践者来共享训练过的模型,叫做 Model Zoo:https://github.com/BVLC/caffe/wiki/Model-Zoo 。

我们可以使用传输学习,将训练过的 bvlc_reference_caffenet 作为起点来构建我们的猫狗分类器。这个模型是在ImageNet上训练过的。

我们使用调优策略来训练模型。

5.2.1   下载bvlc_reference_caffenet模型

cd /home/ubuntu/caffe/models/bvlc_reference_caffenet

wget http://dl.caffe.berkeleyvision.org/bvlc_reference_caffenet.caffemodel

5.2.2   模型定义

模型定义和Sovler配置文件存储在 deeplearning-cats-dogs-tutorial/caffe_models/caffe_model_2 中。我们需要gaiiban原始的 bvlc_reference_caffenet 模型配置文件。

  1. 改变输入数据路径和平均图像:24、40、51行
  2. 改变最后全连接层从fc8到fc8-cats-dogs:360、363、387、397行
  3. 改变输出数量:从1000到2,373行

现在我们保持层的名字不变,并传入训练过的模型权重到Caffe,就会选择从训练过的模型载入权重。如果我们想要冻结层,就需要设置他的 lr_mult 参数为0。

模型配置的 caffe_train_val_2.prototxt 就不粘贴了,400行呢。文件中 lr_mult 有多处,取值是1和2,没见到0。

5.2.3   Solver定义

使用一个相似的Sovler:

net: "/home/ubuntu/cats-dogs-tutorial/caffe_models/caffe_model_2/caffenet_train_val_2.prototxt"

test_iter: 1000

test_interval: 1000

base_lr: 0.001

lr_policy: "step"

gamma: 0.1

stepsize: 2500

display: 50

max_iter: 40000

momentum: 0.9

weight_decay: 0.0005

snapshot: 5000

snapshot_prefix: "/home/ubuntu/cats-dogs-tutorial/caffe_models/caffe_model_2/caffe_model_2"

solver_mode: GPU

5.2.4   通过传输学习训练模型

定义好模型和Solver后,可以开始训练。注意我们传递训练过的模型权重作为 --weights 参数:

/home/ubuntu/caffe/build/tools/caffe train \

    --solver=/home/ubuntu/deeplearning-cats-dogs-tutorial/caffe_models/caffe_model_2/solver_2.prototxt \

    --weights /home/ubuntu/caffe/models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel 2>&1 \

    | tee /home/ubuntu/deeplearning-cats-dogs-tutorial/caffe_models/caffe_model_2/model_2_train.log

5.2.5   绘制学习曲线

类似于之前的章节,我们绘制学习曲线。可以看到在1000次迭代后,模型的精度就达到了97%。这展示了传输学习的力量。我们可以在更小的迭代就获得类似的准确率:

python /home/ubuntu/deeplearning-cats-dogs-tutorial/code/plot_learning_curve.py \

    /home/ubuntu/deeplearning-cats-dogs-tutorial/caffe_models/caffe_model_2/model_2_train.log \

    /home/ubuntu/deeplearning-cats-dogs-tutorial/caffe_models/caffe_model_2/caffe_model_2_learning_curve.png

5.2.6   在新数据上的预测

之前做过,预测并上传到Kaggle来获得模型精度。预测的代码在 deeplearning-cats-dogs-tutorial/code/make_predictions_2.py 。

模型的精度达到了0.97154,比之前从头训练的还好。

6   总结

 

本文覆盖了深度学习和CNN的核心概念。也学习了如何使用Caffe和Python来从头构建CNN,以及使用Transfer Learning。如果想要了解更多,强烈推荐Stanford的CNN视觉识别:http://cs231n.github.io/ 。

点击收藏到自己的收藏夹!回本站首页
您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力  
上一篇:Tomcat和nodeJs的区别
下一篇:下拉框赋值
相关文章
图文推荐
排行
热门
网站
工具
无线
关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训
版权所有: 中国黑帽网--致力于做最好的网络安全技术学习网站 。