由於利用Pyhon來作數據的預處理比較方便,所以在data_layer選擇上,採用了MemoryDataLayer,能夠比較方便的直接用Python 根據set_input_array進行feed數據,而後再調用solver進行step就能夠了。說一下我碰到的問題,當時檢查了一下感受沒有哪裏出錯,可是報python
Segmentation Fault(Core Abort)
感受好囧,最怕這個了。通常說段錯誤都是內存錯誤,好比數組越界,無效的指針,引用被釋放的資源等等。通過一步步debug以後發現問題出如今git
solver.net.set_input_arrays
solver在將數據傳送到網絡低端的時候報錯。那麼接下來找到python
目錄下的caffe\python\caffe\_caffe.cpp
文件,這個文件是基於boost python的,用來將C++的接口導出,供python調用。進一步咱們找到相關函數github
void Net_SetInputArrays(Net<Dtype>* net, bp::object data_obj, bp::object labels_obj) { // check that this network has an input MemoryDataLayer shared_ptr<MemoryDataLayer<Dtype> > md_layer = boost::dynamic_pointer_cast<MemoryDataLayer<Dtype> >(net->layers()[0]); if (!md_layer) { throw std::runtime_error("set_input_arrays may only be called if the" " first layer is a MemoryDataLayer"); } // check that we were passed appropriately-sized contiguous memory PyArrayObject* data_arr = reinterpret_cast<PyArrayObject*>(data_obj.ptr()); PyArrayObject* labels_arr = reinterpret_cast<PyArrayObject*>(labels_obj.ptr()); CheckContiguousArray(data_arr, "data array", md_layer->channels(), md_layer->height(), md_layer->width()); CheckContiguousArray(labels_arr, "labels array", 1, 1, 1); if (PyArray_DIMS(data_arr)[0] != PyArray_DIMS(labels_arr)[0]) { throw std::runtime_error("data and labels must have the same first" " dimension"); } if (PyArray_DIMS(data_arr)[0] % md_layer->batch_size() != 0) { throw std::runtime_error("first dimensions of input arrays must be a" " multiple of batch size"); } md_layer->Reset(static_cast<Dtype*>(PyArray_DATA(data_arr)), static_cast<Dtype*>(PyArray_DATA(labels_arr)), PyArray_DIMS(data_arr)[0]); }
問題就出在了最後的一個語句數組
md_layer->Reset(static_cast<Dtype*>(PyArray_DATA(data_arr)), static_cast<Dtype*>(PyArray_DATA(labels_arr)), PyArray_DIMS(data_arr)[0]);
當執行reset MemoryDataLayer的Reset函數時出錯。於此同時在github上也發現了一樣的問題,https://github.com/BVLC/caffe/issues/2334也是由於Python MemoryDataLayer引起的段錯誤。他說到,在裏面把傳入的data和label作要給深拷貝就能夠解決,估計是運行時數據已經被釋放了,只傳了指針引起了段錯誤。網絡
解決方案:
找到caffe\src\layers\memory_data_layer.cpp
打開,給Reset函數添加相應的深拷貝代碼app
template <typename Dtype> void MemoryDataLayer<Dtype>::Reset(Dtype* data, Dtype* labels, int n) { CHECK(data); CHECK(labels); CHECK_EQ(n % batch_size_, 0) << "n must be a multiple of batch size"; // Warn with transformation parameters since a memory array is meant to // be generic and no transformations are done with Reset(). if (this->layer_param_.has_transform_param()) { LOG(WARNING) << this->type() << " does not transform array data on Reset()"; } // data_ = data; 將這裏註釋掉, // labels_ = labels; //如下部分是進行深拷貝 if(data_) delete []data_; if(labels_) delete [] labels_; data_ = new Dtype[n*size_]; labels_ = new Dtype[n * num_tasks_]; memcpy(data_, data, sizeof(Dtype)*n*size_); memcpy(labels_, labels, sizeof(Dtype) * n * num_tasks_); n_ = n; pos_ = 0; }
Ok進行修改以後,回到Caffe的根目錄,執行make all
,make test
,`make runtest
,make pycaffe
。從新編譯完成以後,從新運行就行了,繼續開始訓練。函數