gpt4 book ai didi

c++ - 使用 Caffe 内存层不会产生一致且确定的结果

转载 作者:太空狗 更新时间:2023-10-29 21:38:27 25 4
gpt4 key购买 nike

我在 Windows 7 64 位机器上使用 Windows 的 Caffe 框架(从 here 下载)。我在 Visual Studio Community 2013 中使用 C++。我使用预训练的 GoogLeNet 模型提取 loss1-fc 层输出以用作每个图像的特征向量。到目前为止一切顺利。

最近我尝试更改我的软件以用于视频帧。所以我将第一层从 ImageData 层更改为 Memory 层,这样我就可以向 Caffe 发送一个 OpenCV 垫的 vector ,而不是将每个帧写入磁盘并将文件列表发送到 Caffe 的幼稚方法。

现在,我注意到对于相同的图像我不会得到相同的结果!使用 ImageData 层时,没有这样的东西。

我使用 CPU(没有 Cudnn,没有 GPU)。

我用于特征提取的函数如下:

void feature_extraction_pipeline_memory(boost::shared_ptr<Net<Dtype>> feature_extraction_net, vector<cv::Mat> imgs, vector<int> labels, float** blobFeats, vector<string> blob_names){

boost::dynamic_pointer_cast<caffe::MemoryDataLayer<float>>(feature_extraction_net->layers()[0])->AddMatVector(imgs, labels);

size_t num_mini_batches = imgs.size();
size_t num_features = blob_names.size();
int dim_features;
int batch_size;
vector<Blob<float>*> input_vec;
vector<int> image_indices(num_features, 0);

for (size_t batch_index = 0; batch_index < num_mini_batches; ++batch_index) {
feature_extraction_net->Forward(input_vec);
for (size_t i = 0; i < num_features; ++i) {
const boost::shared_ptr<Blob<Dtype>> feature_blob = feature_extraction_net->blob_by_name(blob_names[i]);
batch_size = feature_blob->num();
dim_features = feature_blob->count() / batch_size;
const Dtype* feature_blob_data;
for (size_t n = 0; n < batch_size; ++n) {
feature_blob_data = feature_blob->cpu_data() + feature_blob->offset(n);
for (size_t d = 0; d < dim_features; ++d)
blobFeats[i][(image_indices[i] * dim_features) + d] = feature_blob_data[d];

++image_indices[i];
} // n < batch_size
} // i < num_features
} // batch_index < num_mini_batches
}

imgs vector 是 mat 的 vector 。 labels 是一个 int vector ,全部设置为 0。一旦将它们添加到 vector 中,我将所有图像再次写入磁盘。我检查了一下,没有问题。所以加载图像时没有错。顺便说一句,我使用 OpenCV 3.1。

GoogLeNet prototxt文件中的内存层声明如下:

layer {
name: "data"
type: "MemoryData"
top: "data"
top: "label"
memory_data_param {
batch_size: 1
channels: 3
height: 227
width: 227
}
transform_param {
crop_size: 227
mirror: true
mean_file: "model_googlenet_mem/imagenet_mean.binaryproto"
}
include: { phase: TEST }
}

并且是第一层。

我为每个图像打印前 10 个值。请注意,图像 0、1、2、3 是复制的完全相同的文件,同样适用于 6、7 和 8 图像。

1st run:
0.jpg :: 3.149, 0.000, 0.000, 0.000, 1.586, 0.000, 0.000, 0.755, 0.000, 4.749,
1.jpg :: 2.680, 0.000, 0.000, 0.560, 0.970, 0.000, 0.000, 1.083, 0.000, 4.420,
2.jpg :: 2.680, 0.000, 0.000, 0.560, 0.970, 0.000, 0.000, 1.083, 0.000, 4.420,
3.jpg :: 2.680, 0.000, 0.000, 0.560, 0.970, 0.000, 0.000, 1.083, 0.000, 4.420,
4.jpg :: 3.957, 0.000, 0.000, 0.000, 0.868, 0.000, 0.000, 0.000, 0.000, 6.396,
5.jpg :: 3.179, 0.000, 0.000, 0.000, 0.906, 0.000, 0.000, 0.000, 0.000, 5.508,
6.jpg :: 4.951, 0.000, 0.000, 0.000, 0.000, 0.343, 2.993, 0.000, 0.000, 0.000,
7.jpg :: 4.567, 0.000, 0.000, 0.000, 0.000, 1.251, 2.446, 0.000, 0.000, 0.000,
8.jpg :: 4.951, 0.000, 0.000, 0.000, 0.000, 0.343, 2.993, 0.000, 0.000, 0.000,
9.jpg :: 5.678, 0.000, 0.000, 2.010, 0.000, 1.064, 2.412, 0.000, 0.000, 0.000,

第二次运行:

0.jpg ::  2.680, 0.000, 0.000, 0.560, 0.970, 0.000, 0.000, 1.083, 0.000, 4.420,
1.jpg :: 2.680, 0.000, 0.000, 0.560, 0.970, 0.000, 0.000, 1.083, 0.000, 4.420,
2.jpg :: 3.149, 0.000, 0.000, 0.000, 1.586, 0.000, 0.000, 0.755, 0.000, 4.749,
3.jpg :: 2.680, 0.000, 0.000, 0.560, 0.970, 0.000, 0.000, 1.083, 0.000, 4.420,
4.jpg :: 3.957, 0.000, 0.000, 0.000, 0.868, 0.000, 0.000, 0.000, 0.000, 6.396,
5.jpg :: 2.928, 0.000, 0.000, 0.000, 0.769, 0.000, 0.000, 0.000, 0.000, 5.552,
6.jpg :: 4.567, 0.000, 0.000, 0.000, 0.000, 1.251, 2.446, 0.000, 0.000, 0.000,
7.jpg :: 4.567, 0.000, 0.000, 0.000, 0.000, 1.251, 2.446, 0.000, 0.000, 0.000,
8.jpg :: 4.951, 0.000, 0.000, 0.000, 0.000, 0.343, 2.993, 0.000, 0.000, 0.000,
9.jpg :: 5.678, 0.000, 0.000, 2.010, 0.000, 1.064, 2.412, 0.000, 0.000, 0.000,

相同图像和不同运行的图层输出不同!当对 ImageData 层使用相同的过程时,就没有这样的问题。此外,该问题也适用于其他层的输出,例如 loss3/classifier。因此,我怀疑 MemoryLayer 实现中可能存在错误。

有没有人注意到这种奇怪的行为?我读到 cudnn 可能会产生不确定的结果,但我在 CPU 上运行了我的模型。欢迎对此有任何想法。

最佳答案

我发现出了什么问题,我会在这里发布答案以帮助其他人。

事实证明,GoogLeNet 要求输入图像的大小为 224x224x3,并且您不能在 TEST 阶段减去均值。因此,通过将 .prototxt 文件中的内存层定义更改为:

name: "GoogleNet"
layer {
name: "data"
type: "MemoryData"
top: "data"
top: "label"
memory_data_param {
batch_size: 1
channels: 3
height: 224
width: 224
}
}
...

我得到了预期的结果。非常感谢@Miki 指出关于他们的 dnn 模块的 OpenCV 教程,这帮助我澄清了这一点。

关于c++ - 使用 Caffe 内存层不会产生一致且确定的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35481805/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com