forked from SciSharp/TensorFlow.NET
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTensor.cs
More file actions
139 lines (118 loc) · 4.14 KB
/
Tensor.cs
File metadata and controls
139 lines (118 loc) · 4.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
using NumSharp.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace Tensorflow
{
/// <summary>
/// A tensor is a generalization of vectors and matrices to potentially higher dimensions.
/// Internally, TensorFlow represents tensors as n-dimensional arrays of base datatypes.
/// </summary>
public class Tensor
{
public Operation op { get; }
public int value_index { get; }
public Graph graph => op.graph;
public string name;
public TF_DataType dtype { get; }
public IntPtr handle { get; }
public ulong bytesize { get; }
public ulong dataTypeSize { get;}
public ulong size => bytesize / dataTypeSize;
public IntPtr buffer { get; }
public long[] shape { get; }
/// <summary>
/// number of dimensions
/// 0 Scalar (magnitude only)
/// 1 Vector (magnitude and direction)
/// 2 Matrix (table of numbers)
/// 3 3-Tensor (cube of numbers)
/// n n-Tensor (you get the idea)
/// </summary>
public int rank;
/// <summary>
/// if original buffer is free.
/// </summary>
private bool deallocator_called;
public Tensor(IntPtr handle)
{
this.handle = handle;
dtype = c_api.TF_TensorType(handle);
rank = c_api.TF_NumDims(handle);
bytesize = c_api.TF_TensorByteSize(handle);
buffer = c_api.TF_TensorData(handle);
dataTypeSize = c_api.TF_DataTypeSize(dtype);
shape = new long[rank];
for (int i = 0; i < rank; i++)
shape[i] = c_api.TF_Dim(handle, i);
}
public Tensor(NDArray nd)
{
var data = Marshal.AllocHGlobal(sizeof(float) * nd.size);
Marshal.Copy(nd.Data<float>(), 0, data, nd.size);
var dataType = ToTFDataType(nd.dtype);
var handle = c_api.TF_NewTensor(dataType,
nd.shape.Select(x => (long)x).ToArray(), // shape
nd.ndim,
data,
(UIntPtr)(nd.size * sizeof(float)),
(IntPtr values, IntPtr len, ref bool closure) =>
{
// Free the original buffer and set flag
Marshal.FreeHGlobal(data);
closure = true;
},
ref deallocator_called);
this.handle = handle;
dtype = c_api.TF_TensorType(handle);
rank = c_api.TF_NumDims(handle);
bytesize = c_api.TF_TensorByteSize(handle);
buffer = c_api.TF_TensorData(handle);
dataTypeSize = c_api.TF_DataTypeSize(dtype);
shape = new long[rank];
for (int i = 0; i < rank; i++)
shape[i] = c_api.TF_Dim(handle, i);
}
public Tensor(Operation op, int value_index, TF_DataType dtype)
{
this.op = op;
this.value_index = value_index;
this.dtype = dtype;
}
public TF_Output _as_tf_output()
{
return c_api_util.tf_output(op._c_op, value_index);
}
public T[] Data<T>()
{
// Column major order
// https://en.wikipedia.org/wiki/File:Row_and_column_major_order.svg
// matrix:[[1, 2, 3], [4, 5, 6]]
// index: 0 2 4 1 3 5
// result: 1 4 2 5 3 6
var data = new T[size];
for (ulong i = 0; i < size; i++)
{
data[i] = Marshal.PtrToStructure<T>(buffer + (int)(i * dataTypeSize));
}
return data;
}
public byte[] Data()
{
var data = new byte[bytesize];
Marshal.Copy(buffer, data, 0, (int)bytesize);
return data;
}
public TF_DataType ToTFDataType(Type type)
{
switch (type.Name)
{
case "Single":
return TF_DataType.TF_FLOAT;
}
return TF_DataType.DtInvalid;
}
}
}