Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
TensorFlow C+的推理错误+;关于iOS:“;无效参数:在运行()之前未使用图形创建会话&引用; 我试图用TensorFlow的C++ API在iOS上运行模型。模型是一个SavedModel另存为.pb文件。但是,调用Session::Run()会导致以下错误:_C++_Ios_Tensorflow - Fatal编程技术网

TensorFlow C+的推理错误+;关于iOS:“;无效参数:在运行()之前未使用图形创建会话&引用; 我试图用TensorFlow的C++ API在iOS上运行模型。模型是一个SavedModel另存为.pb文件。但是,调用Session::Run()会导致以下错误:

TensorFlow C+的推理错误+;关于iOS:“;无效参数:在运行()之前未使用图形创建会话&引用; 我试图用TensorFlow的C++ API在iOS上运行模型。模型是一个SavedModel另存为.pb文件。但是,调用Session::Run()会导致以下错误:,c++,ios,tensorflow,C++,Ios,Tensorflow,“无效参数:在运行()之前未使用图形创建会话!” 在Python中,我可以使用以下代码成功地在模型上运行推理: with tf.Session() as sess: tf.saved_model.loader.load(sess, ['serve'], '/path/to/model/export') result = sess.run(['OutputTensorA:0', 'OutputTensorB:0'], feed_dict={ 'InputTensor

“无效参数:在运行()之前未使用图形创建会话!”

在Python中,我可以使用以下代码成功地在模型上运行推理:

with tf.Session() as sess:
    tf.saved_model.loader.load(sess, ['serve'], '/path/to/model/export')
    result = sess.run(['OutputTensorA:0', 'OutputTensorB:0'], feed_dict={
        'InputTensorA:0': np.array([5000.00] * 1000).reshape(1, 1000),
        'InputTensorB:0': np.array([300.00] * 1000).reshape(1, 1000)
    })
    print(result[0])
    print(result[1])
在iOS上C++,我尝试模仿这个工作片段如下:

tensorflow::Input::Initializer input_a(5000.00, tensorflow::TensorShape({1, 1000}));
tensorflow::Input::Initializer input_b(300.00, tensorflow::TensorShape({1, 1000}));

tensorflow::Session* session_pointer = nullptr;

tensorflow::SessionOptions options;
tensorflow::Status session_status = tensorflow::NewSession(options, &session_pointer);

std::cout << session_status.ToString() << std::endl; // prints OK

std::unique_ptr<tensorflow::Session> session(session_pointer);

tensorflow::GraphDef model_graph;

NSString* model_path = FilePathForResourceName(@"saved_model", @"pb");
PortableReadFileToProto([model_path UTF8String], &model_graph);

tensorflow::Status session_init = session->Create(model_graph);

std::cout << session_init.ToString() << std::endl; // prints OK

std::vector<tensorflow::Tensor> outputs;
tensorflow::Status session_run = session->Run({{"InputTensorA:0", input_a.tensor}, {"InputTensorB:0", input_b.tensor}}, {"OutputTensorA:0", "OutputTensorB:0"}, {}, &outputs);

std::cout << session_run.ToString() << std::endl; // Invalid argument: Session was not created with a graph before Run()!
tensorflow::Input::初始值设定项Input_a(5000.00,tensorflow::TensorShape({11000}));
tensorflow::Input::初始值设定项Input_b(300.00,tensorflow::TensorShape({1,1000}));
tensorflow::Session*Session_pointer=nullptr;
tensorflow::SessionOptions选项;
tensorflow::Status session\u Status=tensorflow::NewSession(选项和会话指针);

STD::CUT

这里的主要问题是,将图形导出到Python中,然后以C++的形式读取它。虽然两者都有一个

.pb
扩展名并且相似,但它们并不等同

发生的情况是,您正在使用
PortableReadFileToProto()
读取
SavedModel
,但它失败了,留下一个指向
GraphDef
对象的空指针(
model\u graph
)。因此,在执行了PortableReadFileToProto()
之后,
model_graph
仍然是一个空的但有效的,
GraphDef
,这就是为什么错误显示在运行()之前没有使用图形创建会话的原因<代码>会话->创建()成功,因为您成功创建了一个带有空图的会话

检查PortableReadFileToProto()是否失败的方法是检查其返回值。它返回一个布尔值,如果在图形中读取失败,该布尔值将为0。如果希望在此处获得描述性错误,请使用。另一种判断读取图形是否失败的方法是检查
model\u graph.node\u size()
的值。如果该值为0,则您有一个空图形,并且在中读取它失败

虽然您可以使用TensorFlow的C API通过和对
SavedModel
执行推断,但推荐的方法是使用导出图形到冻结模型,或使用写入
GraphDef
。我将用使用
tf.train.write_graph()
导出的模型演示成功的推理:

在Python中:

# Build graph, call it g
g = tf.Graph()

with g.as_default():
    input_tensor_a = tf.placeholder(dtype=tf.int32, name="InputTensorA")
    input_tensor_b = tf.placeholder(dtype=tf.int32, name="InputTensorB")
    output_tensor_a = tf.stack([input_tensor_a], name="OutputTensorA")
    output_tensor_b = tf.stack([input_tensor_b], name="OutputTensorB")

# Save graph g
with tf.Session(graph=g) as sess:
    sess.run(tf.global_variables_initializer())
    tf.train.write_graph(
        graph_or_graph_def=sess.graph_def,
        logdir='/path/to/export',
        name='saved_model.pb',
        as_text=False
    )
C++(XCODEL)

使用名称空间tensorflow;
使用名称空间std;
NSMutableArray*预测=[NSMutableArray];
Input::初始化器Input_tensor_a(1,TensorShape({1}));
Input::初始化器Input_tensor_b(2,TensorShape({1}));
会话选项;
Session*Session_指针=nullptr;
状态会话\状态=新闻会话(选项和会话\指针);
唯一的会话(会话指针);
GraphDef模型图;
string model_path=string([FilePathForResourceName(@“saved_model”,“pb”)UTF8String]);
状态加载\图形=ReadBinaryProto(Env::Default()、模型\路径和模型\图形);
状态会话\初始化=会话->创建(模型\图形);

除了上面非常全面的解释之外,还有一个补充:

@jshapy8说得对,“您必须找到包含REGISTER_OP(“YourOperation”)的.cc并将其添加到tf_OP_files.txt中”,有一个过程可以稍微简化这一点:

## build the print_selective_register_header tool. Run from tensorflow root
bazel build tensorflow/python/tools:print_selective_registration_header
bazel-bin/tensorflow/python/tools/print_selective_registration_header \
--graphs=<path to your frozen model file here>/model_frozen.pb > ops_to_register.h
但是,您可以根据自己的需要向makefile传递很多信息,我发现以下是您的最佳选择:

make -f tensorflow/contrib/makefile/Makefile \
TARGET=IOS IOS_ARCH=ARM64,x86_64 OPTFLAGS="-O3 -DANDROID_TYPES=ANDROID_TYPES_FULL -DSELECTIVE_REGISTRATION -DSUPPORT_SELECTIVE_REGISTRATION"
特别是,您在这里告诉它只编译5种体系结构中的两种,以加快编译时间(完整列表是:i386 x86_64 armv7 armv7s arm64,显然需要更长的时间)-IOS_ARCH=arm64,x86_64-然后您告诉它不要编译ANDROID_类型的_SLIM(这将给您带来上面提到的浮点/整数转换问题)最后,您告诉它提取所有必需的ops内核文件,并将它们包含在生成过程中

更新。我不知道为什么昨天这对我不起作用,但这可能是一种更干净、更安全的方法:

build_all_ios.sh OPTFLAGS="-O3 -DANDROID_TYPES=ANDROID_TYPES_FULL -DSELECTIVE_REGISTRATION -DSUPPORT_SELECTIVE_REGISTRATION"
如果要加快速度,请编辑/Makefile目录中的compile_ios_tensorflow.sh。查找以下行:

BUILD_TARGET="i386 x86_64 armv7 armv7s arm64"
并将其更改为:

BUILD_TARGET="x86_64 arm64"
BUILD_TARGET="i386 x86_64 armv7 armv7s arm64"
BUILD_TARGET="x86_64 arm64"