@@ -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); | |||
@@ -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}"; | |||
} | |||
} | |||
} |
@@ -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; | |||
@@ -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; | |||
} | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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; | |||
@@ -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>(); | |||
@@ -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()}"; | |||
} | |||
@@ -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)); | |||
} | |||
} | |||
} |
@@ -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); | |||
} | |||
} | |||
} |