Browse Source

NDArrayRender

tags/v0.60-tf.numpy
Oceania2018 4 years ago
parent
commit
45e136575a
10 changed files with 173 additions and 259 deletions
  1. +1
    -1
      src/TensorFlowNET.Core/Data/MnistModelLoader.cs
  2. +9
    -2
      src/TensorFlowNET.Core/Eager/EagerTensor.ToString.cs
  3. +9
    -11
      src/TensorFlowNET.Core/NumPy/NDArray.Index.cs
  4. +138
    -0
      src/TensorFlowNET.Core/NumPy/NDArrayRender.cs
  5. +1
    -1
      src/TensorFlowNET.Core/Numpy/NDArray.cs
  6. +3
    -0
      src/TensorFlowNET.Core/Operations/array_ops.cs
  7. +0
    -240
      src/TensorFlowNET.Core/Tensors/tensor_util.cs
  8. +1
    -1
      src/TensorFlowNET.Core/Variables/BaseResourceVariable.cs
  9. +3
    -3
      test/TensorFlowNET.UnitTest/Numpy/Array.Creation.Test.cs
  10. +8
    -0
      test/TensorFlowNET.UnitTest/Numpy/Math.Test.cs

+ 1
- 1
src/TensorFlowNET.Core/Data/MnistModelLoader.cs View File

@@ -146,7 +146,7 @@ namespace Tensorflow

bytestream.Read(buf, 0, buf.Length);

var labels = np.frombuffer(buf, new Shape(num_items), np.uint8);
var labels = np.frombuffer(buf, new Shape(num_items), np.@byte);

if (one_hot)
return DenseToOneHot(labels, num_classes);


+ 9
- 2
src/TensorFlowNET.Core/Eager/EagerTensor.ToString.cs View File

@@ -1,8 +1,15 @@
namespace Tensorflow.Eager
using Tensorflow.NumPy;

namespace Tensorflow.Eager
{
public partial class EagerTensor
{
public override string ToString()
=> $"tf.Tensor: shape={shape}, dtype={dtype.as_numpy_name()}, numpy={tensor_util.to_numpy_string(this)}";
{
var nd = new NDArray(this);
var str = NDArrayRender.ToString(nd);
return $"tf.Tensor: shape={shape}, dtype={dtype.as_numpy_name()}, numpy={str}";
}
}
}

+ 9
- 11
src/TensorFlowNET.Core/NumPy/NDArray.Index.cs View File

@@ -134,8 +134,8 @@ namespace Tensorflow.NumPy

return array;
}
NDArray GetData(int[] indices, int axis = 0)
unsafe NDArray GetData(int[] indices, int axis = 0)
{
if (shape.IsScalar)
return GetScalar();
@@ -148,19 +148,17 @@ namespace Tensorflow.NumPy
var array = np.ndarray(dims, dtype: dtype);

dims[0] = 1;
var bytesize = new Shape(dims).size * dtype.get_datatype_size();
var len = new Shape(dims).size * dtype.get_datatype_size();

int dst_index = 0;
foreach (var index in indices)
foreach (var pos in indices)
{
var src_offset = (ulong)ShapeHelper.GetOffset(shape, index);
var src_offset = (ulong)ShapeHelper.GetOffset(shape, pos);
var dst_offset = (ulong)ShapeHelper.GetOffset(array.shape, dst_index++);
unsafe
{
var src = (byte*)data + src_offset * dtypesize;
var dst = (byte*)array.data.ToPointer() + dst_offset * dtypesize;
System.Buffer.MemoryCopy(src, dst, bytesize, bytesize);
}

var src = (byte*)data + src_offset * dtypesize;
var dst = (byte*)array.data + dst_offset * dtypesize;
System.Buffer.MemoryCopy(src, dst, len, len);
}

return array;


+ 138
- 0
src/TensorFlowNET.Core/NumPy/NDArrayRender.cs View File

@@ -0,0 +1,138 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;

namespace Tensorflow.NumPy
{
public class NDArrayRender
{
public static string ToString(NDArray array)
{
Shape shape = array.shape;
if (shape.IsScalar)
return Render(array);

var s = new StringBuilder();
s.Append("array(");
Build(s, array);
s.Append(")");
return s.ToString();
}

static void Build(StringBuilder s, NDArray array)
{
var shape = array.shape;

if (shape.Length == 1)
{
s.Append("[");
s.Append(Render(array));
s.Append("]");
return;
}

var len = shape[0];
s.Append("[");

if (len <= 10)
{
for (int i = 0; i < len; i++)
{
Build(s, array[i]);
if (i < len - 1)
{
s.Append(", ");
s.AppendLine();
}
}
}
else
{
for (int i = 0; i < 5; i++)
{
Build(s, array[i]);
if (i < len - 1)
{
s.Append(", ");
s.AppendLine();
}
}

s.Append(" ... ");
s.AppendLine();

for (int i = (int)len - 5; i < len; i++)
{
Build(s, array[i]);
if (i < len - 1)
{
s.Append(", ");
s.AppendLine();
}
}
}

s.Append("]");
}

static string Render(NDArray array)
{
if (array.buffer == IntPtr.Zero)
return "<null>";

var dtype = array.dtype;
var shape = array.shape;

if (dtype == TF_DataType.TF_STRING)
{
if (array.rank == 0)
return "'" + string.Join(string.Empty, array.StringBytes()[0]
.Take(25)
.Select(x => x < 32 || x > 127 ? "\\x" + x.ToString("x") : Convert.ToChar(x).ToString())) + "'";
else
return $"['{string.Join("', '", array.StringData().Take(25))}']";
}
else if (dtype == TF_DataType.TF_VARIANT)
{
return "<unprintable>";
}
else if (dtype == TF_DataType.TF_RESOURCE)
{
return "<unprintable>";
}
else
{
return dtype switch
{
TF_DataType.TF_BOOL => Render(array.ToArray<bool>(), array.shape),
TF_DataType.TF_INT8 => Render(array.ToArray<sbyte>(), array.shape),
TF_DataType.TF_INT32 => Render(array.ToArray<int>(), array.shape),
TF_DataType.TF_INT64 => Render(array.ToArray<long>(), array.shape),
TF_DataType.TF_FLOAT => Render(array.ToArray<float>(), array.shape),
TF_DataType.TF_DOUBLE => Render(array.ToArray<double>(), array.shape),
_ => Render(array.ToArray<byte>(), array.shape)
};
}
}

static string Render<T>(T[] array, Shape shape)
{
if (array == null)
return "<null>";

if (array.Length == 0)
return "<empty>";

if (shape.IsScalar)
return array[0].ToString();

var display = "";
if (array.Length <= 10)
display += string.Join(", ", array);
else
display += string.Join(", ", array.Take(5)) + ", ..., " + string.Join(", ", array.Skip(array.Length - 5));
return display;
}
}
}

+ 1
- 1
src/TensorFlowNET.Core/Numpy/NDArray.cs View File

@@ -46,6 +46,6 @@ namespace Tensorflow.NumPy
public byte[] ToByteArray() => BufferToArray();
public static string[] AsStringArray(NDArray arr) => throw new NotImplementedException("");

public override string ToString() => tensor_util.to_numpy_string(this);
public override string ToString() => NDArrayRender.ToString(this);
}
}

+ 3
- 0
src/TensorFlowNET.Core/Operations/array_ops.cs View File

@@ -90,6 +90,9 @@ namespace Tensorflow
case TF_DataType.TF_FLOAT:
zeros = constant(0f);
break;
case TF_DataType.TF_INT8:
zeros = constant((byte)0);
break;
default:
zeros = constant(0);
break;


+ 0
- 240
src/TensorFlowNET.Core/Tensors/tensor_util.cs View File

@@ -470,246 +470,6 @@ would not be rank 1.", tensor.op.get_attr("axis")));
return ops.convert_to_tensor(shape, dtype: TF_DataType.TF_INT32, name: "shape");
}

public static string to_numpy_string(NDArray array)
{
Shape shape = array.shape;
if (shape.ndim == 0)
return array[0].ToString();

var s = new StringBuilder();
s.Append("array(");
PrettyPrint(s, array);
s.Append(")");
return s.ToString();
}

static void PrettyPrint(StringBuilder s, NDArray array)
{
var shape = array.shape;

if (shape.Length == 1)
{
s.Append("[");
s.Append(Render(array));
s.Append("]");
return;
}

var len = shape[0];
s.Append("[");

if (len <= 10)
{
for (int i = 0; i < len; i++)
{
PrettyPrint(s, array[i]);
if (i < len - 1)
{
s.Append(", ");
s.AppendLine();
}
}
}
else
{
for (int i = 0; i < 5; i++)
{
PrettyPrint(s, array[i]);
if (i < len - 1)
{
s.Append(", ");
s.AppendLine();
}
}

s.Append(" ... ");
s.AppendLine();

for (int i = (int)len - 5; i < len; i++)
{
PrettyPrint(s, array[i]);
if (i < len - 1)
{
s.Append(", ");
s.AppendLine();
}
}
}

s.Append("]");
}

static string Render(NDArray tensor)
{
if (tensor.buffer == IntPtr.Zero)
return "<null>";

var dtype = tensor.dtype;
var shape = tensor.shape;

if (dtype == TF_DataType.TF_STRING)
{
if (tensor.rank == 0)
return "'" + string.Join(string.Empty, tensor.StringBytes()[0]
.Take(25)
.Select(x => x < 32 || x > 127 ? "\\x" + x.ToString("x") : Convert.ToChar(x).ToString())) + "'";
else
return $"['{string.Join("', '", tensor.StringData().Take(25))}']";
}
else if (dtype == TF_DataType.TF_VARIANT)
{
return "<unprintable>";
}
else if (dtype == TF_DataType.TF_RESOURCE)
{
return "<unprintable>";
}
else
{
return dtype switch
{
TF_DataType.TF_BOOL => DisplayArrayAsString(tensor.ToArray<bool>(), tensor.shape),
TF_DataType.TF_INT8 => DisplayArrayAsString(tensor.ToArray<sbyte>(), tensor.shape),
TF_DataType.TF_INT32 => DisplayArrayAsString(tensor.ToArray<int>(), tensor.shape),
TF_DataType.TF_INT64 => DisplayArrayAsString(tensor.ToArray<long>(), tensor.shape),
TF_DataType.TF_FLOAT => DisplayArrayAsString(tensor.ToArray<float>(), tensor.shape),
TF_DataType.TF_DOUBLE => DisplayArrayAsString(tensor.ToArray<double>(), tensor.shape),
_ => DisplayArrayAsString(tensor.ToArray<byte>(), tensor.shape)
};
}
}

public static string to_numpy_string(Tensor array)
{
Shape shape = array.shape;
if (shape.ndim == 0)
return array[0].ToString();

var s = new StringBuilder();
s.Append("array(");
PrettyPrint(s, array);
s.Append(")");
return s.ToString();
}

static string Render(Tensor tensor)
{
if (tensor.buffer == IntPtr.Zero)
return "<null>";

var dtype = tensor.dtype;
var shape = tensor.shape;

if (dtype == TF_DataType.TF_STRING)
{
if (tensor.rank == 0)
return "'" + string.Join(string.Empty, tensor.StringBytes()[0]
.Take(25)
.Select(x => x < 32 || x > 127 ? "\\x" + x.ToString("x") : Convert.ToChar(x).ToString())) + "'";
else
return $"['{string.Join("', '", tensor.StringData().Take(25))}']";
}
else if (dtype == TF_DataType.TF_VARIANT)
{
return "<unprintable>";
}
else if (dtype == TF_DataType.TF_RESOURCE)
{
return "<unprintable>";
}
else
{
return dtype switch
{
TF_DataType.TF_BOOL => DisplayArrayAsString(tensor.ToArray<bool>(), tensor.shape),
TF_DataType.TF_INT8 => DisplayArrayAsString(tensor.ToArray<sbyte>(), tensor.shape),
TF_DataType.TF_INT32 => DisplayArrayAsString(tensor.ToArray<int>(), tensor.shape),
TF_DataType.TF_INT64 => DisplayArrayAsString(tensor.ToArray<long>(), tensor.shape),
TF_DataType.TF_FLOAT => DisplayArrayAsString(tensor.ToArray<float>(), tensor.shape),
TF_DataType.TF_DOUBLE => DisplayArrayAsString(tensor.ToArray<double>(), tensor.shape),
_ => DisplayArrayAsString(tensor.ToArray<byte>(), tensor.shape)
};
}
}

static string DisplayArrayAsString<T>(T[] array, Shape shape)
{
if (array == null)
return "<null>";

if (array.Length == 0)
return "<empty>";

if (shape.ndim == 0)
return array[0].ToString();

var display = "";
if (array.Length <= 10)
display += string.Join(", ", array);
else
display += string.Join(", ", array.Take(5)) + ", ..., " + string.Join(", ", array.Skip(array.Length - 5));
return display;
}

static void PrettyPrint(StringBuilder s, Tensor array, bool flat = false)
{
var shape = array.shape;

if (shape.Length == 1)
{
s.Append("[");
s.Append(Render(array));
s.Append("]");
return;
}

var len = shape[0];
s.Append("[");

if (len <= 10)
{
for (int i = 0; i < len; i++)
{
PrettyPrint(s, array[i], flat);
if (i < len - 1)
{
s.Append(", ");
if (!flat)
s.AppendLine();
}
}
}
else
{
for (int i = 0; i < 5; i++)
{
PrettyPrint(s, array[i], flat);
if (i < len - 1)
{
s.Append(", ");
if (!flat)
s.AppendLine();
}
}

s.Append(" ... ");
s.AppendLine();

for (int i = (int)len - 5; i < len; i++)
{
PrettyPrint(s, array[i], flat);
if (i < len - 1)
{
s.Append(", ");
if (!flat)
s.AppendLine();
}
}
}

s.Append("]");
}

public static ParsedSliceArgs ParseSlices(Slice[] slices)
{
var begin = new List<int>();


+ 1
- 1
src/TensorFlowNET.Core/Variables/BaseResourceVariable.cs View File

@@ -222,7 +222,7 @@ namespace Tensorflow
public override string ToString()
{
if (tf.Context.executing_eagerly())
return $"tf.Variable: '{Name}' shape={string.Join(",", shape)}, dtype={dtype.as_numpy_name()}, numpy={tensor_util.to_numpy_string(read_value())}";
return $"tf.Variable: '{Name}' shape={string.Join(",", shape)}, dtype={dtype.as_numpy_name()}, numpy={read_value()}";
else
return $"tf.Variable: '{Name}' shape={string.Join(",", shape)}, dtype={dtype.as_numpy_name()}";
}


+ 3
- 3
test/TensorFlowNET.UnitTest/Numpy/Array.Creation.Test.cs View File

@@ -94,9 +94,9 @@ namespace TensorFlowNET.UnitTest.NumPy
public void to_numpy_string()
{
var nd = np.arange(10 * 10 * 10 * 10).reshape((10, 10, 10, 10));
var str = tensor_util.to_numpy_string(nd);
Assert.AreEqual("array([[[[0, 1, 2, ..., 7, 8, 9],", str.Substring(0, 33));
Assert.AreEqual("[9990, 9991, 9992, ..., 9997, 9998, 9999]]]])", str.Substring(str.Length - 45));
var str = NDArrayRender.ToString(nd);
Assert.AreEqual("array([[[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],", str.Substring(0, 40));
Assert.AreEqual("[9990, 9991, 9992, 9993, 9994, 9995, 9996, 9997, 9998, 9999]]]])", str.Substring(str.Length - 64));
}
}
}

+ 8
- 0
test/TensorFlowNET.UnitTest/Numpy/Math.Test.cs View File

@@ -27,5 +27,13 @@ namespace TensorFlowNET.UnitTest.NumPy
Assert.AreEqual(p.shape, 2);
Assert.IsTrue(Equal(p.ToArray<double>(), new[] { 2.0, 12.0 }));
}

[TestMethod]
public void astype()
{
var x = np.array(new byte[] { 1, 100, 200 });
var x1 = x.astype(np.float32);
Assert.AreEqual(x1[2], 200f);
}
}
}

Loading…
Cancel
Save