使用caffe的HDF5数据完成回归任务

一直在研究如何用caffe做行人检测问题,然而参考那些经典结构比如faster-rcnn等,都是自定义的caffe层来完成的检测任务。这些都要求对caffe框架有一定程度的了解。最近看到了如何用caffe完成回归的任务,就想把检测问题当成回归问题来解决。

我们把行人检测问题当成回归来看待,就需要限制检出目标的个数,因为我们的输出个数是固定的。所以,这里我假定每张图片最多检出的目标个数为2。即每个目标用4个值来表示其位置信息(中心位置坐标x,y。BBox的宽和高),则网络的最后输出是8个值。

制作HDF5数据

这里我们使用HDF5格式的数据来完成我们的回归任务,那么首先我们需要的是制作h5格式的数据。这里以VOC数据集为例。下面是制作HDF5格式数据的python代码。

import h5py
import caffe
import os
import xml.etree.ElementTree as ET
import cv2
import time
import math
from os.path import join, exists
import numpy as np

def convert(size, box):
    dw = 1./size[0]
    dh = 1./size[1]
    x = (box[0] + box[1])/2.0
    y = (box[2] + box[3])/2.0
    w = box[1] - box[0]
    h = box[3] - box[2]
    x = x*dw
    w = w*dw
    y = y*dh
    h = h*dh
    return (x,y,w,h)

def shuffle_in_unison_scary(a, b):
    rng_state = np.random.get_state()
    np.random.shuffle(a)
    np.random.set_state(rng_state)
    np.random.shuffle(b)

def processImage(imgs):
    imgs = imgs.astype(np.float32)
    for i, img in enumerate(imgs):
        m = img.mean()
        s = img.std()
        imgs[i] = (img - m) / s
    return imgs

TrainImgDir = ‘F:/GenerateHDF5/trainImage‘
TrainLabelDir = ‘F:/GenerateHDF5/trainLabels‘
TestImgDir = ‘F:/GenerateHDF5/testImg‘
TestLabelDir = ‘F:/GenerateHDF5/testLabels‘

InImg = []
InBBox = []

for rootDir,dirs,files in os.walk(TestLabelDir):                                       #####
    for file in files:
        file_name = file.split(‘.‘)[0]
        full_file_name = ‘%s%s‘%(file_name,‘.jpg‘)
        full_file_dir = ‘%s/%s‘%(TestImgDir,full_file_name)                            #####
        Img = cv2.imread(full_file_dir,cv2.CV_LOAD_IMAGE_GRAYSCALE)
        xml_file = open("%s/%s"%(rootDir,file))
        tree = ET.parse(xml_file)
        root = tree.getroot()
        size = root.find(‘size‘)
        w = int(size.find(‘width‘).text)
        h = int(size.find(‘height‘).text)

        landmark = np.zeros(8)
        count = 0
        for obj in root.iter(‘object‘):
            count = count + 1
            if count == 3:
                break
            xmlbox = obj.find(‘bndbox‘)
            b = (float(xmlbox.find(‘xmin‘).text), float(xmlbox.find(‘xmax‘).text), float(xmlbox.find(‘ymin‘).text), float(xmlbox.find(‘ymax‘).text))
            bb = convert((w,h), b)
            landmark[(count-1)*4+0]=bb[0]
            landmark[(count-1)*4+1]=bb[1]
            landmark[(count-1)*4+2]=bb[2]
            landmark[(count-1)*4+3]=bb[3]

        InBBox.append(landmark.reshape(8))
        Img = cv2.resize(Img,(h,w))
        InImg.append(Img.reshape((1,h,w)))           

InImg, InBBox = np.asarray(InImg), np.asarray(InBBox)
InImg = processImage(InImg)
shuffle_in_unison_scary(InImg, InBBox)

outputDir = ‘hdf5/‘
HDF5_file_name = ‘hdf5_test.h5‘                                                  #####
if not os.path.exists(outputDir):
    os.makedirs(outputDir)

output = join(outputDir,HDF5_file_name)
with h5py.File(output, ‘w‘) as h5:
    h5[‘data‘] = InImg.astype(np.float32)
    h5[‘labels‘] = InBBox.astype(np.float32)
    h5.close()

这里注意一点,所有的BBox数据都要做归一化操作,即所有坐标要除以图片对应的宽高。据说,这样做能使最后得到的结果更好。

制作好了HDF5数据后,注意每个H5文件大小不能超过2G(这是caffe的规定,如果一个文件超过2G,请分开制作多个)。然后建立一个TXT文件,文件里写上所有H5文件的绝对路径,比如我这里建立的文件是list_train.txt。然后我只有一个H5文件,即hdf5_train.h5。所以我的list_train.txt文件中的内容就是/home/XXX/caffe/model/hdf5/hdf5_train.h5

配置solver文件

接下来是caffe的solver文件,这个文件没有什么区别,

test_iter: 20
test_interval: 70
base_lr: 0.0000000005
display: 9
max_iter: 210000
lr_policy: "step"
gamma: 0.1
momentum: 0.9
weight_decay: 0.0001
stepsize: 700
snapshot: 500
snapshot_prefix: "snapshot"
solver_mode: GPU
net: "train_val.prototxt"
solver_type: SGD

配置train_val.prototxt文件

接下来是网络的train_val.prototxt文件。这是caffe的网络结构文件,我们这里以LeNet网络为例,我这里是这样的:

name: "LeNet"
layer {
  name: "data"
  type: "HDF5Data"
  top: "data"
  top: "labels"
  include {
    phase: TRAIN
  }
  hdf5_data_param {
    source: "list_train.txt"
    batch_size: 50
  }
}
layer {
  name: "data"
  type: "HDF5Data"
  top: "data"
  top: "labels"
  include {
    phase: TEST
  }
  hdf5_data_param {
    source: "list_test.txt"
    batch_size: 50
  }
}
layer {
  name: "conv1"
  type: "Convolution"
  bottom: "scaled"
  top: "conv1"
  param {
    lr_mult: 1.0
  }
  param {
    lr_mult: 2.0
  }
  convolution_param {
    num_output: 20
    kernel_size: 5
    stride: 1
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "pool1"
  type: "Pooling"
  bottom: "conv1"
  top: "pool1"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {
  name: "conv2"
  type: "Convolution"
  bottom: "pool1"
  top: "conv2"
  param {
    lr_mult: 1.0
  }
  param {
    lr_mult: 2.0
  }
  convolution_param {
    num_output: 50
    kernel_size: 5
    stride: 1
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "pool2"
  type: "Pooling"
  bottom: "conv2"
  top: "pool2"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {
  name: "ip1"
  type: "InnerProduct"
  bottom: "pool2"
  top: "ip1"
  param {
    lr_mult: 1.0
  }
  param {
    lr_mult: 2.0
  }
  inner_product_param {
    num_output: 500
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "relu1"
  type: "ReLU"
  bottom: "ip1"
  top: "ip1"
}
layer {
  name: "ip2"
  type: "InnerProduct"
  bottom: "ip1"
  top: "ip2"
  param {
    lr_mult: 1.0
  }
  param {
    lr_mult: 2.0
  }
  inner_product_param {
    num_output: 8
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "error"
  type: "EuclideanLoss"
  bottom: "ip2"
  bottom: "labels"
  top: "error"
  include {
      phase: TEST
  }
}
layer {
  name: "loss"
  type: "EuclideanLoss"
  bottom: "ip2"
  bottom: "labels"
  top: "loss"
  include {
      phase: TRAIN
  }
}

这里注意的是,最后的一层全连接层,输出的num_output应该是你label的维度,我这里是8。然后最后的loss计算,我使用的是欧氏距离的loss,也可以试着用其他类型的loss。

开始训练

按照以上步骤配置好了,最后就是训练了。在控制台中输入以下指令来训练我们的数据:

./cafferoot/caffe/tools/caffe train --solver=solver.prototxt

可能是我数据源的问题,我的loss一开始非常大,然后一直降不下来。也有可能是LeNet本身网络性能就不好。关于网络的性能还需要另外再想办法提升。

时间: 2024-10-28 15:46:18

使用caffe的HDF5数据完成回归任务的相关文章

总结一下用caffe跑图片数据的研究流程

最近在用caffe玩一些数据集,这些数据集是从淘宝爬下来的图片.主要是想研究一下对女性衣服的分类. 下面是一些具体的操作流程,这里总结一下. 1 爬取数据.写爬虫从淘宝爬取自己需要的数据. 2 数据预处理.将图片从jpg,png格式转为leveldb格式.因为caffe的输入层datalayer是从leveldb读取的.这一步自己基于caffe写了个工具实现转换. 转换命令例子: ./convert_imagedata.bin /home/linger/imdata/skirt_train/ /

caffe 中 python 数据层

caffe中大多数层用C++写成. 但是对于自己数据的输入要写对应的输入层,比如你要去图像中的一部分,不能用LMDB,或者你的label 需要特殊的标记. 这时候就需要用python 写一个输入层. 如在fcn 的voc_layers.py 中 有两个类: VOCSegDataLayer SBDDSegDataLayer 分别包含:setup,reshape,forward, backward, load_image, load_label. 不需要backward 没有参数更新. import

机器学习——预测数值型数据:回归

线性回归 优点:结果易于理解,计算上不复杂 缺点:对非线性的数据拟合不好 适用数据类型:数值型和标称型数据 回归的目的就预测数值型的目标值.最直接的办法就是依据输入写一个目标值的计算公式.这个计算公式就是所谓的回归方程(regression equation),其中的参数就是回归系数,求这些回归系数的过程就是回归. 说道回归,一般都是指线性回归(linear regression). 一元线性回归的矩阵形式可以写成,其中 是噪声,b是回归系数(斜率) 或者 ,其中y.X.a.都是n维向量,而b是

Windows Caffe(三) 图像数据转化为Caffe可以运行的数据

在运行Caffe自带的两个例子的时候,我们的数据都来自互联网,是直接下载的二进制文件. 但我们大多数情况下使用的是原始的图片数据(如.jpg .png等),接下来研究如何将原始的图片数据转化为caffe可以运行的数据. 1.准备图片数据 caffe安装完成之后,在example/images文件下会有四张.jpg图片,cat.jpg, cat gray,jpg, cat_gray.jpg, fish-back.jpg 2.生成图片清单 我们写需要一个sh脚本,调用Linux命令生成图片的清单.W

机器学习实战第8章预测数值型数据:回归

1.简单的线性回归 假定输入数据存放在矩阵X中,而回归系数存放在向量W中,则对于给定的数据X1,预测结果将会是 这里的向量都默认为列向量 现在的问题是手里有一些x和对应的y数据,怎样才能找到W呢?一个常用的方法是找到使误差最小的W,这里的误差是指预测y值与真实y值之间的差值,使用该误差的简单累加将使得正差值和负差值相互抵消,所以我们采用平方误差. 平方误差可以写做: 用矩阵表示可以写成 使用上式对w进行求导: 具体可参考https://blog.csdn.net/nomadlx53/articl

机器学习实战第8章预测数值型数据:回归2

1. Shrinkage(缩减) Methods 当特征比样本点还多时(n>m),输入的数据矩阵X不是满秩矩阵,在求解(XTX)-1时会出现错误.接下来主要介绍岭回归(ridge regression)和前向逐步回归(Foward Stagewise Regression)两种方法. 1.1 岭回归(ridge regression) 简单来说,岭回归就是在矩阵XTX上加上一个从而使得矩阵非奇异,进而能进行求逆.其中矩阵I是一个单位矩阵,是一个调节参数. 岭回归的回归系数计算公式为: 岭回归最先

Win10移动版数据开关回归:不用进设置了

随着Windows 10功能开发已因7月29号正式发布而告一段落,一部分Windows开发团队成员终于可以分出时间用于Windows 10 Mobile系统的开发了. 据悉,Windows 10 Mobile的最新Build 10134中,带来了新的应用商店(Beta).Edge 浏览器以及全新Cortana欢迎界面.今天又有网友贴出了新版Windows 10 Mobile控制中心的截图.如图所示,Windows 10 Mobile预览版系统以后将在控制中心增加数据流量开关(Cellular D

第八章:预测数值型数据:回归

本章内容□ 线性回归□ 局部加权线性回归□ 岭回归和逐步线性回归□ 预测鲍鱼年龄和玩具售价  8.1用线性回归找到最佳拟合直线

caffe数据层

在caffe网络中数据层通常是最底层,数据通过Data layer进入caffe网络.效率起见,数据一般从databases(LevelDB, LMDB)导入,也可直接从内存(memory)导入.如不看重效率,也可从HDF5或是常见的图片格式导入. 一些通常的输入预处理(mean subtraction, scaling , random cropping , mirroring)可在一些层的TransformationParameters中进行注明.当TransformationParamet