美文网首页
Caffe训练自己的数据集

Caffe训练自己的数据集

作者: dacf13a4e779 | 来源:发表于2018-01-08 11:13 被阅读0次

    标签(空格分隔): caffe Linux 深度学习


    之前,我们已经完成了faster-rcnn的训练和测试工作,得到了person所在的区域。接下来我们将训练一个简单分类神经网络来对person进行简单地分类。

    数据集准备

    这里我们需要做类似于行人检测的工作,因此将INRIA Person Dataset中的某一部分行人样本图像进行训练。需要生成train.txt和val.txt,大家可以直接调用我的函数(注意,只是函数,不是完整的脚本哦),两者图像数量之比依旧是经典的1:1

    def WriteText(trainfilename, valfilename, fileset, count):
        rate = [0.5, 0.5]
        trainset = []
        valset = []
        trainposset = set(random.sample(xrange(len(fileset)), int(len(fileset) * rate[0])))
        valposset = set(xrange(len(fileset))) - trainposset
        for pos in trainposset:
            trainset.append(fileset[pos])
        for pos in valposset:
            valset.append(fileset[pos])
        with open(trainfilename, 'a') as f:
            for file in trainset:
                writetext = file + " " + str(count)
                writetext = writetext + "\n"
                f.write(writetext)
        with open(valfilename, 'a') as f:
            for file in valset:
                writetext = file + " " + str(count)
                writetext = writetext + "\n"
                f.write(writetext)
    
    
    def ReadJpeg(srcdir, ext=".jpg"):
        fileset = []
        for file in os.listdir(srcdir):
            absfilename = os.path.join(srcdir, file)
            if os.path.isfile(absfilename) and os.path.splitext(absfilename)[1] == ext:
                fileset.append(file)
        return sorted(fileset)
    
    
    def CreateTrainValTxt(imsetpath, fileset):
        trainfilename = os.path.join(imsetpath, 'train.txt')
        valfilename = os.path.join(imsetpath, 'val.txt')
        if os.path.exists(trainfilename):
            os.remove(trainfilename)
        if os.path.exists(valfilename):
            os.remove(valfilename)
        clsset = []
        count = -1
        previousname = ''
        for file in fileset:
            personname = file[:-5]
            if previousname == personname:
                clsset.append(file)
            else:
                if 0 != len(clsset):
                    WriteText(trainfilename, valfilename, clsset, count)
                clsset = []
                clsset.append(file)
                previousname = personname
                count = count + 1
    

    记住,为了后面训练的顺利进行,我们用脚本将图像规模统一调整为256*256,利用PIL的Image模块进行resize:

    def ConvertImagesize(imsetpath, fileset):
        for file in fileset:
            print "Convert:" + file
            filepath = os.path.join(imsetpath, file)
            im = Image.open(filepath)
            out = im.resize((256, 256), Image.ANTIALIAS)
            out.save(filepath)
    

    官方脚本的修改

    这些脚本都是用来进行预处理的脚本,我们可以根据自身需求更改路径,或者重新写一个脚本即可。这些脚本都保存在examples/imagenet目录下。
    1.create_imagenet.sh
    该脚本主要利用build/tools目录下的convert_imageset工具生成lmdb,某些路径可以自己修改。这里我直接将其改写成了一个Python脚本函数:

    def CreateImagenet(tooldir='build/tools', datadir='data/ilsvrc12/Persons', exampledir='examples/imagenet'):
        imdbdir = exampledir + "/ilsvrc12_train_lmdb"
        if os.path.exists(imdbdir):
            shutil.rmtree(imdbdir)
        cmd = tooldir + "/convert_imageset --shuffle " + datadir + "/ " + datadir + "/train.txt " + imdbdir
        print cmd
        os.system(cmd)
        imdbdir = exampledir + "/ilsvrc12_val_lmdb"
        if os.path.exists(imdbdir):
            shutil.rmtree(imdbdir)
        cmd = tooldir + "/convert_imageset --shuffle " + datadir + "/ " + datadir + "/val.txt " + imdbdir
        print cmd
        os.system(cmd)
    

    2.make_imagenet.mean.sh
    该脚本主要生成所有训练图像的平均值,利用到的是compute_image_mean工具,生成imagenet_mean.binaryproto。在这我也同样改成了一个Python脚本函数:

    def MakeImagenetMean(tooldir='build/tools', datadir='data/ilsvrc12/Persons', exampledir='examples/imagenet'):
        cmd = tooldir + "/compute_image_mean " + exampledir + "/ilsvrc12_train_lmdb " + datadir + "/imagenet_mean.binaryproto"
        print cmd
        os.system(cmd)
    
    

    网络结构的修改

    网络结构文件存放在models下,这里我使用的是bvlc_reference_caffenet,修改其train_val.prototxt文件:

    layer {
      name: "fc8"
      type: "InnerProduct"
      bottom: "fc7"
      top: "fc8"
      param {
        lr_mult: 1
        decay_mult: 1
      }
      param {
        lr_mult: 2
        decay_mult: 0
      }
      inner_product_param {
        num_output: 1000 #修改为需要输出的类别数
        weight_filler {
          type: "gaussian"
          std: 0.01
        }
        bias_filler {
          type: "constant"
          value: 0
        }
      }
    }
    

    执行训练脚本

    训练脚本路径为examples/imagenet/train_caffenet.sh目录下,这里为了方便同样的将shell脚本改写成Python脚本,为了方便起见,finetuning脚本也写在一起。

    def TrainCaffeNet(mode=1):
        tooldir = 'build/tools'
        abspath = os.getcwd()
        imsetpath = os.path.join(abspath, 'data/ilsvrc12/Persons')
        fileset = ReadJpeg(imsetpath)
        CreateTrainValTxt(imsetpath, fileset)
        ConvertImagesize(imsetpath, fileset)
        CreateImagenet()
        MakeImagenetMean()
        ChangePrototxt()
        if 1==mode:
            cmd = tooldir + "/caffe train --solver=models/bvlc_reference_caffenet/solver.prototxt"
        else:
            cmd = tooldir + "/caffe train --solver=examples/finetune_pascal_detection/pascal_finetune_trainval_test.prototxt"\
            +" --weights models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel"
        print cmd
        os.system(cmd)
    

    finetuning网络

    按照官方教程介绍,finetuning的工作在网络上的修改只是最后一层,以AlexNet为例则是fc8,目录examples/finetune_pascal_detection下有以下用到的文件。
    1.修改pascal_finetune_trainval_test.prototxt网络全连接层fc8

    layer {
      name: "fc8-finetune" # 要将本层改名,这样网络才会随机初始化权值
      type: "InnerProduct"
      bottom: "fc7"
      top: "fc8-finetune" #改名
      param {
        lr_mult: 10 # 本层学习速率为以前的10倍
        decay_mult: 1
      }
      param {
        lr_mult: 2
        decay_mult: 0
      }
      inner_product_param {
        num_output: 246 # 类别数,按需修改
        weight_filler {
          type: "gaussian"
          std: 0.01
        }
        bias_filler {
          type: "constant"
          value: 0
        }
      }
    }
    layer {
      name: "accuracy"
      type: "Accuracy"
      bottom: "fc8-finetune" # 本层学习速率为以前的10倍
      bottom: "label"
      top: "accuracy"
      include {
        phase: TEST
      }
    }
    layer {
      name: "loss"
      type: "SoftmaxWithLoss"
      bottom: "fc8-finetune" # 本层学习速率为以前的10倍
      bottom: "label"
      top: "loss"
    }
    
    

    2.修改pascal_finetune_solver.prototxt学习速率

    net: "models/bvlc_reference_caffenet/fintune-train_val.prototxt"
    test_iter: 100 #减少测试迭代次数
    test_interval: 1000
    base_lr: 0.001 #学习速率减小
    lr_policy: "step"
    gamma: 0.1
    stepsize: 20000 #学习步长增加
    display: 20
    max_iter: 100000 #减少最大迭代次数
    momentum: 0.9
    weight_decay: 0.0005
    snapshot: 10000
    snapshot_prefix: "models/bvlc_reference_caffenet/caffenet_train"
    solver_mode: GPU
    
    

    3.执行训练脚本(见上文)

    相关文章

      网友评论

          本文标题:Caffe训练自己的数据集

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