Python 张量流C++;推理结果与Keras推理略有不同 我在KRAS中训练了模型,并用C++(未量化)将其转换为TysFooRoad模型进行推理。我的C++推理代码是直接的。p>

Python 张量流C++;推理结果与Keras推理略有不同 我在KRAS中训练了模型,并用C++(未量化)将其转换为TysFooRoad模型进行推理。我的C++推理代码是直接的。p>,python,c++,tensorflow,keras,Python,C++,Tensorflow,Keras,我直接从文件中读取图像。我使用以下函数执行解码png、调整大小和规格化操作 static Status ReadFile(Env *oEnv, const string &sFileName, Tensor *output) { uint64 nFileSize = 0; TF_RETURN_IF_ERROR(oEnv->GetFileSize(sFileName, &nFileSize)); string oFile; oFile.res

我直接从文件中读取图像。我使用以下函数执行解码png、调整大小和规格化操作

static Status ReadFile(Env *oEnv, const string &sFileName, Tensor *output)
{
    uint64 nFileSize = 0;
    TF_RETURN_IF_ERROR(oEnv->GetFileSize(sFileName, &nFileSize));

    string oFile;
    oFile.resize(nFileSize);

    std::unique_ptr<RandomAccessFile> oFileAccess;
    TF_RETURN_IF_ERROR(oEnv->NewRandomAccessFile(sFileName, &oFileAccess));

    StringPiece oData;
    TF_RETURN_IF_ERROR(oFileAccess->Read(0, nFileSize, &oData, &(oFile)[0]));

    output->scalar<string>()() = oData.ToString();
    return Status::OK();

}

//Reads a PNG image and converts it to a tensor of specified size.
Status ReadImageFromFile(const string &sFileName, const int nWidth, const int nHeight, const float fMean, const float fScale, std::vector<Tensor> *oTensor)
{
    Tensor oTInput(DT_STRING, TensorShape());
    TF_RETURN_IF_ERROR(ReadFile(Env::Default(), sFileName, &oTInput));


    auto oTRoot = Scope::NewRootScope();
    auto oInput = ops::Placeholder(oTRoot.WithOpName("input"), DT_STRING);
    std::vector<std::pair<string, Tensor>> oInputs = { {"input",oTInput} };

    Output oOpImgRead = ops::DecodePng(oTRoot.WithOpName("png_file"), oInput, ops::DecodePng::Channels(3));
    auto oTFloatConv = ops::Cast(oTRoot.WithOpName("float_conv"), oOpImgRead, DT_FLOAT);
    auto oDimExpand = ops::ExpandDims(oTRoot, oTFloatConv, 0);
    auto oResize = ops::ResizeBilinear(oTRoot, oDimExpand, ops::Const(oTRoot.WithOpName("size"), { nHeight, nWidth }));
    auto oMeanSub = ops::Sub(oTRoot, oResize, { fMean });
    auto oScale = ops::Div(oTRoot.WithOpName("output"), oMeanSub, { fScale });

    GraphDef oGraph;
    TF_RETURN_IF_ERROR(oTRoot.ToGraphDef(&oGraph));

    Session *oSess;
    NewSession(SessionOptions(), &oSess);
    TF_RETURN_IF_ERROR(oSess->Create(oGraph));
    TF_RETURN_IF_ERROR(oSess->Run({ oInputs }, { "output" }, {}, oTensor));
    return Status::OK();
}
Status ReadFile(Env*oEnv、const string和sFileName、Tensor*输出)
{
uint64 nFileSize=0;
TF_返回_IF_错误(oEnv->GetFileSize(sFileName,&nFileSize));
一串文件;
调整文件大小(n文件大小);
std::访问的唯一ptr;
TF_返回_IF_错误(oEnv->NewRandomAccessFile(sFileName,&oFileAccess));
弦片小田;
TF_返回_IF_错误(oFileAccess->Read(0,nFileSize,&oData,&oFile)[0]);
输出->标量()()=oData.ToString();
返回状态::OK();
}
//读取PNG图像并将其转换为指定大小的张量。
状态ReadImageFromFile(常量字符串和sFileName、常量整数nWidth、常量整数nHeight、常量浮点fMean、常量浮点fScale、std::vector*oTensor)
{
张量输入(DT_字符串,TensorShape());
TF_返回_IF_错误(ReadFile(Env::Default(),sFileName,&oTInput));
auto-oTRoot=Scope::NewRootScope();
auto-oInput=ops::占位符(oTRoot.WithOpName(“输入”),DT_字符串);
std::vector oInputs={{“输入”,oTInput};
输出oopimgrad=ops::DecodePng(oTRoot.WithOpName(“png_文件”),oInput,ops::DecodePng::Channels(3));
自动oTFloatConv=ops::Cast(oTRoot.WithOpName(“float_conv”)、oopimgrad、DT_float);
auto-oDimExpand=ops::ExpandDims(oTRoot,oTFloatConv,0);
auto-oResize=ops::ResizeBinlinear(oTRoot,oDimExpand,ops::Const(oTRoot.WithOpName(“size”),{nHeight,nWidth});
auto-oMeanSub=ops::Sub(oTRoot,oResize,{fMean});
auto-oScale=ops::Div(oTRoot.WithOpName(“output”),oMeanSub,{fScale});
曲线图;
TF_返回_IF_错误(oTRoot.ToGraphDef(&oGraph));
会话*oSess;
NewSession(会话选项(),&oSess);
TF_返回_IF_错误(操作系统->创建(图形));
TF_返回_IF_错误(oSess->Run({oInputs},{“output”},{},oTensor));
返回状态::OK();
}
然后,我使用以下代码执行推断

GraphDef oGraphDef;
oStatus = ReadBinaryProto(Env::Default(), "models/graph.pb", &oGraphDef);
if (!oStatus.ok())
{
    std::cout << oStatus.ToString() << std::endl;
    getchar();
    return -1;
}
std::cout << "Graph read\n";

std::vector<Tensor> oInputTensors;

oStatus = ReadImageFromFile("temp.png", 224, 224, 127.5, 255.0, &oInputTensors);
if (!oStatus.ok())
{
    std::cout << oStatus.ToString() << std::endl;
    getchar();
    return -1;
}
std::cout << "Input image read\n";
//Create Session
Session *oSess;
oStatus = NewSession(SessionOptions(), &oSess);
if (!oStatus.ok())
{
    std::cout << oStatus.ToString() << std::endl;
    getchar();
    return -1;
}
oStatus = oSess->Create(oGraphDef);
if (!oStatus.ok())
{
    std::cout << oStatus.ToString() << std::endl;
    getchar();
    return -1;
}
std::vector<Tensor> oOutputs;
oStatus = oSess->Run({ { "input_input",oInputTensors[0] } }, { "activation_output/Relu" }, {}, &oOutputs);
if (!oStatus.ok())
{
    std::cout << oStatus.ToString() << std::endl;
    getchar();
    return -1;
}
GraphDef;
oStatus=ReadBinaryProto(Env::Default(),“models/graph.pb”,&graphdef);
如果(!oStatus.ok())
{

std::cout我猜错误不是来自图形的执行,而是来自图像的预处理。对于我来说,候选对象是
ops::ResizeBilinear
,每个库都有一个稍微不同的双线性插值实现,因此您可能会预期tensorflow和keras之间的差异


试着用两个系统中的正确大小的图像来评估差异,这样你就可以避免插值。作为一个例子,我必须重新实现我自己的C++插值,尽可能地接近我在Python中使用的一个。“略有不同"意思是,听起来你的解析/数学/舍入可以为不同的浮点处理带来细微的差别。@ Max LangHOF就是我所想的。但是有时,结果会超过40%。Python确实使用TysFoodsC++ API。浮点错误不应该是一样的吗?@你的KARAS模型?@o.pb文件。(“graph.pb”)那么您的示例不可复制谢谢。调整图像大小是问题所在。