Tensorflow C++ APIを使用してグラデーションを計算したいとします。私はtf.gradientsはPythonのAPIで動作しました:保存されたグラフに基づいてTensorflow C++ APIのグラジエントを計算する方法
import tensorflow as tf
with tf.Session() as sess:
a = tf.Variable([[5.0,1.0,2.0]], name='a')
b = tf.Variable([[9.0,2.0,0.0]], name='b')
c = tf.matmul(a, tf.transpose(b), name="c")
deriv = tf.gradients(c,a, name="deriv") #\partial c/\partial a
sess.run(tf.global_variables_initializer())
print(sess.run(deriv))
#### get the tensor by name ####
tmp = tf.get_default_graph().get_tensor_by_name("deriv/c_grad/MatMul:0")
print(sess.run(tmp))
#### save graph ####
tf.train.write_graph(sess.graph_def, './', 'graph.pb', as_text=False)
tf.train.write_graph(sess.graph_def, './', 'graph.pbtxt', as_text=True)
saver = tf.train.Saver()
saver.save(sess, "variable", global_step=0)
私はprint(sess.run(deriv))
とprint(sess.run(tmp))
両方から正しい答えを持って、graph.pb生成しました。次に、次のC++コードを使用してグラフを読み込み、Pythonで行ったのと同様の方法で勾配計算を行いました。
#include "tensorflow/core/public/session.h"
#include "tensorflow/core/platform/env.h"
#include "tensorflow/cc/framework/ops.h"
void checkStatus(const tensorflow::Status& status) {
if (!status.ok()) {
std::cout << status.ToString() << std::endl;
exit(1);
}
}
int main(int argc, char** argv) {
namespace tf = tensorflow;
tf::Session* session;
tf::Status status = tf::NewSession(tf::SessionOptions(), &session);
checkStatus(status);
tf::GraphDef graph_def;
status = ReadBinaryProto(tf::Env::Default(), "graph.pb", &graph_def);
checkStatus(status);
status = session->Create(graph_def);
checkStatus(status);
tf::Input::Initializer xi({1.0,2.0,-6.0});
tf::Input::Initializer yi({9.0,2.0,0.0});
std::vector<std::pair<tf::string, tf::Tensor>> input_tensors = {{"a", xi.tensor}, {"b", yi.tensor}};
std::vector<tf::Tensor> output_tensors;
status = session->Run(input_tensors, {"deriv/c_grad/MatMul"}, {}, &output_tensors);
checkStatus(status);
tf::Tensor output = output_tensors[0];
auto out = output.vec<float>();
std::cout << out(0) << " " << out(1) << " " << out(2) << std::endl;
session->Close();
return 0;
}
コンパイルがスムーズに走ったが、私はランタイムエラーました:
内部を:double型の出力0は、ノード_recv_b_0 = _Recvclient_terminated =真、recv_device = "/ジョブの宣言出力float型と一致していません。タスク名:0 /タスク:0/cpu:0」、send_device = "/ job:localhost/replica:0/task:0/cpu:0"、send_device_incarnation = -3399984051910545345、tensor_name = "b"、tensor_type = DT_FLOAT "deriv/c_grad/MatMul"の他に、graph.pbtxtの "deriv"に関連する他のすべての名前も試しましたが、いずれも機能しません。
私の質問はどのように勾配計算のノードを参照するのですか? Pythonは "deriv/c_grad/MatMul"を受け入れますが、C++では受け入れられません。私はまたそれを行うための一般的な方法があるかどうか疑問に思っています。ドットプロダクトではなくニューラルネットワーク出力を区別することができます。将来の入力テンソル、MatMul
はもう最後のステップにはなりません。