在C /OBJ-C 中运行Tensorflow分类器模型与Python的结果不同
Running Tensorflow Classifier Model in C++/Obj-C++ results in different result than Python
ive通过Tensorflow的诗人教程进行了InceptionV3模型,并且可以在我的训练有素的数据和新数据上成功运行Label_image.py,并以良好的精度获得正确的标签。太棒了!
如果我通过Mac OBJ-C 应用程序运行模型,我的标签大不相同。
例如 - 我的培训是对哪种视频框架进行分类,(极端闭合,近距离,中等,长,极端长(用于分类视频编辑内容。
label_image.py将视频中的框架分类为85%的可能关闭。我的C /OBJ-C应用程序以相同的框架运行,将其分类为超过60%
两者都在使用AVX/SIMD/FMA优化的Mac OS X CPU上运行相同版本的TensorFlow(1.1(。
我的应用程序管道:
我有一个BGR订购的OpenCV垫图像,我可以在其他地方成功使用,并从中获得理智的结果。我从OS X CVPixelBufferRef创建此CV垫,映射到BGRA CV垫子,如:
cv::cvtColor(BGRAImage, frameMat, cv::COLOR_BGRA2BGR);
i通过从iOS贡献示例中借来的代码将BGR CV MAT(名为Framemat(喂入张量,例如:
void* baseAddress = (void*)frameMat.datastart;
size_t width = (size_t) frameMat.cols;
size_t height = (size_t) frameMat.rows;
size_t bytesPerRow = (size_t) frameMat.cols * 3; // (BGR)
const int wanted_input_width = 299;
const int wanted_input_height = 299;
const int wanted_input_channels = 3;
const float input_mean = 128.0f;
const float input_std = 128.0f;
resized_tensor = tensorflow::Tensor( tensorflow::DT_FLOAT, tensorflow::TensorShape({1, wanted_input_height, wanted_input_width, wanted_input_channels}));
auto image_tensor_mapped = resized_tensor.tensor<float, 4>();
tensorflow::uint8 *in = sourceStartAddr;
float *out = image_tensor_mapped.data();
for (int y = 0; y < wanted_input_height; ++y)
{
float *out_row = out + (y * wanted_input_width * wanted_input_channels);
for (int x = 0; x < wanted_input_width; ++x)
{
const int in_x = (y * (int)width) / wanted_input_width;
const int in_y = (x * image_height) / wanted_input_height;
tensorflow::uint8 *in_pixel = in + (in_y * width * (image_channels)) + (in_x * (image_channels));
float *out_pixel = out_row + (x * wanted_input_channels);
// Interestingly the iOS example uses BGRA and DOES NOT re-order tensor channels to RGB <-> BGR
// Matching that.
out_pixel[0] = ((float)in_pixel[0] - (float)input_mean) / (float)input_std;
out_pixel[1] = ((float)in_pixel[1] - (float)input_mean) / (float)input_std;
out_pixel[2] = ((float)in_pixel[2] - (float)input_mean) / (float)input_std;
}
}
我的会话创建代码:
tensorflow::Status load_graph_status = ReadBinaryProto(tensorflow::Env::Default(), [inception2015GraphPath cStringUsingEncoding:NSUTF8StringEncoding], &inceptionGraphDef);
if (load_graph_status.ok())
{
tensorflow::SessionOptions options;
inceptionSession = std::unique_ptr<tensorflow::Session>(tensorflow::NewSession(options));
tensorflow::Status session_create_status = inceptionSession->Create(inceptionGraphDef);
}
运行图:
tensorflow::Status run_status = inceptionSession->Run({ {input_layer, resized_tensor} }, {feature_layer, final_layer}, {}, &outputs);
并拔出标签/特征向量(倒数第二层(
NSMutableArray* outputLabels = [NSMutableArray arrayWithCapacity:self.labelsArray.count];
NSMutableArray* outputScores = [NSMutableArray arrayWithCapacity:self.labelsArray.count];
// 1 = labels and scores
auto predictions = outputs[1].flat<float>();
for (int index = 0; index < predictions.size(); index += 1)
{
const float predictionValue = predictions(index);
NSString* labelKey = self.labelsArray[index % predictions.size()];
NSNumber* currentLabelScore = self.averageLabelScores[labelKey];
NSNumber* incrementedScore = @([currentLabelScore floatValue] + predictionValue );
self.averageLabelScores[labelKey] = incrementedScore;
[outputLabels addObject:labelKey];
[outputScores addObject:@(predictionValue)];
}
// 0 is feature vector
tensorflow::Tensor feature = outputs[0];
int64_t numElements = feature.NumElements();
tensorflow::TTypes<float>::Flat featureVec = feature.flat<float>();
NSMutableArray* featureElements = [NSMutableArray arrayWithCapacity:numElements];
for(int i = 0; i < numElements; i++)
{
[featureElements addObject:@( featureVec(i) ) ];
}
if(self.averageFeatureVec == nil)
{
self.averageFeatureVec = featureElements;
}
else
{
// average each vector element with the prior
for(int i = 0; i < featureElements.count; i++)
{
float a = [featureElements[i] floatValue];
float b = [self.averageFeatureVec[i] floatValue];
self.averageFeatureVec[i] = @( MAX(a,b)) ;
}
}
return @{ kSynopsisStandardMetadataFeatureVectorDictKey : featureElements ,
@"Labels" : outputLabels,
@"Scores" : outputScores,
};
我试图研究张量订购(NHWC(,并检查了张量创建代码,但我可能缺少其他人明显的东西。我还尝试更改频道顺序,但无济于事。
任何洞察力都会非常有帮助。谢谢!
我通常用于调试此类问题的方法是:
- 首先从我知道有效的示例输入中保存原始的c值。例如,请确保Label_image与您的新训练模型一起使用,然后使用伪代码来写出您从
input_layer->flat<float>().data()
获得的float*数组:
float* input_data = input_layer->flat<float>().data();
int input_data_count = input_layer->flat<float>().size();
printf("float g_test_input[]={n");
for (int i = 0; i < input_data_count; ++i) {
printf(" %f,n", input_data[i]);
}
printf("};n");
-
您应该以一个大型数组来复制到新代码中。覆盖要测试的代码中所拥有的任何输入。现在运行它,您应该看到与从label_image看到的相同输出。如果您不这样做,您知道要加载的模型有所不同。如果输出相同,则您知道输入预处理不同。
-
假设是错误的预处理,我的下一步是尝试从磁盘加载图像。iOS示例代码在简单示例中做到了这一点。将您的一些预期输入保存到图像文件中,然后确保Label_image和您的代码都会产生相同的结果。
所以这个很棘手。
我没有提及我在重新培训图上运行了Graph_transform工具 - 并且正在运行量化权重以降低图形的大小。过去,我根本没有这个混乱的分类分数有问题,但是显然这引起了问题。
使用图形转换调用的上述代码未经量化权重解决问题。
- 为什么"do while"循环不断退出,即使条件计算结果为 false?
- valgrind-hellgrind与泄漏检查的结果不同
- Tensorflow对象检测在Python和C++(OpenCV)之间有不同的结果
- 将 c++-Programm 的结果导入 python
- 为什么同一个逻辑方程在python和c++中返回两个不同的结果
- xgboost C API 不会产生与 Python 相同的结果
- 在C /OBJ-C 中运行Tensorflow分类器模型与Python的结果不同
- python 和 c++ 的结果对于嵌套的 for 语句是不同的
- C++(LAPACK,sgels)和Python(Numpy,lstsq)结果之间的差异
- 相同的算术运算在 C++ 和 Python 中给出不同的结果
- 比较CPP和Python上的程序结果
- (欧拉计划#3)试图将Python中的解决方案复制到C++,结果非常糟糕,不知道如何
- Python和C++使用OpenCV计算基本矩阵的结果不同
- Python vs. c++.不同的结果
- 当计算SHA-1摘要时,Python和c++的结果不同
- Python使用ctypes传递char *数组并填充结果
- Murmurhash3的Javascript实现,给出与Murmurhash3相同的结果.cpp Python的sklearn中可用的transform使用Murmurhash3
- 如何在C或c++中获得与Java中的toLowerCase或Python中的string.lower()相同的结果
- 从Excel VBA/Python调用c++ dll时返回不同的结果
- 将 python 结果传递到C++列表框