Caffe训练自己的数据集

标签(空格分隔): 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.执行训练脚本(见上文)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,100评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,862评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,993评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,309评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,303评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,421评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,830评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,501评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,689评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,506评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,564评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,286评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,826评论 3 305
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,875评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,114评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,705评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,269评论 2 341

推荐阅读更多精彩内容