生活随笔
收集整理的這篇文章主要介紹了
深度学习(十三)caffe之训练数据格式
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
caffe之訓(xùn)練數(shù)據(jù)格式
原文地址:http://blog.csdn.net/hjimce/article/details/49248231
作者:hjimce
caffe對(duì)于訓(xùn)練數(shù)據(jù)格式,支持:lmdb、h5py……,其中l(wèi)mdb數(shù)據(jù)格式常用于單標(biāo)簽數(shù)據(jù),像分類(lèi)等,經(jīng)常使用lmdb的數(shù)據(jù)格式。對(duì)于回歸等問(wèn)題,或者多標(biāo)簽數(shù)據(jù),一般使用h5py數(shù)據(jù)的格式。當(dāng)然好像還有其它格式的數(shù)據(jù)可用,不過(guò)我一般使用這兩種數(shù)據(jù)格式,因此本文就主要針對(duì)這兩種數(shù)據(jù)格式的制作方法,進(jìn)行簡(jiǎn)單講解。
一、lmdb數(shù)據(jù)
lmdb用于單標(biāo)簽數(shù)據(jù)。為了簡(jiǎn)單起見(jiàn),我后面通過(guò)一個(gè)性別分類(lèi)作為例子,進(jìn)行相關(guān)數(shù)據(jù)制作講解。
1、數(shù)據(jù)準(zhǔn)備
首先我們要準(zhǔn)備好訓(xùn)練數(shù)據(jù),然后新建一個(gè)名為train的文件夾和一個(gè)val的文件夾:
train文件存放訓(xùn)練數(shù)據(jù),val文件存放驗(yàn)證數(shù)據(jù)。然后我們?cè)趖rain文件下面,把訓(xùn)練數(shù)據(jù)性別為男、女圖片各放在一個(gè)文件夾下面:
同樣的我們?cè)趘al文件下面也創(chuàng)建文件夾:
兩個(gè)文件也是分別存我們用于驗(yàn)證的圖片數(shù)據(jù)男女性別文件。我們?cè)趖est_female下面存放了都是女性的圖片,然后在test_male下面存放的都是驗(yàn)證數(shù)據(jù)的男性圖片。
2、標(biāo)簽文件.txt文件制作.
接著我們需要制作一個(gè)train.txt、val.txt文件,這兩個(gè)文件分別包含了我們上面的訓(xùn)練數(shù)據(jù)的圖片路徑,以及其對(duì)應(yīng)的標(biāo)簽,如下所示。
我們把女生圖片標(biāo)號(hào)為1,男生圖片標(biāo)記為0。標(biāo)簽數(shù)據(jù)文件txt的生成可以通過(guò)如下代碼,通過(guò)掃描路徑男、女性別下面的圖片,得到標(biāo)簽文件train.txt和val.txt:
[python]?view plaincopy
<span?style="font-family:Arial;font-size:18px;"><span?style="font-size:18px;"><span?style="font-size:18px;">import?os?? import?numpy?as?np?? from?matplotlib?import?pyplot?as?plt?? import?cv2?? import?shutil?? ?? ?? ?? def?GetFileList(FindPath,FlagStr=[]):???????? ????import?os?? ????FileList=[]?? ????FileNames=os.listdir(FindPath)?? ????if?len(FileNames)>0:?? ????????for?fn?in?FileNames:?? ????????????if?len(FlagStr)>0:?? ????????????????if?IsSubString(FlagStr,fn):?? ????????????????????fullfilename=os.path.join(FindPath,fn)?? ????????????????????FileList.append(fullfilename)?? ????????????else:?? ????????????????fullfilename=os.path.join(FindPath,fn)?? ????????????????FileList.append(fullfilename)?? ?? ????? ????if?len(FileList)>0:?? ????????FileList.sort()?? ?? ????return?FileList?? def?IsSubString(SubStrList,Str):???????? ????flag=True?? ????for?substr?in?SubStrList:?? ????????if?not(substr?in?Str):?? ????????????flag=False?? ?? ????return?flag?? ?? txt=open('train.txt','w')?? ?? imgfile=GetFileList('first_batch/train_female')?? for?img?in?imgfile:?? ????str=img+'\t'+'1'+'\n'?? ????txt.writelines(str)?? ?? imgfile=GetFileList('first_batch/train_male')?? for?img?in?imgfile:?? ????str=img+'\t'+'0'+'\n'?? ????txt.writelines(str)?? txt.close()</span></span></span>??
把生成的標(biāo)簽文件,和train\val文件夾放在同一個(gè)目錄下面:
需要注意,我們標(biāo)簽數(shù)據(jù)文件里的文件路徑和圖片的路徑要對(duì)應(yīng)的起來(lái),比如val.txt文件的某一行的圖片路徑,是否在val文件夾下面:
3、生成lmdb數(shù)據(jù)
接著我們的目的就是要通過(guò)上面的四個(gè)文件,把圖片的數(shù)據(jù)和其對(duì)應(yīng)的標(biāo)簽打包起來(lái),打包成lmdb數(shù)據(jù)格式,打包腳本如下:
[python]?view plaincopy
<span?style="font-family:Arial;font-size:18px;"><span?style="font-size:18px;">?? ?? ?? ?? EXAMPLE=.???????????? TOOLS=//../build/tools???????????????????????????????? DATA=.???????????????????? ?? TRAIN_DATA_ROOT=train/???? VAL_DATA_ROOT=val/???????? ?? ?? ?? ?? ?? RESIZE=true?? if?$RESIZE;?then?? ??RESIZE_HEIGHT=256?? ??RESIZE_WIDTH=256?? 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?\?? ????$TRAIN_DATA_ROOT?\?? ????$DATA/train.txt?\?? ????$EXAMPLE/train_lmdb?? ?? echo?"Creating?val?lmdb..."?? ?? GLOG_logtostderr=1?$TOOLS/convert_imageset?\?? ????--resize_height=$RESIZE_HEIGHT?\?? ????--resize_width=$RESIZE_WIDTH?\?? ????--shuffle?\?? ????$VAL_DATA_ROOT?\?? ????$DATA/val.txt?\?? ????$EXAMPLE/val_lmdb?? ?? echo?"Done."</span></span>??
通過(guò)運(yùn)行上面的腳本,我們即將得到文件夾train_lmdb\val_lmdb:
我們打開(kāi)train_lmdb文件夾
并查看一下文件data.mdb數(shù)據(jù)的大小,如果這個(gè)數(shù)據(jù)包好了我們所有的訓(xùn)練圖片數(shù)據(jù),查一下這個(gè)文件的大小是否符合預(yù)期大小,如果文件的大小才幾k而已,那么就代表你沒(méi)有打包成功,估計(jì)是因?yàn)槁窂皆O(shè)置錯(cuò)誤。我們也可以通過(guò)如下的代碼讀取上面打包好的數(shù)據(jù),把圖片、和標(biāo)簽打印出來(lái),查看一下,查看lmdb數(shù)據(jù)請(qǐng)參考下面的代碼:
python lmdb數(shù)據(jù)驗(yàn)證:
[python]?view plaincopy
<span?style="font-family:Arial;font-size:18px;"><span?style="font-size:18px;">?? caffe_root?=?'/home/hjimce/caffe/'?? import?sys?? sys.path.insert(0,?caffe_root?+?'python')?? import?caffe?? ?? import?os?? import?lmdb?? import?numpy?? import?matplotlib.pyplot?as?plt?? ?? ?? def?readlmdb(path,visualize?=?False):?? ????env?=?lmdb.open(path,?readonly=True,lock=False)?? ?? ????datum?=?caffe.proto.caffe_pb2.Datum()?? ????x=[]?? ????y=[]?? ????with?env.begin()?as?txn:?? ????????cur?=?txn.cursor()?? ????????for?key,?value?in?cur:?? ?????????????? ????????????datum.ParseFromString(value)?? ?????????????? ????????????img_data?=?numpy.array(bytearray(datum.data))\?? ????????????????.reshape(datum.channels,?datum.height,?datum.width)?? ????????????print?img_data.shape?? ????????????x.append(img_data)?? ????????????y.append(datum.label)?? ????????????if?visualize:?? ????????????????img_data=img_data.transpose([1,2,0])?? ????????????????img_data?=?img_data[:,?:,?::-1]?? ????????????????plt.imshow(img_data)?? ????????????????plt.show()?? ????????????????print?datum.label?? ????return??x,y</span></span>??
通過(guò)上面的函數(shù),我們可以是讀取相關(guān)的lmdb數(shù)據(jù)文件。
4、制作均值文件。
這個(gè)是為了圖片歸一化而生成的圖片平均值文件,把所有的圖片相加起來(lái),做平均,具體的腳本如下:
[python]?view plaincopy
<span?style="font-family:Arial;font-size:18px;"><span?style="font-size:18px;">?? ?? ?? ?? EXAMPLE=.?? DATA=train?? TOOLS=../../build/tools??? ?? $TOOLS/compute_image_mean?$EXAMPLE/train_lmdb?\ #train_lmdb是我們上面打包好的lmdb數(shù)據(jù)文件?? ??$DATA/imagenet_mean.binaryproto?? ?? echo?"Done."</span></span>??
運(yùn)行這個(gè)腳本,我們就可以訓(xùn)練圖片均值文件:imagenet_mean.binaryproto
至此,我們得到了三個(gè)文件:imagenet_mean.binaryproto、train_lmdb、val_lmdb,這三個(gè)文件就是我們最后打包好的數(shù)據(jù),這些數(shù)據(jù)我們即將作為caffe的數(shù)據(jù)輸入數(shù)據(jù)格式文件,把這三個(gè)文件拷貝出來(lái),就可以把原來(lái)還沒(méi)有打包好的數(shù)據(jù)刪了。這三個(gè)文件,我們?cè)赾affe的網(wǎng)絡(luò)結(jié)構(gòu)文件,數(shù)據(jù)層定義輸入數(shù)據(jù)的時(shí)候,就會(huì)用到了:
[python]?view plaincopy
<span?style="font-family:Arial;font-size:18px;"><span?style="font-size:18px;">name:?"CaffeNet"?? layers?{?? ??name:?"data"?? ??type:?DATA?? ??top:?"data"?? ??top:?"label"?? ??data_param?{?? ????source:?"train_lmdb"#lmbd格式的訓(xùn)練數(shù)據(jù)?? ????backend:?LMDB?? ????batch_size:?50?? ??}?? ??transform_param?{?? ????crop_size:?227?? ????mirror:?true?? ????mean_file:"imagenet_mean.binaryproto"#均值文件?? ?? ??}?? ??include:?{?phase:?TRAIN?}?? }?? layers?{?? ??name:?"data"?? ??type:?DATA?? ??top:?"data"?? ??top:?"label"?? ??data_param?{?? ????source:??"val_lmdb"#lmdb格式的驗(yàn)證數(shù)據(jù)?? ????backend:?LMDB?? ????batch_size:?50?? ??}?? ??transform_param?{?? ????crop_size:?227?? ????mirror:?false?? ????mean_file:"imagenet_mean.binaryproto"#均值文件?? ??}?? ??include:?{?phase:?TEST?}?? }</span></span>??
二、h5py格式數(shù)據(jù)
上面的lmdb一般用于單標(biāo)簽數(shù)據(jù),圖片分類(lèi)的時(shí)候,大部分用lmdb格式。然而假設(shè)我們要搞的項(xiàng)目是人臉特征點(diǎn)識(shí)別,我們要識(shí)別出68個(gè)人臉特征點(diǎn),也就是相當(dāng)于136維的輸出向量。網(wǎng)上查了一下,對(duì)于caffe多標(biāo)簽輸出,需要使用h5py格式的數(shù)據(jù),而且使用h5py的數(shù)據(jù)格式的時(shí)候,caffe是不能使用數(shù)據(jù)擴(kuò)充進(jìn)行相關(guān)的數(shù)據(jù)變換的,很是悲劇啊,所以如果caffe使用h5py數(shù)據(jù)格式的話,需要自己在外部,進(jìn)行數(shù)據(jù)擴(kuò)充,數(shù)據(jù)歸一化等相關(guān)的數(shù)據(jù)預(yù)處理操作。
1、h5py數(shù)據(jù)格式生成
下面演示一下數(shù)據(jù)h5py數(shù)據(jù)格式的制作:
[python]?view plaincopy
<span?style="font-family:Arial;font-size:18px;"><span?style="font-size:18px;">?? caffe_root?=?'/home/hjimce/caffe/'?? import?sys?? sys.path.insert(0,?caffe_root?+?'python')?? import?os?? import?cv2?? import?numpy?as?np?? import?h5py?? from?common?import?shuffle_in_unison_scary,?processImage?? import?matplotlib.pyplot?as?plt?? ?? def?readdata(filepath):?? ????fr=open(filepath,'r')?? ????filesplit=[]?? ????for?line?in?fr.readlines():?? ????????s=line.split()?? ????????s[1:]=[float(x)?for?x?in?s[1:]]?? ????????filesplit.append(s)?? ????fr.close()?? ????return??filesplit?? ?? def?sqrtimg(img):?? ????height,width=img.shape[:2]?? ????maxlenght=max(height,width)?? ????sqrtimg0=np.zeros((maxlenght,maxlenght,3),dtype='uint8')?? ?? ????sqrtimg0[(maxlenght*.5-height*.5):(maxlenght*.5+height*.5),(maxlenght*.5-width*.5):(maxlenght*.5+width*.5)]=img?? ????return??sqrtimg0?? ?? ?? def?generate_hdf5():?? ?? ????labelfile?=readdata('../data/my_alige_landmark.txt')?? ????F_imgs?=?[]?? ????F_landmarks?=?[]?? ?? ?? ????for?i,l?in?enumerate(labelfile):?? ????????imgpath='../data/'+l[0]?? ?? ????????img=cv2.imread(imgpath)?? ????????maxx=max(img.shape[0],img.shape[1])?? ????????img=sqrtimg(img)?? ????????img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)?? ????????f_face=cv2.resize(img,(39,39))?? ?????????? ????????plt.imshow(f_face,cmap='gray')?? ?? ?? ????????f_face?=?f_face.reshape((1,?39,?39))?? ????????f_landmark?=np.asarray(l[1:],dtype='float')?? ?? ????????F_imgs.append(f_face)?? ?? ?? ?????????? ????????f_landmark=f_landmark/maxx??? ????????print?f_landmark?? ????????F_landmarks.append(f_landmark)?? ?? ?? ????F_imgs,?F_landmarks?=?np.asarray(F_imgs),?np.asarray(F_landmarks)?? ?? ?? ????F_imgs?=?processImage(F_imgs)?? ????shuffle_in_unison_scary(F_imgs,?F_landmarks)?? ?? ?????? ????with?h5py.File(os.getcwd()+?'/train_data.h5',?'w')?as?f:?? ????????f['data']?=?F_imgs.astype(np.float32)?? ????????f['landmark']?=?F_landmarks.astype(np.float32)?? ?????? ????with?open(os.getcwd()?+?'/train.txt',?'w')?as?f:?? ????????f.write(os.getcwd()?+?'/train_data.h5\n')?? ????print?i?? ?? ?? if?__name__?==?'__main__':?? ????generate_hdf5()</span></span>??
利用上面的代碼,可以生成一個(gè)train.txt、train_data.h5的文件,然后在caffe的prototxt中,進(jìn)行訓(xùn)練的時(shí)候,可以用如下的代碼,作為數(shù)據(jù)層的調(diào)用:
[python]?view plaincopy
<span?style="font-family:Arial;font-size:18px;"><span?style="font-size:18px;">layer?{?? ????name:?"hdf5_train_data"?? ????type:?"HDF5Data"???? ????top:?"data"?? ????top:?"landmark"?? ????include?{?? ????????phase:?TRAIN?? ????}?? ????hdf5_data_param?{????? ????????source:?"h5py/train.txt"??? ????????batch_size:?64?? ????}?? }?? </span></span>??
上面需要注意的是,相比與lmdb的數(shù)據(jù)格式,我們需要該動(dòng)的地方,我標(biāo)注的地方就是需要改動(dòng)的地方,還有h5py不支持?jǐn)?shù)據(jù)變換。
2、h5py數(shù)據(jù)讀取
[python]?view plaincopy
<span?style="font-family:Arial;font-size:18px;">f=h5py.File('../h5py/train.h5','r')?? x=f['data'][:]?? x=np.asarray(x,dtype='float32')?? y=f['label'][:]?? y=np.asarray(y,dtype='float32')?? print?x.shape?? print?y.shape</span>??
可以通過(guò)上面代碼,查看我們生成的.h5格式文件。
在需要注意的是,我們輸入caffe的h5py圖片數(shù)據(jù)為四維矩陣(number_samples,nchannels,height,width)的矩陣,標(biāo)簽矩陣為二維(number_samples,labels_ndim),同時(shí)數(shù)據(jù)的格式需要轉(zhuǎn)成float32,用于回歸任務(wù)。
**********************作者:hjimce ? 時(shí)間:2015.10.2 ?聯(lián)系QQ:1393852684 ? 地址:http://blog.csdn.net/hjimce? ?原創(chuàng)文章,版權(quán)所有,轉(zhuǎn)載請(qǐng)保留本行信息(不允許刪除)
總結(jié)
以上是生活随笔為你收集整理的深度学习(十三)caffe之训练数据格式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。