Manipulation
Devices and information
Move to CPU
-
void Tensor::toCPU(int dev = DEV_CPU)
Clone a tensor to the CPU.
Tensor* t1 = Tensor::zeros({2, 3}, DEV_GPU); // Tensor created in the GPU
t1->toCPU(); // Tensor transferred to CPU
Move to GPU
-
void Tensor::toGPU(int dev = DEV_GPU)
Clone a tensor to the GPU.
Tensor* t1 = Tensor::zeros({2, 3}, DEV_CPU); // Tensor created in the CPU
t1->toGPU(); // Tensor transferred to GPU
Check tensor device
-
int Tensor::isCPU()
Check if the tensor is in CPU.
- Returns
int
Tensor* t1 = Tensor::zeros({2, 3}, DEV_GPU); // Tensor created in the GPU
t1->isCPU(); // returns 0
-
int Tensor::isGPU()
Check if the tensor is in GPU.
- Returns
int
Tensor* t1 = Tensor::zeros({2, 3}, DEV_GPU); // Tensor created in the GPU
t1->isGPU(); // returns 1
-
int Tensor::isFPGA()
Check if the tensor is in FPGA.
- Returns
int
Tensor* t1 = Tensor::zeros({2, 3}, DEV_GPU); // Tensor created in the GPU
t1->isFPGA(); // returns 0
-
string Tensor::getDeviceName() const
Returns the device name where the tensor is allocated (“CPU”, “GPU” or “FPGA”)
- Returns
string
Tensor* t1 = Tensor::zeros({2, 3}, DEV_GPU); // Tensor created in the GPU
t1->getDeviceName(); // returns "GPU"
Get information from tensor
-
void Tensor::info()
Print shape, device and size information.
- Returns
void
Tensor* t1 = Tensor::empty({2, 3});
t1->info();
// -------------------------------
// class: Tensor
// ndim: 2
// shape: (2, 3)
// strides: (3, 1)
// itemsize: 6
// contiguous: 1
// order: C
// data pointer: 0x7f827a6060d8
// is shared: 0
// type: float (4 bytes)
// device: CPU (code = 0)
// -------------------------------
Print tensor contents
-
void Tensor::print(int precision = 6, bool raw = false)
Print the tensor values.
Prints the content of the tensor.
- Parameters
precision – Number of decimals places to use
raw – Print the tensor without format
- Returns
void
Tensor* t1 = Tensor::randn({3, 3});
t1->print();
// [
// [0.135579 -0.208483 0.537894]
// [0.666481 0.242867 -1.957334]
// [-1.447633 1.231033 0.670430]
// ]
t1->print(0); // No decimals
// [
// [0 -0 1]
// [1 0 -2]
// [-1 1 1]
// ]
t1->print(3); // 3 decimals
// [
// [0.136 -0.208 0.538]
// [0.666 0.243 -1.957]
// [-1.448 1.231 0.670]
// ]
t1->print(3, true); // 3 decimals, presented in row major
// [
// 0.136 -0.208 0.538 0.666 0.243 -1.957 -1.448 1.231 0.670
// ]
Dimension check
-
static bool Tensor::isSquared(Tensor *A)
Check if all dimensions in the tensor are the same.
- Parameters
A – Tensor
- Returns
bool
Tensor* t1 = Tensor::zeros({3, 3});
Tensor::isSquared(t1);
// true
Tensor* t2 = Tensor::zeros({3, 3, 3});
Tensor::isSquared(t2);
// true
Tensor* t3 = Tensor::zeros({3, 1, 3});
Tensor::isSquared(t3);
// false
Changing array shape
reshape
-
Tensor *Tensor::reshape(const vector<int> &new_shape)
Set a new shape to a tensor.
- Parameters
new_shape – A vector containing the new shape.
- Returns
A new tensor with the result
Tensor* t1 = Tensor::zeros({3, 4});
// [
// [0.00 0.00 0.00 0.00]
// [0.00 0.00 0.00 0.00]
// [0.00 0.00 0.00 0.00]
// ]
t1->reshape_({6, 2});
// [
// [0.00 0.00]
// [0.00 0.00]
// [0.00 0.00]
// [0.00 0.00]
// [0.00 0.00]
// [0.00 0.00]
// ]
// Other ways
Tensor* t2 = Tensor::reshape(t1, {6, 2}); // returns new tensor
t1->reshape(t2, {6,2}) // static
flatten
-
Tensor *Tensor::flatten()
In-place conversion tensor to a 1D tensor.
- Returns
A new tensor with the result
Tensor* t1 = Tensor::zeros({3, 4});
// [
// [0.00 0.00 0.00 0.00]
// [0.00 0.00 0.00 0.00]
// [0.00 0.00 0.00 0.00]
// ]
t1->flatten_(); // In-place
// [0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00]
// Other ways
Tensor *t2 = Tensor::flatten(t1); // returns new tensor
t1->flatten(t2) // static
Tiling arrays
repeat
-
static Tensor *Tensor::repeat(Tensor *A, const vector<unsigned int> &repeats, unsigned int axis = 0, Tensor *output = nullptr, bool derivative = false)
Repeats the elements of a tensor along the specified dimension.
- Parameters
A – Input tensor.
repeats – The number of repetitions for the specified dimension (“int” or “vector of ints”)
axis – The axis along which to repeat values.
output – Output tensor
derivative – Apply derivative for: output = repeat(A)
-
static Tensor *Tensor::repeat(Tensor *A, unsigned int repeats, unsigned int axis = 0, Tensor *output = nullptr, bool derivative = false)
Tensor* t1 = Tensor::range(1, 6); t1->reshape_({2, 3});
// [
// [1 2 3]
// [4 5 6]
// ]
// Repeat all rows 2 times. (repeat=2, axis=0)
Tensor *t2 = Tensor::repeat(t1, 2, 0); // returns new tensor
// [
// [1 2 3]
// [1 2 3]
// [4 5 6]
// [4 5 6]
// ]
// Repeat col 1 => 3 times; col 2 => 2 times; col 3 => 1 time. (repeat=[3,2,1], axis=1)
Tensor *t2 = Tensor::repeat(t1, {3, 2, 1}, 1); // returns new tensor
// [
// [1 1 1 2 2 3]
// [4 4 4 5 5 6]
// ]
tile
-
static Tensor *Tensor::tile(Tensor *A, const vector<int> &repeats)
Construct an array by repeating A the number of times given by reps.
- Parameters
A – Input tensor.
repeats – The number of repetitions of A along each axis.
output – Output tensor
derivative – Apply derivative for: output = repeat(A)
// New tensor
Tensor* t1 = new Tensor({1, 2}, {2, 1});
// [
// [1]
// [2]
// ]
// Repeat all rows and columns 2 times each
Tensor* t1_res = Tensor::tile(t1, {2, 2});
// [
// [1 1]
// [2 2]
// [1 1]
// [2 2]
// ]
// New tensor
Tensor* t2 = new Tensor({1, 2, 3}, {3, 1});
// [
// [1]
// [2]
// [3]
// ]
// Repeat columns three times but not rows
Tensor* t2_res = Tensor::tile(t2, {1, 3});
// [
// [1 1 1]
// [2 2 2]
// [3 3 3]
// ]
broadcast
-
static Tensor *Tensor::broadcast(Tensor *A, Tensor *B, Tensor *output = nullptr)
Returns a new tensor A to be broadcasted into B.
- Parameters
A – Input tensor.
B – Input tensor.
output – Output tensor (optional).
- Returns
A new tensor C based on A, but prepared to be broadcasted in to B
// Example: Image - constant RGB
// Define mean
auto* mean = new Tensor( {0.485, 0.456, 0.406}, {3}, DEV_CPU);
// [0.485 0.456 0.406]
// Fake image
auto* image = Tensor::ones( {3, 224, 244});
// -------------------------------
// class: Tensor
// ndim: 3
// shape: (3, 224, 244)
// strides: (54656, 244, 1)
// itemsize: 163968
// contiguous: 1
// order: C
// data pointer: 0x56305561baa8
// is shared: 0
// type: float (4 bytes)
// device: CPU (code = 0)
// -------------------------------
// Compute broadcast for mean
Tensor* mean_broadcasted = Tensor::broadcast(mean, image);
// -------------------------------
// class: Tensor
// ndim: 3
// shape: (3, 224, 244)
// strides: (54656, 244, 1)
// itemsize: 163968
// contiguous: 1
// order: C
// data pointer: 0x56305561f2c8
// is shared: 0
// type: float (4 bytes)
// device: CPU (code = 0)
// -------------------------------
// Apply: X-mean
image->sub_(mean_broadcasted);
Transpose-like operations
permute
-
Tensor *Tensor::permute(const vector<int> &dims)
In-place permutation of tensor dimensions.
- Parameters
dims – A vector containing the new order of the dimensions.
- Returns
A new tensor with the result
Tensor* t1 = Tensor::range(1, 24); t1->reshape_({2, 3, 4});
// [
// [[1.00 2.00 3.00 4.00] [5.00 6.00 7.00 8.00] [9.00 10.00 11.00 12.00]]
// [[13.00 14.00 15.00 16.00] [17.00 18.00 19.00 20.00] [21.00 22.00 23.00 24.00]]
// ]
t1->permute_({2, 1, 0}); // In-place
// [
// [[1.00 13.00] [5.00 17.00] [9.00 21.00]]
// [[2.00 14.00] [6.00 18.00] [10.00 22.00]]
// [[3.00 15.00] [7.00 19.00] [11.00 23.00]]
// [[4.00 16.00] [8.00 20.00] [12.00 24.00]]
// ]
// Other ways
Tensor *t2 = Tensor::permute(t1, {2, 1, 0}); // returns new tensor
t1->permute(t2, {2, 1, 0}); // static
moveaxis
-
Tensor *Tensor::moveaxis(int source, int destination)
Move axes of an array to new positions.
- Parameters
source – Original position of the axis to move. These must be unique.
destination – Destination position for the original axis. These must also be unique
- Returns
A new tensor with the result
Tensor* t1 = Tensor::zeros({1, 2, 3, 4});
// ndim: 4
// shape: (1, 2, 3, 4)
// strides: (24, 12, 4, 1)
t1->moveaxis_(0, 2); // In-place
// ndim: 4
// shape: (2, 3, 1, 4)
// strides: (12, 4, 4, 1)
// Other ways
Tensor *t2 = Tensor::moveaxis(t1, 0, 2); // returns new tensor
t1->moveaxis(t2, 0, 2); // static
swapaxis
-
Tensor *Tensor::swapaxis(int axis1, int axis2)
Interchange two axes of an array.
- Parameters
axis1 – First axis.
axis2 – Destination position for the original axis. These must also be unique
- Returns
A new tensor with the result
Tensor* t1 = Tensor::zeros({1, 2, 3, 4});
// ndim: 4
// shape: (1, 2, 3, 4)
// strides: (24, 12, 4, 1)
t1->swapaxis_(0, 2); // In-place
// ndim: 4
// shape: (3, 2, 1, 4)
// strides: (8, 4, 4, 1)
// Other ways
Tensor *t2 = Tensor::swapaxis(t1, 0, 2); // returns new tensor
t1->swapaxis(t2, 0, 2); // static
Changing number of dimensions
squeeze
-
static Tensor *Tensor::squeeze(Tensor *A, int axis = -1)
Remove all the dimensions of size 1 from the vector.
- Parameters
A – Output tensor where the squeeze is stored.
axis – if given, the input will be squeezed only in this dimension. Else (-1), squeezes all dimensions of size 1
- Returns
A new tensor with the result
Tensor* t1 = Tensor::zeros({1, 3, 4, 1});
// ndim: 4
// shape: (1, 3, 4, 1)
// strides: (12, 4, 1, 1)
Tensor* t2 = t1->squeeze(); // returns new tensor
// shape: (3, 4)
Tensor* t3 = t1->squeeze(0); // returns new tensor
// shape: (3, 4, 1)
Tensor* t3 = t1->squeeze(3); // returns new tensor
// shape: (1, 3, 4)
// Other ways
t1->squeeze_(); // In-place
Tensor *t2 = Tensor::squeeze(t1); // static
unsqueeze
-
static Tensor *Tensor::unsqueeze(Tensor *A, int axis = 0)
Returns a new tensor with a dimension of size one inserted at the specified position.
- Parameters
A – Output tensor where the unsqueeze is stored.
axis – the index at which to insert the singleton dimension. Default: axis=0
- Returns
A new tensor with the result
Tensor* t1 = Tensor::zeros({2, 3, 4});
// ndim: 3
// shape: (2, 3, 4)
// strides: (12, 4, 1)
Tensor* t2 = t1->unsqueeze(); // returns new tensor
// shape: (1, 2, 3, 4)
Tensor* t3 = t1->unsqueeze(2); // returns new tensor
// shape: (2, 3, 4, 1)
// Other ways
t1->unsqueeze_(); // In-place
Tensor *t2 = Tensor::unsqueeze(t1); // Static
Joining arrays
concatenate
-
static Tensor *Tensor::concat(vector<Tensor*> A, unsigned int axis = 0, Tensor *output = nullptr)
Join a sequence of arrays along an existing axis.
- Parameters
Vector – of Tensors The Tensors must have the same shape, except in the dimension corresponding to axis (the first, by default).
axis – The axis along which the arrays will be joined. If axis is None, arrays are flattened before use. Default is 0.
output – Output tensor
Example:
Tensor* t1 = Tensor::full({2, 2, 2}, 2);
Tensor* t2 = Tensor::full({2, 2, 2}, 5);
Tensor* t3 = Tensor::concat({t1, t2});
// ndim: 3
// shape: (4, 2, 2)
// strides: (4, 2, 1)
// [
// [[2.00 2.00] [2.00 2.00]]
// [[2.00 2.00] [2.00 2.00]]
// [[5.00 5.00] [5.00 5.00]]
// [[5.00 5.00] [5.00 5.00]]
// ]
Tensor *t4 = Tensor::concat({t1, t2}, 2);
// ndim: 3
// shape: (2, 2, 4)
// strides: (8, 4, 1)
//
// [
// [[2.00 2.00 5.00 5.00] [2.00 2.00 5.00 5.00]]
// [[2.00 2.00 5.00 5.00] [2.00 2.00 5.00 5.00]]
// ]
stack
-
static Tensor *Tensor::stack(vector<Tensor*> A, unsigned int axis = 0, Tensor *output = nullptr)
Join a sequence of arrays along a new axis.
- Parameters
A – Input tensor.
axis – The axis in the result array along which the input arrays are stacked.
output – Output tensor
Example:
Tensor* t1 = Tensor::full({2, 2}, 2);
Tensor* t2 = Tensor::full({2, 2}, 5);
Tensor* t3 = Tensor::stack({t1, t2}); // axis = 0
// [
// [[2.00 2.00] [2.00 2.00]]
// [[5.00 5.00] [5.00 5.00]]
// ]
Tensor *t4 = Tensor::stack({t1, t2}, 1); // axis = 1
// [
// [[2.00 2.00] [5.00 5.00]]
// [[2.00 2.00] [5.00 5.00]]
// ]
Value operations
Fill constant
-
static void Tensor::fill(Tensor *A, float v)
Fill tensor with a value.
- Parameters
A – The output tensor.
v – the value to fill the tensor with
Tensor* t1 = Tensor::empty({2, 3});
t1->fill_(3.0f); // In-place
// [
// [3.00 3.00 3.00]
// [3.00 3.00 3.00]
// ]
// Other ways
Tensor* t2 = t1->fill(3.0f); // returns new tensor
Tensor::fill(t1, 3.0f); // static
Fill Random Uniform
-
void Tensor::fill_rand_uniform_(float v)
Fills a tensor in-place, with values randomly sampled from a uniform distribution.
- Parameters
v – Scale factor of the values generated by the uniform distribution.
Tensor* t1 = Tensor::empty({2, 3});
t1->fill_rand_uniform_(1.0f); // In-place
// [
// [0.10 0.53 0.88]
// [0.57 0.57 0.89]
// ]
// Other ways
Tensor* t2 = t1->fill_rand_uniform(1.0f); // returns new tensor
Tensor::fill_rand_uniform(t1, 1.0f); // static
Fill Random Signed Uniform
-
void Tensor::fill_rand_signed_uniform_(float v)
Fills a tensor in-place, with values randomly sampled from a signed uniform distribution.
- Parameters
v – Scale factor of the values generated by the signed uniform distribution.
Tensor* t1 = Tensor::empty({2, 3});
t1->fill_rand_signed_uniform_(1.0f); // In-place
// [
// [0.22 -0.34 -0.78]
// [-0.03 0.10 0.90]
// ]
// Other ways
Tensor* t2 = t1->fill_rand_signed_uniform(1.0f); // returns new tensor
Tensor::fill_rand_signed_uniform(t1, 1.0f); // static
Fill Random Normal
-
void Tensor::fill_rand_normal_(float m, float s, bool fast_math = true)
Fills a tensor in-place, with values randomly sampled from a normal distribution.
- Parameters
m – Mean of the normal distribution.
s – Standard deviation of the normal distribution.
fast_math – Whether to use or not the fast math mode.
Tensor* t1 = Tensor::empty({2, 3});
t1->fill_rand_normal_(0.0f, 1.0f); // In-place
// [
// [-0.57 0.49 -1.09]
// [0.75 0.37 -0.32]
// ]
// Other ways
Tensor* t2 = t1->fill_rand_normal(0.0f, 1.0f); // returns new tensor
Tensor::fill_rand_normal(t1, 0.0f, 1.0f); // static
Fill Random Binary
-
void Tensor::fill_rand_binary_(float v)
Fills a tensor in-place, with values randomly sampled from a binary distribution.
- Parameters
v – Binarization threshold. 1 if rnd() >= t, 0 otherwise
Tensor* t1 = Tensor::empty({2, 3});
t1->fill_rand_binary_(0.5f); // In-place
// [
// [0.00 1.00 0.00]
// [1.00 1.00 0.00]
// ]
// Other ways
Tensor* t2 = t1->fill_rand_binary(0.5f); // returns new tensor
Tensor::fill_rand_binary(t1, 0.5f); // static