Для разработчиков, которые работали над корпоративной информационной системой, слово Tensor может быть очень незнакомым, и они понятия не имеют, что оно означает, и даже может звучать странно. В Вики это объясняется так:

В математике тензор — это алгебраический объект, описывающий полилинейную связь между наборами алгебраических объектов, связанных с векторным пространством. Тензоры могут отображаться между различными объектами, такими как векторы, скаляры и даже другие тензоры.

Тензор может быть представлен в виде многомерных данных, и каждое измерение может использоваться для представления определенного набора признаков. Давайте поговорим о том, как использовать C# для выполнения основных операций Tensor. Сама .NET не имеет библиотеки Tensor, нам нужно использовать стороннюю библиотеку с открытым исходным кодом для выполнения операций Tensor.

PM> Install-Package TensorFlow.NET
PM> Install-Package SciSharp.TensorFlow.Redist

Как создать тензор?

После установки необходимых библиотек мы можем начать программировать и использовать Tensor. Во-первых, давайте создадим одномерный тензор. Этот процесс создания аналогичен инициализации массива в C#. Единственное отличие состоит в том, что нам нужно использовать np.array для переноса массива. Тензор может быть представлен структурой многомерного массива, поэтому Tensor и NDArray по сути одно и то же. Их можно конвертировать друг в друга без потери производительности, поскольку блоки данных указывают на одну и ту же область памяти.

using static Tensorflow.Binding;
using Tensorflow.NumPy;

// Create an array in normal way
var a1 = new[] { 1, 2, 3, 4 };
// Wrap it as NDArray
NDArray nd1 = np.array(a1);
// Convert NDArray to Tensor
Tensor t1 = nd1;

// We can also initialize a Tensor from NDArray, 
// That's because there is an implicity conversion.
// Tensor t1 = np.array(a1);

По сути, операция с Tensor — это операция с NDArray. Таким образом, в следующих фрагментах кода мы можем напрямую использовать NDArray вместо Tensor для выполнения различных операций на C#. Наиболее часто используемые операции в Tensor — это преобразование типов данных и преобразование измерений, которые можно легко выполнить с помощью API, предоставляемого в библиотеке TensorFlow Numpy. Прямо сейчас мы можем преобразовать массив nd1 в двумерный массив 2x2:

var nd2 = nd1.reshape((2, 2));

// By looking at the data pointers of these two arrays, 
// you can see that they point to the same data block. 
// Therefore, the conversion of dimensions has almost no performance loss.
// nd1.buffer == nd2.buffer

// But for data type conversion, it is necessary to reallocate memory.
var nd3 = nd2.astype(np.float32);

Для творческих операций у нас также есть несколько часто используемых методов инициализации:

// Allocate a 4 elements filled with zero.
var nd4 = np.zeros(4);

// Allocate a NDArray and filled with one.
var nd5 = np.ones(4);

// Allocate a 4 double data type of memory without default value.
var nd6 = np.empty(4);

// And even an array that contains a range of evenly spaced intervals.
var nd7 = np.arange(2, 9, 2);

// You can also use np.linspace() to create an array with values that are spaced linearly 
// in a specified interval:
var nd8 = np.linspace(0, 10, num: 5);

// While the default data type is floating point (np.float64), 
// you can explicitly specify which data type you want using the dtype keyword.
var nd9 = np.ones(2, dtype: np.int64);

// Return an array of ones with the same shape and type as a given array.
nd7 = nd7.reshape((2, 2));
var nd10 = np.ones_like(nd7);

// Return an array of zeros with the same shape and type as a given array.
nd10 = np.zeros_like(nd7);

Откуда мы знаем форму и количество измерений тензора после того, как NDArray был создан или изменен? В NDArray есть 4 важных свойства: ndim, shape, size и dtype.

ndim сообщит вам количество осей или измерений массива.
size сообщит вам общее количество элементов массива. Это произведение элементов формы массива.
shape отобразит кортеж целых чисел, указывающих количество элементов, хранящихся по каждому измерению массива. Если, например, у вас есть двумерный массив с 2 строками и 3 столбцами, форма вашего массива будет (2, 3).
dtype сообщит вам тип данных массива.

// shape is (2, 2)
print(nd2.shape);

// ndim is 2
print(nd2.ndim);

// dtype is int32
print(nd2.dtype);

// size is 4
print(nd2.size);

Объединение, Сортировка элементов

Если вы хотите отсортировать существующий массив, вы можете использовать np.sort() для работы, которая вернет новый отсортированный массив. Вы можете использовать np.concatenate() для объединения двух разных массивов.

var arr = np.array(new[] { 2, 1, 5, 3, 7, 4, 6, 8 });
arr = np.sort(arr);

// adding more elements
var arr2 = np.array(new[] { 2, 3 });
var arr3 = np.concatenate((arr, arr2));

Вышеприведенный контент посвящен созданию самых основных данных Tesnor. Эта статья будет продолжать обновляться и добавлять больше пояснений кода об операциях Tensor.