|
| 1 | +# Migrating Between TensorFlow Java Releases |
| 2 | + |
| 3 | +TensorFlow Java is still in an alpha stage, therefore is subject to contain breaking changes between the different releases. This guide explain in detail |
| 4 | +how to migrate your code from a previous version to a new one that includes some changes that are not backward compatible. |
| 5 | + |
| 6 | +## Migrating to 0.3.0 |
| 7 | + |
| 8 | +### Non-parameterized Typed Tensors |
| 9 | + |
| 10 | +In previous versions, the `Tensor` class was parameterized with its tensor type interface, which is part of the `TType` family. To access directly the memory |
| 11 | +tensor from the JVM, an explicit conversion between `Tensor` and its tensor type was required by calling `tensor.data()`. |
| 12 | + |
| 13 | +In 0.3.0, tensors are always typed, making this generic parameter and explicit mapping obsolete. As soon as you get a handle to a tensor, you are able to |
| 14 | +access directly its memory for reading (or writing for most tensor types) and no convertion is required. Any instances of a class in the `TType` family |
| 15 | +can also now be manipulated directly as a `Tensor` (e.g. to be passed to a session for inference). |
| 16 | + |
| 17 | +Steps: |
| 18 | +1. Replace a parameterized `Tensor` by its parameter (e.g. `Tensor<TFloat32>` -> `TFloat32`) |
| 19 | +2. Replace instance of `Tensor<?>` with unknown parameter by `Tensor` |
| 20 | +3. Remove any invocation to `Tensor.data()` (e.g. `tensor.data().getFloat()` -> `tensor.getFloat()`) |
| 21 | +4. Replace any invocation to `Operand.data()` by `Operand.asTensor()` |
| 22 | + |
| 23 | +### Use of Java Type System instead of DataType |
| 24 | + |
| 25 | +In previous versions, the `DataType` class was used to carry information about the type of a `Tensor`, that can then be converted back to a tensor of that |
| 26 | +type (see previous section). Since there were a exact parity between interfaces of the `TType` family and an instance of `DataType`, the latter has been dropped |
| 27 | +in 0.3.0 to leverage instead the standard type system in Java, for a better idiomatic experience. |
| 28 | + |
| 29 | +Steps: |
| 30 | +1. Replace all accesses to the `DTYPE` field of a `TType` interface by its class (e.g. `TFloat32.DTYPE` -> `TFloat32.class`) |
| 31 | +2. Use Java type system for checking tensor types at runtime (e.g. using `instanceof` or `isAssignableFrom`) |
| 32 | +3. Replace any invocation to `Tensor.expect()` by an explicit cast (e.g. `tensor.expect(TFloat32.DTYPE)` -> `(TFloat32)tensor`) |
| 33 | + |
| 34 | +### Example |
| 35 | + |
| 36 | +0.2.0: |
| 37 | +``` |
| 38 | +Session session = ...; |
| 39 | +
|
| 40 | +try (Tensor<TFloat32> tensor = TFloat32.tensorOf(Shape.of(1, 2))) { |
| 41 | + TFloat32 tensorData = tensor.data(); |
| 42 | + tensorData.setFloat(10.0f, 0); |
| 43 | + tensorData.setFloat(20.0f, 1); |
| 44 | + |
| 45 | + try (Tensor<?> result = session.runner().feed("x", tensor).fetch("y").run().get(0)) { |
| 46 | + if (result.dataType() == TFloat32.DTYPE) { |
| 47 | + Tensor<TFloat32> typedResult = result.expect(TFloat32.DTYPE); |
| 48 | + TFloat32 resultData = typedResult.data(); |
| 49 | + System.out.println("Result is " + resultData.getFloat()); |
| 50 | + } |
| 51 | + } |
| 52 | +} |
| 53 | +``` |
| 54 | + |
| 55 | +0.3.0: |
| 56 | +``` |
| 57 | +Session session = ...; |
| 58 | +
|
| 59 | +try (TFloat32 tensor = TFloat32.tensorOf(Shape.of(1, 2))) { |
| 60 | + tensor.setFloat(10.0f, 0); |
| 61 | + tensor.setFloat(20.0f, 1); |
| 62 | + |
| 63 | + try (Tensor result = session.runner().feed("x", tensor).fetch("y").run().get(0)) { |
| 64 | + if (result instanceof TFloat32) { |
| 65 | + TFloat32 typedResult = (TFloat32)result; |
| 66 | + System.out.println("Result is " + typedResult.getFloat()); |
| 67 | + } |
| 68 | + } |
| 69 | +} |
| 70 | +``` |
| 71 | + |
0 commit comments