| @@ -25,9 +25,11 @@ https://tensorflownet.readthedocs.io</Description> | |||
| * Eager Mode is added finally. | |||
| * tf.keras is partially working. | |||
| * tf.data is added. | |||
| * autograph works partially. | |||
| * Autograph works partially. | |||
| * Improve memory usage. | |||
| TensorFlow .NET v0.3x is focused on making more Keras API works</PackageReleaseNotes> | |||
| TensorFlow .NET v0.3x is focused on making more Keras API works. | |||
| Keras API is a separate package released as TensorFlow.Keras.</PackageReleaseNotes> | |||
| <FileVersion>0.33.0.0</FileVersion> | |||
| <PackageLicenseFile>LICENSE</PackageLicenseFile> | |||
| <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | |||
| @@ -83,7 +85,7 @@ TensorFlow .NET v0.3x is focused on making more Keras API works</PackageReleaseN | |||
| <PackageReference Include="MethodBoundaryAspect.Fody" Version="2.0.138" /> | |||
| <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.1" /> | |||
| <PackageReference Include="NumSharp.Lite" Version="0.1.12" /> | |||
| <PackageReference Include="Protobuf.Text" Version="0.4.0" /> | |||
| <PackageReference Include="Protobuf.Text" Version="0.5.0" /> | |||
| <PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" /> | |||
| </ItemGroup> | |||
| </Project> | |||
| @@ -0,0 +1,14 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| namespace Tensorflow | |||
| { | |||
| public enum TF_TString_Type | |||
| { | |||
| TF_TSTR_SMALL = 0, | |||
| TF_TSTR_LARGE = 1, | |||
| TF_TSTR_OFFSET = 2, | |||
| TF_TSTR_VIEW = 3 | |||
| } | |||
| } | |||
| @@ -0,0 +1,16 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| using Tensorflow.Util; | |||
| namespace Tensorflow | |||
| { | |||
| public class TStringHandle : SafeTensorflowHandle | |||
| { | |||
| protected override bool ReleaseHandle() | |||
| { | |||
| c_api.TF_StringDealloc(handle); | |||
| return true; | |||
| } | |||
| } | |||
| } | |||
| @@ -8,7 +8,29 @@ namespace Tensorflow | |||
| { | |||
| public partial class Tensor | |||
| { | |||
| public unsafe IntPtr StringTensor(string[] strings, TensorShape shape) | |||
| const ulong TF_TSRING_SIZE = 24; | |||
| public IntPtr StringTensor25(string[] strings, TensorShape shape) | |||
| { | |||
| var handle = c_api.TF_AllocateTensor(TF_DataType.TF_STRING, | |||
| shape.dims.Select(x => (long)x).ToArray(), | |||
| shape.ndim, | |||
| (ulong)shape.size * TF_TSRING_SIZE); | |||
| var data = c_api.TF_TensorData(handle); | |||
| var tstr = c_api.TF_StringInit(handle); | |||
| // AllocationHandle = tstr; | |||
| // AllocationType = AllocationType.Tensorflow; | |||
| for (int i = 0; i< strings.Length; i++) | |||
| { | |||
| c_api.TF_StringCopy(tstr, strings[i], strings[i].Length); | |||
| tstr += (int)TF_TSRING_SIZE; | |||
| } | |||
| // c_api.TF_StringDealloc(tstr); | |||
| return handle; | |||
| } | |||
| public IntPtr StringTensor(string[] strings, TensorShape shape) | |||
| { | |||
| // convert string array to byte[][] | |||
| var buffer = new byte[strings.Length][]; | |||
| @@ -61,11 +83,27 @@ namespace Tensorflow | |||
| return handle; | |||
| } | |||
| public string[] StringData25() | |||
| { | |||
| string[] strings = new string[c_api.TF_Dim(_handle, 0)]; | |||
| var tstrings = TensorDataPointer; | |||
| for (int i = 0; i< strings.Length; i++) | |||
| { | |||
| var tstringData = c_api.TF_StringGetDataPointer(tstrings); | |||
| /*var size = c_api.TF_StringGetSize(tstrings); | |||
| var capacity = c_api.TF_StringGetCapacity(tstrings); | |||
| var type = c_api.TF_StringGetType(tstrings);*/ | |||
| strings[i] = c_api.StringPiece(tstringData); | |||
| tstrings += (int)TF_TSRING_SIZE; | |||
| } | |||
| return strings; | |||
| } | |||
| /// <summary> | |||
| /// Extracts string array from current Tensor. | |||
| /// </summary> | |||
| /// <exception cref="InvalidOperationException">When <see cref="dtype"/> != TF_DataType.TF_STRING</exception> | |||
| public unsafe string[] StringData() | |||
| public string[] StringData() | |||
| { | |||
| var buffer = StringBytes(); | |||
| @@ -181,6 +181,30 @@ namespace Tensorflow | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern unsafe ulong TF_StringEncode(byte* src, ulong src_len, byte* dst, ulong dst_len, SafeStatusHandle status); | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern IntPtr TF_StringInit(IntPtr t); | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern void TF_StringCopy(IntPtr dst, string text, long size); | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern void TF_StringAssignView(IntPtr dst, IntPtr text, long size); | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern IntPtr TF_StringGetDataPointer(IntPtr tst); | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern TF_TString_Type TF_StringGetType(IntPtr tst); | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern ulong TF_StringGetSize(IntPtr tst); | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern ulong TF_StringGetCapacity(IntPtr tst); | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern void TF_StringDealloc(IntPtr tst); | |||
| /// <summary> | |||
| /// Decode a string encoded using TF_StringEncode. | |||
| /// </summary> | |||
| @@ -107,6 +107,32 @@ namespace Tensorflow.Native.UnitTest.Tensors | |||
| Assert.IsTrue(Enumerable.SequenceEqual(nd.Data<float>(), new float[] { 1, 2, 3, 4, 5, 6 })); | |||
| } | |||
| /// <summary> | |||
| /// Port from c_api_test.cc | |||
| /// `TEST_F(CApiAttributesTest, StringTensor)` | |||
| /// </summary> | |||
| [TestMethod, Ignore("Waiting for PR https://github.com/tensorflow/tensorflow/pull/46804")] | |||
| public void StringTensor() | |||
| { | |||
| string text = "Hello world!."; | |||
| var tensor = c_api.TF_AllocateTensor(TF_DataType.TF_STRING, | |||
| null, | |||
| 0, | |||
| 1 * 24); | |||
| var tstr = c_api.TF_StringInit(tensor); | |||
| var data = c_api.TF_StringGetDataPointer(tstr); | |||
| c_api.TF_StringCopy(tstr, text, text.Length); | |||
| Assert.AreEqual((ulong)text.Length, c_api.TF_StringGetSize(tstr)); | |||
| Assert.AreEqual(text, c_api.StringPiece(data)); | |||
| Assert.AreEqual((ulong)text.Length, c_api.TF_TensorByteSize(tensor)); | |||
| Assert.AreEqual(0, c_api.TF_NumDims(tensor)); | |||
| TF_DeleteTensor(tensor); | |||
| c_api.TF_StringDealloc(tstr); | |||
| } | |||
| /// <summary> | |||
| /// Port from tensorflow\c\c_api_test.cc | |||
| /// `TEST(CAPI, SetShape)` | |||