美文网首页
Caffe学习笔记2:LeNet拒绝官方脚本!从数据准备到训练再

Caffe学习笔记2:LeNet拒绝官方脚本!从数据准备到训练再

作者: Zz鱼丸 | 来源:发表于2017-08-23 17:30 被阅读0次

    作为深度学习界的“hello world!”,学习起来真没那么容易。
    接触深度学习,第一个接触的就是mnist。但是初次接触就只跑了三个脚本

    get_mnist.sh
    create_mnist.sh
    train_lenet.sh
    

    然后就结束了,对此我蒙逼了许久。因为对于caffe的整体框架不熟悉,对CNN不深入,因此感觉举步维艰。经过1个多月的沉淀终于能完整的走一遍MNIST。
    对于初学者,深度学习分为三步:1.数据准备 2.训练 3.预测
    一.数据准备
    官方例程推荐的数据集为

    t10k-images-idx3-ubyte
    t10k-labels-idx1-ubyte
    train-images-idx3-ubyte
    train-labels-idx1-ubyte
    

    相信许多人和我一样会问:这是什么啊,打开还是一推二进制数。确实,官方的数据集可视化不好,但是可以借助matlab或者python解析出来。但是,对于普通人拿到的数据往往都是图片格式,而且是很多。

    Paste_Image.png

    这该进行怎么加载训练呢。
    先粗略的看下,官方的数据集。可以看出images对应一个labels,所以我们准备的数据包括图片和标签。
    1)基础准备
    在data文件夹下创建如下文件夹,准备训练集,验证集和测试集


    Paste_Image.png

    创建 train test文件夹和对应的txt将你的训练集放到train中,将验证集放到test中。(这里应该多建一个valid文件夹,里面存放的是验证集,而test中放测试集,这里偷工减料了)
    接着要制作标签,如果量少可以考虑手敲,但是大数据就只能借助代码了。
    创建make_list.py

    #coding=utf-8
    #caffe and opencv test mnist
    #test by yuzefan
    import os
    from os.path import join, isdir
    
    def gen_listfile(dir):
        cwd=os.getcwd() # 获取当前目录
        os.chdir(dir)   # 改变当前的目录
        sd=[d for d in os.listdir('.') if isdir(d)] # 列出当前目录下的所有文件和目录名,os.listdir可以列出文件和目录
        sd.sort()
        class_id=0
        with open(join(dir,'listfile.txt'),'w') as f :  #join():connect string,"with...as"is used for safety,without it,you must write by"file = open("/tmp/foo.txt") file.close()
            for d in sd :
                fs=[join(d,x) for x in os.listdir(d)]
                for img in fs:
                    f.write(img + ' '+str(class_id)+'\n')
                class_id+=1
        os.chdir(cwd)
    
    if __name__ == "__main__":
        root_dir = raw_input('image root dir: ')
        while not isdir(root_dir):
            raw_input('not exist, re-input please: ')
        gen_listfile(root_dir)
    

    运行后可以得到标签,如下:

    Paste_Image.png

    list已经准备好了,接着要把数据转成lmdb。caffe之所以速度快,得益于lmdb数据格式。
    创建creat_lmdb.sh脚本

    #coding=utf-8
    #!/usr/bin/env sh 
    #指定脚本的解释程序
    #by yuzefan
    set -e #如果任何语句的执行结果不是true则应该退出
    # CAFFEIMAGEPATH is the txt file path
    # DATA is the txt file path
    
    CAFFEDATAPATH=mytest/chinese/data
    DATA=mytest/chinese/data/mnist
    TOOLS=~/caffe-master/build/tools
    
    # TRAIN_DATA_PATH & VAL_DATA_ROOT is root path of your images path, so your train.txt file must do not contain
    # this line again!!
    TRAIN_DATA_ROOT=/home/ubuntu/caffe-master/mytest/chinese/data/mnist/train/
    VAL_DATA_ROOT=/home/ubuntu/caffe-master/mytest/chinese/data/mnist/test/
    # Set RESIZE=true to resize the images to 28x28. Leave as false if images have
    # already been resized using another tool.
    RESIZE=true
    if $RESIZE;then
        RESIZE_HEIGHT=28
        RESIZE_WIDTH=28
    else
        RESIZE_HEIGHT=0
        RESIZE_WIDTH=0
    fi
    if [ ! -d "$TRAIN_DATA_ROOT" ]; then
      echo "Error: TRAIN_DATA_ROOT is not a path to a directory: $TRAIN_DATA_ROOT"
      echo "Set the TRAIN_DATA_ROOT variable in create_imagenet.sh to the path" \
           "where the ImageNet training data is stored."
      exit 1
    fi
    
    if [ ! -d "$VAL_DATA_ROOT" ]; then
      echo "Error: VAL_DATA_ROOT is not a path to a directory: $VAL_DATA_ROOT"
      echo "Set the VAL_DATA_ROOT variable in create_imagenet.sh to the path" \
           "where the ImageNet validation data is stored."
      exit 1
    fi
    
    echo "Creating train lmdb..."
    
    GLOG_logtostderr=1 $TOOLS/convert_imageset \
        --resize_height=$RESIZE_HEIGHT \
        --resize_width=$RESIZE_WIDTH \
        --shuffle \
        --gray=true\
        $TRAIN_DATA_ROOT \
        $DATA/train.txt \
        $CAFFEDATAPATH/caffe_train_lmdb
    
    echo "Creating val lmdb..."
    
    GLOG_logtostderr=1 $TOOLS/convert_imageset \
        --resize_height=$RESIZE_HEIGHT \
        --resize_width=$RESIZE_WIDTH \
        --shuffle \
        --gray=true\
        $VAL_DATA_ROOT \
        $DATA/test.txt \
        $CAFFEDATAPATH/caffe_val_lmdb
    
    echo "Done."
    

    运行完后在data目录下出现

    caffe_train_lmdb
    caffe_val_lmdb
    

    这里使用了caffe的tools中的convert_imageset。使用方法:

    convert_imageset [FLAGS] ROOTFOLDER/ LISTFILE DB_NAME 
    其中 
    参数:ROOTFOLDER 表示输入的文件夹 
    参数:LISTFILE 表示输入文件列表,其每一行为:类似 subfolder1/file1.JPEG 7 
    可选参数:[FLAGS] 可以指示是否使用shuffle,颜色空间,编码等。
    --gray=true  \-------------------------------------------->如果灰度图的话加上即可
    还调用了opencv,对输入图像进行尺寸变换,满足网络的要求。
    

    注意:

    TRAIN_DATA_PATH & VAL_DATA_ROOT is root path of your images path, so your train.txt file must do not contain
    

    到此,数据准备就结束了。
    二.训练
    训练需要模型描述文件和模型求解文件。

    lenet_train_test.prototxt
    lenet_solver.prototxt
    

    对于lenet_train_test.prototxt,需要改的地方只有数据层

    name: "LeNet"
    layer {
      name: "mnist"  #名字随便
      type: "Data"
      top: "data"
      top: "label"
      include {
        phase: TRAIN
      }
      transform_param {
        scale: 0.00390625
      }
      data_param {
        source: "mytest/chinese/data/caffe_train_lmdb"  #这里是上一步生成的lmdb
        batch_size: 64#一次压入网络的数量
        backend: LMDB
      }
    }
    layer {
      name: "mnist"
      type: "Data"
      top: "data"
      top: "label"
      include {
        phase: TEST
      }
      transform_param {
        scale: 0.00390625
      }
      data_param {
        source: "mytest/chinese/data/caffe_val_lmdb"
        batch_size: 100 
        backend: LMDB
      }
    }
    

    对于lenet_solver.prototxt

    # The train/test net protocol buffer definition
    net: "mytest/chinese/lenet_train_test.prototxt"#这里可以把训练和验证放到一起,实际可以分开
    # test_iter specifies how many forward passes the test should carry out.
    # In the case of MNIST, we have test batch size 100 and 100 test iterations,
    # covering the full 10,000 testing images.
    test_iter: 100 #test_iter * batch_size= 10000(test集的大小)
    # Carry out testing every 500 training iterations.
    test_interval: 500 
    # The base learning rate, momentum and the weight decay of the network.
    base_lr: 0.01
    momentum: 0.9
    weight_decay: 0.0005
    # The learning rate policy
    lr_policy: "inv"
    gamma: 0.0001
    power: 0.75
    # Display every 100 iterations
    display: 20
    # The maximum number of iterations
    max_iter: 10000
    # snapshot intermediate results
    snapshot: 5000
    snapshot_prefix: "mytest/chinese/lenet"
    # solver mode: CPU or GPU
    solver_mode: GPU
    

    训练可以执行train_lenet.sh,实际上还是调用了tools

    #!/usr/bin/env sh
    set -e
    
    ./build/tools/caffe train --solver=mytest/chinese/lenet_solver.prototxt $@
    

    没有意外的话就能正常开始训练了。
    三.预测
    预测可以参考我之前写的

    Caffe学习笔记1:用训练好的mnist模型进行预测(两种方法)
    http://www.jianshu.com/p/6fcdefbacf5b
    

    小笔记:均值计算
    减均值预处理能提高训练和预测的速度,利用tools

    二进制格式的均值计算
    build/tools/compute_image_mean examples/mnist/mnist_train_lmdb examples/mnist/mean.binaryproto
    带两个参数:
    第一个参数:examples/mnist/mnist_train_lmdb, 表示需要计算均值的数据,格式为lmdb的训练数据。
    第二个参数:examples/mnist/mean.binaryproto, 计算出来的结果保存文件。
    

    接下来的计划:现在说白了是个10类的分类器,接下来增强网络使其能够训练并预测出0~9 and ‘a’~‘z’

    相关文章

      网友评论

          本文标题:Caffe学习笔记2:LeNet拒绝官方脚本!从数据准备到训练再

          本文链接:https://www.haomeiwen.com/subject/nvzddxtx.html