-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathbasic-graphdef.cc
139 lines (109 loc) · 4.86 KB
/
basic-graphdef.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include <tensorflow/cc/ops/standard_ops.h>
#include <tensorflow/core/framework/tensor.h>
#include <tensorflow/core/public/session.h>
// So far in other examples we have executed the session
// using the scope.
//
// There is an another way of performing the same operation and that is
// by creating the GraphDef object. This method is interesting as with this
// one you can work with op names for both inputs and outputs. Also it is
// the one that is required to run a model that is stored in a file.
//
// Reality is that in the previous example there is already a graph. The
// default graph. It is being implicitly passed to all APIs in the same
// context (scope).
int main(int argc, char** argv) {
using namespace tensorflow;
using namespace tensorflow::ops;
{
// create a root scope
auto scope = Scope::NewRootScope();
auto a = Const(scope.WithOpName("A"), 23);
auto b = Const(scope.WithOpName("B"), 2);
// here we are creating two ops (Add & Sub)
// Add - a + b
// Sub - Result of (a+b) - b
//
// Here you can see that Sub requires Add operation
auto add = Add(scope.WithOpName("Add"), a, b);
auto sub = Sub(scope.WithOpName("Sub"), add, b);
// essentially we are are getting the default graph
// that gets created by the framework for the root scope
GraphDef graph;
TF_CHECK_OK(scope.ToGraphDef(&graph));
// so far in other examples we have used ClientSession
// here is another way to create the session object.
//
// While ClientSession is used to execute graph created with in
// the C++ code, it is desirable (most of the time) to load the
// serialized graph.
//
// Note that in this example we are still creating the grpah in C++. In
// other words not loading from a file.
std::unique_ptr<tensorflow::Session> session(
tensorflow::NewSession(tensorflow::SessionOptions()));
// we are binding the session to this graph
TF_CHECK_OK(session->Create(graph));
std::vector<Tensor> outputs;
// This is where you will see differences between ClientSession & Session
// more clearly
//
// The Run method of Session is quite different from that of ClientSession
//
// Here instead of providing the final node of the constructed graph as the
// input we would supply the Tensor values as the input. To be more clear,
// a vector of pairs that provide the names of the inputs and their
// corresponing value. That said, in this particular example the inputs (A &
// B) are constants so we do not need to specify them.
//
// This is why the first argument of Run is {}
// The second argument is the names of the output nodes that you want to
// extract
TF_CHECK_OK(session->Run({}, {"Sub"}, {}, &outputs));
std::cout << "Size of outputs -> " << outputs.size() << std::endl;
std::cout << "DebugString Sub -> " << outputs[0].DebugString() << std::endl;
//
// What if we wanted the outputs of Add & Sub. Note that Add is not
// necessarily the last node in our graph but it is still possible to
// extract the value of A node. Simply specify the names of the output nodes
// that you want
outputs.clear();
TF_CHECK_OK(session->Run({}, {"Add", "Sub"}, {}, &outputs));
std::cout << "Size of outputs -> " << outputs.size() << std::endl;
std::cout << "DebugString Add -> " << outputs[0].DebugString() << std::endl;
std::cout << "DebugString Sub -> " << outputs[1].DebugString() << std::endl;
}
{
// this is very similar example as above but in this case
// we intend to also supply the values of the inputs i.e. not use
// Consts but Placeholders
auto scope = Scope::NewRootScope();
auto a = Placeholder(scope.WithOpName("A"), DT_INT32);
auto b = Placeholder(scope.WithOpName("B"), DT_INT32);
auto add = Add(scope.WithOpName("Add"), a, b);
GraphDef graph;
TF_CHECK_OK(scope.ToGraphDef(&graph));
std::unique_ptr<tensorflow::Session> session(
tensorflow::NewSession(tensorflow::SessionOptions()));
// we are binding the session to this graph
TF_CHECK_OK(session->Create(graph));
std::vector<Tensor> outputs;
// create two tensors
auto inputA = Tensor(DT_INT32, TensorShape({}));
auto inputB = Tensor(DT_INT32, TensorShape({}));
// set their values
inputA.scalar<int>()() = 10;
inputB.scalar<int>()() = 20;
// This is where you would want to pay attention to
// Here we are specifying the inputs using the name
// of the nodes (see how Placeholders were created)
std::vector<std::pair<string, tensorflow::Tensor>> inputs = {
{"A", inputA},
{"B", inputB},
};
TF_CHECK_OK(session->Run(inputs, {"Add"}, {}, &outputs));
std::cout << "Size of outputs -> " << outputs.size() << std::endl;
std::cout << "DebugString Add -> " << outputs[0].DebugString() << std::endl;
}
return 0;
}