实验室深度学习平台介绍

概述

实验室深度学习资料放在ip为192.168.1.249的web服务器上。(内网台式机的浏览器访问http:://192.168.1.249,即可看到) 需要看的文档主要是深度学习平台->Caffe->Caffe使用手册。 欢迎大家浏览

AmaxGPU服务器5块C2075。由于服务器需要,该服务器重装系统,暂时还未重装Caffe依赖。后面几天我会重装Caffe依赖。今天2017/06/07。

K80服务器4块K80。由于景行锐创统一管理平台问题,还未加上该节点。

环境:Linux操作系统(RedHat)

使用之前

学习资料位置,内网台式机的浏览器访问http:://192.168.1.249

../../../_images/192.168.1.249_index.png

caffe使用文档位置

../../../_images/192.168.1.249_caffe使用文档.png

使用实验室深度学习框架,登录景行锐创统一门户

../../../_images/192.168.2.82_login.png

进入景行锐创,选择GPU服务器

../../../_images/192.168.2.82_index.png

Amax服务器用户

../../../_images/amax_service_home.png

使用

整体流程

  1. 将数据集转换为lmdb,hdf5等caffe可以处理的格式。
  2. 配置训练模型的网络与solver,进行训练,得到模型参数。
  3. 使用模型进行分类等工作。
../../../_images/whole_process.png

caffe编译使用

目的:每个用户的工程一般建立在~/caffe-master/examples/下,为了不相互干扰,每人在自己的主目录下编译一个caffe。 编译方法如下:

  • 进入GPU服务器
  • 通过内网台式机的浏览器192.168.2.82的超算平台使用VNC登录GPU服务器
  • 没有账号的,找吴老师申请账号和密码,通过ssh连接GPU服务器。
  • 不清楚的,内网台式机的浏览器访问http:://192.168.1.249,查看《使用GPU服务器.docx》。
  • 在GPU服务器终端下,执行以下代码,编译caffe

    wget http://192.168.1.249/caffe/caffe_usage.sh
    sh caffe_usage.sh
    

执行以上代码,caffe会安装在用户主目录的caffe-master文件夹中。 目录如下所示,假设用户名为test。

根目录(/)

  • home(系统的文件夹)

    • test(文件夹,找吴老师申请的账号命名的文件夹,系统生成的)

      • caffe-master(文件夹,编译生成的caffe主目录)

        • examples(编译生成的文件夹,用来包含的caffe自带的demo和自己创建的工程)

          • projectname(文件夹,自己创建的工程,自己命名)

            • projectname_train_lmdb(文件夹,训练数据,包含data和label,通过mat2lmdb.py工具生成)
            • projectname_test_lmdb(文件夹,测试数据,包含data和label,通过mat2lmdb.py工具生成)
            • projectname_net.prototxt(网络配置文件)
            • projectname_solver.prototxt(解决方案配置文件)

备注

projectname_net.prototxt中的后缀名prototxt是protobuf文件的后缀名,后缀名不可改。

默认网络配置文件的命名方式是projectname_net.prototxt(projectname是自己定义的工程名)

默认解决方案配置文件的命名方式是projectname_solover.prototxt(projectname是自己定义的工程名)

创建工程示例

假设创建的工程名为HSI,则在caffe-master/examples文件夹下创建HSI文件夹,作为工程主目录。 在该目录下新建HSI_net.prototxt,HSI_solver.prototxt文档

最终结构如下:

  • caffe-master(文件夹,生成的caffe主目录)

    • examples(生成的文件夹,用来包含的caffe自带的demo和自己创建的工程)

      • HSI(文件夹)

        • HSI_train_lmdb(文件夹,训练数据,包含data和label,通过mat2lmdb.py工具生成)
        • HSI_test_lmdb(文件夹,测试数据,包含data和label,通过mat2lmdb.py工具生成)
        • HSI_net.prototxt(网络配置文件)
        • HSI_solver.prototxt(解决方案配置文件)

数据采集与数据转换

可以先将数据都存储成mat格式。

mat转lmdb 功能 将特定格式的mat文件转换为lmdb,仅适用于单标签。

注释 mat数据格式必须存储为n*c*h*w的形式,四维,n表示样本编号,c表示通道数,h表示图像的高度(行),w表示图像的宽度(列)。 标签的格式为n*1,一维,n表示标签个数。

一般,训练样本:测试样本 = 9:1,可根据需要修改。

单标签:将图像分类,如果有100类,则标签为0~99,整数。

含义 Indian pines图像是145*145*200的,要打标签的是145*145个像素点,每个像素点是200维,每个样本(1*1*200)对应一个标签,共有145*145个样本。 这样的训练样本只是200维的向量,为了充分利用CNN的卷积功能,我们将每个200维的向量reshape成20*10的图像来分析不同类别的光谱结构。

将这样的数据存储为mat文件,格式是n*c*h*w,n是样本个数145*145,c是通道数为1,h是图像高度为20,w是图像宽度为10。

使用 具体使用方法如下:

在GPU节点的Linux终端下

  • 下载该工具

    wget http://192.168.1.249/caffe/tools/mat2lmdb.py
    
  • 转换

    python mat2lmdb.py  data.mat  label.mat  XXX_lmdb(生成的是名为XXX_lmdb的文件夹)
    
  • 使用

    • 将转换好的文件放在caffe-master/examples/HSI文件夹下
    • 对训练数据和测试通过以上操作,则生成HSI_train_lmdb和HSI_test_lmdb。将其放在caffe-master/examples/HSI文件夹下
  • 例子

    • 获得mat文件,在终端通过输入以下命令获得

      wget http://192.168.1.249/caffe/practice/HSI/train_data1.mat
      wget http://192.168.1.249/caffe/practice/HSI/train_label1.mat
      wget http://192.168.1.249/caffe/practice/HSI/test_data1.mat
      wget http://192.168.1.249/caffe/practice/HSI/test_label1.mat
      
    • 转换使用

      wget http://192.168.1.249/caffe/tools/mat2lmdb.py
      python mat2lmdb.py train_data1.mat train_label1.mat HSI_train_lmdb
      python mat2lmdb.py test_data1.mat test_label1.mat HSI_test_lmdb
      

如果只是想实践一下,可以跳过五、六节,直接到第七节。

网络配置文件(HSI_net.prototxt)的修改

网络配置文件是用来指定训练模型,即输入数据,卷积,池化等操作的参数配置。

net分为数据层,视觉层,激活层和其他层(softmax_loss层,Inner Product层,accuracy层) 网络结构如下。

HSI_net.prototxt的下载

wget http://192.168.1.249/caffe/practice/HSI/HSI_net.prototxt

HSI_net.prototxt内容如下:

name: "HSI"  #工程名
layer {
  name: "data"  #该层的名称
  type: "Data"  #该层的类型
  top: "data"  #该层的输出
  top: "label"  #该层的输出
  data_param {  #data层的参数
    source: "examples/HSI/HSI_train_lmdb"  #输入
    batch_size: 128 #输入
    backend: LMDB  #输入的数据格式
  }
  include: { phase: TRAIN }  #阶段,表明是训练阶段(该层仅在训练阶段使用)
}
layer {            ##测试数据层
  name: "data"  #该层的名称
  type: "Data"   #该层的类型
  top: "data"  #该层的输出
  top: "label"  #该层的输出
  data_param {  #data层的参数
    source: "examples/HSI/HSI_test_lmdb"  #输入
    batch_size: 209  #输入
    backend: LMDB  #输入的数据格式
  }
  include: { phase: TEST }  #阶段,表明是测试阶段(该层仅在训练阶段使用)
}

layer {
  name: "conv1"  #该层的名称
  type: "Convolution"  #该层的类型
  bottom: "data"  #该层的输入
  top: "conv1"  #该层的输出
  param {     #权值
    lr_mult: 1  #学习系数
  }
  param {   #偏置
    lr_mult: 0.1  #学习系数
  }
  convolution_param {  #卷积的参数
    num_output: 64  #过滤器的个数
    kernel_size: 9  #过滤器的大小
    stride: 1  #卷积的步长
    pad: 0  #指定在输入的每一边加上多少个像素
    weight_filler {  #权重的初始化方法
      type: "gaussian"  #类型,高斯。
      std: 0.001  #高斯的标准平方差
    }
    bias_filler {  #偏置的初始化方法
      type: "constant"  #类型,常数
      value: 0  #偏置是0常数
    }
  }
}

layer {                    #激活层
  name: "relu1"   #名称
  type: "ReLU"    #激活函数,一般为ReLU,以前是sigmoid
  bottom: "conv1"    #输入
  top: "conv1"  #输出
}

layer {                    #卷积层
  name: "conv2"
  type: "Convolution"
  bottom: "conv1"
  top: "conv2"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 0.1
  }
  convolution_param {
    num_output: 32
    kernel_size: 1
    stride: 1
    pad: 0
    weight_filler {
      type: "gaussian"
      std: 0.001
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}

layer {                   #激活层
  name: "relu2"
  type: "ReLU"
  bottom: "conv2"
  top: "conv2"
}

layer {                  #卷积层
  name: "conv3"
  type: "Convolution"
  bottom: "conv2"
  top: "conv3"
  param {
    lr_mult: 0.1
  }
  param {
    lr_mult: 0.1
  }
  convolution_param {
    num_output: 1
    kernel_size: 3
    stride: 1
    pad: 0
    weight_filler {
      type: "gaussian"
      std: 0.001
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}

layer {           #全连接层
  name: "ip1"   #该层的名称
  type: "InnerProduct"  #该层的类型
  bottom: "conv3"  #该层的输入
  top: "ip1"  #该层的输出
  param {  #参数
    lr_mult: 1  #学习率系数
  }
  param {
    lr_mult: 2  #学习率系数
  }
  inner_product_param {
    num_output: 17  #过滤器(filfter)的个数
    weight_filler {  #权重初始化
      type: "xavier"  #vaxier算法
    }
    bias_filler {  #偏置初始化
      type: "constant"  #常数
    }
  }
}

layer {                 #准确度层
  name: "accuracy"   #该层的名称
  type: "Accuracy"    #该层的类型
  bottom: "ip1"      #该层的输入
  bottom: "label"     #该层的输入
  top: "accuracy"     #该层的输出
  include {
    phase: TEST      #表明阶段,测试阶段(该层仅测试阶段使用)
  }
}

layer {      #损失函数层
  name: "loss"  #该层的名称
  type: "SoftmaxWithLoss"  #该层的类型
  bottom: "conv3"  #该层的输入
  bottom: "label"  #该层的输入
  top: "loss"  #该层的输出
}




数据层
数据层用于输入lmdb,hdf5等格式的数据。
lmdb为例
layer {
  name: "data"  #该层的名称
  type: "Data"  #该层的类型
  top: "data"  #该层的输出
  top: "label"  #该层的输出
  data_param {  #data层的参数
    source: "examples/HSI/HSI_train_lmdb"  #输入
    batch_size: 128  #批处理大小
    backend: LMDB  #输入的数据格式
  }
  include: { phase: TRAIN }  #阶段,表明是训练阶段还是测试阶段
}


卷积层
卷积层,是卷积神经网络(CNN)的核心层。
示例:
layer {
  name: "conv1"  #该层的名称
  type: "Convolution"  #该层的类型
  bottom: "data"  #该层的输入
  top: "conv1"  #该层的输出
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 0.1
  }
  convolution_param {  #卷积的参数
    num_output: 64  #过滤器的个数
    kernel_size: 9  #过滤器的大小
    stride: 1  #卷积的步长
    pad: 0  #指定在输入的每一边加上多少个像素
    weight_filler {  #权重的初始化方法
      type: "gaussian"  #类型,高斯。
      std: 0.001  #高斯的标准平方差
    }
    bias_filler {  #偏置的初始化方法
      type: "constant"  #类型,常数
      value: 0  #偏置是0常数
    }
  }
}

卷积层

lr_mult: 学习率的系数,最终的学习率是这个数乘以solver.prototxt配置文件中的base_lr。
num_output: 卷积核(filter)的个数
kernel_size: 卷积核的大小。
stride: 卷积核的步长,默认为1。
pad: 扩充边缘,默认为0,不扩充。 扩充的时候是左右、上下对称的,比如卷积核的大小为5*5,那么pad设置为2,则四个边缘都扩充2个像素,即宽度和高度都扩充了4个像素,这样卷积运算之后的特征图就不会变小。
weight_filler: 权值初始化。 默认为“constant",值全为0,很多时候我们用" gaussian "算法来进行初始化。
bias_filler: 偏置项的初始化。一般设置为"constant",值全为0或者用" gaussian "算法来进行初始化。
bias_term: 是否开启偏置项,默认为true, 开启
输入:n*c0*w0*h0
输出:n*c1*w1*h1
其中,c1就是参数中的num_output,生成的特征图个数
w1=(w0+2*pad-kernel_size)/stride+1;
h1=(h0+2*pad-kernel_size)/stride+1;
如果设置stride为1,前后两次卷积部分存在重叠。如果设置pad=(kernel_size-1)/2,则运算后,宽度和高度不变。

池化层

为了减少运算量和数据维度而设置的一种层
kernel_size: 池化核大小。
pool: 池化方法,默认为MAX。目前可用的方法有MAX, AVE
pad: 和卷积层的pad的一样,进行边缘扩充。默认为0
stride: 池化的步长,默认为1。一般我们设置为2,即不重叠。

激活层

对输入数据进行激活操作(实际上就是一种函数变换),是逐元素进行运算的。从bottom得到一个blob数据输入,运算后,从top输入一个blob数据。在运算过程中,没有改变数据的大小,即输入和输出的数据大小是相等的。
示例
layer {
  name: "relu1"
  type: "ReLU"
  bottom: "conv1"
  top: "conv1"
}


常用的激活函数有sigmoid, tanh, relu等,下面主要介绍RELU。
ReLU是目前使用最多的激活函数,主要因为其收敛更快,并且能保持同样效果。
标准的ReLU函数为max(x, 0),当x>0时,输出x; 当x<=0时,输出0
f(x)=max(x,0)
可选参数:
negative_slope:默认为0. 对标准的ReLU函数进行变化,如果设置了这个值,那么数据为负数时,就不再设置为0,而是用原始数据乘以negative_slope

全连接层

全连接层,把输入当作成一个向量,输出也是一个简单向量(把输入数据blobs的width和height全变为1)。
输入: n*c0*h*w
输出: n*c1*1*1
示例:

layer {
  name: "ip1"   #该层的名称
  type: "InnerProduct"  #该层的类型
  bottom: "conv3"  #该层的输入
  top: "ip1"  #该层的输出
  param {  #参数
    lr_mult: 1  #学习率系数
  }
  param {
    lr_mult: 2  #学习率系数
  }
  inner_product_param {
    num_output: 17  #过滤器(filfter)的个数
    weight_filler {  #权重初始化
      type: "xavier"  #vaxier算法
    }
    bias_filler {  #偏置初始化
      type: "constant"  #常数
    }
  }
}

由于标签有17个,所以在全连接层的num_output的个数至少为17个,可以多,不可少。

accuracy层

输出分类(预测)精确度,只有test阶段才有,因此需要加入include参数。
层类型:Accuracy

layer {
  name: "accuracy"   #该层的名称
  type: "Accuracy"    #该层的类型
  bottom: "ip1"      #该层的输入
  bottom: "label"     #该层的输入
  top: "accuracy"     #该层的输出
  include {
    phase: TEST      #表明阶段,测试阶段(该层仅测试阶段使用)
  }
}

Loss层

layer {
  name: "loss"  #该层的名称
  type: "SoftmaxWithLoss"  #该层的类型
  bottom: "conv3"  #该层的输入
  bottom: "label"  #该层的输入
  top: "loss"  #该层的输出
}
#单标签一般使用SoftmaxWithLoss
#多标签一般使用EuclideanLoss

解决方案文件配置solver.prototxt

Solver方法一般用来解决loss函数的最小化问题。对于一个数据集D,需要优化的目标函数是整个数据集中所有数据loss的平均值。

HSI_solver.prototxt的下载

wget http://192.168.1.249/caffe/practice/HSI/HSI_solver.prototxt

HSI_solver.prototxt的参数 参数设置:

net : “examples/HSI/HSI_net.prototxt”   #网络配置文件的指向
test_iter : 5  #样本总数/批处理个数(批处理个数在网络配置文件的data层配置)
test_interval : 1000   #训练时迭代次数

base_lr : 0.001  #基本学习率
momentum : 0.9  #动量
weight_decay: 0  #
display : 100   #迭代多少次显示一次
max_iter : 150000  #最大迭代次数
snapshot : 5000  #迭代多少次保存一下结果(caffemodel和solverstate)
snapshot_prefix : “examples/HSI/HSI” #保存结果(caffemodel和solverstate)的前缀,实际名称是$(snapshot_prefix)_iter_$(迭代次数). caffemodel和$(snapshot_prefix)_iter_$(迭代次数). solverstate
solver_mode: GPU   #使用cpu还是gpu进行训练。cpu训练,solver_mode: CPU
device_id: 0  #使用哪一个gpu进行训练。设备号从0开始。该参数不写,默认为0

训练

总共需要的文件 HSI_net.prototxt(网络模型), HSI_solver.prototxt(解决方案),HSI_train_lmdb, HSI_test_lmdb。

HSI_net.prototxt的下载

wget http://192.168.1.249/caffe/practice/HSI/HSI_net.prototxt

HSI_solver.prototxt的下载

wget http://192.168.1.249/caffe/practice/HSI/HSI_solver.prototxt

训练 在caffe主目录下输入以下命令

./build/tools/caffe train --solver examples/HSI/HSI_solver.prototxt 2>&1 |tee examples/HSI/HSI_train.log

HSI_train.log:输出的日志,自己定义。

在已训练的参数上继续训练 准备:可以通过以下命令获得HSI_iter_10000.caffemodel和HSI_iter_10000.solverstate

wget http://192.168.1.249/caffe/practice/HSI/HSI_iter_10000.caffemodel
wget http://192.168.1.249/caffe/practice/HSI/HSI_iter_10000.solverstate
./build/tools/caffe train --solver examples/HSI/HSI_solver.prototxt --snapshot examples/HSI/HSI_iter_10000.solverstate 2>&1 |tee examples/HSI/HSI_resume.log

HSI_iter_10000.caffemodel(已训练的迭代10000次的模型) HSI_resume.log:输出的日志,自己定义。

测试

./build/tools/caffe test --model examples/HSI/HSI_net.prototxt --weights examples/HSI/HSI_iter_10000.caffemodel 2>&1 |tee  examples/HSI/HSI_test.log

HSI_test.log:输出的日志,自己定义。

工具使用

caffe自带以及自己写的脚本。

详细使用说明在

  • 使用caffe自带convert_imageset转换lmdb

    • 将图像和标签进行组织,然后使用convert_imageset转换

    组织形式

  • mat转hdf5

    • 将特定格式的mat文件转换为lmdb,适用于多标签。
    • 数据的mat格式必须存储为n*c*h*w的形式,四维,n表示样本编号,c表示通道数,h表示图像的高度(行),w表示图像的宽度(列)。
    • 标签的mat格式必须存储为n*c*h*w的形式,四维,n表示样本编号,c表示通道数,h表示图像的高度(行),w表示图像的宽度(列)。
  • 计算图像均值

    • 使用caffe自带的compute_imgmean计算图像均值
  • 画网络图

    • 根据网络配置文件XXX_net.prototxt画出网络图
    ../../../_images/HSI_net.prototxt.png
  • 根据日志画Loss曲线

    ../../../_images/face_recognition_train_loss_iters.png ../../../_images/face_recognition_test_loss_iters.png ../../../_images/face_recognition_train_learning_iters.png ../../../_images/face_recognition_test_accuracy_iters.png
  • 画特征图(Feature Map)

    ../../../_images/face_recognition_data_feature.png ../../../_images/face_recognition_conv1_feature.png ../../../_images/face_recognition_conv2_feature.png ../../../_images/face_recognition_conv3_feature.png ../../../_images/face_recognition_conv4_feature.png
  • 将caffemodel转换为mat

  • 保存网络中间结果

    • 保存每一层神经元处理后的特征图以及特征值。

deepID的文档

增加deepID使用文档和分析文档,在http://192.168.1.249/doku.php/平台/深度学习平台/caffe例子/face_recognition都可以找到。 practice/face_recognition/face_recognition_all.pdf practice/face_recognition/ caffe-face_recognition.pdf