Jak zbudować i używać API Google TensorFlow C ++

168

Naprawdę nie mogę się doczekać rozpoczęcia korzystania z nowej biblioteki Google Tensorflow w C ++. Witryna i dokumentacja są po prostu naprawdę niejasne, jeśli chodzi o tworzenie interfejsu API C ++ projektu i nie wiem, od czego zacząć.

Czy ktoś z większym doświadczeniem może pomóc, odkrywając i udostępniając przewodnik po korzystaniu z interfejsu API C ++ tensorflow?

theideasmith
źródło
4
+1 na Twoje pytanie. Jakaś szansa na instalację / kompilację w systemie Windows? Witryna pokazuje tylko Linux / Mac. Potrzebny jest przewodnik po uruchomieniu bazel. Ten przykład może być dobrym punktem wyjścia do nauki: github.com/tensorflow/tensorflow/tree/master/tensorflow/ ...
alrama
Na to pytanie nadal nie ma odpowiedzi. Jak zainstalować tylko C ++ biblioteki tensorflow C ++ API nie ma do nich przewodnika, a zaakceptowana odpowiedź nie daje żadnych wskazówek, jak to zrobić, nawet za pośrednictwem któregokolwiek z wielu podanych linków.
iantonuk
W przypadku systemu Windows najbardziej pomocne okazało się to pytanie i zaakceptowana odpowiedź. Budując przykładowy projekt trenera, tworzysz cały projekt TensorFlow jako bibliotekę statyczną, a następnie łączysz się z nim. Możesz tworzyć własne projekty i łączyć TensorFlow w ten sam sposób.
omatai

Odpowiedzi:

2

Jedną z alternatyw dla korzystania z Tensorflow C ++ API, które znalazłem, jest użycie cppflow .

Jest to lekkie opakowanie C ++ wokół interfejsu API języka C Tensorflow . Otrzymujesz bardzo małe pliki wykonywalne i łączy się z libtensorflow.sojuż skompilowanym plikiem. Istnieją również przykłady użycia i używasz CMAKE zamiast Bazela.

Bersan
źródło
55

Aby rozpocząć, należy pobrać kod źródłowy z Github, postępując zgodnie z instrukcjami tutaj (będziesz potrzebować Bazela i najnowszej wersji GCC).

C ++ API (i zaplecze systemu) jest w tensorflow/core. Obecnie obsługiwane są tylko C ++ Session i C API . Możesz użyć dowolnego z nich do wykonywania wykresów TensorFlow, które zostały zbudowane przy użyciu interfejsu API języka Python i serializowane do GraphDefbuforu protokołu. Dostępna jest również funkcja eksperymentalna do tworzenia wykresów w C ++, ale obecnie nie jest ona w pełni funkcjonalna jak API Pythona (np. Obecnie nie obsługuje automatycznego różnicowania). Możesz zobaczyć przykładowy program, który tworzy mały wykres w C ++ tutaj .

Druga część C ++ API to API do dodawania nowego OpKernel, czyli klasy zawierającej implementacje numerycznych jąder dla CPU i GPU. Istnieje wiele przykładów, jak je wbudować tensorflow/core/kernels, a także samouczek dotyczący dodawania nowej operacji w C ++ .

mrry
źródło
7
Brak instrukcji instalacji dla C ++ tensorflow.org/install , ale są pokazane przykładowe programy tensorflow.org/api_guides/cc/guide, które wyraźnie używają C ++ api. Jak dokładnie zainstalowałeś C ++ dla Tensorflow?
user3667089
@ user3667089 Lokalizacja procedury instalacji znajduje się teraz na tensorflow.org/install/install_sources
Dwight.
6
@Dwight Widziałem tę stronę wcześniej, ale nie widzę żadnych informacji o C ++
user3667089
2
@ user3667089 Nagłówki, po powyższej procedurze instalacji, będą znajdować się w folderze dist-packages dystrybucji Pythona wybranej podczas procedury instalacji (np. /usr/local/lib/python2.7/dist-packages). W tym folderze będzie folder tensorflow / include, który będzie zawierał wszystkie nagłówki. Będziesz musiał trochę popracować, aby upewnić się, że cokolwiek budujesz, ma to na ścieżce włączania. Osobiście używam CMAKE, więc przedzieram się przez to .
Dwight
4
To nie jest prawdziwa odpowiedź do tej pory. Zaczyna się od „Aby rozpocząć”, a następnie nie zawiera odnośników do żadnych istotnych informacji w miejscu, które ludzie szukający tutaj wskazówek już by szukali. Następnie nie zapewnia kolejnego kroku, zmiany tematu.
iantonuk
28

Aby dodać do posta @ mrry, przygotowałem samouczek, który wyjaśnia, jak załadować wykres TensorFlow za pomocą interfejsu API C ++. Jest to bardzo minimalne i powinno pomóc ci zrozumieć, jak wszystkie elementy pasują do siebie. Oto jego mięso:

Wymagania:

  • Zainstalowano Bazel
  • Klonuj repozytorium TensorFlow

Struktura folderów:

  • tensorflow/tensorflow/|project name|/
  • tensorflow/tensorflow/|project name|/|project name|.cc (e.g. https://gist.github.com/jimfleming/4202e529042c401b17b7)
  • tensorflow/tensorflow/|project name|/BUILD

BUDOWAĆ:

cc_binary(
    name = "<project name>",
    srcs = ["<project name>.cc"],
    deps = [
        "//tensorflow/core:tensorflow",
    ]
)

Dwa zastrzeżenia, dla których prawdopodobnie istnieją obejścia:

  • W tej chwili tworzenie elementów musi odbywać się w repozytorium TensorFlow.
  • Skompilowany plik binarny jest ogromny (103 MB).

https://medium.com/@jimfleming/loading-a-tensorflow-graph-with-the-c-api-4caaff88463f

Jim
źródło
1
Cześć Jim. czy ten samouczek jest nadal najlepszym / najłatwiejszym sposobem kompilacji projektu C ++ z TF? A może jest teraz łatwiejszy sposób, gdy przewidujesz na końcu swojego posta?
Sander
3
Uważam, że jest teraz wbudowana reguła kompilacji. Jakiś czas temu przesłałem do niego PR. Nie jestem pewien co do zastrzeżeń. Spodziewałbym się, że pierwszy pozostanie, ponieważ jest to wynik Bazela, a nie TF. Drugi prawdopodobnie można by ulepszyć.
Jim
I przestrzegać tego samouczka, ale po uruchomieniu ./loaderpojawia się błąd: Not found: models/train.pb.
9th Dimension
3
Czy jest teraz sposób na umieszczenie projektu poza katalogiem kodu źródłowego TensorFlow?
Seanny123
tak, jak to zrobić, biorąc pod uwagę, że masz wspólną bibliotekę .so tensorflow?
Xyz
15

Jeśli chcesz uniknąć zarówno budowania swoich projektów w Bazelu, jak i generowania dużego pliku binarnego, przygotowałem repozytorium instruujące użycie biblioteki TensorFlow C ++ z CMake. Znajdziesz go tutaj . Ogólne pomysły są następujące:

  • Sklonuj repozytorium TensorFlow.
  • Dodaj regułę kompilacji do tensorflow/BUILD(dostarczone nie obejmują wszystkich funkcji C ++).
  • Zbuduj współdzieloną bibliotekę TensorFlow.
  • Zainstaluj określone wersje Eigen i Protobuf lub dodaj je jako zależności zewnętrzne.
  • Skonfiguruj projekt CMake do korzystania z biblioteki TensorFlow.
cjweeks
źródło
15

Po pierwsze, po zainstalowaniu protobufi eigenchcesz zbudować Tensorflow:

./configure
bazel build //tensorflow:libtensorflow_cc.so

Następnie skopiuj poniższe nagłówki i dynamiczną bibliotekę współdzieloną do /usr/local/libi /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/

Na koniec skompiluj na przykładzie:

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
lababidi
źródło
Uważam, że nie jest konieczne instalowanie protobuf i eigen. Konfiguracja obszaru roboczego bazel obejmuje zasady pobierania i tworzenia tych komponentów.
dni
wreszcie zwariowany OFICJALNY przewodnik po kompilacji na tensorflow.org/install/source służy do budowania modułu pip, tks dla opcji kompilacji „tensorflow: libtensorflow_cc.so”, nie jest nawet udokumentowany na tensorflow.org
datdinhquoc
@lababidi jakie zależności C ++ powinny znajdować się przed poleceniem „bazel build”? Mam problem, że kompilacja kończy się niepowodzeniem po godzinie, trudno jest ponownie przetestować kompilację
datdinhquoc
15

Jeśli myślisz o użyciu interfejsu API Tensorflow c ++ na samodzielnym pakiecie, prawdopodobnie będziesz potrzebować tensorflow_cc.so (istnieje również wersja tensorflow.so ac api), aby zbudować wersję c ++, której możesz użyć:

bazel build -c opt //tensorflow:libtensorflow_cc.so

Uwaga 1: Jeśli chcesz dodać obsługę funkcji wewnętrznych, możesz dodać te flagi jako: --copt=-msse4.2 --copt=-mavx

Uwaga 2: Jeśli myślisz o wykorzystaniu OpenCV również w swoim projekcie, występuje problem podczas używania obu bibliotek razem ( problem z tensorflow ) i powinieneś użyć --config=monolithic.

Po zbudowaniu biblioteki musisz dodać ją do swojego projektu. Aby to zrobić, możesz uwzględnić te ścieżki:

tensorflow
tensorflow/bazel-tensorflow/external/eigen_archive
tensorflow/bazel-tensorflow/external/protobuf_archive/src
tensorflow/bazel-genfiles

I połącz bibliotekę ze swoim projektem:

tensorflow/bazel-bin/tensorflow/libtensorflow_framework.so (unused if you build with --config=monolithic)
tensorflow/bazel-bin/tensorflow/libtensorflow_cc.so

A kiedy budujesz swój projekt, powinieneś również wskazać swojemu kompilatorowi, że zamierzasz używać standardów C ++ 11.

Uwaga boczna: ścieżki względem tensorflow w wersji 1.5 (może być konieczne sprawdzenie, czy w Twojej wersji coś się zmieniło).

Również ten link bardzo mi pomógł w znalezieniu tych wszystkich informacji: link

Renan Wille
źródło
1
Potrzebowałem tej dodatkowej ścieżki dołączania do kompilacji z wersją 1.11:tensorflow/bazel-tensorflow/external/com_google_absl
Noah_S
8

Jeśli nie masz nic przeciwko używaniu CMake, istnieje również projekt tensorflow_cc , który buduje i instaluje API TF C ++, wraz z wygodnymi celami CMake, z którymi możesz się połączyć. Projekt README zawiera przykład i pliki Dockerfiles, które możesz łatwo śledzić.

Floop
źródło
8

Jeśli nie chcesz samodzielnie budować Tensorflow, a Twój system operacyjny to Debian lub Ubuntu, możesz pobrać gotowe pakiety z bibliotekami Tensorflow C / C ++. Ta dystrybucja może być używana do wnioskowania C / C ++ z procesorem, obsługa GPU nie jest uwzględniona:

https://github.com/kecsap/tensorflow_cpp_packaging/releases

Istnieją instrukcje, jak zamrozić punkt kontrolny w Tensorflow (TFLearn) i załadować ten model do wnioskowania za pomocą interfejsu API C / C ++:

https://github.com/kecsap/tensorflow_cpp_packaging/blob/master/README.md

Uwaga: jestem twórcą tego projektu na Githubie.

kecsap
źródło
5

Używam hacka / obejścia, aby uniknąć konieczności samodzielnego budowania całej biblioteki TF (co oszczędza zarówno czas (jest konfigurowany w 3 minuty), miejsce na dysku, instalowanie zależności dev i rozmiar wynikowego pliku binarnego). Oficjalnie nie jest obsługiwany, ale działa dobrze, jeśli chcesz po prostu szybko wskoczyć.

Zainstaluj TF przez pip ( pip install tensorflowlub pip install tensorflow-gpu). Następnie znajdź jego bibliotekę _pywrap_tensorflow.so(TF 0. * - 1.0) lub _pywrap_tensorflow_internal.so(TF 1.1+). W moim przypadku (Ubuntu) znajduje się pod adresem /usr/local/lib/python2.7/dist-packages/tensorflow/python/_pywrap_tensorflow.so. Następnie utwórz dowiązanie symboliczne do tej biblioteki o nazwie lib_pywrap_tensorflow.sogdzieś, gdzie znajduje ją twój system budowania (np /usr/lib/local.). Prefiks libjest ważny! Możesz również nadać mu inną lib*.sonazwę - jeśli ją nazwiesz libtensorflow.so, możesz uzyskać lepszą kompatybilność z innymi programami napisanymi do pracy z TF.

Następnie stwórz projekt w C ++ taki, do jakiego jesteś przyzwyczajony (CMake, Make, Bazel, cokolwiek lubisz).

A potem jesteś gotowy, aby po prostu połączyć się z tą biblioteką, aby mieć TF dostępne dla twoich projektów (i musisz również połączyć się z python2.7bibliotekami)! W CMake np. Po prostu dodajesz target_link_libraries(target _pywrap_tensorflow python2.7).

Pliki nagłówkowe C ++ znajdują się wokół tej biblioteki, np /usr/local/lib/python2.7/dist-packages/tensorflow/include/. W.

Jeszcze raz: ten sposób jest oficjalnie nieobsługiwany i możesz biegać w różnych sprawach. Biblioteka wydaje się być statycznie połączona z np. Protobuf, więc możesz działać z dziwnymi problemami w czasie łączenia lub wykonywania. Ale jestem w stanie załadować zapisany wykres, przywrócić wagi i uruchomić wnioskowanie, co jest najbardziej pożądaną funkcją IMO w C ++.

Martin Pecka
źródło
Nie mogłem zmusić tego do pracy. Otrzymałem kilka błędów czasu łącza dotyczących niezdefiniowanych odwołań do rzeczy w Pythonie, takich jak:undefined reference to 'PyType_IsSubtype'
0xcaff
Och, dziękuję za wskazanie tego ... Musisz także linkować do python2.7biblioteki ... Odpowiednio zmodyfikuję post.
Martin Pecka
@MartinPecka Wypróbowałem to na Raspbian Buster z armv7l (Raspberry PI 2). Najnowsze dostępne koła Pythona 2.7 i 3.7 są przeznaczone dla wersji 1.14.0, ale moim celem jest 2.0.0. W każdym razie dzięki, zagłosowałem za twojego włamania.
Daisuke Aramaki
2

Sam Tensorflow zawiera tylko bardzo podstawowe przykłady dotyczące interfejsów API C ++.
Oto dobry zasób, który zawiera przykłady zestawów danych, rnn, lstm, cnn i więcej
przykładów tensorflow c ++

Rock Zhuang
źródło
2

powyższe odpowiedzi są wystarczająco dobre, aby pokazać, jak zbudować bibliotekę, ale sposób zbierania nagłówków jest nadal trudny. tutaj udostępniam mały skrypt, którego używam do kopiowania niezbędnych nagłówków.

SOURCEjest pierwszym parametrem, który jest direcoty źródła (kompilacji) tensorflow;
DSTjest drugim parametrem, czyli include directoryprzechowuje zebrane nagłówki. (np. w 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
hakunami
źródło
1
to był naprawdę pomocny fragment, wystąpił problem podczas tworzenia katalogu, więc musiałem to dodać mkdir -p $DST/tensorflow$target_dirwcześniejcp $line $DST/tensorflow/$target_dir
user969068
@hakunami Zrobiłem sedno tego skryptu . Powiedz mi co myślisz. Jeśli chcesz stworzyć własną treść, usunę moje i sklonuję twoje.
Daisuke Aramaki