Tensorflow: Java интерфейс

Созданный на 9 нояб. 2015  ·  112Комментарии  ·  Источник: tensorflow/tensorflow

Проблема с отслеживанием усилий интерфейса swig для java. Начато внедрение - буду обновлять по мере продвижения. Если у кого-то есть комментарии / советы - приглашаем присоединиться к обсуждению!

Самый полезный комментарий

Обновление: мне удалось успешно наладить работу с javacpp (благодаря @saudet ) и заставить Java-программы читать / выполнять модели TensorFlow.

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

Все 112 Комментарий

Отлично!

Перемещение этого комментария сюда с https://github.com/tensorflow/tensorflow/issues/3 :


Есть набор тестов с довольно хорошей конвергенцией, но в настоящее время это в основном Python с несколькими тестами C ++. Также есть много функций для построения графиков, которые в настоящее время только Python, в частности, функция автоматического дифференцирования, хотя это не имеет значения для оценки графиков в Java. В будущем планируется перенести эту функциональность в базовый C ++, и тогда привязки Java SWIG будут более полезны для создания графиков.

Если кто-то возьмется за задачу Java SWIG, мы будем рады принять ее в ожидании проверки и т. Д., После чего это станет частью нашего непрерывного тестирования. Детали принятия взносов в настоящее время изменяются, но это стабилизируется.

Привет ребята
Мы также заинтересованы в адаптации TensorFlow для Java. @ravwojdyla Вы случайно не начали работать над интерфейсом Swig для Java? Если да, мы могли бы объединить наши усилия и сотрудничать в этом

Привет,
Я работаю над SWIG-оболочкой основного C ++ API. Вы можете видеть мой прогресс на моей вилке, но то, что там наверху, еще не закончено; В настоящее время у меня возникла проблема, из-за которой #include "tensorflow/core/lib/core/error_codes.pb.h" не удается разрешить, и я не могу найти нужный файл в любом месте файлов проекта. Любой вклад будет очень признателен.

Предустановки javacpp доступны для таких библиотек, как Caffe и OpenCV. См. Также https://github.com/bytedeco/javacpp-presets/issues/111. Java-cpp включает также IOS с RoboVM

/ cc @saudet

@pslam - Мне удалось немного поработать над этим - определенно

Привет, ребята, я считаю, что у меня есть довольно функциональные привязки для JavaCPP: https://github.com/bytedeco/javacpp-presets/tree/master/tensorflow. Дайте мне знать, если вы увидите что-нибудь, что можно сделать с помощью SWIG, но не с JavaCPP. Я определенно мог бы воспользоваться обратной связью. (Спасибо за копию @bhack!)

Очень красиво сделано @saudet! Я почти закончил обертку SWIG, но похоже, что ваша реализация работает так же хорошо. Я не вижу ничего, что может сделать моя обертка SWIG, чего не может сделать ваша. JavaCPP кажется очень крутым, мне нужно будет изучить его использование в будущих проектах.

Привет, @kylevedder , вы решили проблему, связанную с error_codes.pb.h ?
[Отредактировано]
Все файлы .pb.h скомпилированы из .proto

@tngan Да, я тоже это обнаружил. Кроме того, файлы .proto в этом проекте требуют использования ProtoBuff3. Я использую Ubuntu 14.04, а ProtoBuff3 не был доступен в моем диспетчере пакетов, поэтому я скомпилировал его из исходного кода, который я получил из бета-версии 3.0.0 .

Текущее препятствие, которое я пытаюсь решить, заключается в том, как заставить ProtoBuff выполнять рекурсию по всему дереву файлов и компилировать файлы .proto файлы .h и .cc ; выполнение каждой папки по частям приводит к сбоям из-за неудовлетворенных зависимостей от других, еще не скомпилированных файлов .proto .

@kylevedder Ваши обертки SWIG находятся в отдельном репозитории или вы работаете в репозитории tensorflow? protoc работает аналогично другим компиляторам. Если вы работаете в репозитории тензорного потока или используете Bazel, вам потребуется настроить цели сборки protobuf и зависимости между ними.

Если вы работаете в отдельном репозитории и используете другую систему сборки, вам необходимо использовать плагин protobuf для этой системы сборки.

Я буду рад помочь вам настроить сборку, если хотите.

@davidzchen Спасибо за предложение, любая помощь очень ценится.

Что у меня есть на данный момент:

Я уже установил Bazel и скомпилировал его в файл .whl , который затем передал pip и подтвердил, что могу запустить программу First TensorFlow .

Я создал файлы-оболочки SWIG в моем разветвленном репозитории. Они находятся в папке под core/javaWrapper . [[ссылка] (https://github.com/kylevedder/tensorflow/tree/master/tensorflow/core/javaWrapper)]

Что я пытаюсь сделать:

В конечном итоге моя цель - создать файл .so который можно было бы назвать собственной библиотекой в ​​Java. В настоящее время я пытаюсь использовать g ++ для компиляции всей системы в файл .so ; однако файлы .proto должны быть сначала расширены до .h s и .cc s перед этой компиляцией, и это то, что я пытаюсь сделать с protoc .

Вы можете увидеть мою попытку сценария переноса здесь, чтобы потенциально лучше понять, к чему я клоню, хотя до сих пор все мои попытки использовать protoc выполнялись по каталогам и, следовательно, не в сценарии.

Наконец, мы будем очень благодарны за любые отзывы об областях, в которых можно улучшить. Спасибо!

@kylevedder У меня уже есть .so как часть предустановок JavaCPP: https://github.com/bytedeco/javacpp-presets/tree/master/tensorflow. Благодаря Базелу это действительно просто. Просто примените такой патч:

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(

И запускаем Базель вот так, например:

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

AFAIK, это должно поглотить практически все, что представляет интерес для C ++ API.

@saudet Есть ли причина, по которой вы используете правило cc_binary для создания разделяемой библиотеки, а не cc_library ? Вы можете просто иметь правило cc_library с именем tensorflow и цель сборки создаст общую библиотеку с именем libtensorflow.so .

@kylevedder Если ваша цель - создать файл .so , то сработает что-то похожее на то, что предлагает

Если вам нужно использовать протоколы TensorFlow в Java-коде, вам нужно будет добавить зависимости от ваших целей сборки java_* Bazel к целям proto_library которые генерируют классы Java из .proto files.

Нам еще предстоит немного поработать, прежде чем мы откроем исходный код собственных правил proto_library (см. Bazelbuild / bazel # 52), но тем временем TensorFlow использует cc_proto_library и py_proto_library Правила , а для Java вы должны иметь возможность использовать правило Java genproto , которое включено в Bazel . Я уточню у команды, каков график для proto_library и стоит ли унифицировать правила, предоставляемые Protobuf, с genproto .

Еще несколько отзывов:

  • Я думаю, было бы лучше сохранить согласованность имен каталогов и использовать java_wrapper а не javaWrapper
  • Возможно, лучшим местом для оболочки Java было бы //tensorflow/java/wrapper а не //tensorflow/core/java_wrapper ?
  • Внутри у нас есть некоторые правила сборки, которые берут .swig файлов и генерируют исходники. Это более идеальный вариант, потому что мы бы избегали проверки сгенерированных файлов. Я могу посмотреть, насколько сложно нам было бы добавить некоторые правила сборки SWIG для Bazel, чтобы упростить подобные вещи.

@davidzchen Без linkshared=1 как я видел, упомянутый в списке рассылки, работал. Так что спасибо за подсказку! Я буду обновлять это.

@saudet Спасибо! Я просто проверял, не проблема с Базел. :) Не стесняйтесь сообщать мне или сообщать об ошибке, если у вас возникнут какие-либо проблемы.

@saudet Спасибо за информацию об использовании Bazel. Я тоже новичок в этом и не осознавал, что он способен генерировать .so таким образом.

@davidzchen Спасибо за добавление об использовании cc_library , я соответствующим образом изменил пример из @saudet, когда реализовал свою сборку оболочки Bazil . Также благодарю вас за информацию о структуре каталогов; Я обновил структуру папок в соответствии с вашими предложениями.

Кроме того, в моем предыдущем комментарии я был не очень ясен по поводу создания файлов .so ; в то время как моя цель - создать файл .so из исходного источника, я также хочу включить файл .cxx который SWIG генерирует внутри .so , чтобы облегчить JNI звонки. В настоящее время я столкнулся с проблемой, из-за которой я не могу скомпилировать сгенерированный SWIG файл .cxx ; он пытается сослаться на JNI.h , заголовок, расположенный в $JAVA_HOME/include/ , но я не могу заставить Базель понять внешний путь включения.

@davidzchen Хм, нет, cc_library не работает. Я не вижу другого способа заставить Базель передать компилятору параметр -shared : http://bazel.io/docs/be/c-cpp.html.

@saudet Я не думаю, что вам нужно самому передавать -shared . cc_library .so по умолчанию должен создавать

@kylevedder Вы не сможете добавить заголовки JNI таким образом, поскольку они находятся за пределами рабочей области. Однако Bazel включает локальный JDK в качестве локального репозитория и предоставляет ряд встроенных целей (см. jdk.WORKSPACE и соответствующий jdk.BUILD ), которые можно использовать для зависимости от локального JDK. Они включены в каждое рабочее пространство Bazel по умолчанию.

Сам Bazel использует JNI и таким образом взаимодействует с локальным JDK (см. src/main/native/BUILD ). В этом файле BUILD есть два genrule s для копирования заголовков JNI и цель cc_library для создаваемой библиотеки, которая использует JNI, который зависит от заголовков, и includes = ["."] чтобы код C ++ мог включать заголовок JNI с #include <jni.h> . В настоящее время это не задокументировано, потому что мы работаем над рядом улучшений механизма внешнего репозитория, и имя @local-jdk может измениться, но мы можем использовать его для TensorFlow и любого другого проекта Bazel, который пока использует JNI. .

Вот патч для вашего файла BUILD, который добавляет цели genrule для копирования нужных заголовков JNI и некоторые изменения в цели cc_library для установки правильных зависимостей, а именно:

  1. Добавьте jni.h и jni_md.h , которые копируются в текущий пакет с помощью genrule s в srcs
  2. Добавьте зависимость от //tensorflow/core чтобы можно было включать заголовки в tensorflow/core/public . Обратите внимание, что заголовки или любой исходный файл в отдельном каталоге находятся в отдельном пакете с точки зрения Bazel, и вам нужно будет добавить зависимость от цели сборки, которая содержит эти файлы.
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"],
 )

Обратите внимание, что в целом действия компиляции в Bazel запускаются из корня исходного дерева, и вам нужно будет изменить включения в вашем файле SWIG следующим образом, а затем повторно сгенерировать файлы C ++, чтобы они имели правильные включения, как хорошо:

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"

Как только это сработает, у вас будет настроена сборка JNI для Linux, поскольку copy_link_jni_md_header genrule копирует только заголовок, специфичный для Linux. Чтобы он скопировал правильный заголовок JNI, зависящий от платформы, нам нужно сделать следующее:

  1. Настройте cpu config_setting s для других платформ. В настоящее время тензорный поток имеет config_setting для --cpu=darwin в tensorflow/python/BUILD . Вероятно, нам следует переместить этот более подходящий пакет, например //tensorflow/core . По сути, нам нужен тот же набор config_setting s, что и у Bazel (см. src/BUILD ).
  2. Попросите copy_link_jni_md_header скопировать правильный заголовок JNI, в зависимости от того, какой параметр конфигурации установлен с помощью select() , аналогично тому, как это сделано в Bazel . Наши genrule будут выглядеть примерно так:
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 $< $@",
)

Я буду рад помочь вам с этим, если у вас возникнут какие-либо проблемы. Сообщите мне, работает ли это для вас.

@davidzchen cc_library генерирует группу файлов .a, но не файл .so. Я использую 0.1.0, как было рекомендовано ранее для TensorFlow ... Может быть, это исправлено в 0.1.1? Придется попробовать еще раз.

@davidzchen Большое спасибо за вашу помощь. Я выполнил ваши инструкции и обновил как файл оболочки Java SWIG .i как вы предложили. Кроме того, я переместил сценарий переноса из core/java/wrapper в корневой каталог и соответствующим образом обновил ссылки.

На данный момент я пропустил обобщение genrule для файла jni_md.h , вместо этого сосредоточившись на попытке построить libtensorflow.so . К сожалению, мне кажется, что libtensorflow.so не создается; Я закончил поиск по всей своей файловой системе чего-либо, названного каким-то вариантом "libtensorflow", и ничего подходящего не обнаружилось. Он может называться по-другому или это может быть простой случай ошибки пользователя. Кроме того, существует вероятность того, что оно может быть связано с проблемой , что @saudet испытывает с cc_library правилу .so поколения.

Еще раз спасибо за вашу помощь, я очень ценю это.

Извините, но оказалось, что я ошибался. Чтобы построить .so который включает транзитивные зависимости, то, что сделал @saudet , используя cc_binary с linkshared = 1 и name = "libtensorflow.so" было правильным. Из документации cc_binary.linkshared :

Создайте общую библиотеку. Чтобы включить этот атрибут, включите linkshared = 1 в свое правило. По умолчанию эта опция выключена. Если вы включите его, вы должны назвать свой двоичный файл libfoo.so (или каким-либо другим соглашением об именах библиотек на целевой платформе) для некоторого разумного значения foo.

Основное различие между .so , созданными с помощью целей cc_library и .so созданными с помощью cc_binary с использованием описанного выше метода, заключается в том, что cc_library артефакты содержат код только в srcs . Вот почему создание целей cc_library без srcs и только deps , например //tensorflow/core , не приводит к появлению каких-либо артефактов. С другой стороны, цели cc_binary будут связывать все транзитивные зависимости.

Прошу прощения за недоразумение. Возможно, нам следует улучшить нашу документацию и добавить пример сборки .so s.

Я думаю, вам следует выполнить эти шаги, чтобы создать Tensorflow и все его зависимости. Мы работаем над переносом TensorFlow на node.js, и я реализовал сценарий оболочки для компиляции и получения только необходимых источников из всего репозитория:
https://github.com/node-tensorflow/node-tensorflow/blob/1.0.0/tools/install.sh#L233 -L282

@davidzchen Спасибо за информацию о создании .so . Я соответствующим образом обновил свою настройку и создал tensorflow/core/java/wrapper/example с _extremely_ базовым тестером, чтобы доказать, что функция JNI вызывает .so работает. Обратите внимание, что createWrapper.sh необходимо запустить перед запуском compileAndRun.sh .

Я постараюсь улучшить оболочку SWIG и сделать лучший пример, тот, который у меня сейчас есть, просто минимальное доказательство работоспособности привязок.

Наконец, я хочу поблагодарить @davidzchen и @saudet за их помощь; Без них я бы не справился.

Отлично! Спасибо за работу, @kylevedder!

Если вам интересно, я могу попробовать интегрировать ваши сценарии createWrapper.sh и compileAndRun.sh в сборку Bazel путем 1) создания правила Skylark SWIG и 2) использования правил Java Bazel для сборки кода Java.

@davidzchen Было бы здорово! Я буду работать над улучшением оболочки SWIG и базового примера.

Я завершил предустановки для JavaCPP и перенес образец example_trainer.cc :
https://github.com/bytedeco/javacpp-presets/tree/master/tensorflow
С нетерпением жду возможности сравнить это с эквивалентной оболочкой, использующей SWIG!

Похоже, ссылка на API не работает: http://bytedeco.org/javacpp-presets/tensorflow/apidocs/

@verdiyanto Извините, у меня еще нет CI, но загрузить документы API достаточно просто, так что я, по крайней мере, это сделал. Наслаждаться!

@saudet Отличная работа над пресетами JavaCPP!

Обновленная информация о моей работе: я еще немного поработал над оболочкой SWIG, и вы можете увидеть работу, которую я проделал здесь . Однако я нахожусь на небольшом перекрестке, и я не уверен, как лучше всего двигаться дальше.

Я новичок в SWIG, учитывая, что это мой первый крупный проект, использующий его, поэтому я прочитал документацию SWIG по основам SWIG, а также по SWIG и Java, в которых рассказывается, как работает SWIG и как обернуть C / C ++ оболочкой SWIG Java.

В документации объясняется, как SWIG преобразует указатели в C / C ++ в непрозрачные объекты Java, поэтому вы получаете такие классы, как SWIGTYPE_p_void созданные SWIG. Проблема в том, что нет простого способа преобразовать POJO в эти классы SWIG.

Так, например, в tensor_c_api.h метод C TF_CreateTensor() принимает void* который указывает на входные данные, и параметр size чтобы указать размер входные данные в байтах. Это вполне разумный шаблон проектирования для C / C ++, но совершенно бессмысленный для Java. Сгенерированный SWIG метод Java TF_CreateTensor() принимает в качестве данных объект SWIGTYPE_p_void вместе с size , но нет способа преобразовать POJO, например String в SWIGTYPE_p_void без написания большого количества кода.

И это перекресток, на котором я сейчас лежу: я либо пишу тонну методов преобразования C / C ++, которые принимают любой тип, определенный в TF_DataType и конвертирую в void* , либо пишу кучу Карты типов SWIG делают то же самое. Документация SWIG, похоже, не поддерживает ни одно из решений, поскольку они оба кажутся взаимозаменяемыми.

Итак, вопрос в том, функции преобразования C / C ++ или карты типов SWIG?

@kylevedder Я вижу, вы начинаете понимать, почему я вообще создал JavaCPP. :)

Я использовал предустановки JavaCPP от @saudet, очень полезные, спасибо! Я использую его для создания интерфейса Clojure для tenorflow.

Некоторые комментарии:

а) Есть возможность упрощения / более высокий уровень

Многие из API JavaCPP реплицируют функциональные возможности protobuf, которые могут быть реализованы непосредственно на JVM, без моста. Мне потребовалось немного времени, чтобы осознать это, но я просто создаю объект protobuf, используя привязки JavaCPP, создавая это независимое от платформы представление с помощью взаимодействия, а затем вставляя его в сеанс.

В итоге я просто использовал protobufs на основе jvm для непосредственного построения графа, минуя функции конструктора JavaCPP. У этого есть несколько преимуществ - более простой API для программирования, а также красивый формат .toString, который показывает читаемый человеком protobuf.

В частности, для Clojure гораздо проще описать граф тензорного потока в терминах структур данных и затем преобразовать их напрямую в protobuf, чем искать и вызывать функцию конструктора для каждого узла в моей структуре данных.

б) Улучшения сборки и пакета

Я не эксперт в создании собственного кода или в инструментах сборки, используемых в этих проектах. Было бы здорово иметь искусные артефакты; в частности, если они также включали сгенерированные классы java protobuf. Мне потребовалось унизительное количество времени, чтобы понять, как это сделать.

c) Было бы полезно иметь небольшое количество тестовых примеров графа для таргетинга.

Прямо сейчас моя методология несколько громоздка: используйте функции конструктора JavaCPP для создания графика, вставьте его в мои прототипы JVM и посмотрите удобочитаемую форму и выясните, как создать свои собственные конструкторы для создания такой же формы.

Было бы полезно иметь небольшую коллекцию очень простых графиков, которые реализуют основные функции TensorFlow, чтобы у таких людей, как я, был разумный набор тестовых примеров для взаимодействия с разными языками.

В любом случае спасибо за все усилия и продолжайте в том же духе!

@kovasb Спасибо за отзыв! Очевидно, что еще многое предстоит сделать, чтобы сделать интерфейс более естественным для Java, Scala, Clojure и т. Д.

Если у вас есть вспомогательные классы для интеграции C ++ API с Java protobuf API, не стесняйтесь поместить все это в следующий пакет, включая сами сгенерированные классы Java protobuf, и отправьте PR:
https://github.com/bytedeco/javacpp-presets/tree/master/tensorflow/src/main/java/org/bytedeco/javacpp/helper
Это то, для чего он предназначен, и он будет автоматически упакован в артефакт Maven, что, по-видимому, не поддерживает Bazel. В любом случае спасибо, что разобрались с этим!

@kovasb Интерфейс clojure звучит очень интересно. Есть еще какой-нибудь код, которым можно поделиться?

Спасибо!

Таким образом, люди в этом потоке также знают, что в https://github.com/tensorflow/tensorflow/issues/3 было поднято: автоматическая дифференциация в настоящее время не работает, если вы не используете TF из python api. Это похоже на остановку в ожидании того, что эта функциональность будет перенесена на C ++.

Я не совсем понимаю поток данных, но, возможно, можно запустить вспомогательный материал python вместе с библиотекой C ++?

Другое решение, на которое я смотрю, - это просто использование Jpy или одного из других мостов (у кого-то есть рекомендации?) JyNi также выглядит довольно интересно, но довольно далеко от прайм-тайма (хотя было бы здорово увидеть за ним больше импульса / сообщества)

Если с JyNi разберутся, он + jython даст JVM действительно потрясающую историю взаимодействия с экосистемой Python. Можно мечтать.

+1 за интерфейс Java!

если бы мы могли использовать javaCPP, нужен ли еще SWIG? будем ли мы сотрудничать для реализации интерфейса SWIG?

@maxiwu Мне нравится думать, что JavaCPP работает лучше, чем SWIG, но я все за то, чтобы сравнивать их, чтобы на самом деле это доказать :)

@kovasb Мне было бы очень интересно помочь / внести свой вклад в интерфейс Clojure.

@sorenmacbeth, напишите мне на почту

Похоже, у нас есть довольно полный пресет Javacpp. Это приемлемое решение для «команды»?

@saudet Я пытаюсь создать копию оболочек JavaCPP, но мне кажется, что из-за быстрой скорости изменения источника тензорного потока они несовместимы ни с выпуском 0.6.0, ни с сегодняшней основной веткой. Можно ли обновить их с помощью указателя на точную фиксацию / версию тензорного потока, с которой они были протестированы?

@nikitakit Я только что https://github.com/bytedeco/javacpp-presets/commit/43bdcdf03beaaddb4bd5badf5d4f79669e9e78dd

В отличие от Caffe, кажется, что TensorFlow выпускается примерно раз в месяц, поэтому я думаю, что я начну стабилизировать привязки в этих точках, начиная со следующего выпуска (0.7.0?)

@martinwicke Что ты думаешь?

Когда есть стабильная привязка к Java, я рад работать над Scala API.

/ cc @databricks

@kovasb Я думаю, что пропустил этот первый раз. Вы хотите сказать, что вся чудесная магия автодифференцирования, которую мы получаем от использования TensorFlow через python, реализована внутри python, а не в библиотеках c ++? Значит, на практике Java API либо потребуется заново реализовать все это, либо будет просто еще одной библиотекой для числовых данных? Я недостаточно знаком с внутренним устройством TensorFlow или клея для Python, чтобы точно понимать, какие тяжелые работы и где выполняются.

@drdozer , это мое понимание, основанное на комментариях @girving, а затем немного

Если кому-то действительно интересно, я бы просто рекомендовал попробовать сделать несколько обучающих примеров с использованием Java api (пока я только что видел / делал прямой путь).

Интересно, как далеко мы продвинемся с кодом Python с Jython ...

Я считаю, что уровень API Python имеет много логики, которую API уровня C ++ не раскрывает.
Я пытался следовать по пути JavaCpp, но в конце будет много дублированного кода, и будет сложно поддерживать согласованность, когда что-то изменится в реализации Python.

Вероятно, более простой путь - использовать Jython, как упоминал ранее @saudet ...

Он был назначен в https://github.com/tensorflow/tensorflow/issues/476 для @ josh11b. Если он работает над этим, нет смысла использовать Jython.

Если мы будем использовать jython, будет ли работать код c ++? Я хочу использовать это для сервера на Java, но я застрял между попыткой прямого маршрута Java или просто отправкой данных через сокет в процесс Python

Я хотел бы упомянуть, что, хотя Java API не включает в себя множество функций, таких как автоматическая дифференциация, я не обнаружил, что это препятствие для моей собственной работы. Мне очень удалось создать модель на Python, сериализовать ее в файл .proto, а затем открыть ее через оболочку Java для обучения. То же самое можно сделать и во время тестирования, поскольку я считаю, что функция Saver доступна через API C ++ и Java.

+1

@saudet
Спасибо за создание javacpp и предустановок для tenorflow. Мне удалось успешно воссоздать график Python на Java, но я застрял, пытаясь восстановить из сохраненного файла модели. Эта строка не работает:

Тензор fn = новый тензор (tenorflow.DT_STRING, новый TensorShape (1));
CharBuffer buffer = fn.createBuffer ();
buffer.put ("modelfile.tf");
session.Run (...);

но CharBuffer оказывается NULL. Если я изменю DT_STRING на DT_FLOAT, я получу FloatBuffer, но DT_STRING, похоже, не работает.

@nikitakit, ты сказал, что это работает. не могли бы вы поделиться своим кодом?

@lakshmanok

РЕДАКТИРОВАТЬ: извините, неправильно прочитал то, что вы здесь сказали. Я не могу помочь с использованием внешних заставок из Java

Для справки, часть моего кода, которая импортирует графики тензорного потока, находится здесь: https://gist.github.com/nikitakit/d3ec270aee9d930267cec3efa844d5aa

Это на Scala, но перенос на Java / другой язык JVM должен быть простым.

Мой код для фактического запуска узлов в графе, к сожалению, сильно привязан к используемой мной платформе Scala, поэтому вам придется полагаться на документацию по API tenorflow для этой части.

Кто-нибудь получил что-нибудь с встраиванием среды python tensorflow в jvm? Скажите с jython + JyNI? Или все это слишком экспериментально, чтобы заставить работать надежно?

В настоящее время я работаю над расширением C API, чтобы добавить поддержку определения графов. Не уверен, когда это будет сделано, но это одна из наших целей до версии 1.0.

Я работаю над использованием тензорного потока из java. Я подхожу к проблеме, используя jython и модифицируя библиотеку cpython тензорного потока для размещения другого интерпретатора Python. cpython должен продолжать работать безупречно, и мой код определяет, является ли интерпретатор Jython, и изменяет импорт / модули, чтобы он работал. Ниже он использует привязки javacpp для libtensorflow_cc.so. Будет ли это что-то, что команда Google хотела бы разместить в официальном репозитории? @vrv

Это кажется хорошим подтверждением концепции, но я думаю, что официальная привязка, вероятно, захотела бы привязать более естественным образом, чем через Python :(

нет, вместо вызова оболочки c-python мы вызываем оболочку javaccp. Таким образом, это будет то же самое, что и поток тензорного потока cpython, но вычисленный из JVM с использованием Jython. Повторная реализация всей логики Python на другом языке кажется слишком сложной, и вы получаете другой API. Привязки javacpp позволяют без проблем запускать Inference, но на данный момент модель должна быть построена / обучена с помощью скрипта cpython.

Кто-нибудь смотрел, как заставить tenorflow работать с Kotlin? Это кажется более естественным, и в конце концов это все еще 100% java. Я считаю, что язык Kotlin - это очень хорошая середина между Python и чистой Java.

Обновление: мне удалось успешно наладить работу с javacpp (благодаря @saudet ) и заставить Java-программы читать / выполнять модели TensorFlow.

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

Спасибо @lakshmanok и @saudet . Похоже, что проект javacpp реализует большинство API-интерфейсов TensorFlow. Мы пытаемся запустить тензорный поток / обслуживание на Java.

API прост и определяется protobuf . Теперь мы реализовали сервер и хотим реализовать клиент на Java. Ему просто нужно построить TensorProto в Java и вызвать вызов gRPC . TensorFlow предоставляет вспомогательные функции для преобразования многомерных массивов для Python и C ++, но не для Java.

Можете ли вы сказать, как использовать javacpp или реализовать для этого самостоятельно?

То, что вы ищете, вероятно, уже находится в https://github.com/bytedeco/javacpp-presets/blob/master/tensorflow/src/main/java/org/bytedeco/javacpp/helper/tensorflow.java, но дайте мне знать если там чего-то не хватает. Спасибо!

над этим все еще работают? есть ли официальное репозиторий на github для этого проекта переноса? Я вижу пару случайных репозиториев, но не могу сказать.

Ага, но, вероятно, где-нибудь в октябре / ноябре. Мы используем C API вместо SWIGing to C ++ API. А пока вы можете использовать привязки, упомянутые saudet.

как вы пришли к выводу, что использовать C API? мы работаем над
интерфейс ruby ​​с использованием swig:
http://github.com/somaticio/tensorflow.rb

Во вторник, 13 сентября 2016 г., в 18:22, Джонатан Хсеу [email protected]
написал:

Ага, но, вероятно, где-нибудь в октябре / ноябре. Мы используем C API
вместо SWIG перехода к C ++ API. А пока вы можете использовать
привязки, упомянутые saudet.

-
Вы получили это, потому что прокомментировали.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/tensorflow/tensorflow/issues/5#issuecomment -246844192,
или отключить поток
https://github.com/notifications/unsubscribe-auth/AAA5v3g86Z6D1rz-aTGdMyMWnQZhrZUYks5qpyIJgaJpZM4Getd8
.

Забегая вперед, мы бы предпочли, чтобы все языковые привязки использовали C API. Скоро появится документ.

Вы можете увидеть здесь пример использования:
https://github.com/tensorflow/tensorflow/tree/master/tensorflow/go

Тем не менее, в этом нет необходимости, и на данный момент можно использовать SWIG.

@jhseu Означает ли это, что C API будет расширен, чтобы охватить все, к чему привязки Python в настоящее время имеют доступ?

Вау, большая перемена. Желаю, чтобы это было решено раньше. В любом случае, чтобы увидеть документы
раньше?

В среду, 14 сентября 2016 г., в 17:56, Самуэль Одет [email protected]
написал:

@jhseu https://github.com/jhseu Означает ли это, что C API будет
расширен, чтобы охватить все, к чему привязки Python в настоящее время имеют доступ?

-
Вы получили это, потому что прокомментировали.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/tensorflow/tensorflow/issues/5#issuecomment -247167887,
или отключить поток
https://github.com/notifications/unsubscribe-auth/AAA5vwfBJoZC2s33_7E9Xy6-NYNUjHjnks5qqG2FgaJpZM4Getd8
.

@saudet Большая часть функциональности, за исключением краткосрочного отсутствия некоторых вещей (например, градиентов, оптимизаторов).
@jtoy Нет необходимости в срочном

Документы просто описывают, как это сделать, и соглашения об именах. Однако вы можете начать переход на C API и без них:
https://github.com/tensorflow/tensorflow/blob/master/tensorflow/c/c_api.h

Спасибо @saudet . Я нашел это в stackoverflow о создании TensorProto с чистым API protobuf. А вот пример кода TensorFlow, обслуживающего Java-клиент gRPC.

@ tobegit3hub Хорошо , если вы можете заставить эту работу работать с C ++ API, добавьте его во вспомогательный пакет пресетов JavaCPP и отправьте запрос на перенос! Этому парню было бы интересно что-нибудь в этом роде: https://github.com/bytedeco/javacpp-presets/issues/240

@girving Javacpp уже решает проблему?
Я хочу внести свой вклад в tenorflow java api, я предпочитаю реализовывать его как python.

Привет, ребята, кто-нибудь уже начал работать над привязками языков Java / Scala с помощью C API?
(вместо того, чтобы строить поверх SWIG)

У меня есть рабочий интерфейс Java / Scala для tenorflow, использующий только C API через JNR . К сожалению, у меня пока нет разрешения на его открытие с исходным кодом. Я опубликую здесь, если и когда я его выпущу. Это все еще незавершенная работа, но она очень функциональна.

@jdolson Принимает ли предоставляемый вами API буферные объекты протокола @saudet, заключается в том, что когда вы манипулируете тензорными объектами в клиентском коде Java, вы имеете дело с org.tensorflow.framework.TensorProto, которое генерируется компилятором буфера протокола, когда настроен на вывод java. Но в оболочке API TensorFlow вы имеете дело с org.bytedeco.javacpp.tensorflow.TensorProto.TensorProto, который генерируется javacpp при указании на код c, сгенерированный компилятором буфера протокола при настройке на создание C. Точно так же вы не можете напрямую использовать тензоры своего java-кода при вызове обернутого API TensorFlow.

@Intropy Да, я компилирую все источники тензорного потока *.proto в исходный код Java с помощью protoc и использую эти классы в API.

@jhseu Интерфейс C API все еще находится на пути к выпуску где-то в ноябре? Если нет, то каков текущий статус?

@eaplatanios : C API в основном стабилен (и официально станет таковым к 1.0) и пригоден для использования, хотя и не полон (по-прежнему отсутствует возможность автоматического градиентных вычислений к графику). Документ, описывающий, как C API может использоваться для создания языковых привязок, находится по адресу https://www.tensorflow.org/how_tos/language_bindings/index.html.

Go API был реализован с использованием C API в качестве первого примера следования приведенному выше документу.

Мы надеемся, что привязки Java будут также построены поверх этого (с использованием JNI), и начали немного изучать это. Было бы неплохо узнать о любых комментариях / уроках, которые есть у людей, основанных на замечательной работе @saudet по обеспечению работы JavaCPP.

У меня есть несколько предложений, основанных на использовании привязок JavaCPP.

Во-первых, поскольку буферы протокола компилируются непосредственно в java, следует использовать версии java. Я предпочтительно думаю, что буферы протокола, которые участвуют в API, должны быть отдельно доступны в качестве модуля maven и должны поставляться с определениями прототипов, чтобы у людей в стеке Java был простой способ получить определения как в двоичном, так и в простом виде. способ получить прото-определения для включения в другие прото-определения.

Во-вторых, было бы полезно найти минимальную версию libc, которая нужна TensorFlow, и создать ее для этого.

В-третьих, гораздо проще использовать продуманный API, чем автоматически сгенерированный. Я знаю, что это очевидно и звучит как выстрел в JavaCPP. Я не хотел, чтобы это было. Я действительно рад, что существует автоматически сгенерированный интерфейс. Это _is_ полезно. Но это требует странных формулировок, в нем много недостатков, и довольно сложно читать код, чтобы понять, как делать то, что вы пытаетесь сделать. Хотелось бы, чтобы это предложение было более полезным, чем «вы должны сделать это хорошо», но я думаю, дело в том, что посмотрите, насколько отличаются C ++ API и Python API. Оба они просты, потому что они подходят для своей среды таким образом, что автоматически преобразованный код вряд ли будет совпадать.

Возможно, было бы лучше поддерживать бэкэнд C Swig и генерировать TF C API через Swig: https://github.com/swig/swig/issues/800, чтобы другие языки, такие как Go, Ruby, R, могли использовать C api для написания собственных привязок.

У нас есть C API для добавления поддержки любого языка с C FFI:
https://github.com/tensorflow/tensorflow/blob/master/tensorflow/c/c_api.h

(И это то, что используется для создания привязок Go, Java, Rust и т. Д. Для TensorFlow)

Можно ли получить доступ к C API с помощью JNA ?

@jhseu Я имел в виду, что он мог быть сгенерирован из C ++ API раньше, прежде чем вручную реализовать C API.

@ Quantum64, здесь является Scala связывания tensorflow , который использует ЮНУ.

Поскольку этот вопрос все еще открыт, как
https://github.com/tensorflow/tensorflow/tree/master/tensorflow/java
реализуется, и каков был PR для фиксации?

@hsaputra : Не могли бы вы рассказать о том, что ищете? Есть несколько коммитов, которые вносят вклад в код в tensorflow/java , большинство из которых упоминается в этой проблеме (например, 2b1cd28, d73a266 и многие другие между ними)

Привет @asimshankar , спасибо за ответ.

Мне просто интересно, какой путь выбрал tensorflow/java для реализации Java API, поскольку этот билет не закрыт.
Были дискуссии об использовании JavaCPP против SWIG против вызова через Jython.

Похоже, что tensorflow/java реализован с прямым JNI для вызова C API вместо этого?

Верный.

Привет,

У меня только вчера работали эти привязки Swig. У меня есть запрос на изменение API. В настоящее время для генерации тензоров требуется отражение, а формат массивов немного нестабилен, поскольку они требуют использования n-мерных нативных массивов Java. Можем ли мы сохранить этот интерфейс, но также добавить несколько методов для создания тензоров, требующих одномерных массивов, и определения формы с использованием другого массива long? Я предполагаю, что это могло бы выглядеть примерно так:

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);

Это также приведет к возможности создания тензоров int8, int16, uint8, uint16, uint32, что поможет с совместимостью.

Должен ли я сделать это проблемой? Или здесь нормально?

Кроме того, мы более чем счастливы попытаться создать эти методы.

@hollinwilkins : Я надеюсь, что PR # 6577

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

@asimshankar Это здорово! Спасибо за быстрый ответ. Похоже, он тоже довольно близок к слиянию: +1:

Я пытаюсь использовать новый Java API, и я столкнулся с некоторыми вещами, которые усложняют использование, чем я думаю:

  1. API Java должен принимать объект GraphDef. В настоящее время он принимает только массив байтов, представляющий сериализованный двоичный файл буфера протокола GraphDef. Странно требовать этап сериализации / десериализации на границе библиотеки.
  2. Session.Runner.feed должен иметь возможность принимать org.tensorflow.framework.TensorProto или должен быть хороший способ создать org.tensorflow.Tensor из org.tensorflow.framework.TensorProto.
  3. Session.Runner.run возвращает список объектов Tensor. Как и в предыдущем случае, должен быть простой способ получить вывод TensorProto напрямую или предоставив org.tensorflow.Tensor хороший способ конвертировать в TensorProto.
  4. Session.Runner.run проглатывает статус. Должен быть способ получить эту информацию о сбоях, например, с помощью исключения.

Кроме того, возможно, я пропустил способ справиться с этим, но мне кажется, что я не могу получить все поддерживаемые типы тензора в выводе из run. Например, если мой выходной тензор имеет тип dtype INT16, то нет возможности извлечь из него значение. Там нет Tensor.shortValue и т.п., а Tensor.intValue, похоже, требует точного совпадения. Я основываю это на чтении DEFINE_GET_SCALAR_METHOD в tensor_jni.cc.

@Intropy : Спасибо за ваши комментарии, они определенно имеют смысл. А пока я могу поделиться с вами некоторыми мыслями:

RE: protobufs: На этом этапе мы пытаемся сохранить независимость API ядра от protobufs по ряду причин (включая использование в системах с ограниченными ресурсами, где что-то вроде nanproto может быть более подходящим). Вот почему мы колебались, но мы думаем об этом, и предложения приветствуются. Одна из возможностей - иметь все функции, связанные с protobuf, в отдельном пакете, чтобы было четкое разделение.

Итак, возвращаясь к вашим пунктам:

  1. См. Выше. Хотя я бы поспорил, что во многих случаях byte[] имеет больше смысла (например, чтение графика из файла или сетевого канала)

  2. Дело принято

  3. См. Выше.

  4. Session.runner.run не должен быть глотающим. В случае ошибки будет выдано исключение ( session_jni.cc:166 ). Если этого не происходит, сообщите об ошибке.

Вы правы, пока поддерживаются не все типы, но их достаточно легко добавить. Если вам срочно нужны недостающие типы, пожалуйста, сообщите о проблеме и / или отправьте PR. Взносы приветствуются :)

@asimshankar Спасибо за ваши мысли.

Что касается первого пункта, это не имеет большого значения. Как вы говорите, бывают случаи, когда byte [] имеет наибольший смысл. В моем случае использования у меня есть InputStream, который легко преобразовать в byte []. API буфера протокола упрощает преобразование. Я просто считаю byte [] бородавкой в ​​API, потому что вам все равно придется десериализовать (в TF_GraphImportGraphDef), и таким образом вы теряете некоторую безопасность типов. Также следует рассмотреть json-сериализацию proto3.

Что касается статуса глотания, вы правы. Я пропустил непроверенное исключение.

Наиболее очевидный способ обработки 2 и 3 - предоставить org.tensorflow.Tensor фабрику, которая преобразует TensorProto и некоторые toTensorProto (). Если проблема с буферами протокола связана с вариантами использования с ограниченными ресурсами, то люди в таких обстоятельствах просто не могут использовать эти функции. Проблема в том, что люди, которые действительно используют эти функции, будут платить за преобразование, которого, вероятно, можно было бы избежать, если бы Tensor сохранял свои данные непосредственно в протобаффе. Я никогда раньше не работал с jni, поэтому у меня возникают проблемы с отслеживанием того, как хранятся данные, но похоже, что он по сути обрабатывает nativeHandle как указатель на TF_Tensor, у которого есть TensorBuffer, который обрабатывается по существу как размер void *.

Можем ли мы разделить эту проблему и зарегистрировать отдельные проблемы для каждой функции в интерфейсе Java? Будет легче отслеживать / анализировать, тогда мы сможем закрыть эту проблему.

@drpngx : Я намерен внести еще пару изменений (чтение тензоров из буферов), прежде чем закрыть это, как мы это сделали для Go, и чтобы функции / ошибки регистрировались индивидуально. Надеюсь, скоро.

Звучит хорошо, спасибо!

Хорошо, похоже, у нас достаточно базы для развития (например, достаточно, чтобы построить пример LabelImage, и люди отправляют более конкретные сообщения об ошибках / запросы функций.

Я собираюсь закрыть этот вопрос. В Java API еще многое предстоит сделать, но давайте обсудим / проследим их в отдельных вопросах. Спасибо!

@asimshankar, мы находимся в процессе выбора фреймворка глубокого обучения (mxnet / tf), и наши etl / api основаны на потоке spark / akka ... Есть ли план добавить поддержку Distributed_runtime в Java API для запуска параллельного обучения модели с помощью ps узлы? Узел ps критически важен для нас во многих случаях использования ... пресеты javacpp может быть проще экспортировать для первого сокращения, поскольку в самом API C, похоже, нет distribution_runtime ...

@ debasish83 : Включение распределенной среды выполнения само по себе тривиально, но в API Python есть множество конструкций более высокого уровня, таких как класс Estimator которые заботятся о множестве вещей (контрольные точки, итоговое сохранение и т. д., которые сделать визуализацию с помощью TensorBoard тривиальной), что может сделать его более подходящим для выполнения обучающих заданий на Python.

Все это может быть построено с использованием существующих примитивов в Java API, но правильный подход будет зависеть от ваших конкретных потребностей.

Может быть, нам следует синхронизироваться вне потока?

@asimshankar Есть ли уже способ из привязки тензорного потока Java для извлечения информации из graphDef (построенного из файла .pb графа на диске), такого как список узлов, формат ввода и вывода, или это входящая функция? Спасибо!

@asimshankar Я не уверен, что понимаю, чего не хватает для обучения с TF Java. Это проблема числовой библиотеки (отсутствует numpy)? Я имею в виду, если вы не интересуетесь датавизом TensorBoard, а только обучением с использованием собственной числовой библиотеки Java, зачем использовать python только для обучения (как вы предлагаете относительно класса Estimator )?

Спасибо.

Каково состояние обучающих моделей в Java? Я подумывал написать плагин ImageJ (популярный и бесплатный пакет для анализа изображений), чтобы применить такие подходы, как https://arxiv.org/pdf/1505.04597.pdf (недавно очень популярный в сегментации изображений для отслеживания клеток и биомедицинских приложений). Я думаю, было бы полезно предоставить ряд предварительно обученных моделей и дать пользователям возможность уточнить их для своего конкретного случая использования. Для этого я искал DL4J. Есть ли какие-либо конкретные планы по установке привязок TF Java?

@bergwerf : Обучение Java, конечно, возможно, хотя и не особенно удобно.
Вы можете найти образец на https://github.com/tensorflow/models/tree/master/samples/languages/java/training

(Кроме того, я уверен, что вы в курсе, но см. Также https://imagej.net/TensorFlow)

Ой, круто! Значит, моя информация устарела ;-). Я думал, что прочитал
где-то Java API предназначался только для прогнозирования с предварительно обученными
модели. Я рассмотрю этот пример.

В среду, 28 марта 2018 г., 22:01 Асим Шанкар [email protected] написал:

@bergwerf https://github.com/bergwerf : Обучение Java, безусловно,
возможно, если не особо удобно.
Вы можете найти образец на
https://github.com/tensorflow/models/tree/master/samples/languages/java/training

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/tensorflow/tensorflow/issues/5#issuecomment-377015867 ,
или отключить поток
https://github.com/notifications/unsubscribe-auth/AEQJ1UD9-xACQAII5996ees_UFJ_NzL-ks5ti-wSgaJpZM4Getd8
.

@asimshankar , это круто 👍 💯 🥇, я собираюсь добавить в свое репо https://github.com/loretoparisi/tensorflow-java

Была ли эта страница полезной?
0 / 5 - 0 рейтинги