正常的CNN,其输入是图像,其输出是一个label整数,其正是用Caffe的底层数据Datum(Image,LMDB,LevelDB的基础)来表示
message Datum {
optional int32 channels = 1;
optional int32 height = 2;
optional int32 width = 3;
// the actual image data, in bytes
optional bytes data = 4;
optional int32 label = 5;
// Optionally, the datum could also hold float data.
repeated float float_data = 6;
// If true data contains an encoded image that need to be decoded
optional bool encoded = 7 [default = false];
}
当数据读入的时候,其是通过
CVMatToDatum(cv_img, datum);
datum->set_label(label);
所以,Image输入,LevelDB输入,LMDB输入,不能解决多输出问题(改动代码,对其它代码的影响比较大)
在HDF5作为输入中,其是接受多输出的,但其只能接受double和float的输入,但是我们的图像一般是0–255的,所以其实只要用int8 就可以满足了,可以节省4-8倍的空间。
而hdf5只能是float和double的原因在于,其是直接将4维数组转化为blob数据结构。
blob->Reshape(
dims[0],
(dims.size() > 1) ? dims[1] : 1,
(dims.size() > 2) ? dims[2] : 1,
(dims.size() > 3) ? dims[3] : 1);
虽然Blob是一个模板,但是,其unsigned int 和int的类型都没有实现
template <> void Blob<unsigned int>::Update()
{ NOT_IMPLEMENTED; }
template <> void Blob<int>::Update()
{ NOT_IMPLEMENTED; }
没有实现的原因,是因为输入数据和里面的所有的中间数据都采用相同的结构(Blob),所以如果用int来保存的化,就没有办法进行求梯度等操作。
//The "update" method is used for parameter blobs in a Net, which are stored
//as Blob<float> or Blob<double> -- hence we do not define it for
//Blob<int> or Blob<unsigned int>.
template <> unsigned int Blob<unsigned int>::asum_data() const
{
NOT_IMPLEMENTED;
return 0;
}
template <> int Blob<int>::asum_data() const
{
NOT_IMPLEMENTED;
return 0;
}
template <> unsigned int Blob<unsigned int>::asum_diff() const
{
NOT_IMPLEMENTED;
return 0;
}
template <> int Blob<int>::asum_diff() const
{
NOT_IMPLEMENTED;
return 0;
}
template <> unsigned int Blob<unsigned int>::sumsq_data() const
{
NOT_IMPLEMENTED;
return 0;
}
template <> int Blob<int>::sumsq_data() const
{
NOT_IMPLEMENTED;
return 0;
}
template <> unsigned int Blob<unsigned int>::sumsq_diff() const
{
NOT_IMPLEMENTED;
return 0;
}
template <> int Blob<int>::sumsq_diff() const
{
NOT_IMPLEMENTED;
return 0;
}
template <> void Blob<unsigned int>::scale_data(unsigned int scale_factor)
{
NOT_IMPLEMENTED;
}
template <> void Blob<int>::scale_data(int scale_factor)
{
NOT_IMPLEMENTED;
}
template <> void Blob<unsigned int>::scale_diff(unsigned int scale_factor)
{
NOT_IMPLEMENTED;
}
template <> void Blob<int>::scale_diff(int scale_factor)
{
NOT_IMPLEMENTED;
}
HDF5最大的缺点在于,因为其是直接将数据转化为Blob,所以其不能利用所有的DataTransformer功能,因为数据转换层又是基于Datum或者图像cv::Mat来转换.(最近加了直接对Blob的转换)
解决方案:
1. 自己添加一层DataBlob层来实现。
2. 直接存储uint8格式,HDF5输入的时候,强制转化为float格式即可。
时间: 2024-10-16 10:07:41