From be0ebe51de60c9f861fb4e61bd2f9f44014a90d6 Mon Sep 17 00:00:00 2001 From: klessard Date: Tue, 24 Aug 2021 23:43:53 -0400 Subject: [PATCH 1/7] Fix filename tensor name in SaverDef --- .../src/main/java/org/tensorflow/Graph.java | 64 +++++++++---------- .../src/main/java/org/tensorflow/Output.java | 21 ++++-- .../main/java/org/tensorflow/Signature.java | 32 +++++----- .../org/tensorflow/SavedModelBundleTest.java | 9 ++- 4 files changed, 70 insertions(+), 56 deletions(-) diff --git a/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/Graph.java b/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/Graph.java index 0f7a291466c..e6fc8b9ac47 100644 --- a/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/Graph.java +++ b/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/Graph.java @@ -461,11 +461,12 @@ synchronized SaverDef saverDef() { // regenerate SaverDef without mutating. The names mirror // the python implementation for compatibility. // https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/training/saver.py - saverDef = SaverDef.newBuilder() - .setFilenameTensorName("save/filename") - .setSaveTensorName("save/control_dependency") - .setRestoreOpName("save/restore_all") - .build(); + saverDef = + SaverDef.newBuilder() + .setFilenameTensorName("save/filename:0") + .setSaveTensorName("save/control_dependency") + .setRestoreOpName("save/restore_all") + .build(); } } return saverDef; @@ -812,36 +813,35 @@ private static SaverDef addVariableSaver(Graph graph) { } } - // FIXME Need an easier way to initialize an NdArray from a list - String[] tmp = new String[varNames.size()]; - Constant varNamesTensor = tf.constant(StdArrays.ndCopyOf(varNames.toArray(tmp))); - Operand varSlices = tf.zerosLike(varNamesTensor); - - Placeholder saveFilename = tf.withName("filename").placeholder(TString.class); - Save saveVariables = tf.train.save( - saveFilename, - varNamesTensor, - varSlices, - varOutputs - ); - Identity id = tf.withControlDependencies(Arrays.asList(saveFilename,saveVariables)) - .withName("control_dependency").identity(saveFilename); - Restore restoreVariables = tf.train.restore( - saveFilename, - varNamesTensor, - varSlices, - varTypes - ); - List restoreOps = new ArrayList<>(varOutputs.size()); - for (int i = 0; i < varOutputs.size(); ++i) { - restoreOps.add(tf.assign(varOutputs.get(i), (Operand) restoreVariables.tensors().get(i))); + Placeholder filename = tf.withName("filename").placeholder(TString.class); + Identity save = null; + NoOp restore = null; + + if (varNames.isEmpty()) { + save = tf.withName("empty_save").identity(filename); + restore = tf.withName("restore_all").noOp(); + } else { + String[] tmp = new String[varNames.size()]; + Constant varNamesTensor = tf.constant(StdArrays.ndCopyOf(varNames.toArray(tmp))); + Operand varSlices = tf.zerosLike(varNamesTensor); + Save saveVars = tf.train.save(filename, varNamesTensor, varSlices, varOutputs); + List saveDeps = Arrays.asList(filename, saveVars); + Restore restoreVars = tf.train.restore(filename, varNamesTensor, varSlices, varTypes); + List restoreDeps = new ArrayList<>(varOutputs.size()); + for (int i = 0; i < varOutputs.size(); ++i) { + restoreDeps.add(tf.assign(varOutputs.get(i), (Operand) restoreVars.tensors().get(i))); + } + save = tf.withControlDependencies(saveDeps).withName("control_dependency").identity(filename); + restore = tf.withControlDependencies(restoreDeps).withName("restore_all").noOp(); } - NoOp restoreAll = tf.withControlDependencies(restoreOps).withName("restore_all").noOp(); + // 'Filename' must be the name of a tensor (i.e. with output index) + // 'Save' must be an operation name, even if the field name is confusing (see SaverDef doc) + // 'Restore' must be an operation name return SaverDef.newBuilder() - .setFilenameTensorName(saveFilename.op().name()) - .setSaveTensorName(id.op().name()) - .setRestoreOpName(restoreAll.op().name()) + .setFilenameTensorName(filename.output().name()) + .setSaveTensorName(save.op().name()) + .setRestoreOpName(restore.op().name()) .build(); } diff --git a/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/Output.java b/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/Output.java index 9e7dedfdc75..a7e48fcb9ee 100644 --- a/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/Output.java +++ b/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/Output.java @@ -38,6 +38,11 @@ public int index() { return index; } + /** Returns the full name of this Output (a.k.a. tensor name) */ + public String name() { + return op().name() + ":" + index; + } + /** Returns the DataType of the tensor referred to by this Output. */ @SuppressWarnings("unchecked") public DataType dataType() { @@ -48,7 +53,7 @@ public DataType dataType() { @SuppressWarnings("unchecked") @Override public Class type() { - return (Class)TensorTypeRegistry.find(dataType()).type(); + return (Class) TensorTypeRegistry.find(dataType()).type(); } /** @@ -63,7 +68,10 @@ public Class type() { public Output expect(Class type) { if (type != type()) { throw new IllegalArgumentException( - "Cannot cast from output of " + this.type().getSimpleName() + " to output of " + type.getSimpleName()); + "Cannot cast from output of " + + this.type().getSimpleName() + + " to output of " + + type.getSimpleName()); } return ((Output) this); } @@ -80,17 +88,16 @@ public Output expect(Class type) { * * @return tensor * @throws IllegalStateException if this output results from a graph - * @throws ClassCastException if the type of the tensor and this output are unexpectedly incompatible + * @throws ClassCastException if the type of the tensor and this output are unexpectedly + * incompatible * @see EagerSession */ @SuppressWarnings("unchecked") public T asTensor() { - return (T)operation.tensor(index); + return (T) operation.tensor(index); } - /** - * Returns the (possibly partially known) shape of the tensor referred to by this output. - */ + /** Returns the (possibly partially known) shape of the tensor referred to by this output. */ @Override public Shape shape() { return operation.shape(index); diff --git a/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/Signature.java b/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/Signature.java index c0d15050159..f9db09639de 100644 --- a/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/Signature.java +++ b/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/Signature.java @@ -1,18 +1,18 @@ -/* - * Copyright 2020 The TensorFlow Authors. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +/* Copyright 2020-2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +======================================================================= +*/ package org.tensorflow; import java.util.HashMap; @@ -171,7 +171,7 @@ public Set outputNames() { @Override public String toString() { - StringBuilder strBuilder = new StringBuilder("Signature for \"" + key +"\":\n"); + StringBuilder strBuilder = new StringBuilder("Signature for \"" + key + "\":\n"); String methodName = methodName(); if (methodName != null && !methodName.isEmpty()) { strBuilder.append("\tMethod: \"").append(methodName).append("\"\n"); diff --git a/tensorflow-core/tensorflow-core-api/src/test/java/org/tensorflow/SavedModelBundleTest.java b/tensorflow-core/tensorflow-core-api/src/test/java/org/tensorflow/SavedModelBundleTest.java index cd8ac7e2ae4..91e430ef1b0 100644 --- a/tensorflow-core/tensorflow-core-api/src/test/java/org/tensorflow/SavedModelBundleTest.java +++ b/tensorflow-core/tensorflow-core-api/src/test/java/org/tensorflow/SavedModelBundleTest.java @@ -44,6 +44,7 @@ import org.tensorflow.proto.framework.RunOptions; import org.tensorflow.proto.framework.SignatureDef; import org.tensorflow.proto.framework.TensorInfo; +import org.tensorflow.proto.util.SaverDef; import org.tensorflow.types.TFloat32; /** Unit tests for {@link org.tensorflow.SavedModelBundle}. */ @@ -123,7 +124,13 @@ public void exportFunctionWithVariables() throws IOException { try (SavedModelBundle savedModel = SavedModelBundle.load(testFolder.toString(), SavedModelBundle.DEFAULT_TAG)) { assertNotNull(savedModel.metaGraphDef()); - assertNotNull(savedModel.metaGraphDef().getSaverDef()); + + SaverDef saverDef = savedModel.metaGraphDef().getSaverDef(); + assertNotNull(saverDef); + assertEquals("save/filename:0", saverDef.getFilenameTensorName()); + assertEquals("save/control_dependency", saverDef.getSaveTensorName()); + assertEquals("save/restore_all", saverDef.getRestoreOpName()); + assertEquals(1, savedModel.metaGraphDef().getSignatureDefCount()); assertEquals(Signature.DEFAULT_KEY, savedModel.metaGraphDef().getSignatureDefMap().keySet().iterator().next()); From 585dcf0792166dffdadfbc3ad9348b33616c7781 Mon Sep 17 00:00:00 2001 From: Till Brychcy Date: Fri, 6 Aug 2021 15:04:05 +0200 Subject: [PATCH 2/7] Don't dealloc strings if the TensorBuffer is shared (#357) (#358) --- .../internal/c_api/AbstractTF_Tensor.java | 160 ++++++++++-------- 1 file changed, 89 insertions(+), 71 deletions(-) diff --git a/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/internal/c_api/AbstractTF_Tensor.java b/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/internal/c_api/AbstractTF_Tensor.java index b4b498f95ef..f081b6cdaac 100644 --- a/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/internal/c_api/AbstractTF_Tensor.java +++ b/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/internal/c_api/AbstractTF_Tensor.java @@ -1,19 +1,19 @@ /* - Copyright 2019 The TensorFlow Authors. All Rights Reserved. +Copyright 2019 The TensorFlow Authors. All Rights Reserved. - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - ======================================================================= - */ +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +======================================================================= +*/ package org.tensorflow.internal.c_api; @@ -25,6 +25,7 @@ import static org.tensorflow.internal.c_api.global.tensorflow.TF_TString_Init; import static org.tensorflow.internal.c_api.global.tensorflow.TF_TensorData; import static org.tensorflow.internal.c_api.global.tensorflow.TF_TensorElementCount; +import static org.tensorflow.internal.c_api.global.tensorflow.TF_TensorMaybeMove; import static org.tensorflow.internal.c_api.global.tensorflow.TF_TensorType; import org.bytedeco.javacpp.Pointer; @@ -32,76 +33,93 @@ @Properties(inherit = org.tensorflow.internal.c_api.presets.tensorflow.class) public abstract class AbstractTF_Tensor extends Pointer { - protected static class DeleteDeallocator extends TF_Tensor implements Pointer.Deallocator { - DeleteDeallocator(TF_Tensor s) { super(s); } - @Override public void deallocate() { - if (!isNull()) { - if (TF_TensorType(this) == TF_STRING) { - // we need to deallocate the strings themselves before deallocating the tensor memory - long n = TF_TensorElementCount(this); - TF_TString data = new TF_TString(TF_TensorData(this)); - for (int i = 0; i < n; i++) { - TF_TString_Dealloc(data.position(i)); - } - } - TF_DeleteTensor(this); + protected static class DeleteDeallocator extends TF_Tensor implements Pointer.Deallocator { + DeleteDeallocator(TF_Tensor s) { + super(s); + } + + @Override + public void deallocate() { + if (!isNull()) { + if (TF_TensorType(this) == TF_STRING) { + TF_Tensor moved = TF_TensorMaybeMove(this); + if (moved != null) { + // we need to deallocate the strings themselves before deallocating the tensor memory + long n = TF_TensorElementCount(moved); + TF_TString data = new TF_TString(TF_TensorData(moved)); + for (int i = 0; i < n; i++) { + TF_TString_Dealloc(data.position(i)); } - setNull(); + TF_DeleteTensor(moved); + } else { + // TensorBuffer is shared, leave contained strings alone. + TF_DeleteTensor(this); + } + } else { + TF_DeleteTensor(this); } + } + setNull(); } + } - /** TensorFlow crashes if we don't pass it a deallocator, so... */ - protected static Deallocator_Pointer_long_Pointer dummyDeallocator = new Deallocator_Pointer_long_Pointer() { - @Override public void call(Pointer data, long len, Pointer arg) { } - }.retainReference(); + /** TensorFlow crashes if we don't pass it a deallocator, so... */ + protected static Deallocator_Pointer_long_Pointer dummyDeallocator = + new Deallocator_Pointer_long_Pointer() { + @Override + public void call(Pointer data, long len, Pointer arg) {} + }.retainReference(); - /** A reference to prevent deallocation. */ - protected Pointer pointer; + /** A reference to prevent deallocation. */ + protected Pointer pointer; - public AbstractTF_Tensor(Pointer p) { super(p); } + public AbstractTF_Tensor(Pointer p) { + super(p); + } - /** - * Calls TF_NewTensor(), and registers a deallocator. - * @return TF_Tensor created. Do not call TF_DeleteTensor() on it. - */ - public static TF_Tensor newTensor(int dtype, long[] dims, Pointer data) { - TF_Tensor t = TF_NewTensor(dtype, dims, dims.length, data, data.limit(), dummyDeallocator, null); - if (t != null) { - t.pointer = data; - t.deallocator(new DeleteDeallocator(t)); - } - return t; + /** + * Calls TF_NewTensor(), and registers a deallocator. + * + * @return TF_Tensor created. Do not call TF_DeleteTensor() on it. + */ + public static TF_Tensor newTensor(int dtype, long[] dims, Pointer data) { + TF_Tensor t = + TF_NewTensor(dtype, dims, dims.length, data, data.limit(), dummyDeallocator, null); + if (t != null) { + t.pointer = data; + t.deallocator(new DeleteDeallocator(t)); } + return t; + } - /** - * Calls TF_AllocateTensor(), and registers a deallocator. - * @return TF_Tensor created. Do not call TF_DeleteTensor() on it. - */ - public static TF_Tensor allocateTensor(int dtype, long[] dims, long length) { - TF_Tensor t = TF_AllocateTensor(dtype, dims, dims.length, length); - if (t != null) { - if (TF_TensorType(t) == TF_STRING) { - // we need to initialize the strings themselves after allocating the tensor memory - long n = TF_TensorElementCount(t); - TF_TString data = new TF_TString(TF_TensorData(t)); - for (int i = 0; i < n; i++) { - TF_TString_Init(data.position(i)); - } - } - t.deallocator(new DeleteDeallocator(t)); + /** + * Calls TF_AllocateTensor(), and registers a deallocator. + * + * @return TF_Tensor created. Do not call TF_DeleteTensor() on it. + */ + public static TF_Tensor allocateTensor(int dtype, long[] dims, long length) { + TF_Tensor t = TF_AllocateTensor(dtype, dims, dims.length, length); + if (t != null) { + if (TF_TensorType(t) == TF_STRING) { + // we need to initialize the strings themselves after allocating the tensor memory + long n = TF_TensorElementCount(t); + TF_TString data = new TF_TString(TF_TensorData(t)); + for (int i = 0; i < n; i++) { + TF_TString_Init(data.position(i)); } - return t; + } + t.deallocator(new DeleteDeallocator(t)); } + return t; + } - /** Registers a deallocator and returns this. */ - public TF_Tensor withDeallocator() { - return (TF_Tensor)this.deallocator(new DeleteDeallocator((TF_Tensor)this)); - } + /** Registers a deallocator and returns this. */ + public TF_Tensor withDeallocator() { + return (TF_Tensor) this.deallocator(new DeleteDeallocator((TF_Tensor) this)); + } - /** - * Calls the deallocator, if registered, otherwise has no effect. - */ - public void delete() { - deallocate(); - } + /** Calls the deallocator, if registered, otherwise has no effect. */ + public void delete() { + deallocate(); + } } From 788b4da799494ccb88b5deca8cbad53ace6673c5 Mon Sep 17 00:00:00 2001 From: klessard Date: Sat, 28 Aug 2021 13:04:07 -0400 Subject: [PATCH 3/7] Releasing 0.3.3 --- README.md | 15 ++++++++------- ndarray/README.md | 2 +- ndarray/pom.xml | 2 +- pom.xml | 2 +- tensorflow-core/pom.xml | 2 +- tensorflow-core/tensorflow-core-api/pom.xml | 2 +- tensorflow-core/tensorflow-core-generator/pom.xml | 2 +- .../tensorflow-core-platform-gpu/pom.xml | 2 +- .../tensorflow-core-platform-mkl-gpu/pom.xml | 2 +- .../tensorflow-core-platform-mkl/pom.xml | 2 +- tensorflow-core/tensorflow-core-platform/pom.xml | 2 +- tensorflow-framework/pom.xml | 2 +- 12 files changed, 19 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 45f56c31095..5db730e7447 100644 --- a/README.md +++ b/README.md @@ -61,12 +61,12 @@ systems, you should add the following dependencies: org.tensorflow tensorflow-core-api - 0.3.2 + 0.3.3 org.tensorflow tensorflow-core-api - 0.3.2 + 0.3.3 linux-x86_64${javacpp.platform.extension} ``` @@ -77,24 +77,24 @@ native dependencies as follows: org.tensorflow tensorflow-core-api - 0.3.2 + 0.3.3 org.tensorflow tensorflow-core-api - 0.3.2 + 0.3.3 linux-x86_64${javacpp.platform.extension} org.tensorflow tensorflow-core-api - 0.3.2 + 0.3.3 macosx-x86_64${javacpp.platform.extension} org.tensorflow tensorflow-core-api - 0.3.2 + 0.3.3 windows-x86_64${javacpp.platform.extension} ``` @@ -107,7 +107,7 @@ artifact includes transitively all the artifacts above as a single dependency: org.tensorflow tensorflow-core-platform${javacpp.platform.extension} - 0.3.2 + 0.3.3 ``` @@ -152,6 +152,7 @@ This table shows the mapping between different version of TensorFlow for Java an | 0.3.0 | 2.4.1 | | 0.3.1 | 2.4.1 | | 0.3.2 | 2.4.1 | +| 0.3.3 | 2.4.1 | ## How to Contribute? diff --git a/ndarray/README.md b/ndarray/README.md index 33725cc5598..fc4189544fd 100644 --- a/ndarray/README.md +++ b/ndarray/README.md @@ -11,7 +11,7 @@ To import the NdArray library in your project, simply add the following dependen org.tensorflow ndarray - 0.3.2 + 0.3.3 ``` diff --git a/ndarray/pom.xml b/ndarray/pom.xml index e20803bf2ea..dad085cb6a1 100644 --- a/ndarray/pom.xml +++ b/ndarray/pom.xml @@ -22,7 +22,7 @@ org.tensorflow tensorflow-java - 0.3.2 + 0.3.3 ndarray jar diff --git a/pom.xml b/pom.xml index 956beebb01c..285b6775a57 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.tensorflow tensorflow-java - 0.3.2 + 0.3.3 pom TensorFlow Java Parent diff --git a/tensorflow-core/pom.xml b/tensorflow-core/pom.xml index 983bb40cda2..76a62a37a98 100644 --- a/tensorflow-core/pom.xml +++ b/tensorflow-core/pom.xml @@ -22,7 +22,7 @@ org.tensorflow tensorflow-java - 0.3.2 + 0.3.3 tensorflow-core pom diff --git a/tensorflow-core/tensorflow-core-api/pom.xml b/tensorflow-core/tensorflow-core-api/pom.xml index 6f1e9fca9f6..d6355c2456b 100644 --- a/tensorflow-core/tensorflow-core-api/pom.xml +++ b/tensorflow-core/tensorflow-core-api/pom.xml @@ -6,7 +6,7 @@ org.tensorflow tensorflow-core - 0.3.2 + 0.3.3 tensorflow-core-api jar diff --git a/tensorflow-core/tensorflow-core-generator/pom.xml b/tensorflow-core/tensorflow-core-generator/pom.xml index c70f03ad716..b68e9c6123b 100644 --- a/tensorflow-core/tensorflow-core-generator/pom.xml +++ b/tensorflow-core/tensorflow-core-generator/pom.xml @@ -5,7 +5,7 @@ org.tensorflow tensorflow-core - 0.3.2 + 0.3.3 tensorflow-core-generator jar diff --git a/tensorflow-core/tensorflow-core-platform-gpu/pom.xml b/tensorflow-core/tensorflow-core-platform-gpu/pom.xml index 1d2c6e8a654..9c71e94ba7a 100644 --- a/tensorflow-core/tensorflow-core-platform-gpu/pom.xml +++ b/tensorflow-core/tensorflow-core-platform-gpu/pom.xml @@ -22,7 +22,7 @@ org.tensorflow tensorflow-core - 0.3.2 + 0.3.3 tensorflow-core-platform-gpu TensorFlow Core API Library Platform GPU diff --git a/tensorflow-core/tensorflow-core-platform-mkl-gpu/pom.xml b/tensorflow-core/tensorflow-core-platform-mkl-gpu/pom.xml index 13261f8c564..58576433658 100644 --- a/tensorflow-core/tensorflow-core-platform-mkl-gpu/pom.xml +++ b/tensorflow-core/tensorflow-core-platform-mkl-gpu/pom.xml @@ -22,7 +22,7 @@ org.tensorflow tensorflow-core - 0.3.2 + 0.3.3 tensorflow-core-platform-mkl-gpu TensorFlow Core API Library Platform MKL GPU diff --git a/tensorflow-core/tensorflow-core-platform-mkl/pom.xml b/tensorflow-core/tensorflow-core-platform-mkl/pom.xml index 6cab15b0289..1ddecdf6f29 100644 --- a/tensorflow-core/tensorflow-core-platform-mkl/pom.xml +++ b/tensorflow-core/tensorflow-core-platform-mkl/pom.xml @@ -22,7 +22,7 @@ org.tensorflow tensorflow-core - 0.3.2 + 0.3.3 tensorflow-core-platform-mkl TensorFlow Core API Library Platform MKL diff --git a/tensorflow-core/tensorflow-core-platform/pom.xml b/tensorflow-core/tensorflow-core-platform/pom.xml index b4b15e1a1e9..e5ff9ac6b74 100644 --- a/tensorflow-core/tensorflow-core-platform/pom.xml +++ b/tensorflow-core/tensorflow-core-platform/pom.xml @@ -22,7 +22,7 @@ org.tensorflow tensorflow-core - 0.3.2 + 0.3.3 tensorflow-core-platform TensorFlow Core API Library Platform diff --git a/tensorflow-framework/pom.xml b/tensorflow-framework/pom.xml index 2ce6810f6de..89ee38ec799 100644 --- a/tensorflow-framework/pom.xml +++ b/tensorflow-framework/pom.xml @@ -22,7 +22,7 @@ org.tensorflow tensorflow-java - 0.3.2 + 0.3.3 tensorflow-framework jar From 80a5d1c107c6f87b2b16b4456cb9d371da1726ac Mon Sep 17 00:00:00 2001 From: Adam Pocock Date: Fri, 9 Jul 2021 18:09:07 -0400 Subject: [PATCH 4/7] Fix for SavedModelBundle to load empty tags as these are present in some TF-hub models. --- .../src/main/java/org/tensorflow/SavedModelBundle.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/SavedModelBundle.java b/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/SavedModelBundle.java index d27b2fbad9b..9200003bb6a 100644 --- a/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/SavedModelBundle.java +++ b/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/SavedModelBundle.java @@ -29,6 +29,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.stream.Collectors; import org.bytedeco.javacpp.BytePointer; import org.bytedeco.javacpp.PointerScope; @@ -432,7 +433,7 @@ private static SavedModelBundle load( } private static void validateTags(String[] tags) { - if (tags == null || Arrays.stream(tags).anyMatch(t -> t == null || t.isEmpty())) { + if (tags == null || Arrays.stream(tags).anyMatch(Objects::isNull)) { throw new IllegalArgumentException("Invalid tags: " + Arrays.toString(tags)); } } From a0559e012b6fb07a03844aa9557daae260359c63 Mon Sep 17 00:00:00 2001 From: Adam Pocock Date: Mon, 30 Aug 2021 10:11:01 -0400 Subject: [PATCH 5/7] Removing inaccurate tests. --- .../src/test/java/org/tensorflow/SavedModelBundleTest.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tensorflow-core/tensorflow-core-api/src/test/java/org/tensorflow/SavedModelBundleTest.java b/tensorflow-core/tensorflow-core-api/src/test/java/org/tensorflow/SavedModelBundleTest.java index 91e430ef1b0..41cdc1be05c 100644 --- a/tensorflow-core/tensorflow-core-api/src/test/java/org/tensorflow/SavedModelBundleTest.java +++ b/tensorflow-core/tensorflow-core-api/src/test/java/org/tensorflow/SavedModelBundleTest.java @@ -274,18 +274,12 @@ public void cannotExportOrImportInvalidTags() { assertThrows(IllegalArgumentException.class, () -> SavedModelBundle.loader("/").withTags(new String[]{"tag", null}) ); - assertThrows(IllegalArgumentException.class, () -> - SavedModelBundle.loader("/").withTags(new String[]{"tag", ""}) - ); assertThrows(IllegalArgumentException.class, () -> SavedModelBundle.exporter("/").withTags(null) ); assertThrows(IllegalArgumentException.class, () -> SavedModelBundle.exporter("/").withTags(new String[]{"tag", null}) ); - assertThrows(IllegalArgumentException.class, () -> - SavedModelBundle.exporter("/").withTags(new String[]{"tag", ""}) - ); } @Test From ae7194fd2e966d076b3e9d261ca96be911dae52c Mon Sep 17 00:00:00 2001 From: Karl Lessard Date: Mon, 30 Aug 2021 10:15:04 -0400 Subject: [PATCH 6/7] Delete pom.xml.asc --- tensorflow-core/tensorflow-core-api/pom.xml.asc | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 tensorflow-core/tensorflow-core-api/pom.xml.asc diff --git a/tensorflow-core/tensorflow-core-api/pom.xml.asc b/tensorflow-core/tensorflow-core-api/pom.xml.asc deleted file mode 100644 index 74b09cfdf57..00000000000 --- a/tensorflow-core/tensorflow-core-api/pom.xml.asc +++ /dev/null @@ -1,11 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iQEzBAABCgAdFiEEWu023GNpk04uFesXZq1sy4nWP0UFAmBMBX4ACgkQZq1sy4nW -P0WtsAgAhEuh6JPep7J54gWfpQuhHqI2Fg1/mL767pjeF5I0y+oON3OucWS4NXp9 -N9ALsfAjEOUg4zpOJvDq+F1+0jRP3J+39ieWrmGQGKNUimd1y1MWtfXXfbSjGvgy -AL+0PzMxBlJFALIOUHGTq8fBGYIfv2rWggScggi82nDM0mMXMppPjvVPbpKf03nH -sSQ8czG0SRwrW0FsvTwidGo7HRfsKfGoSsQVAbs75d0oS6IOFTmqOzugFb/yMLcv -7Z1CZ0mKJNh7EbMMSm2AXhE1opNfdVP4HrgjZWXb4VyPqgooZUAQUY1jVYB4ZxOY -iFTVHvCUF8QM2a/fTrfPj+Z1Gbug6g== -=lLR5 ------END PGP SIGNATURE----- From 1ce2ddaefbb1bf4e7417abc01083cbad8be783f6 Mon Sep 17 00:00:00 2001 From: klessard Date: Mon, 30 Aug 2021 10:40:30 -0400 Subject: [PATCH 7/7] Use invariable op names for saver def --- .../src/main/java/org/tensorflow/Graph.java | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/Graph.java b/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/Graph.java index e6fc8b9ac47..4859d0e267c 100644 --- a/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/Graph.java +++ b/tensorflow-core/tensorflow-core-api/src/main/java/org/tensorflow/Graph.java @@ -453,19 +453,17 @@ public Output[] whileLoop( synchronized SaverDef saverDef() { if (saverDef == null) { // Check to see if this graph has a restore operation - if (operation("save/restore_all") == null) { + if (operation(SAVER_DEF_SCOPE + "/" + SAVER_DEF_RESTORE_OP) == null) { // No saver, create one by mutating the graph saverDef = addVariableSaver(this); } else { // This graph already has saving/restoring operations, - // regenerate SaverDef without mutating. The names mirror - // the python implementation for compatibility. - // https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/training/saver.py + // regenerate SaverDef without mutating. saverDef = SaverDef.newBuilder() - .setFilenameTensorName("save/filename:0") - .setSaveTensorName("save/control_dependency") - .setRestoreOpName("save/restore_all") + .setFilenameTensorName(SAVER_DEF_SCOPE + "/" + SAVER_DEF_FILENAME_OP + ":0") + .setSaveTensorName(SAVER_DEF_SCOPE + "/" + SAVER_DEF_SAVE_OP) + .setRestoreOpName(SAVER_DEF_SCOPE + "/" + SAVER_DEF_RESTORE_OP) .build(); } } @@ -571,6 +569,13 @@ public void remove() { private int position; } + // These names mirror the python implementation, to reduce the risk of incompatibility. + // https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/training/saver.py + private static final String SAVER_DEF_SCOPE = "save"; + private static final String SAVER_DEF_FILENAME_OP = "filename"; + private static final String SAVER_DEF_SAVE_OP = "control_dependency"; + private static final String SAVER_DEF_RESTORE_OP = "restore_all"; + private static TF_Graph allocate() { return TF_NewGraph(); } @@ -798,7 +803,7 @@ private static Object[] whileLoop( } private static SaverDef addVariableSaver(Graph graph) { - Ops tf = Ops.create(graph).withSubScope("save"); + Ops tf = Ops.create(graph).withSubScope(SAVER_DEF_SCOPE); List varNames = new ArrayList<>(); List> varOutputs = new ArrayList<>(); @@ -813,13 +818,13 @@ private static SaverDef addVariableSaver(Graph graph) { } } - Placeholder filename = tf.withName("filename").placeholder(TString.class); + Placeholder filename = tf.withName(SAVER_DEF_FILENAME_OP).placeholder(TString.class); Identity save = null; NoOp restore = null; if (varNames.isEmpty()) { - save = tf.withName("empty_save").identity(filename); - restore = tf.withName("restore_all").noOp(); + save = tf.withName(SAVER_DEF_SAVE_OP).identity(filename); + restore = tf.withName(SAVER_DEF_RESTORE_OP).noOp(); } else { String[] tmp = new String[varNames.size()]; Constant varNamesTensor = tf.constant(StdArrays.ndCopyOf(varNames.toArray(tmp))); @@ -831,8 +836,8 @@ private static SaverDef addVariableSaver(Graph graph) { for (int i = 0; i < varOutputs.size(); ++i) { restoreDeps.add(tf.assign(varOutputs.get(i), (Operand) restoreVars.tensors().get(i))); } - save = tf.withControlDependencies(saveDeps).withName("control_dependency").identity(filename); - restore = tf.withControlDependencies(restoreDeps).withName("restore_all").noOp(); + save = tf.withControlDependencies(saveDeps).withName(SAVER_DEF_SAVE_OP).identity(filename); + restore = tf.withControlDependencies(restoreDeps).withName(SAVER_DEF_RESTORE_OP).noOp(); } // 'Filename' must be the name of a tensor (i.e. with output index)