| @@ -14,8 +14,12 @@ | |||
| <PlatformTarget>x64</PlatformTarget> | |||
| </PropertyGroup> | |||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | |||
| <DefineConstants>DEBUG;TRACE</DefineConstants> | |||
| </PropertyGroup> | |||
| <ItemGroup> | |||
| <PackageReference Include="SciSharp.TensorFlow.Redist" Version="2.6.0-rc0" /> | |||
| <PackageReference Include="SciSharp.TensorFlow.Redist-Windows-GPU" Version="2.5.0" /> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| @@ -271,14 +271,18 @@ namespace Tensorflow | |||
| } | |||
| } | |||
| public static IEnumerable<(T, T)> zip<T>(NDArray t1, NDArray t2) | |||
| public static IEnumerable<(T, T)> zip<T>(NDArray t1, NDArray t2, Axis axis = null) | |||
| where T : unmanaged | |||
| { | |||
| /*var a = t1.AsIterator<T>(); | |||
| var b = t2.AsIterator<T>(); | |||
| while (a.HasNext() && b.HasNext()) | |||
| yield return (a.MoveNext(), b.MoveNext());*/ | |||
| throw new NotImplementedException(""); | |||
| if (axis == null) | |||
| { | |||
| var a = t1.Data<T>(); | |||
| var b = t2.Data<T>(); | |||
| for (int i = 0; i < a.Length; i++) | |||
| yield return (a[i], b[i]); | |||
| } | |||
| else | |||
| throw new NotImplementedException(""); | |||
| } | |||
| public static IEnumerable<(T1, T2)> zip<T1, T2>(IList<T1> t1, IList<T2> t2) | |||
| @@ -166,7 +166,7 @@ namespace Tensorflow | |||
| for (int row = 0; row < num_labels; row++) | |||
| { | |||
| var col = labels[row]; | |||
| labels_one_hot.SetData(1.0, row, col); | |||
| labels_one_hot[row, col] = 1.0; | |||
| } | |||
| return labels_one_hot; | |||
| @@ -25,6 +25,10 @@ namespace Tensorflow.NumPy | |||
| { | |||
| if (x.ndim != y.ndim) | |||
| return false; | |||
| else if (x.size != y.size) | |||
| return false; | |||
| else if (x.dtype != y.dtype) | |||
| return false; | |||
| return Enumerable.SequenceEqual(x.ToByteArray(), y.ToByteArray()); | |||
| } | |||
| @@ -8,7 +8,7 @@ namespace Tensorflow.NumPy | |||
| { | |||
| public void Deconstruct(out byte blue, out byte green, out byte red) | |||
| { | |||
| var data = Data<byte>(); | |||
| var data = ToArray<byte>(); | |||
| blue = data[0]; | |||
| green = data[1]; | |||
| red = data[2]; | |||
| @@ -17,23 +17,23 @@ namespace Tensorflow.NumPy | |||
| public static implicit operator NDArray(Array array) | |||
| => new NDArray(array); | |||
| public static implicit operator bool(NDArray nd) | |||
| => nd._tensor.ToArray<bool>()[0]; | |||
| public unsafe static implicit operator bool(NDArray nd) | |||
| => *(bool*)nd.data; | |||
| public static implicit operator byte(NDArray nd) | |||
| => nd._tensor.ToArray<byte>()[0]; | |||
| public unsafe static implicit operator byte(NDArray nd) | |||
| => *(byte*)nd.data; | |||
| public static implicit operator byte[](NDArray nd) | |||
| => nd.ToByteArray(); | |||
| public unsafe static implicit operator int(NDArray nd) | |||
| => *(int*)nd.data; | |||
| public static implicit operator int(NDArray nd) | |||
| => nd._tensor.ToArray<int>()[0]; | |||
| public unsafe static implicit operator long(NDArray nd) | |||
| => *(long*)nd.data; | |||
| public static implicit operator float(NDArray nd) | |||
| => nd._tensor.ToArray<float>()[0]; | |||
| public unsafe static implicit operator float(NDArray nd) | |||
| => *(float*)nd.data; | |||
| public static implicit operator double(NDArray nd) | |||
| => nd._tensor.ToArray<double>()[0]; | |||
| public unsafe static implicit operator double(NDArray nd) | |||
| => *(double*)nd.data; | |||
| public static implicit operator NDArray(bool value) | |||
| => new NDArray(value); | |||
| @@ -8,76 +8,78 @@ namespace Tensorflow.NumPy | |||
| { | |||
| public partial class NDArray | |||
| { | |||
| public NDArray this[int index] | |||
| public NDArray this[params int[] index] | |||
| { | |||
| get | |||
| get => _tensor[index.Select(x => new Slice | |||
| { | |||
| return _tensor[index]; | |||
| } | |||
| Start = x, | |||
| Stop = x + 1, | |||
| IsIndex = true | |||
| }).ToArray()]; | |||
| set | |||
| set => SetData(index.Select(x => new Slice | |||
| { | |||
| Start = x, | |||
| Stop = x + 1, | |||
| IsIndex = true | |||
| }), value); | |||
| } | |||
| } | |||
| public NDArray this[params Slice[] slices] | |||
| { | |||
| get => _tensor[slices]; | |||
| set => SetData(slices, value); | |||
| } | |||
| public NDArray this[params int[] index] | |||
| public NDArray this[NDArray mask] | |||
| { | |||
| get | |||
| { | |||
| return _tensor[index.Select(x => new Slice(x, x + 1)).ToArray()]; | |||
| throw new NotImplementedException(""); | |||
| } | |||
| set | |||
| { | |||
| var offset = ShapeHelper.GetOffset(shape, index); | |||
| unsafe | |||
| { | |||
| if (dtype == TF_DataType.TF_BOOL) | |||
| *((bool*)data + offset) = value; | |||
| else if (dtype == TF_DataType.TF_UINT8) | |||
| *((byte*)data + offset) = value; | |||
| else if (dtype == TF_DataType.TF_INT32) | |||
| *((int*)data + offset) = value; | |||
| else if (dtype == TF_DataType.TF_INT64) | |||
| *((long*)data + offset) = value; | |||
| else if (dtype == TF_DataType.TF_FLOAT) | |||
| *((float*)data + offset) = value; | |||
| else if (dtype == TF_DataType.TF_DOUBLE) | |||
| *((double*)data + offset) = value; | |||
| } | |||
| throw new NotImplementedException(""); | |||
| } | |||
| } | |||
| public NDArray this[params Slice[] slices] | |||
| void SetData(IEnumerable<Slice> slices, NDArray array) | |||
| => SetData(slices, array, -1, slices.Select(x => 0).ToArray()); | |||
| void SetData(IEnumerable<Slice> slices, NDArray array, int currentNDim, int[] indices) | |||
| { | |||
| get | |||
| { | |||
| return _tensor[slices]; | |||
| } | |||
| if (dtype != array.dtype) | |||
| throw new ArrayTypeMismatchException($"Required dtype {dtype} but {array.dtype} is assigned."); | |||
| set | |||
| if (!slices.Any()) | |||
| return; | |||
| var slice = slices.First(); | |||
| if (slices.Count() == 1) | |||
| { | |||
| var pos = _tensor[slices]; | |||
| var len = value.bytesize; | |||
| if (slice.Step != 1) | |||
| throw new NotImplementedException(""); | |||
| indices[indices.Length - 1] = slice.Start ?? 0; | |||
| var offset = (ulong)ShapeHelper.GetOffset(shape, indices); | |||
| var bytesize = array.bytesize; | |||
| unsafe | |||
| { | |||
| System.Buffer.MemoryCopy(value.data.ToPointer(), pos.TensorDataPointer.ToPointer(), len, len); | |||
| var dst = (byte*)data + offset * dtypesize; | |||
| System.Buffer.MemoryCopy(array.data.ToPointer(), dst, bytesize, bytesize); | |||
| } | |||
| // _tensor[slices].assign(constant_op.constant(value)); | |||
| } | |||
| } | |||
| public NDArray this[NDArray mask] | |||
| { | |||
| get | |||
| { | |||
| throw new NotImplementedException(""); | |||
| return; | |||
| } | |||
| set | |||
| currentNDim++; | |||
| for (var i = slice.Start ?? 0; i < slice.Stop; i++) | |||
| { | |||
| indices[currentNDim] = i; | |||
| SetData(slices.Skip(1), array, currentNDim, indices); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,16 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using static Tensorflow.Binding; | |||
| namespace Tensorflow.NumPy | |||
| { | |||
| public partial class NDArray | |||
| { | |||
| public static NDArray operator +(NDArray lhs, NDArray rhs) => lhs.Tensor + rhs.Tensor; | |||
| public static NDArray operator -(NDArray lhs, NDArray rhs) => lhs.Tensor - rhs.Tensor; | |||
| public static NDArray operator *(NDArray lhs, NDArray rhs) => lhs.Tensor * rhs.Tensor; | |||
| public static NDArray operator /(NDArray lhs, NDArray rhs) => lhs.Tensor / rhs.Tensor; | |||
| } | |||
| } | |||
| @@ -25,6 +25,7 @@ namespace Tensorflow.NumPy | |||
| public partial class NDArray | |||
| { | |||
| Tensor _tensor; | |||
| public Tensor Tensor => _tensor; | |||
| public TF_DataType dtype => _tensor.dtype; | |||
| public ulong size => _tensor.size; | |||
| public ulong dtypesize => _tensor.dtypesize; | |||
| @@ -47,15 +48,12 @@ namespace Tensorflow.NumPy | |||
| public ValueType GetValue(params int[] indices) | |||
| => throw new NotImplementedException(""); | |||
| public void SetData(object value, params int[] indices) | |||
| => throw new NotImplementedException(""); | |||
| public NDIterator<T> AsIterator<T>(bool autoreset = false) where T : unmanaged | |||
| => throw new NotImplementedException(""); | |||
| public bool HasNext() => throw new NotImplementedException(""); | |||
| public T MoveNext<T>() => throw new NotImplementedException(""); | |||
| public NDArray reshape(Shape newshape) => new NDArray(_tensor, newshape); | |||
| public NDArray reshape(Shape newshape) => new NDArray(tf.reshape(_tensor, newshape)); | |||
| public NDArray astype(Type type) => new NDArray(math_ops.cast(_tensor, type.as_tf_dtype())); | |||
| public NDArray astype(TF_DataType dtype) => new NDArray(math_ops.cast(_tensor, dtype)); | |||
| public NDArray ravel() => throw new NotImplementedException(""); | |||
| @@ -14,13 +14,13 @@ namespace Tensorflow.Keras.Engine.DataAdapters | |||
| IDataAdapter _adapter; | |||
| public IDataAdapter DataAdapter => _adapter; | |||
| IDatasetV2 _dataset; | |||
| int _inferred_steps; | |||
| public int Inferredsteps => _inferred_steps; | |||
| int _current_step; | |||
| int _step_increment; | |||
| public int StepIncrement => _step_increment; | |||
| long _inferred_steps; | |||
| public long Inferredsteps => _inferred_steps; | |||
| long _current_step; | |||
| long _step_increment; | |||
| public long StepIncrement => _step_increment; | |||
| bool _insufficient_data; | |||
| int _steps_per_execution_value; | |||
| long _steps_per_execution_value; | |||
| int _initial_epoch => args.InitialEpoch; | |||
| int _epochs => args.Epochs; | |||
| IVariableV1 _steps_per_execution; | |||
| @@ -30,8 +30,8 @@ namespace Tensorflow.Keras.Engine.DataAdapters | |||
| this.args = args; | |||
| if (args.StepsPerExecution == null) | |||
| { | |||
| _steps_per_execution = tf.Variable(1); | |||
| _steps_per_execution_value = 1; | |||
| _steps_per_execution = tf.Variable(1L); | |||
| _steps_per_execution_value = 1L; | |||
| } | |||
| else | |||
| { | |||
| @@ -103,7 +103,7 @@ namespace Tensorflow.Keras.Engine.DataAdapters | |||
| // _adapter.on_epoch_end() | |||
| } | |||
| public IEnumerable<int> steps() | |||
| public IEnumerable<long> steps() | |||
| { | |||
| _current_step = 0; | |||
| while (_current_step < _inferred_steps) | |||
| @@ -229,7 +229,7 @@ namespace TensorFlowNET.Keras.UnitTest | |||
| Assert.AreEqual(9, oov_count); | |||
| } | |||
| [TestMethod, Ignore("slice assign doesn't work")] | |||
| [TestMethod] | |||
| public void PadSequencesWithDefaults() | |||
| { | |||
| var tokenizer = keras.preprocessing.text.Tokenizer(oov_token: OOV); | |||
| @@ -241,12 +241,12 @@ namespace TensorFlowNET.Keras.UnitTest | |||
| Assert.AreEqual(4, padded.dims[0]); | |||
| Assert.AreEqual(22, padded.dims[1]); | |||
| Assert.AreEqual(tokenizer.word_index["worst"], padded[0, 19]); | |||
| Assert.AreEqual(padded[0, 19], tokenizer.word_index["worst"]); | |||
| for (var i = 0; i < 8; i++) | |||
| Assert.AreEqual(0, padded[0, i]); | |||
| Assert.AreEqual(tokenizer.word_index["proud"], padded[1, 10]); | |||
| Assert.AreEqual(padded[0, i], 0); | |||
| Assert.AreEqual(padded[1, 10], tokenizer.word_index["proud"]); | |||
| for (var i = 0; i < 20; i++) | |||
| Assert.AreNotEqual(0, padded[1, i]); | |||
| Assert.AreNotEqual(padded[1, i], 0); | |||
| } | |||
| [TestMethod, Ignore("slice assign doesn't work")] | |||
| @@ -38,7 +38,7 @@ namespace TensorFlowNET.UnitTest | |||
| var c = tf.strings.substr(a, 4, 8); | |||
| using (var sess = tf.Session()) | |||
| { | |||
| var result = UTF8Encoding.UTF8.GetString((byte[])c.eval(sess)); | |||
| var result = UTF8Encoding.UTF8.GetString(c.eval(sess).ToByteArray()); | |||
| Console.WriteLine(result); | |||
| result.Should().Be("heythere"); | |||
| } | |||
| @@ -55,7 +55,7 @@ namespace TensorFlowNET.UnitTest | |||
| var c = tf.strings.substr(a, 0, size - 5000); | |||
| using (var sess = tf.Session()) | |||
| { | |||
| var result = UTF8Encoding.UTF8.GetString((byte[])c.eval(sess)); | |||
| var result = UTF8Encoding.UTF8.GetString(c.eval(sess).ToByteArray()); | |||
| Console.WriteLine(result); | |||
| result.Should().HaveLength(size - 5000).And.ContainAll("a"); | |||
| } | |||
| @@ -0,0 +1,57 @@ | |||
| using Microsoft.VisualStudio.TestTools.UnitTesting; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using Tensorflow; | |||
| using Tensorflow.NumPy; | |||
| namespace TensorFlowNET.UnitTest.NumPy | |||
| { | |||
| /// <summary> | |||
| /// https://numpy.org/doc/stable/user/basics.indexing.html | |||
| /// </summary> | |||
| [TestClass] | |||
| public class ArrayIndexingTest : EagerModeTestBase | |||
| { | |||
| [TestMethod] | |||
| public void int_params() | |||
| { | |||
| var x = np.arange(24).reshape((2, 3, 4)); | |||
| x[1, 2, 3] = 1; | |||
| var y = x[1, 2, 3]; | |||
| Assert.AreEqual(y.shape, Shape.Scalar); | |||
| Assert.AreEqual(y, 1); | |||
| x[0, 0] = new[] { 3, 1, 1, 2 }; | |||
| y = x[0, 0]; | |||
| Assert.AreEqual(y.shape, 4); | |||
| Assert.AreEqual(y, new[] { 3, 1, 1, 2 }); | |||
| y = x[0]; | |||
| Assert.AreEqual(y.shape, (3, 4)); | |||
| var z = np.arange(12).reshape((3, 4)); | |||
| x[1] = z; | |||
| Assert.AreEqual(x[1], z); | |||
| } | |||
| [TestMethod] | |||
| public void slice_params() | |||
| { | |||
| var x = np.arange(12).reshape((3, 4)); | |||
| var y = x[new Slice(0, 1), new Slice(2)]; | |||
| Assert.AreEqual(y.shape, (1, 2)); | |||
| Assert.AreEqual(y, np.array(new[] { 2, 3 }).reshape((1, 2))); | |||
| } | |||
| [TestMethod] | |||
| public void slice_string_params() | |||
| { | |||
| var x = np.arange(12).reshape((3, 4)); | |||
| var y = x[Slice.ParseSlices("0:1,2:")]; | |||
| Assert.AreEqual(y.shape, (1, 2)); | |||
| Assert.AreEqual(y, np.array(new[] { 2, 3 }).reshape((1, 2))); | |||
| } | |||
| } | |||
| } | |||
| @@ -5,13 +5,13 @@ using System.Linq; | |||
| using System.Text; | |||
| using Tensorflow.NumPy; | |||
| namespace TensorFlowNET.UnitTest.Numpy | |||
| namespace TensorFlowNET.UnitTest.NumPy | |||
| { | |||
| /// <summary> | |||
| /// https://numpy.org/doc/stable/reference/routines.array-creation.html | |||
| /// </summary> | |||
| [TestClass] | |||
| public class NumpyArrayCreationTest : EagerModeTestBase | |||
| public class ArrayCreationTest : EagerModeTestBase | |||
| { | |||
| [TestMethod] | |||
| public void empty_zeros_ones_full() | |||
| @@ -6,13 +6,13 @@ using System.Text; | |||
| using Tensorflow; | |||
| using Tensorflow.NumPy; | |||
| namespace TensorFlowNET.UnitTest.Numpy | |||
| namespace TensorFlowNET.UnitTest.NumPy | |||
| { | |||
| /// <summary> | |||
| /// https://numpy.org/doc/stable/reference/generated/numpy.prod.html | |||
| /// </summary> | |||
| [TestClass] | |||
| public class NumpyMathTest : EagerModeTestBase | |||
| public class MathTest : EagerModeTestBase | |||
| { | |||
| [TestMethod] | |||
| public void prod() | |||