| @@ -20,9 +20,20 @@ namespace Tensorflow | |||
| { | |||
| public partial class tensorflow | |||
| { | |||
| public SparseTensor<T> SparseTensor<T>(long[,] indices, T[] values, int[] dense_shape) | |||
| public SparseTensor<T> SparseTensor<T>(long[,] indices, T[] values, long[] dense_shape) | |||
| => new SparseTensor<T>(indices, values, dense_shape); | |||
| public Tensor sparse_tensor_to_dense<T>(SparseTensor<T> sp_input, | |||
| T default_value = default, | |||
| bool validate_indices = true, | |||
| string name = null) | |||
| => gen_sparse_ops.sparse_to_dense(sp_input.indices, | |||
| sp_input.dense_shape, | |||
| sp_input.values, | |||
| default_value: default_value, | |||
| validate_indices: validate_indices, | |||
| name: name); | |||
| /// <summary> | |||
| /// Converts a sparse representation into a dense tensor. | |||
| /// </summary> | |||
| @@ -1,4 +1,6 @@ | |||
| using static Tensorflow.Binding; | |||
| using System; | |||
| using System.Linq; | |||
| using static Tensorflow.Binding; | |||
| namespace Tensorflow.Framework | |||
| { | |||
| @@ -8,15 +10,20 @@ namespace Tensorflow.Framework | |||
| public class SparseTensor<T> : CompositeTensor, _TensorLike | |||
| { | |||
| long[,] _indices; | |||
| Tensor indices; | |||
| public Tensor indices; | |||
| T[] _values; | |||
| Tensor values; | |||
| public Tensor values; | |||
| int[] _dense_shape; | |||
| Tensor dense_shape; | |||
| long[] _dense_shape; | |||
| public Tensor dense_shape; | |||
| public SparseTensor(long[,] indices_, T[] values_, int[] dense_shape_) | |||
| TensorShape _shape; | |||
| public TensorShape shape => _shape; | |||
| public TF_DataType dtype => dtypes.as_dtype(typeof(T)); | |||
| public SparseTensor(long[,] indices_, T[] values_, long[] dense_shape_) | |||
| { | |||
| tf_with(ops.name_scope(null, "SparseTensor", new { }), delegate | |||
| { | |||
| @@ -37,6 +44,8 @@ namespace Tensorflow.Framework | |||
| indices_shape[0].merge_with(values_shape.dims[0]); | |||
| indices_shape[1].merge_with(dense_shape_shape.dims[0]); | |||
| _shape = new TensorShape(_dense_shape.Select(x => Convert.ToInt32(x)).ToArray()); | |||
| } | |||
| } | |||
| @@ -15,6 +15,7 @@ | |||
| ******************************************************************************/ | |||
| using System.Collections.Generic; | |||
| using Tensorflow.Framework; | |||
| namespace Tensorflow | |||
| { | |||
| @@ -50,5 +51,24 @@ namespace Tensorflow | |||
| return _op.output; | |||
| } | |||
| public static Tensor sparse_to_dense<T>(Tensor sparse_indices, | |||
| Tensor output_shape, | |||
| Tensor sparse_values, | |||
| T default_value = default, | |||
| bool validate_indices = true, | |||
| string name = null) | |||
| { | |||
| var _op = _op_def_lib._apply_op_helper("SparseToDense", name, args: new | |||
| { | |||
| sparse_indices, | |||
| output_shape, | |||
| sparse_values, | |||
| default_value, | |||
| validate_indices | |||
| }); | |||
| return _op.output; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,27 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| namespace Tensorflow | |||
| { | |||
| public class Dimension | |||
| { | |||
| int _value; | |||
| public int value => _value; | |||
| public Dimension(int value) | |||
| { | |||
| _value = value; | |||
| } | |||
| public Dimension merge_with(Dimension other) | |||
| { | |||
| if (_value == -1) | |||
| return new Dimension(other.value); | |||
| else | |||
| return new Dimension(_value); | |||
| } | |||
| public override string ToString() => $"Dimension({_value})"; | |||
| } | |||
| } | |||
| @@ -1,9 +1,10 @@ | |||
| using NumSharp; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Diagnostics.CodeAnalysis; | |||
| using System.Linq; | |||
| using System.Runtime.CompilerServices; | |||
| using NumSharp.Utilities; | |||
| using static Tensorflow.Binding; | |||
| namespace Tensorflow | |||
| { | |||
| @@ -196,12 +197,26 @@ namespace Tensorflow | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Returns a `TensorShape` combining the information in `self` and `other`. | |||
| /// </summary> | |||
| /// <param name="other"></param> | |||
| /// <returns></returns> | |||
| public TensorShape merge_with(TensorShape other) | |||
| { | |||
| if (dims.Length == 0) | |||
| return other; | |||
| throw new NotImplementedException("merge_with"); | |||
| var new_dims = new List<int>(); | |||
| foreach (var i in range(ndim)) | |||
| { | |||
| var dim = new Dimension(dims[i]); | |||
| var merged = dim.merge_with(new Dimension(other.dims[i])); | |||
| new_dims.Add(merged.value); | |||
| } | |||
| return new TensorShape(new_dims.ToArray()); | |||
| } | |||
| /// <summary> | |||
| @@ -118,110 +118,10 @@ namespace Tensorflow | |||
| if (values == null) | |||
| throw new ValueError("None values not supported."); | |||
| if(np_dt == null) | |||
| { | |||
| switch (values) | |||
| { | |||
| case bool boolVal: | |||
| nparray = boolVal; | |||
| break; | |||
| case int intVal: | |||
| nparray = intVal; | |||
| break; | |||
| case int[] intVals: | |||
| nparray = np.array(intVals); | |||
| break; | |||
| case int[,] intVals: | |||
| nparray = np.array(intVals); | |||
| break; | |||
| case long intVal: | |||
| nparray = intVal; | |||
| break; | |||
| case long[] intVals: | |||
| nparray = np.array(intVals); | |||
| break; | |||
| case long[,] intVals: | |||
| nparray = np.array(intVals); | |||
| break; | |||
| case float floatVal: | |||
| nparray = floatVal; | |||
| break; | |||
| case float[] floatVals: | |||
| nparray = floatVals; | |||
| break; | |||
| case float[,] floatVals: | |||
| nparray = np.array(floatVals); | |||
| break; | |||
| case double doubleVal: | |||
| nparray = doubleVal; | |||
| break; | |||
| case double[] doubleVals: | |||
| nparray = np.array(doubleVals); | |||
| break; | |||
| case double[,] doubleVals: | |||
| nparray = np.array(doubleVals); | |||
| break; | |||
| case string strVal: | |||
| nparray = strVal; | |||
| break; | |||
| case string[] strVals: | |||
| nparray = strVals; | |||
| break; | |||
| case byte[] byteValues: | |||
| nparray = byteValues; | |||
| break; | |||
| case byte[,] byteValues: | |||
| nparray = np.array(byteValues); | |||
| break; | |||
| default: | |||
| throw new NotImplementedException($"make_tensor_proto: Support for type {values.GetType()} Not Implemented"); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| // convert data type | |||
| switch (np_dt.Name) | |||
| { | |||
| case "Int32": | |||
| if (values.GetType().IsArray) | |||
| nparray = np.array((int[])values, np_dt); | |||
| else | |||
| nparray = Converts.ToInt32(values); | |||
| break; | |||
| case "Int64": | |||
| if (values.GetType().IsArray) | |||
| nparray = np.array((int[])values, np_dt); | |||
| else | |||
| nparray = Converts.ToInt64(values); | |||
| break; | |||
| case "Single": | |||
| if (values.GetType().IsArray) | |||
| nparray = np.array((float[])values, np_dt); | |||
| else | |||
| nparray = Converts.ToSingle(values); | |||
| break; | |||
| case "Double": | |||
| if (values.GetType().IsArray) | |||
| nparray = np.array((double[])values, np_dt); | |||
| else | |||
| nparray = Converts.ToDouble(values); | |||
| break; | |||
| case "String": | |||
| if (values.GetType().IsArray) | |||
| nparray = np.array((string[])values, np_dt); | |||
| else | |||
| nparray = NDArray.FromString(Converts.ToString(values)); | |||
| break; | |||
| case "Boolean": | |||
| if (values.GetType().IsArray) | |||
| nparray = np.array((bool[])values, np_dt); | |||
| else | |||
| nparray = Converts.ToBoolean(values); | |||
| break; | |||
| default: | |||
| throw new NotImplementedException($"make_tensor_proto: Support for type {np_dt.Name} Not Implemented"); | |||
| } | |||
| } | |||
| nparray = convert_to_numpy_ndarray(values); | |||
| if (np_dt != null && np_dt != typeof(string)) | |||
| nparray = nparray.astype(np_dt); | |||
| } | |||
| var numpy_dtype = nparray.dtype.as_dtype(dtype: dtype); | |||
| @@ -316,23 +216,59 @@ namespace Tensorflow | |||
| case NDArray val: | |||
| nd = val; | |||
| break; | |||
| case int val: | |||
| nd = np.asarray(val); | |||
| case bool boolVal: | |||
| nd = boolVal; | |||
| break; | |||
| case int intVal: | |||
| nd = intVal; | |||
| break; | |||
| case int[] intVals: | |||
| nd = np.array(intVals); | |||
| break; | |||
| case int[,] intVals: | |||
| nd = np.array(intVals); | |||
| break; | |||
| case long intVal: | |||
| nd = intVal; | |||
| break; | |||
| case long[] intVals: | |||
| nd = np.array(intVals); | |||
| break; | |||
| case long[,] intVals: | |||
| nd = np.array(intVals); | |||
| break; | |||
| case float floatVal: | |||
| nd = floatVal; | |||
| break; | |||
| case float[] floatVals: | |||
| nd = floatVals; | |||
| break; | |||
| case float[,] floatVals: | |||
| nd = np.array(floatVals); | |||
| break; | |||
| case double doubleVal: | |||
| nd = doubleVal; | |||
| break; | |||
| case double[] doubleVals: | |||
| nd = np.array(doubleVals); | |||
| break; | |||
| case double[,] doubleVals: | |||
| nd = np.array(doubleVals); | |||
| break; | |||
| case int[] val: | |||
| nd = np.array(val); | |||
| case string strVal: | |||
| nd = NDArray.FromString(strVal); | |||
| break; | |||
| case float val: | |||
| nd = np.asarray(val); | |||
| case string[] strVals: | |||
| nd = strVals; | |||
| break; | |||
| case double val: | |||
| nd = np.asarray(val); | |||
| case byte[] byteValues: | |||
| nd = byteValues; | |||
| break; | |||
| case string val: | |||
| nd = np.asarray(val); | |||
| case byte[,] byteValues: | |||
| nd = np.array(byteValues); | |||
| break; | |||
| default: | |||
| throw new Exception("Not Implemented"); | |||
| throw new NotImplementedException($"convert_to_numpy_ndarray: Support for type {values.GetType()} Not Implemented"); | |||
| } | |||
| return nd; | |||
| @@ -225,14 +225,22 @@ namespace TensorFlowNET.UnitTest | |||
| [TestMethod] | |||
| public void sparse_tensor_to_dense() | |||
| { | |||
| /*int[,] dense_array = | |||
| var decoded_list = tf.SparseTensor(new[,] | |||
| { | |||
| { 1, 0, 0, 0, 0 }, | |||
| { 0, 1, 0, 0, 0 }, | |||
| { 0, 0, 1, 0, 0 }, | |||
| { 0, 0, 0, 1, 0 } | |||
| }; | |||
| var sparseTensor = new SparseTensor<int>(indices, values, dense_shape);*/ | |||
| { 0L, 0L }, | |||
| { 1L, 2L } | |||
| }, | |||
| new int[] { 1, 2 }, | |||
| new[] { 3L, 4L }); | |||
| var onehot = tf.sparse_tensor_to_dense(decoded_list); | |||
| using (var sess = tf.Session()) | |||
| { | |||
| var result = sess.run(onehot); | |||
| Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 1, 0, 0, 0 }, result[0].ToArray<int>())); | |||
| Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 0, 0, 2, 0 }, result[1].ToArray<int>())); | |||
| Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 0, 0, 0, 0 }, result[2].ToArray<int>())); | |||
| } | |||
| } | |||
| } | |||
| } | |||