最近用caffe做了一下regression問題,先用data layer中的data,float_data試了一下,data用來存放圖片,float_data存放regression的values,label存放標簽,發現不行,因為float_data和label這倆是指向同一塊內存,兩者不能共存,除非改caffe源碼。我又仔細看了一下caffe的源碼,發現我這個地方說的不對,具體來講,caffe讀取image和label是這樣一個流程:
1.編寫程序將image和label轉換成Datum格式,並寫入lmdb
2.Data layer從lmdb中讀取Datum格式的數據,然后轉化成一個Batch
3.從Batch里面把image和label的數據復制到top的內存或顯存
上述的2,3步可以查看data_layer.cpp,base_data_layer.cpp和base_data_layer.cu這三個文件,里面和float_data半點關系都沒有,所以就算你把regression values保存在Datum的float_data里面,Data layer也不會把它讀出來的。我目前想到的辦法只有兩種,要么改caffe源碼,要么lmdb和hdf5一起用,源碼怕改出錯,就嘗試了一下hdf5格式做輸入,雖然搞定了,但也有坑。
說一下怎么把數據寫入hdf5文件,我用的是python,numpy格式的數組可以直接存放進去,方法如下:
#1. 先創建一個空的numpy數組
hdf_data = np.zeros((len(all_samples), num), dtype=np.float32) #2. 填充hdf_data
# 3.打開h5文件然后寫入hdf_data
h5_file = h5py.File(h5_path, 'w') h5_file.create_dataset('hdf_data', data=hdf_data) h5_file.close() # 把h5文件路徑寫到一個txt中
h5txt_file = open(h5txt_path, 'w') h5txt_file.write(h5_path) h5txt_file.close()
在定義網絡的prototxt文件中,這樣使用
layer { name: "hdf5_data" type: "HDF5Data" top: "hdf_data" include { phase: TRAIN } hdf5_data_param { source: "your_h5txt_file_path" batch_size: 1024 } }
其中source是那個只有一行的txt的路徑。top是你需要使用的h5中保存的數據塊名稱。
需要注意的是,如果是圖像數據,預處理要先做,再存進h5文件,因為HDF5Data layer不支持預處理功能。另外這里有個坑,盡量不要把圖片放在h5文件中,因為HDF5Data layer不能按照batch來讀取數據,只能一次性把所有數據從h5文件中讀到內存中,如果h5文件非常大,就會報錯,具體是掛在HDF5Data的實現代碼中了,有一個數據大小的斷言。所以既不想改caffe代碼又想保證訓練程序能跑起來的方法如下:
把regression values按照hdf5格式存放,image和label按照正常數據存放在lmdb即可。在定義網絡的prototxt中可以讀取不同來源的數據,例如下面這種方法:
layer {
name: "lmdb_data"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
data_param {
source: "train_data"
batch_size: 1024
backend: LMDB
}
transform_param {
mean_value: 128
scale: 0.0078125
}
}
layer {
name: "hdf5_data"
type: "HDF5Data"
top: "bbox"
include {
phase: TRAIN
}
hdf5_data_param {
source: "hdf5_train.txt"
batch_size: 1024
}
}