Tensorflow: Java-Schnittstelle

Erstellt am 9. Nov. 2015  ·  112Kommentare  ·  Quelle: tensorflow/tensorflow

Problem, um den Aufwand der Swig-Schnittstelle für Java zu verfolgen. Implementierung gestartet - wird mit Fortschritt aktualisiert. Falls jemand Kommentare/Tipps hat - bitte gerne mitdiskutieren!

Hilfreichster Kommentar

Update: Ich konnte die Dinge mit javacpp erfolgreich in Gang bringen (dank @saudet ) und Java-Programme TensorFlow-Modelle lesen/ausführen lassen.

https://medium.com/google-cloud/how-to-invoke-a-trained-tensorflow-model-from-java-programs-27ed5f4f502d#.tx8nyds5v

Alle 112 Kommentare

Schön!

Diesen Kommentar von https://github.com/tensorflow/tensorflow/issues/3 hierher verschieben:


Es gibt eine Testsuite mit ziemlich guter Konvergenz, aber derzeit ist es hauptsächlich Python mit einigen C++-Tests. Es gibt auch viele Funktionen zum Erstellen von Graphen, die derzeit nur in Python enthalten sind, insbesondere die automatische Differenzierungsfunktion, obwohl dies für die Auswertung von Graphen in Java keine Rolle spielt. Es ist geplant, diese Funktionalität in Zukunft in das zugrunde liegende C++ zu verlagern, wobei Java SWIG-Bindungen für die Erstellung von Graphen nützlicher wären.

Wenn jemand die Java SWIG-Herausforderung annimmt, nehmen wir sie gerne vor der ausstehenden Überprüfung usw. an, die dann Teil unserer kontinuierlichen Tests wäre. Die Details zur Annahme von Beiträgen sind derzeit im Fluss, aber das wird sich stabilisieren.

Hallo Leute
Wir sind auch daran interessiert, TensorFlow für Java anzupassen. @ravwojdyla Hast du zufällig angefangen, an der Swig-Schnittstelle für Java zu arbeiten? Wenn ja, könnten wir unsere Bemühungen bündeln und daran zusammenarbeiten

Hallo,
Ich arbeite an einem SWIG-Wrap der wichtigsten C++-API. Sie können meinen bisherigen Fortschritt auf meiner Gabelung sehen, aber das, was dort oben steht, ist noch nicht fertig; Ich habe derzeit ein Problem, bei dem #include "tensorflow/core/lib/core/error_codes.pb.h" nicht gelöst werden kann und ich die gewünschte Datei nirgendwo in den Projektdateien finden kann. Input jeglicher Art wäre sehr dankbar.

Es gibt javacpp-Presets für Bibliotheken wie Caffe und OpenCV. Siehe auch https://github.com/bytedeco/javacpp-presets/issues/111. Java-cpp aktiviert auch IOS mit RoboVM

/cc @saudet

@pslam - ich konnte nur ein bisschen daran arbeiten - könnte definitiv etwas Hilfe gebrauchen!

Hallo Leute, ich glaube, ich habe ziemlich funktionale Bindungen für JavaCPP: https://github.com/bytedeco/javacpp-presets/tree/master/tensorflow. Lassen Sie es mich wissen, wenn Sie etwas sehen, das mit SWIG gemacht werden könnte, aber nicht mit JavaCPP. Das Feedback könnte ich auf jeden Fall gebrauchen. (Danke für den cc @bhack!)

Sehr schön gemacht @saudet! Ich habe einen SWIG-Wrap fast fertig, aber Ihre Implementierung scheint genauso gut zu funktionieren. Ich sehe nichts, was mein SWIG-Wrap kann, was Ihres nicht kann. JavaCPP scheint sehr cool zu sein, ich muss es für zukünftige Projekte verwenden.

Hallo @kylevedder , hast du das Problem im Zusammenhang mit error_codes.pb.h gelöst?
[Bearbeitet]
Alle .pb.h-Dateien werden aus .proto . kompiliert

@tngan Ja, das habe ich auch entdeckt. Außerdem erfordern die .proto Dateien in diesem Projekt die Verwendung von ProtoBuff3. Ich verwende Ubuntu 14.04 und ProtoBuff3 war in meinem Paketmanager nicht verfügbar, also habe ich es aus dem Quellcode kompiliert, den ich aus der Betaversion 3.0.0 erhalten habe .

Die aktuelle Hürde, die ich zu lösen versuche, ist, wie man ProtoBuff dazu bringt, über den gesamten Dateibaum zu rekursieren und die .proto Dateien in .h und .cc Dateien zu kompilieren; die stückweise Ausführung jedes Ordners führt zu Fehlern aufgrund nicht erfüllter Abhängigkeiten von anderen, noch zu kompilierenden .proto Dateien.

@kylevedder Sind Ihre SWIG-Wrapper in einem separaten Repository oder arbeiten Sie im Tensorflow-Repository? protoc funktioniert ähnlich wie andere Compiler. Wenn Sie im Tensorflow-Repository arbeiten oder Bazel verwenden, müssen Sie die Protobuf-Build-Ziele und die Abhängigkeiten zwischen ihnen einrichten.

Wenn Sie in einem separaten Repository arbeiten und ein anderes Build-System verwenden, müssen Sie das protobuf-Plugin für dieses Build-System verwenden.

Ich helfe Ihnen gerne beim Aufbau des Builds, wenn Sie möchten.

@davidzchen Vielen Dank für das Angebot, jede Hilfe ist sehr

Was ich bisher habe:

Ich habe Bazel bereits eingerichtet und in eine .whl Datei kompilieren lassen, die ich dann an pip und bestätigt habe, dass ich das First TensorFlow-Programm ausführen kann.

Ich habe SWIG-Wrapper-Dateien in meinem geforkten Repository generiert. Sie befinden sich in einem Ordner unter core/javaWrapper . [[link](https://github.com/kylevedder/tensorflow/tree/master/tensorflow/core/javaWrapper)]

Was ich versuche zu tun:

Letztendlich ist es mein Ziel, eine .so Datei zu generieren, die dann als native Bibliothek in Java aufgerufen werden kann. Derzeit versuche ich, das gesamte System mit g++ in eine .so Datei zu kompilieren; Allerdings müssen die .proto Dateien vor dieser Kompilierung zuerst in .h s und .cc s expandiert werden, und genau das versuche ich mit protoc .

Sie können meinen Versuch, ein Wrap-Skript zu erstellen, hier sehen, um möglicherweise eine bessere Vorstellung davon zu bekommen, was ich erreichen möchte, obwohl alle meine Versuche, protoc zu verwenden, Verzeichnis für Verzeichnis waren und folglich nicht im Skript.

Schließlich wäre jedes Feedback zu Verbesserungsbereichen sehr dankbar. Vielen Dank!

@kylevedder Ich habe bereits einen .so Build als Teil der JavaCPP Presets: https://github.com/bytedeco/javacpp-presets/tree/master/tensorflow. Dank Bazel ist es ganz einfach. Wenden Sie einfach einen Patch wie diesen an:

diff -ruN tensorflow/tensorflow/cc/BUILD tensorflow-patch/tensorflow/cc/BUILD
--- tensorflow/tensorflow/cc/BUILD  2015-11-22 00:00:02.441829192 +0900
+++ tensorflow-patch/tensorflow/cc/BUILD    2015-11-14 11:15:12.689330351 +0900
@@ -75,6 +75,17 @@
     ],
 )

+cc_binary(
+    name = "libtensorflow.so",
+    copts = tf_copts(),
+    linkshared = 1,
+    deps = [
+        ":cc_ops",
+        "//tensorflow/core:kernels",
+        "//tensorflow/core:tensorflow",
+    ],
+)
+
 filegroup(
     name = "all_files",
     srcs = glob(

Und führen Sie Bazel zum Beispiel so aus:

bazel build -c opt //tensorflow/cc:libtensorflow.so

AFAIK, das sollte so ziemlich alles verschlingen, was für die C++-API von Interesse ist.

@saudet Gibt es einen Grund , warum Sie eine verwenden cc_binary Regel die gemeinsame Bibliothek , anstatt zu bauen cc_library ? Sie können einfach eine cc_library Regel mit dem Namen tensorflow und das Build-Ziel erstellt eine gemeinsam genutzte Bibliothek namens libtensorflow.so .

@kylevedder Wenn Ihr Ziel darin besteht, eine .so Datei zu generieren, dann würde etwas Ähnliches wie das von @saudet vorgeschlagene funktionieren.

Wenn Sie die TensorFlow-Protos in Java-Code verwenden müssen, müssen Sie Abhängigkeiten von Ihren java_* Bazel-Build-Zielen zu den proto_library Zielen hinzufügen, die die Java-Klassen aus den .proto generieren

Wir haben noch ein bisschen Arbeit vor uns, bevor wir die nativen proto_library Regeln (siehe bazelbuild/bazel#52) als Open Source öffnen, aber in der Zwischenzeit verwendet TensorFlow die cc_proto_library und py_proto_library Regeln, die von protobuf bereitgestellt werden , und für Java sollten Sie die Java-Regel genproto , die in Bazel enthalten ist . Ich werde mich mit dem Team erkundigen, wie der Zeitplan für proto_library ist und ob es sich lohnt, die von Protobuf bereitgestellten Regeln mit genproto zu vereinheitlichen.

Noch ein paar Feedbacks:

  • Ich denke, es wäre besser, die Verzeichnisnamen konsistent zu halten und java_wrapper anstelle von javaWrapper
  • Vielleicht wäre //tensorflow/java/wrapper ein besserer Ort für den Java-Wrapper als //tensorflow/core/java_wrapper ?
  • Intern haben wir einige Build-Regeln, die .swig Dateien verwenden und die Quellen generieren. Dies ist idealer, da wir das Einchecken der generierten Dateien vermeiden würden. Ich kann einen Blick darauf werfen, wie schwierig es für uns wäre, einige SWIG-Build-Regeln für Bazel hinzuzufügen, um solche Dinge einfacher zu machen.

@davidzchen Keinen besonderen Grund. Ich bin neu bei Bazel und benutze nur linkshared=1 wie ich auf der Mailingliste gesehen habe, funktionierte. Also danke für den Tipp! Ich werde das aktualisieren.

@saudet Danke! Ich habe nur nachgesehen, ob es kein Problem mit Bazel war. :) Fühlen Sie sich frei, mich wissen zu lassen oder einen Fehler zu öffnen, wenn Sie auf Probleme stoßen.

@saudet Vielen Dank für die Informationen zur Verwendung von Bazel. Ich bin auch neu darin und wusste nicht, dass es auf diese Weise ein .so erzeugen kann.

@davidzchen Danke für den Nachtrag zur Verwendung eines cc_library , ich habe das Beispiel von @saudet entsprechend meinen Bazil-Wrapper-Build implementiert

Außerdem war ich in meinem vorherigen Kommentar zum Generieren von .so Dateien nicht ganz klar; Während mein Ziel darin besteht, eine .so Datei aus der Originalquelle zu generieren, möchte ich auch die .cxx Datei, die SWIG generiert, in die .so Datei einfügen , um die JNI . zu erleichtern Anrufe. Derzeit stoße ich auf ein Problem, bei dem ich die von SWIG generierte .cxx Datei nicht zum Kompilieren bekommen kann; Es versucht, auf JNI.h zu verweisen, einen Header, der sich in $JAVA_HOME/include/ , aber ich kann Bazel anscheinend nicht dazu bringen, den externen Include-Pfad zu verstehen.

@davidzchen Hum, nein, cc_library funktioniert nicht. Ich sehe keine andere Möglichkeit, Bazel dazu zu bringen, die Option -shared an den Compiler weiterzugeben: http://bazel.io/docs/be/c-cpp.html.

@saudet Ich glaube nicht, dass Sie -shared selbst übergeben müssen. cc_library sollte standardmäßig ein .so erstellen. Funktioniert das für dich?

@kylevedder Sie können die JNI-Header nicht auf diese Weise hinzufügen, da sie sich außerhalb des Arbeitsbereichs befinden. Bazel enthält jedoch das lokale JDK als lokales Repository und bietet eine Reihe integrierter Ziele (siehe jdk.WORKSPACE und entsprechende jdk.BUILD ), die Sie verwenden können, um vom lokalen JDK abzuhängen. Diese sind standardmäßig in jedem Bazel-Arbeitsbereich enthalten.

Bazel selbst verwendet JNI und verbindet sich auf diese Weise mit dem lokalen JDK (siehe src/main/native/BUILD ). In dieser BUILD-Datei gibt es zwei genrule s zum Kopieren der JNI-Header und ein cc_library Ziel für die Bibliothek, die es erstellt, die JNI verwendet, das von den Headern abhängt, und ein includes = ["."] damit der C++-Code den JNI-Header mit #include <jni.h> einschließen kann. Dies ist derzeit nicht dokumentiert, da wir an einer Reihe von Verbesserungen am externen Repository-Mechanismus arbeiten und sich der Name @local-jdk möglicherweise ändern kann, aber wir können ihn für TensorFlow und jedes andere Bazel-Projekt verwenden, das in der Zwischenzeit JNI verwendet .

Hier ist ein Patch für Ihre BUILD-Datei, der die genrule Ziele zum Kopieren der benötigten JNI-Header und einige Änderungen am cc_library Ziel hinzufügt, um die richtigen Abhängigkeiten einzurichten, nämlich:

  1. Fügen Sie jni.h und jni_md.h , die von den genrule s in das aktuelle Paket kopiert werden zu srcs
  2. Fügen Sie eine Abhängigkeit von //tensorflow/core damit Sie die Header unter tensorflow/core/public . Beachten Sie, dass Header oder jede Quelldatei in einem separaten Verzeichnis aus Bazels Sicht in einem separaten Paket sind und Sie eine Abhängigkeit vom Build-Ziel hinzufügen müssen, das diese Dateien enthält.
diff --git a/tensorflow/core/java/wrapper/BUILD b/tensorflow/core/java/wrapper/BUILD
index 72b4076..04a3394 100644
--- a/tensorflow/core/java/wrapper/BUILD
+++ b/tensorflow/core/java/wrapper/BUILD
@@ -7,10 +7,30 @@ exports_files(["LICENSE"])
 load("/tensorflow/tensorflow", "tf_copts")
 load("/tensorflow/tensorflow", "tf_gen_op_wrappers_cc")

+genrule(
+    name = "copy_link_jni_md_header",
+    srcs = ["//external:jni_md_header-linux"],
+    outs = ["jni_md.h"],
+    cmd = "cp -f $< $@",
+)
+
+genrule(
+    name = "copy_link_jni_header",
+    srcs = ["//external:jni_header"],
+    outs = ["jni.h"],
+    cmd = "cp -f $< $@",
+)
+
 cc_library(
     name = "java_wrapper",
-    srcs = glob(["*.cc","*.cxx","*.h"]),
-    copts = ["-I$$JAVA_HOME/include/", "-I$$JAVA_HOME/include/linux/"],
+    srcs = glob(["*.cc", "*.cxx", "*.h"]) + [
+        ":jni.h",
+        ":jni_md.h",
+    ],
+    includes = ["."],
+    deps = [
+        "//tensorflow/core",
+    ],
     visibility = ["//visibility:public"],
 )

Beachten Sie, dass Kompilierungsaktionen in Bazel im Allgemeinen vom Stamm des Quellbaums ausgeführt werden und Sie die Includes in Ihrer SWIG-Datei wie folgt ändern und dann die C++-Dateien neu generieren müssen, damit sie die richtigen Includes wie haben Gut:

diff --git a/tensorflow/core/java/wrapper/tensor_c_api.i b/tensorflow/core/java/wrapper/tensor_c_api.i
index d08b571..9ab1fa1 100644
--- a/tensorflow/core/java/wrapper/tensor_c_api.i
+++ b/tensorflow/core/java/wrapper/tensor_c_api.i
@@ -1,8 +1,8 @@
 %module tensor_c_api_module
 %{
-#include "../../public/tensor_c_api.h"
+#include "tensorflow/core/public/tensor_c_api.h"
 %}
-%include "../../public/tensor_c_api.h"
+%include "tensorflow/core/public/tensor_c_api.h"
 %include "stddef.h"

Sobald dies funktioniert, müssten Sie den JNI-Build für Linux einrichten, da copy_link_jni_md_header genrule nur den Linux-spezifischen Header kopiert. Damit es den richtigen plattformspezifischen JNI-Header kopiert, müssen wir Folgendes tun:

  1. Richten Sie cpu config_setting s für andere Plattformen ein. Derzeit hat tensorflow ein config_setting für --cpu=darwin in tensorflow/python/BUILD . Wir sollten das wahrscheinlich in ein geeigneteres Paket wie //tensorflow/core . Im Grunde würden wir den gleichen Satz von config_setting s wie Bazel wollen (siehe src/BUILD ).
  2. Lassen Sie copy_link_jni_md_header den richtigen JNI-Header basierend auf der Konfigurationseinstellung kopieren, indem Sie select() , ähnlich wie in Bazel . Unser genrule würde in etwa so aussehen:
genrule(
    name = "copy_link_jni_md_header",
    srcs = select({
        "//tensorflow/core:darwin": ["//external:jni_md_header-darwin"],
        "//tensorflow/core:darwin_x86_64": ["//external:jni_md_header-darwin"],
        "//tensorflow/core:freebsd": ["//external:jni_md_header-freebsd"],
        "//conditions:default": ["//external:jni_md_header-linux"],
    }),
    outs = ["jni_md.h"],
    cmd = "cp -f $< $@",
)

Ich helfe Ihnen gerne dabei, wenn Sie auf Probleme stoßen. Lass mich wissen, ob das für dich funktioniert.

@davidzchen cc_library generiert eine Reihe von .a-Dateien, aber keine .so-Datei. Ich verwende 0.1.0, wie es zuvor für TensorFlow empfohlen wurde ... Vielleicht ist es in 0.1.1 behoben? Ich muss es noch einmal versuchen.

@davidzchen Vielen Dank für deine Hilfe. Ich habe Ihre Anweisungen befolgt und sowohl die Java-Wrapper- Datei BUILD als auch die SWIG- Datei .i wie von Ihnen vorgeschlagen aktualisiert. Außerdem habe ich das Wrap-Skript von core/java/wrapper in das Stammverzeichnis verschoben und die Links entsprechend aktualisiert.

Im Moment habe ich die Verallgemeinerung der genrule für die jni_md.h Datei übersprungen und mich stattdessen darauf konzentriert, libtensorflow.so bauen. Leider scheint es mir, als ob libtensorflow.so nicht generiert wird; Am Ende durchsuchte ich mein gesamtes Dateisystem nach etwas, das als eine Variante von "libtensorflow" bezeichnet wurde, und es erschien nichts Relevantes. Es kann anders benannt sein oder es kann sich um einen einfachen Benutzerfehler handeln. Darüber hinaus besteht die Möglichkeit, dass dies mit dem Problem zusammenhängt, das @saudet mit der cc_library Regel für die .so Generierung hat.

Nochmals vielen Dank für Ihre Hilfe, ich weiß es wirklich zu schätzen.

Entschuldigung, es stellte sich heraus, dass ich falsch lag. Um ein .so zu erstellen, das die transitiven Abhängigkeiten enthält, war es richtig , was cc_binary mit linkshared = 1 und name = "libtensorflow.so" . Aus der cc_binary.linkshared Dokumentation :

Erstellen Sie eine gemeinsam genutzte Bibliothek. Um dieses Attribut zu aktivieren, schließen Sie linksshared=1 in Ihre Regel ein. Standardmäßig ist diese Option deaktiviert. Wenn Sie es aktivieren, müssen Sie Ihre Binärdatei libfoo.so (oder wie auch immer die Namenskonvention von Bibliotheken auf der Zielplattform ist) für einen vernünftigen Wert von foo benennen.

Der Hauptunterschied zwischen den .so 's, die mit cc_library Zielen erstellt wurden, und den .so die mit cc_binary Verwendung der oben beschriebenen Methode erstellt wurden, besteht darin, dass die cc_library Artefakte enthalten nur den Code in srcs . Aus diesem Grund werden beim Erstellen von cc_library Zielen ohne srcs und nur deps , wie z. B. //tensorflow/core , keine Artefakte erzeugt. Auf der anderen Seite werden cc_binary Ziele in allen transitiven Abhängigkeiten verknüpft.

Ich entschuldige mich für die Verwirrung. Vielleicht sollten wir unsere Dokumentation verbessern und ein Beispiel zum Erstellen von .so s hinzufügen.

Ich denke, Sie sollten diese Schritte befolgen, um Tensorflow und alle seine Abhängigkeiten zu erstellen. Wir arbeiten daran, TensorFlow nach node.js zu portieren, und ich habe ein Shell-Skript implementiert, um nur die wesentlichen Quellen aus dem gesamten Repository zu kompilieren und abzurufen:
https://github.com/node-tensorflow/node-tensorflow/blob/1.0.0/tools/install.sh#L233 -L282

@davidzchen Vielen Dank für die Informationen zur Erstellung eines .so . Ich habe mein Setup entsprechend aktualisiert und ein tensorflow/core/java/wrapper/example mit einem _extrem_ einfachen Tester erstellt, um zu beweisen, dass JNI-Funktionsaufrufe an .so funktionieren. Beachten Sie, dass createWrapper.sh muss, bevor compileAndRun.sh .

Ich werde versuchen, den SWIG-Wrapper zu verbessern und ein besseres Beispiel zu geben, das ich jetzt habe, ist einfach ein minimaler Beweis für funktionierende Bindungen.

Schließlich möchte ich @davidzchen und @saudet für ihre Hilfe danken; Ohne sie hätte ich das nicht geschafft.

Schön! Danke für die Arbeit, @kylevedder!

Wenn Sie interessiert sind, kann ich versuchen, Ihre Skripte createWrapper.sh und compileAndRun.sh in den Bazel-Build zu integrieren, indem Sie 1) die Skylark SWIG-Regel erstellen und 2) die Java-Regeln von

@davidzchen Das wäre toll! Ich werde daran arbeiten, den SWIG-Wrapper und das Basisbeispiel zu verbessern.

Ich habe die Voreinstellungen für JavaCPP fertiggestellt und das example_trainer.cc Beispiel portiert:
https://github.com/bytedeco/javacpp-presets/tree/master/tensorflow
Ich freue mich darauf, dies mit einem gleichwertigen Wrapper mit SWIG zu vergleichen!

Anscheinend ist der API-Link defekt: http://bytedeco.org/javacpp-presets/tensorflow/apidocs/

@verdiyanto Tut

@saudet Schöne Arbeit an den JavaCPP-Presets!

Ein Update zu meiner Arbeit: Ich habe noch etwas am SWIG-Wrapper gearbeitet, und Sie können meine Arbeit hier sehen . Ich stehe jedoch an einer Kreuzung und bin mir nicht sicher, wie ich am besten vorgehen soll.

Ich bin ziemlich neu bei SWIG, da dies mein erstes großes Projekt ist, das es verwendet, also habe ich die SWIG-Dokumentation zu SWIG-Grundlagen und zu SWIG und Java gelesen, die die Funktionsweise von SWIG und das Wrapping von C/C++ mit SWIG-Java-Wrappern erläutert.

Die Dokumentation erklärt, wie SWIG Zeiger in C/C++ in undurchsichtige Java-Objekte umwandelt, weshalb Sie von SWIG generierte Klassen wie SWIGTYPE_p_void . Das Problem ist, dass es keine einfache Möglichkeit gibt, POJOs in diese SWIG-Klassen umzuwandeln.

So nimmt beispielsweise in tensor_c_api.h die C-Methode TF_CreateTensor() ein void* das auf die Eingabedaten zeigt, und einen size Parameter, um die Größe von . anzugeben die Eingangsdaten in Bytes. Dies ist ein vollkommen vernünftiges Entwurfsmuster für C/C++, aber völlig unsinnig in Java. Die von SWIG generierte Java-Methode TF_CreateTensor() ein SWIGTYPE_p_void Objekt als Daten, zusammen mit size , aber es gibt keine Möglichkeit, ein POJO wie ein String zu konvertieren. SWIGTYPE_p_void umwandeln, ohne viel Code von Hand zu schreiben.

Und das ist der Scheideweg, an dem ich derzeit liege: Ich schreibe entweder eine Menge C/C++-Konvertierungsmethoden, die jeden in TF_DataType definierten Typ annehmen und in void* konvertieren, oder schreibe eine Reihe von SWIG typemaps, um dasselbe zu tun. Die SWIG-Dokumentation scheint keine der beiden Lösungen zu bevorzugen, da beide scheinbar austauschbar sind.

Die Frage ist also, C/C++-Konvertierungsfunktionen oder SWIG-Typemaps?

@kylevedder Ich sehe, Sie beginnen zu verstehen, warum ich JavaCPP überhaupt erstellt habe. :)

Ich habe die JavaCPP -Voreinstellungen von @saudet verwendet, sehr nützlich, danke! Ich verwende es, um eine Clojure-Schnittstelle zu Tensorflow zu erstellen.

Einige Kommentare:

a) Es besteht die Möglichkeit zur Vereinfachung / einer übergeordneten Ebene

Ein Großteil der JavaCPP-API repliziert die Protobuf-Funktionalität, die ohne Bridge direkt auf der JVM erreicht werden kann. Ich habe ein bisschen gebraucht, um das zu erkennen, aber man baut einfach ein Protobuf-Objekt mit den JavaCPP-Bindungen auf, erzeugt diese plattformunabhängige Darstellung mit Interop und füllt sie dann in die Session.

Am Ende habe ich nur jvm-basierte Protobufs verwendet, um den Graphen direkt zu erstellen und die JavaCPP-Konstruktorfunktionen zu umgehen. Dies hat mehrere Vorteile - eine einfachere API zum Programmieren und auch ein schönes .toString-Format, das das von Menschen lesbare Protobuf anzeigt.

Insbesondere für Clojure ist es viel einfacher, den Tensorflow-Graphen in Form von Datenstrukturen zu beschreiben und sie dann direkt in Protobuf umzuwandeln, als für jeden Knoten in meiner Datenstruktur eine Konstruktorfunktion nachzuschlagen und aufzurufen.

b) Gebäude- und Paketverbesserungen

Ich bin kein Experte im Erstellen von nativem Code oder in den Build-Tools, die in diesen Projekten verwendet werden. Es wäre großartig, kunstfertige Artefakte zu haben; insbesondere wenn sie auch die generierten Java-Protobuf-Klassen enthalten. Es hat mir peinlich viel Zeit gekostet, herauszufinden, wie das geht.

c) Es wäre nützlich, eine kleine Anzahl von Graph-Testfällen als Ziel zu haben.

Im Moment ist meine Methodik etwas umständlich: Verwenden Sie die JavaCPP-Konstruktorfunktionen, um einen Graphen zu generieren, mischen Sie ihn in meine JVM-Protobufs und sehen Sie sich die menschenlesbare Form an und finden Sie heraus, wie Sie meine eigenen Konstruktoren erstellen können, um dieselbe Form zu erstellen.

Es wäre nützlich, eine kleine Sammlung sehr einfacher Diagramme zu haben, die die Kernfunktionen von TensorFlow ausüben, damit Leute wie ich einen vernünftigen Satz von Testfällen für die Interoperabilität in verschiedenen Sprachen haben.

Trotzdem vielen Dank für alle Bemühungen und macht weiter so!

@kovasb Danke für das Feedback! Offensichtlich gibt es noch viel zu tun, um die Benutzeroberfläche für Java, Scala, Clojure usw. natürlicher zu gestalten.

Wenn Sie über Hilfsklassen zum Integrieren der C++-API mit der Java-Protobuf-API verfügen, können Sie dies alles in das folgende Paket packen, einschließlich der generierten Java-Protobuf-Klassen selbst, und eine PR senden:
https://github.com/bytedeco/javacpp-presets/tree/master/tensorflow/src/main/java/org/bytedeco/javacpp/helper
Dafür ist es gedacht und es wird automatisch in das Maven-Artefakt gepackt, etwas, das Bazel anscheinend nicht unterstützt. Danke auf jeden Fall, dass du dir das angeschaut hast!

@kovasb Eine Clojure-Schnittstelle klingt wirklich interessant. Haben Sie noch einen Code zum Teilen?

Vielen Dank!

Die Leute in diesem Thread wissen also auch, in https://github.com/tensorflow/tensorflow/issues/3 wurde angesprochen: Die automatische Unterscheidung funktioniert derzeit nicht, es sei denn, Sie verwenden TF von der Python-API. Dies scheint ein Showstopper zu sein, bis diese Funktionalität auf C++ portiert wird.

Ich verstehe den Datenfluss nicht ganz, aber vielleicht ist es möglich, das Python-Hilfsprogramm zusammen mit der C++-Bibliothek zu starten?

Eine andere Lösung, die ich mir ansehe, ist die Verwendung von Jpy oder einer der anderen Brücken (hat jemand Empfehlungen?).

Wenn JyNi aussortiert wird, würde es + Jython der JVM eine wirklich tolle Geschichte bezüglich Python-Ökosystem-Interop geben. Man kann träumen.

+1 für eine Java-Schnittstelle!

Wenn wir javaCPP verwenden könnten, ist SWIG dann noch notwendig? sollen wir bei der Implementierung der SWIG-Schnittstelle zusammenarbeiten?

@maxiwu Ich denke gerne, dass JavaCPP einen besseren Job macht als SWIG, aber ich bin dafür, sie zu vergleichen, um es tatsächlich zu beweisen :)

@kovasb Ich wäre sehr daran interessiert, der Clojure-Benutzeroberfläche zu helfen/beizutragen.

@sorenmacbeth schickt mir Google Mail, ich freue mich, Sie durch das zu führen, was ich habe ...

Es scheint, dass wir hier ein ziemlich vollständiges Javacpp-Preset haben. Ist es eine akzeptable Lösung für "das Team"?

@saudet Ich versuche, eine Kopie der JavaCPP-Wrapper zu erstellen, aber es scheint, dass sie aufgrund der schnellen Änderungsrate der Tensorflow-Quelle weder mit der Version 0.6.0 noch mit dem heutigen Master-Zweig kompatibel sind. Wäre es möglich, sie mit einem Zeiger auf den genauen Tensorflow-Commit/die genaue Version zu aktualisieren, mit der sie getestet wurden?

@nikitakit Ich habe gerade hier ein Update für den Master-Zweig gemacht: https://github.com/bytedeco/javacpp-presets/commit/43bdcdf03beaaddb4bd5badf5d4f79669e9e78dd

Im Gegensatz zu Caffe scheint TensorFlow jedoch jeden Monat oder so eine Veröffentlichung zu bekommen, also werde ich wohl an diesen Punkten mit der Stabilisierung der Bindungen beginnen, beginnend mit der nächsten Veröffentlichung (0.7.0?)

@martinwicke Was denkst du?

Wenn es eine stabile Java-Bindung gibt, arbeite ich gerne an der Scala-API.

/cc @databricks

@kovasb Ich glaube, ich habe das beim ersten Mal verpasst. Wollen Sie damit sagen, dass all die schöne automatische Differenzierungsmagie, die wir durch die Verwendung von TensorFlow durch Python erhalten, in Python implementiert ist, nicht in den C++-Bibliotheken? In der Praxis müsste eine Java-API also entweder all dies neu implementieren oder wäre nur eine weitere numerische Bibliothek? Ich bin mit den Interna von TensorFlow oder dem Python-Kleber nicht vertraut genug, um genau zu verstehen, was wo schweres Heben gemacht wird.

@drdozer das ist mein Verständnis, basierend auf Kommentaren von @girving und dann selbst ein bisschen nach der Quelle suchen. Die Neuimplementierung von Dingen in Java scheint ein Nichtstarter zu sein. Ich schlage vor, die Kommentare in #3 zu lesen

Wenn jemand wirklich interessiert ist, würde ich nur empfehlen, einige Trainingsbeispiele mit der Java-API zu erstellen (bisher habe ich nur den Vorwärtspfad gesehen / ausgeführt).

Ich frage mich, wie weit wir mit dem Ausführen des Python-Codes mit Jython kommen würden ...

Ich glaube, die Python-API-Schicht hat viel Logik, die die C++-Schicht-API nicht bereitstellt.
Ich habe versucht, dem JavaCpp-Pfad zu folgen, aber am Ende wird es viel Duplizierungscode geben und es wird schwierig sein, Konsistenzen aufrechtzuerhalten, wenn sich etwas in der Python-Implementierung ändert.

Der wahrscheinlich einfachere Weg ist die Verwendung von Jython, wie @saudet bereits erwähnt hatte ...

Es wurde in https://github.com/tensorflow/tensorflow/issues/476 @josh11b zugewiesen. Wenn er daran arbeitet, macht es keinen Sinn, Jython zu verwenden.

Wenn wir jython verwenden, funktioniert der C++-Code noch? Ich möchte dies für einen Server in Java verwenden, aber ich stecke fest zwischen dem direkten Versuch einer Java-Route oder dem Senden der Daten über einen Socket an einen Python-Prozess

Ich möchte erwähnen, dass die Java-API zwar nicht viele Funktionen wie die automatische Differenzierung enthält, dies jedoch für meine eigene Arbeit nicht als Hindernis empfunden wurde. Ich habe großen Erfolg gehabt, ein Modell in Python zu generieren, es in eine .proto-Datei zu serialisieren und es dann zum Training über den Java-Wrapper zu öffnen. Das gleiche kann für die Testzeit gemacht werden, da ich glaube, dass die Saver-Funktionalität über die C++- und Java-APIs verfügbar ist.

+1

@saudet
Vielen Dank für das Erstellen von javacpp und die Voreinstellungen für Tensorflow. Ich konnte erfolgreich ein Python-Diagramm in Java neu erstellen, aber ich versuche nicht, aus einer gespeicherten Modelldatei wiederherzustellen. Diese Zeile funktioniert nicht:

Tensor fn = neuer Tensor (tensorflow.DT_STRING, neuer TensorShape(1));
CharBuffer-Puffer = fn.createBuffer();
buffer.put("Modelldatei.tf");
Sitzung.Ausführen(...);

aber der CharBuffer stellt sich als NULL heraus. Wenn ich DT_STRING in DT_FLOAT ändere, erhalte ich einen FloatBuffer, aber DT_STRING scheint nicht zu funktionieren.

@nikitakit du hast gesagt, du hast das zum

@lakshmanok

EDIT: sorry, hab das was du hier gesagt hast falsch gelesen. Ich kann keine Hilfe bei der Verwendung externer Saver von Java geben

Als Referenz ist der Teil meines Codes, der Tensorflow-Graphen importiert, hier: https://gist.github.com/nikitakit/d3ec270aee9d930267cec3efa844d5aa

Es ist in Scala, aber die Portierung auf Java / eine andere JVM-Sprache sollte einfach sein.

Mein Code zum tatsächlichen Ausführen von Knoten im Diagramm ist leider stark mit einem Scala-Framework verbunden, das ich verwende, sodass Sie sich für diesen Teil auf die Tensorflow-API-Dokumentation verlassen müssen.

Hat jemand etwas mit der Einbettung der Python-Tensorflow-Umgebung in das JVM? Sagen Sie mit Jython + JyNI? Oder ist das alles ein bisschen zu experimentell, um zuverlässig zum Laufen zu kommen?

Ich arbeite derzeit daran, die C-API zu erweitern, um Unterstützung für die Diagrammdefinition hinzuzufügen. Ich bin mir nicht sicher, wann es fertig sein wird, aber es ist eines unserer Ziele vor 1.0.

Ich arbeite daran, Tensor Flow von Java zu verwenden. Ich nähere mich dem Problem, indem ich Jython verwende und die Tensor-Flow-Cpython-Bibliothek ändere, um einen anderen Python-Interpreter aufzunehmen. das cpython sollte weiterhin fehlerfrei funktionieren und mein Code erkennt, ob der Interpreter Jython ist und ändert die Importe / Module, damit es funktioniert. Darunter werden die javacpp-Bindungen für libtensorflow_cc.so verwendet. Ist dies etwas, für das das Google-Team im offiziellen Repo offen wäre? @vrv

Das scheint ein netter Proof of Concept zu sein, aber ich denke, eine offizielle Bindung würde wahrscheinlich nativ binden wollen, als Python zu durchlaufen:(

nein, anstatt den c-python-Wrapper aufzurufen, rufen wir den javaccp-Wrapper auf. Es wäre also dasselbe wie cpython-Tensor-Flow, aber von der JVM mit Jython ausgewertet. Die Neuimplementierung der gesamten Python-Logik in einer anderen Sprache scheint zu viel, Sie erhalten eine andere API. javacpp-Bindungen ermöglichen es Ihnen, Inference ohne Probleme auszuführen, aber das Modell muss im Moment aus einem Python-Skript erstellt/trainiert werden.

Hat jemand versucht, Tensorflow mit Kotlin zum Laufen zu bringen? Es scheint eine natürlichere Passform zu sein und ist am Ende des Tages immer noch 100% Java. Ich finde die Kotlin-Sprache ein sehr schöner Mittelweg zwischen Python und reinem Java.

Update: Ich konnte die Dinge mit javacpp erfolgreich in Gang bringen (dank @saudet ) und Java-Programme TensorFlow-Modelle lesen/ausführen lassen.

https://medium.com/google-cloud/how-to-invoke-a-trained-tensorflow-model-from-java-programs-27ed5f4f502d#.tx8nyds5v

Danke @lakshmanok und @saudet . Das javacpp Projekt scheint die meisten TensorFlow-APIs zu implementieren. Wir versuchen, den Tensorflow/Serving in Java

Die API ist einfach und wird durch protobuf . Nun haben wir den Server implementiert und wollen den Client in Java implementieren. Es muss nur TensorProto in Java konstruieren und den gRPC Aufruf aufrufen. TensorFlow bietet Hilfsfunktionen zum Konvertieren mehrerer Dimensionsarrays für Python und C++, jedoch nicht für Java.

Können Sie sagen, wie man javacpp oder selbst dafür implementiert?

Was Sie suchen, ist wahrscheinlich bereits in https://github.com/bytedeco/javacpp-presets/blob/master/tensorflow/src/main/java/org/bytedeco/javacpp/helper/tensorflow.java enthalten, aber lassen Sie es mich wissen wenn da was fehlt. Vielen Dank!

wird daran noch gearbeitet? Gibt es ein offizielles Github-Repository für dieses Portierungsprojekt? Ich sehe ein paar zufällige Repos, kann es aber nicht sagen.

Ja, aber wahrscheinlich irgendwann im Oktober/November. Wir verwenden die C-API, anstatt zur C++-API zu wechseln. In der Zwischenzeit können Sie die genannten Bindungen verwenden.

Wie sind Sie zu dem Schluss gekommen, die C-API zu verwenden? wir arbeiten an a
Ruby-Schnittstelle mit swig:
http://github.com/somaticio/tensorflow.rb

Am Di, 13. September 2016 um 18:22, Jonathan Hseu [email protected]
schrieb:

Ja, aber wahrscheinlich irgendwann im Oktober/November. Wir verwenden die C-API
anstatt zur C++-API zu wechseln. In der Zwischenzeit können Sie die
Bindungen, die saudet erwähnt.


Sie erhalten dies, weil Sie einen Kommentar abgegeben haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/tensorflow/tensorflow/issues/5#issuecomment -246844192,
oder den Thread stumm schalten
https://github.com/notifications/unsubscribe-auth/AAA5v3g86Z6D1rz-aTGdMyMWnQZhrZUYks5qpyIJgaJpZM4Getd8
.

In Zukunft würden wir es vorziehen, dass alle Sprachbindungen die C-API verwenden. Ein Dokument ist in Vorbereitung.

Sie können hier eine Beispielanwendung sehen:
https://github.com/tensorflow/tensorflow/tree/master/tensorflow/go

Es besteht jedoch keine Dringlichkeit, und es ist vorerst in Ordnung, auf SWIG aufzubauen.

@jhseu Bedeutet das, dass die C-API erweitert wird, um alle abzudecken, auf die die Python-Bindungen derzeit Zugriff haben?

Wow, große Veränderung. Ich wünschte, dies wäre früher entschieden worden. Wie auch immer, um die Dokumente zu sehen
früher?

Am Mittwoch, 14. September 2016 um 17:56 Uhr, Samuel Audet [email protected]
schrieb:

@jhseu https://github.com/jhseu Bedeutet das, dass die C-API sein wird ?
erweitert, um alles abzudecken, worauf die Python-Bindungen derzeit Zugriff haben?


Sie erhalten dies, weil Sie einen Kommentar abgegeben haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/tensorflow/tensorflow/issues/5#issuecomment -247167887,
oder den Thread stumm schalten
https://github.com/notifications/unsubscribe-auth/AAA5vwfBJoZC2s33_7E9Xy6-NYNUjHjnks5qqG2FgaJpZM4Getd8
.

@saudet Die meisten Funktionen, außer kurzfristig fehlen einige Dinge (wie Farbverläufe, Optimierer).
@jtoy Es besteht keine Dringlichkeit für die Migration. SWIG wird noch eine Weile weiterarbeiten.

Die Dokumente beschreiben nur, wie es geht und Benennungskonventionen. Sie können jedoch auch ohne sie zur C-API migrieren:
https://github.com/tensorflow/tensorflow/blob/master/tensorflow/c/c_api.h

Danke @saudet . Ich habe dies im Stackoverflow über das Generieren von TensorProto mit einer reinen Protobuf-API gefunden. Und hier ist der Beispielcode von TensorFlow, der den gRPC-Java-Client bereitstellt.

@tobegit3hub Schön, wenn Sie dies mit der C++ API zum Laufen bringen können, fügen Sie es bitte zum Hilfspaket der JavaCPP-Presets hinzu und senden Sie einen Pull-Request! Dieser Typ wäre an so etwas interessiert: https://github.com/bytedeco/javacpp-presets/issues/240

@girving Löst javacpp das Problem bereits?
Ich möchte zu tensorflow java api beitragen, ich ziehe es vor, es wie Python zu implementieren.

Hallo Leute, hat jemand bereits mit der Arbeit an den Java/Scala-Sprachbindungen mit der C-API begonnen?
(statt auf SWIG zu bauen)

Ich habe eine funktionierende Java/Scala-Schnittstelle zu Tensorflow, die nur die C-API über JNR verwendet . Leider habe ich noch keine Berechtigung zum Open Source. Ich werde hier posten, wenn und wenn ich es veröffentliche. Es ist noch in Arbeit, aber es ist sehr funktional.

@jdolson Akzeptiert die von Ihnen @saudet hatte, ist, dass Sie es bei der Manipulation von

@Intropy Ja, ich kompiliere alle Tensorflow- *.proto Quellen in Java-Quellcode mit protoc und verwende diese Klassen in der API.

@jhseu Ist die C-API-Schnittstelle noch auf dem

@eaplatanios : Die C-API ist größtenteils stabil (und wird es offiziell ab 1.0 sein) und verwendbar, wenn auch nicht vollständig (es fehlt immer noch die Fähigkeit, automatisch Gradientenberechnungen zum Graphen durchzuführen). Ein Dokument, in dem beschrieben wird, wie die C-API zum Erstellen von Sprachbindungen verwendet werden kann, finden Sie unter https://www.tensorflow.org/how_tos/language_bindings/index.html

Die Go-API wurde unter Verwendung der C-API als erstes Beispiel für das Befolgen des obigen Dokuments implementiert.

Wir hoffen, dass auch die Java-Bindungen darauf aufgebaut werden (mit JNI) und haben damit begonnen, dies ein wenig zu erkunden. Alle Kommentare / Erkenntnisse, die die Leute auf der Grundlage der wunderbaren Arbeit von @saudet mit dem Funktionieren von JavaCPP haben, wären schön zu wissen.

Ich habe ein paar Vorschläge, die auf der Verwendung von JavaCPP-Bindungen basieren.

Da Protokollpuffer direkt nach Java kompilieren, sollten zunächst die Java-Versionen verwendet werden. Ich denke, dass die Protokollpuffer, die an der API teilnehmen, vorzugsweise separat als Maven-Modul verfügbar sein sollten und mit den Proto-Definitionen geliefert werden sollten, damit Leute auf einem Java-Stack eine einfache Möglichkeit haben, die Definitionen sowohl als Binär- als auch als einfaches zu erhalten Möglichkeit, die Proto-Definitionen für die Aufnahme in andere Proto-Definitionen zu erhalten.

Zweitens wäre es hilfreich, die Mindestversion von libc zu finden, die TensorFlow benötigt, und darauf aufzubauen.

Drittens ist es viel einfacher, eine durchdachte API zu verwenden als eine automatisch generierte. Ich weiß, dass das offensichtlich ist und klingt wie ein Schuss auf JavaCPP. Ich meine es nicht. Ich bin wirklich froh, dass die automatisch generierte Schnittstelle existiert. Es _ist_ verwendbar. Aber es erfordert seltsame Umschreibungen, es hat viele Warzen und es ist ziemlich schwierig, den Code zu lesen, um herauszufinden, wie Sie das tun, was Sie tun möchten. Ich wünschte, dieser Vorschlag wäre hilfreicher als "Sie sollten es gut machen", aber ich denke, der Punkt ist, wie unterschiedlich die C++-API und die Python-API sind. Beide sind unkompliziert, weil sie so in ihre Umgebung passen, dass automatisch konvertierter Code wahrscheinlich nicht übereinstimmt.

Es wäre vielleicht schöner gewesen, das C-Backend von Swig zu unterstützen und auch die TF-C-API über Swig zu generieren: https://github.com/swig/swig/issues/800, damit andere Sprachen wie Go, Ruby, R das verwenden können C api, um eigene Bindungen zu schreiben.

Wir haben eine vorhandene C-API zum Hinzufügen von Unterstützung für jede Sprache mit einem C-FFI:
https://github.com/tensorflow/tensorflow/blob/master/tensorflow/c/c_api.h

(Und das wird verwendet, um die Go-, Java-, Rust usw.-Bindungen für TensorFlow zu erstellen)

Könnte mit JNA auf die C-API zugegriffen werden?

@jhseu Ich meinte, es hätte vielleicht früher aus der C++-API generiert werden können, bevor die C-API manuell implementiert wurde.

@Quantum64 , hier ist eine Scala-Bindung von Tensorflow, die JNA verwendet.

Da dieses Thema noch offen ist, wie funktioniert?
https://github.com/tensorflow/tensorflow/tree/master/tensorflow/java
implementiert und was war die PR für das Commit?

@hsaputra : Könnten Sie tensorflow/java beitragen, von denen die meisten in dieser Ausgabe referenziert werden (z. B. 2b1cd28, d73a266 und viele andere dazwischen).

HI @asimshankar , danke für die Antwort.

Ich frage mich nur, welchen Weg tensorflow/java , um die Java-API zu implementieren, da dieses Ticket nicht geschlossen ist.
Es gab Diskussionen über die Verwendung von JavaCPP vs SWIG vs Call über Jython.

Scheint, als wäre tensorflow/java mit direktem JNI implementiert, um stattdessen C-APIs aufzurufen?

Richtig.

Hey,

Ich habe gestern diese Swig-Bindungen zum Laufen gebracht. Ich habe eine Anfrage für eine API-Änderung. Derzeit ist zur Generierung von Tensoren Reflexion erforderlich, und das Format der Arrays ist etwas unpassend, da sie die Verwendung von n-dimensionalen nativen Java-Arrays erfordern. Können wir diese Schnittstelle beibehalten, aber auch einige Methoden zum Erstellen von Tensoren hinzufügen, die eindimensionale Arrays erfordern und die Form mit einem anderen Array von long angeben? Ich kann mir vorstellen, dass es etwa so aussehen könnte:

double[] matrix = {1.414, 2.718, 3.1415, 3.4, 56.7, 89.0};
long[] shape = {2, 3};

// add a method for each primitive type
org.tensorflow.Tensor tensor = org.tensorflow.Tensor.createDouble(matrix, shape);

Dies würde auch zu der Möglichkeit führen, int8-, int16-, uint8-, uint16-, uint32-Tensoren zu erstellen, was bei der Kompatibilität hilft.

Soll ich das zum Thema machen? Oder ist es hier in Ordnung?

Gerne versuche ich auch, diese Methoden zu entwickeln.

@hollinwilkins : Ich hoffe, dass PR #6577 dies anspricht, mit nur einer leichten Anpassung Ihrer vorgeschlagenen Fabrikmethode:

Tensor tensor = Tensor.create(shape, DoubleBuffer.wrap(matrix));

@asimshankar Das ist großartig! Danke für die schnelle Antwort. Es sieht so aus, als ob es auch kurz davor steht, zusammengeführt zu werden :+1:

Ich versuche, die neue Java-API zu verwenden, und bin auf einige Dinge gestoßen, die die Verwendung schwieriger machen, als ich denke, dass sie sein sollte:

  1. Die Java-API sollte ein GraphDef-Objekt akzeptieren. Derzeit akzeptiert es nur ein Byte-Array, das die serialisierte Binärdatei des GraphDef-Protokollpuffers darstellt. Es ist seltsam, einen Serialisierungs-/Deserialisierungsschritt an der Bibliotheksgrenze zu erfordern.
  2. Session.Runner.feed sollte org.tensorflow.framework.TensorProto akzeptieren können oder es sollte eine gute Möglichkeit geben, org.tensorflow.Tensor aus org.tensorflow.framework.TensorProto zu erstellen.
  3. Session.Runner.run gibt eine Liste von Tensor-Objekten zurück. Ähnlich wie oben sollte es eine einfache Möglichkeit geben, die TensorProto-Ausgabe entweder direkt zu erhalten oder indem Sie org.tensorflow.Tensor eine gute Möglichkeit geben, in TensorProto zu konvertieren.
  4. Session.Runner.run schluckt Status. Es sollte eine Möglichkeit geben, diese Informationen über Fehler zu erhalten, möglicherweise durch Auslösen einer Ausnahme.

Es ist auch möglich, dass ich die Möglichkeit übersehen habe, dies zu handhaben, aber es sieht so aus, als ob ich nicht alle unterstützten Tensortypen in der Ausgabe von run abrufen kann. Wenn mein Ausgabetensor beispielsweise vom dtype INT16 ist, gibt es keine Möglichkeit, den Wert daraus zu extrahieren. Es gibt keinen Tensor.shortValue oder ähnliches, und Tensor.intValue scheint eine genaue Übereinstimmung zu erfordern. Ich stütze dies auf das Lesen von DEFINE_GET_SCALAR_METHOD in tensor_jni.cc.

@Intropy : Danke für deine Kommentare und sie machen definitiv Sinn. Für jetzt kann ich einige kurze Gedanken mit Ihnen teilen:

RE: protobufs: An dieser Stelle versuchen wir aus einer Reihe von Gründen, die Kern-API unabhängig von Protobufs zu halten (einschließlich der Verwendung auf ressourcenbeschränkten Systemen, wo so etwas wie nanproto möglicherweise besser geeignet ist). Das ist der Grund, warum wir gezögert haben, aber darüber denken wir nach und Vorschläge sind willkommen. Eine Möglichkeit besteht darin, alle protobuf-bezogenen Funktionalitäten in einem separaten Paket zu haben, damit eine klare Trennung besteht.

Also zurück zu deinen Punkten:

  1. Siehe oben. Ich würde jedoch wetten, dass es viele Fälle gibt, in denen byte[] sinnvoller ist (z. B. das Lesen des Diagramms aus einer Datei oder einem Netzwerkkanal).

  2. Punkt erreicht

  3. Siehe oben.

  4. Session.runner.run sollte keinen Status schlucken. Bei einem Fehler wird eine Ausnahme ausgelöst ( session_jni.cc:166 ). Wenn dies nicht der Fall ist, melden Sie bitte einen Fehler.

Sie haben Recht, es werden noch nicht alle Typen unterstützt, aber das Hinzufügen sollte einfach sein. Wenn Sie die fehlenden Typen dringend benötigen, können Sie gerne ein Problem melden und/oder eine PR einsenden. Beiträge sind willkommen :)

@asimshankar Danke für deine Gedanken.

Was den ersten Punkt betrifft, ist es nicht wirklich eine große Sache. Wie Sie sagen, gibt es Zeiten, in denen ein byte[] am sinnvollsten ist. In meinem eigenen Anwendungsfall habe ich einen InputStream, dessen Konvertierung in byte[] trivial ist. Die Protokollpuffer-API macht die Konvertierung unkompliziert. Ich halte das byte[] einfach für eine Warze in der API, weil Sie sowieso (in TF_GraphImportGraphDef) deserialisieren müssen und auf diese Weise etwas Typsicherheit verloren geht. Es ist auch die Json-Serialisierung von proto3 zu berücksichtigen.

Was den Schluckstatus angeht, hast du recht. Ich habe die ungeprüfte Ausnahme übersehen.

Der offensichtlichste Weg, 2 und 3 zu handhaben, besteht darin, org.tensorflow.Tensor eine Factory zu geben, die von einem TensorProto und einigen toTensorProto() konvertiert. Wenn ressourcenbegrenzte Anwendungsfälle das Problem mit Protokollpuffern sind, könnten die Leute unter diesen Umständen diese Funktionen einfach nicht verwenden. Das Problem ist, dass Leute, die diese Funktionen nutzen, die Kosten für eine Konvertierung zahlen würden, die wahrscheinlich vermieden werden könnte, indem der Tensor seine Daten direkt in einem Protobuff speichert. Ich habe noch nie mit jni gearbeitet, daher habe ich Probleme, zu verfolgen, wie die Daten gespeichert werden, aber es sieht so aus, als würde nativeHandle im Wesentlichen wie ein Zeiger auf einen TF_Tensor behandelt, der einen TensorBuffer hat, der im Wesentlichen wie ein großes Void behandelt wird *.

Könnten wir dieses Problem auflösen und separate Probleme für jede Funktion in der Java-Schnittstelle einreichen? Es wird einfacher zu verfolgen/zu analysieren, dann können wir dieses Problem schließen.

@drpngx : Meine Absicht ist es, ein paar weitere Änderungen vorzunehmen (Tensoren aus Puffern zu lesen), bevor dies wie bei Go geschlossen wird und Funktionen / Fehler einzeln abgelegt werden. Also hoffentlich bald.

Klingt gut. Danke!

Okay, es scheint, als hätten wir genug Basis, auf der wir aufbauen können (z. B. genug, um das LabelImage-Beispiel zu erstellen, und die Leute reichen spezifischere

Ich werde dieses Thema schließen. Es gibt noch viel zu tun in der Java-API, aber lassen Sie uns diese in separaten Ausgaben besprechen/verfolgen. Vielen Dank!

@asimshankar wir sind dabei, ein Deep-Learning-Framework (mxnet/tf) auszuwählen und unsere etl/api basieren auf spark/akka flow... Gibt es einen Plan, die Java-API mit verteilter_runtime-Unterstützung hinzuzufügen, um modellparalleles Training mit ps auszuführen? Knoten? ps-Knoten ist für uns für viele Anwendungsfälle von entscheidender Bedeutung ... javacpp-Presets können für den ersten Schnitt einfacher zu exportieren sein, da die C-API selbst keine verteilte_runtime enthält ...

@debasish83 : Die verteilte Laufzeit allein Estimator Klasse, die sich um eine Reihe von Dingen kümmern (Checkpointing, Zusammenfassungsspeicherung usw.) die Visualisierung durch TensorBoard trivial machen), wodurch es möglicherweise besser geeignet ist, die Trainingsjobs in Python auszuführen.

All dies kann mit den vorhandenen Primitiven in der Java-API erstellt werden, aber der richtige Ansatz hängt von Ihren genauen Anforderungen ab.

Vielleicht sollten wir Off-Thread synchronisieren?

@asimshankar Gibt es bereits eine Möglichkeit aus der Tensorflow-Java-Bindung, Informationen aus einer graphDef (erstellt aus der .pb-Datei des Graphen auf der Festplatte) wie der Liste der Knoten, dem Eingabe- und Ausgabeformat abzurufen, oder handelt es sich um eine eingehende Funktion? Vielen Dank!

@asimshankar Ich bin mir nicht sicher, Estimator vorschlagen)?

Vielen Dank.

Wie ist der Stand der Trainingsmodelle in Java? Ich habe darüber nachgedacht, ein ImageJ-Plugin (eine beliebte und kostenlose Bildanalysesuite) zu schreiben, um Ansätze wie https://arxiv.org/pdf/1505.04597.pdf (in letzter Zeit sehr beliebt in der Bildsegmentierung für Zellverfolgung und biomedizinische Anwendungen) anzuwenden. Ich denke, es wäre nützlich, eine Reihe von vortrainierten Modellen bereitzustellen und es den Benutzern zu ermöglichen, diese für ihren spezifischen Anwendungsfall zu verfeinern. Ich habe zu diesem Zweck nach DL4J gesucht. Gibt es konkrete Pläne, das Einpassen der TF-Java-Bindungen zu ermöglichen?

@bergwerf : Eine Schulung in Java ist sicherlich möglich, wenn auch nicht besonders praktisch.
Ein Beispiel finden Sie unter https://github.com/tensorflow/models/tree/master/samples/languages/java/training

(Außerdem bin ich mir sicher, dass Sie sich dessen bewusst sind, aber siehe auch https://imagej.net/TensorFlow)

Oh toll! Meine Angaben müssen dann veraltet sein ;-). Ich dachte ich hätte gelesen
irgendwo war die Java-API nur für die Vorhersage mit vortrainierten
Modelle. Ich werde mir das Beispiel anschauen.

Am Mittwoch, 28. März 2018, 22:01 Uhr schrieb Asim Shankar [email protected] :

@bergwerf https://github.com/bergwerf : Ausbildung in Java ist sicherlich
möglicherweise, wenn nicht besonders bequem.
Ein Muster finden Sie unter
https://github.com/tensorflow/models/tree/master/samples/languages/java/training


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/tensorflow/tensorflow/issues/5#issuecomment-377015867 ,
oder den Thread stumm schalten
https://github.com/notifications/unsubscribe-auth/AEQJ1UD9-xACQAII5996ees_UFJ_NzL-ks5ti-wSgaJpZM4Getd8
.

@asimshankar das ist großartig 👍 💯 🥇 , werde ich zu meinem Repo hinzufügen https://github.com/loretoparisi/tensorflow-java

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen