C ++でGoogleの新しいTensorflowライブラリを使い始めたいと思っています。Webサイトとドキュメントは、プロジェクトのC ++ APIを構築する方法の点で本当に不明確であり、どこから始めればよいかわかりません。
より経験のある人がtensorflowのC ++ APIを使用するためのガイドを見つけて共有することで手助けできますか?
C ++でGoogleの新しいTensorflowライブラリを使い始めたいと思っています。Webサイトとドキュメントは、プロジェクトのC ++ APIを構築する方法の点で本当に不明確であり、どこから始めればよいかわかりません。
より経験のある人がtensorflowのC ++ APIを使用するためのガイドを見つけて共有することで手助けできますか?
回答:
私が見つけたTensorflow C ++ APIを使用する別の方法は、cppflowを使用することです。
これは、Tensorflow C APIの軽量C ++ラッパーです。非常に小さな実行可能ファイルを取得し、libtensorflow.so
すでにコンパイルされたファイルにリンクします。使用例もあり、Bazelの代わりにCMAKEを使用します。
開始するには、こちらの手順に従って、 Githubからソースコードをダウンロードする必要があります(Bazelと最新バージョンのGCC が必要です)。
C ++ API(およびシステムのバックエンド)はにありtensorflow/core
ます。現在、C ++セッションインターフェイスとC APIのみがサポートされています。これらのいずれかを使用して、Python APIを使用して構築され、GraphDef
プロトコルバッファーにシリアル化されたTensorFlowグラフを実行できます。C ++でグラフを構築するための実験的な機能もありますが、これは現在、Python APIほど完全には機能していません(たとえば、現在のところ自動微分のサポートはありません)。C ++で小さなグラフを作成するサンプルプログラムは、こちらにあります。
C ++ APIの2番目の部分は、新しいを追加するためのAPIですOpKernel
。これは、CPUおよびGPUの数値カーネルの実装を含むクラスです。これらをでビルドする方法の例や、C ++で新しいopを追加するためtensorflow/core/kernels
のチュートリアルがあります。
@mrryの投稿に追加するために、C ++ APIでTensorFlowグラフをロードする方法を説明するチュートリアルをまとめました。これは非常に最小限であり、すべての要素がどのように組み合わされるかを理解するのに役立ちます。ここにその肉があります:
要件:
フォルダー構造:
tensorflow/tensorflow/|project name|/
tensorflow/tensorflow/|project name|/|project name|.cc (e.g. https://gist.github.com/jimfleming/4202e529042c401b17b7)
tensorflow/tensorflow/|project name|/BUILD
構築:
cc_binary(
name = "<project name>",
srcs = ["<project name>.cc"],
deps = [
"//tensorflow/core:tensorflow",
]
)
おそらく回避策がある2つの警告:
https://medium.com/@jimfleming/loading-a-tensorflow-graph-with-the-c-api-4caaff88463f
./loader
するとエラーが発生しますNot found: models/train.pb
。
Bazelでのプロジェクトのビルドと大きなバイナリの生成の両方を回避したい場合は、CMakeでTensorFlow C ++ライブラリの使用方法を指示するリポジトリを作成しました。あなたはここでそれを見つけることができます。一般的なアイデアは次のとおりです。
tensorflow/BUILD
(提供されているものにはすべてのC ++機能が含まれているわけではありません)。まず、protobuf
およびをインストールした後eigen
、Tensorflowをビルドします。
./configure
bazel build //tensorflow:libtensorflow_cc.so
次に、次のインクルードヘッダーと動的共有ライブラリを/usr/local/lib
andにコピーします/usr/local/include
。
mkdir /usr/local/include/tf
cp -r bazel-genfiles/ /usr/local/include/tf/
cp -r tensorflow /usr/local/include/tf/
cp -r third_party /usr/local/include/tf/
cp -r bazel-bin/libtensorflow_cc.so /usr/local/lib/
最後に、例を使用してコンパイルします。
g++ -std=c++11 -o tf_example \
-I/usr/local/include/tf \
-I/usr/local/include/eigen3 \
-g -Wall -D_DEBUG -Wshadow -Wno-sign-compare -w \
-L/usr/local/lib/libtensorflow_cc \
`pkg-config --cflags --libs protobuf` -ltensorflow_cc tf_example.cpp
スタンドアロンパッケージでTensorflow c ++ apiを使用することを考えている場合、使用できるc ++バージョンをビルドするには、おそらくtensorflow_cc.so(ac apiバージョンtensorflow.soもあります)が必要になります。
bazel build -c opt //tensorflow:libtensorflow_cc.so
注1:組み込みサポートを追加する場合は、このフラグを次のように追加できます。 --copt=-msse4.2 --copt=-mavx
注2:プロジェクトでOpenCV を使用することを検討している場合、両方のライブラリを一緒に使用すると問題が発生し(テンソルフローの問題)、を使用する必要があります--config=monolithic
。
ライブラリをビルドしたら、プロジェクトに追加する必要があります。これを行うには、次のパスを含めることができます。
tensorflow
tensorflow/bazel-tensorflow/external/eigen_archive
tensorflow/bazel-tensorflow/external/protobuf_archive/src
tensorflow/bazel-genfiles
ライブラリをプロジェクトにリンクします。
tensorflow/bazel-bin/tensorflow/libtensorflow_framework.so (unused if you build with --config=monolithic)
tensorflow/bazel-bin/tensorflow/libtensorflow_cc.so
また、プロジェクトをビルドするときは、コンパイラーにc ++ 11標準を使用することも指定する必要があります。
補足:tensorflowバージョン1.5に関連するパス(バージョンで変更されているかどうかを確認する必要がある場合があります)。
また、このリンクは、このすべての情報を見つけるのに大いに役立ちました:リンク
tensorflow/bazel-tensorflow/external/com_google_absl
このShellScriptを使用して、依存関係の(ほとんど)をインストールし、複製、ビルド、コンパイルして、必要なすべてのファイルを../src/includes
フォルダーに取得できます。
https://github.com/node-tensorflow/node-tensorflow/blob/master/tools/install.sh
CMakeを使用してもかまわない場合は、TF C ++ APIをビルドしてインストールするtensorflow_ccプロジェクトと、リンクできる便利なCMakeターゲットがあります。プロジェクトのREADMEには、サンプルと簡単にフォローできるDockerfileが含まれています。
Tensorflowを自分でビルドしたくなく、オペレーティングシステムがDebianまたはUbuntuの場合は、Tensorflow C / C ++ライブラリを含むビルド済みパッケージをダウンロードできます。このディストリビューションは、CPUによるC / C ++推論に使用できます。GPUサポートは含まれていません。
https://github.com/kecsap/tensorflow_cpp_packaging/releases
Tensorflow(TFLearn)でチェックポイントをフリーズし、C / C ++ APIで推論するためにこのモデルをロードする方法が書かれた指示があります。
https://github.com/kecsap/tensorflow_cpp_packaging/blob/master/README.md
注意:私はこのGithubプロジェクトの開発者です。
私はハック/回避策を使用して、TFライブラリ全体を自分でビルドする必要がないようにしています(これにより、時間(3分で設定されます)、ディスク領域、インストールする開発依存関係、および結果のバイナリのサイズの両方が節約されます)。正式にはサポートされていませんが、すぐに利用したい場合は問題なく機能します。
TFをpip(pip install tensorflow
またはpip install tensorflow-gpu
)からインストールします。次に、そのライブラリ_pywrap_tensorflow.so
(TF 0. *-1.0)または_pywrap_tensorflow_internal.so
(TF 1.1+)を見つけます。私の場合(Ubuntu)にあり/usr/local/lib/python2.7/dist-packages/tensorflow/python/_pywrap_tensorflow.so
ます。次にlib_pywrap_tensorflow.so
、ビルドシステムが見つけた場所(たとえば/usr/lib/local
)で呼び出されるこのライブラリへのシンボリックリンクを作成します。接頭辞lib
は重要です!別のlib*.so
名前を付けることもできます。呼び出すとlibtensorflow.so
、TFで動作するように作成された他のプログラムとの互換性が向上する場合があります。
次に、慣れているようにC ++プロジェクトを作成します(CMake、Make、Bazelなど)。
そして、このライブラリにリンクするだけで、プロジェクトでTFを使用できるようになります(また、python2.7
ライブラリにリンクする必要があります)。CMakeでは、たとえばを追加するだけtarget_link_libraries(target _pywrap_tensorflow python2.7)
です。
C ++ヘッダーファイルは、このライブラリの周囲、たとえばにあり/usr/local/lib/python2.7/dist-packages/tensorflow/include/
ます。
繰り返しますが、この方法は公式にはサポートされておらず、さまざまな問題が発生する可能性があります。ライブラリは、たとえばprotobufに対して静的にリンクされているようです。そのため、奇妙なリンク時または実行時の問題で実行される可能性があります。しかし、保存されたグラフをロードし、重みを復元して推論を実行できます。これは、IMOがC ++で最も必要な機能です。
undefined reference to 'PyType_IsSubtype'
python2.7
ライブラリにもリンクする必要があります...それに応じて投稿を編集します。
Tensorflow自体は、C ++ APIに関する非常に基本的な例のみを提供します。
これは、データセットの例、rnn、lstm、cnn、およびその他のtensorflow c ++の例を含む優れたリソース
です
上記の回答は、ライブラリの構築方法を示すのに十分ですが、ヘッダーを収集する方法はまだトリッキーです。ここで、必要なヘッダーをコピーするために使用する小さなスクリプトを共有します。
SOURCE
最初のパラメータです。これはテンソルフローのソース(ビルド)ディレクトリです。
DST
はinclude directory
収集されたヘッダーを保持する2番目のパラメーターです。(例:cmakeでinclude_directories(./collected_headers_here)
)。
#!/bin/bash
SOURCE=$1
DST=$2
echo "-- target dir is $DST"
echo "-- source dir is $SOURCE"
if [[ -e $DST ]];then
echo "clean $DST"
rm -rf $DST
mkdir $DST
fi
# 1. copy the source code c++ api needs
mkdir -p $DST/tensorflow
cp -r $SOURCE/tensorflow/core $DST/tensorflow
cp -r $SOURCE/tensorflow/cc $DST/tensorflow
cp -r $SOURCE/tensorflow/c $DST/tensorflow
# 2. copy the generated code, put them back to
# the right directories along side the source code
if [[ -e $SOURCE/bazel-genfiles/tensorflow ]];then
prefix="$SOURCE/bazel-genfiles/tensorflow"
from=$(expr $(echo -n $prefix | wc -m) + 1)
# eg. compiled protobuf files
find $SOURCE/bazel-genfiles/tensorflow -type f | while read line;do
#echo "procese file --> $line"
line_len=$(echo -n $line | wc -m)
filename=$(echo $line | rev | cut -d'/' -f1 | rev )
filename_len=$(echo -n $filename | wc -m)
to=$(expr $line_len - $filename_len)
target_dir=$(echo $line | cut -c$from-$to)
#echo "[$filename] copy $line $DST/tensorflow/$target_dir"
cp $line $DST/tensorflow/$target_dir
done
fi
# 3. copy third party files. Why?
# In the tf source code, you can see #include "third_party/...", so you need it
cp -r $SOURCE/third_party $DST
# 4. these headers are enough for me now.
# if your compiler complains missing headers, maybe you can find it in bazel-tensorflow/external
cp -RLf $SOURCE/bazel-tensorflow/external/eigen_archive/Eigen $DST
cp -RLf $SOURCE/bazel-tensorflow/external/eigen_archive/unsupported $DST
cp -RLf $SOURCE/bazel-tensorflow/external/protobuf_archive/src/google $DST
cp -RLf $SOURCE/bazel-tensorflow/external/com_google_absl/absl $DST
mkdir -p $DST/tensorflow$target_dir
前にcp $line $DST/tensorflow/$target_dir