简体   繁体   中英

Tensorflow C++ inference result is slightly different from Keras inference

I trained my model in Keras and I converted it to tensorflow model for inference using C++ (I didn't quantize). My inference code in C++ is straight forward.

I read image directly from file. I perform Decode png, resize and normalize operations using the following functions.

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();
}

Then I perform inference using the following code.

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;
}

Am I missing something?

I would guess that the error does not come from the execution of the graph but on the preprocessing you do on the image. For me the candidate is ops::ResizeBilinear , each library has a slightly different implementation of the bilinear interpolation so you might expect differences between tensorflow and keras.

Try to evaluate the difference using an image of the correct size in both systems, so you can avoid the interpolation. As an example, I had to reimplement my own C++ interpolation to be as close as possible to the one i had use in python.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM