Vector and Matrix templates

OpenNN has been written in ANSI C++. This means that the library can be built on any operating system with little effort.

Contents:
  1. The Vector template
  2. The Matrix template

1. The Vector template

The Vector class is a template, which means that it can be applied to different types. That is, we can create a Vector or int numbers, MyClass objects, etc.

The Vector in OpenNN is derived from the vector in the Standard Template Library.

Members

The OpenNN Vector derives from the std vector and it does not include any additional member.

Constructors

Multiple constructors are defined in the Vector class, where the different constructors take different parameters.

The easiest way of creating a vector object is by means of the default constructor, wich builds a vector of size zero. For example, in order to construct an empty Vector of int numbers we use the following.

Vector<int> v;

The following sentence constructs a Vector of 3 double numbers.

Vector<double> v(3)

If we want to construct Vector of 5 bool variables and initialize all the elements to false, we can use

Vector<bool> v(5, false);

It is also possible to construct an object of the Vector class and at the same time load its members from a file. In order to do that we can do

Vector<int> v("Vector.dat");

The file `Vector.dat' contains a first row with the size of the vector and an aditional row for each element of the vector.

The following sentence constructs a Vector which is a copy of another Vector,

Vector<MyClass> v(3);
Vector<MyClass> w(v);

A very useful way to create a vector object is to through a list:

Vector<int> v({1, 2, 3});
Vector<string> w({"one","two","three"});

Operators

The Vector class also implements different types of operators for assignment, reference, arithmetic or comparison.

The assignment operator copies a vector into another vector,

Vector<int> v;
Vector<int> w = v;

The following sentence constructs a vector and sets the values of their elements using the reference operator. Note that indexing goes from 0 to n-1, where n is the Vector size.

Vector<double> v(3);
    v[0] = 1.0;
    v[1] = 2.0;
    v[2] = 3.0;

Sum, difference, product and quotient operators are included in the Vector class to perform arithmetic operations with a scalar or another Vector. Note that the arithmetic operators with another Vector require that they have the same sizes.

The following sentence uses the vector-scalar sum operator,

Vector<int> v(3, 1.0);

Vector<int> w = v + 3.1415926;

An example of the use of the vector-vector multiplication operator is given below,

Vector<double> v(3, 1.2);
Vector<double> w(3, 3.4);

Vector<double> x = v*w;

Assignment by sum, difference, product or quotient with a scalar or another Vector is also possible by using the arithmetic and assignment operators. If another Vector is to be used, it must have the same size.

For instance, to assign by difference with a scalar, we might do

Vector<int> v(3, 2);
v -= 1;

In order to assign by quotation with another Vector, we can write

Vector<double> v(3, 2.0);
Vector<double> w(3, 0.5);
v /= w;

Equality and relational operators are also implemented here. They can be used with a scalar or another Vector. For the last case the same sizes are assumed. An example of the equal to operator with a scalar is

Vector<bool> v(5, false);
bool is_equal = (v == false);

The less than operator with another Vector can be used as follows,

Vector<double> v(5, 2.3);
Vector<double> w(5, 3.2);

bool is_less = (v < w);

Methods

Get and set methods for each member of this class are implemented to exchange information among objects.

The method get_size() returns the size of a Vector.

Vector<int> v({1, 2, 3, 4, 5});
				
size_t size =v.size();

On the other hand, the method set() sets a new size to a Vector. Note that the element values of that Vector are lost.

Vector<bool> v(3);

v.set(6);

If we want to initialize a vector at random we can use the randomize_uniform() or randomize_normal() methods,

Vector<double> v(5);
Vector<double> w(3);

v.randomize_uniform(-1,1);
w.randomize_normal(0,1);

To get the first or last elements of a vector the following methods are used:

Vector<int> v({1, 2, 3, 4, 5, 6, 7, 8, 9});

Vector<int> first_5 = v.get_first(5);
Vector<int> last_5 =v.get_last(5);

The Vector class also includes some mathematical methods which can be useful in the development of neural networks algorithms and applications.

The calculate_L1_norm() method calculates the norm of the vector,

Vector<double> v(5, 3.1415927);
double norm = v.calculate_L1_norm();

In order to calculate the dot product between this Vector and another Vector we can do

Vector<double> v(3, 2.0);
Vector<double> w(3, 5.0);

double dot = v.dot(w);

We can calculate the mean or the standard deviation values of the elements in a Vector by using the calculate_mean() and calculate_standard_deviation() methods, respectively. For instance

Vector<double> v({1.2, 2.5, 3.6, 2.4});

double mean = v.calculate_mean();
double standard_deviation = v.calculate_standard_deviation();

Finally, utility methods for serialization or loading and saving the class members to a file are also included. In order to obtain a std::string representation of a Vector object we can make the following.

Vector<bool> v(1, false);

Vector<std::string> vector_string = v.to_string_vector();

To save a Vector object to a file we can do

Vector<int> v(2, 0);

v.save("Vector.dat", ';');

The save method only needs the path and the separator.

If we want to load a Vector object from a data file we could write

Vector<int> v;

v.load("Vector.dat"); 

2. The Matrix template

As it happens with the Vector class, the Matrix class is also a template. Therefore, a Matrix of any type can be created.

Members

The Matrix class has three members:

That members are private. Private members can be accessed only within methods of the class itself.

Constructors

The Matrix class also implements multiple constructors, with different parameters.

The default constructor creates a matrix with zero rows and zero columns.

Matrix m;

In order to construct an empty Matrix with a specified number of rows and columns we use

Matrix<int> m(2, 3);

We can specify the number of rows and columns and initialize the Matrix elements at the same time by doing

Matrix<double> m(1, 5, 0.0);

To build a Matrix object by loading its members from a data file the following constructor is used,

Matrix<double> m("Matrix.dat");

A matrix data file contains the matrix elements arranged in rows and columns. For instance, the next data will correspond to a Matrix of zeros with 2 rows and 3 columns.

   0 0 0
   0 0 0

The copy constructor builds an object which is a copy of another object.

Matrix<bool> a(3, 5);
Matrix<bool> b(a);

One of the most convenient ways to initialize a matrix object is through a Vector List:

 Matrix<double> m({Vector<double>({1, 2, 3}),Vector<double>({1, 2, 3})},{"a","b"});

The first argument of m is a list of vectors that correspond to the columns of the matrix. The second argument concerns to the header.

Operators

The Matrix class also implements the assignment operator.

Matrix<double> a(2, 1);
Matrix<double> b = a;

Below there is an usage example of the reference operator here. Note that row indexing goes from 0 to rows_number-1 and column indexing goes from 0 to columns_number-1.

Matrix<int> m(2, 2);
     m(0, 0) = 1;
     m(1, 1) = 1;
     m(0, 1) = 0;
     m(1, 0) = 0;

The use of the arithmetic operators for the Matrix class are very similar to those for the Vector class. The following sentence uses the scalar difference operator,

Matrix<double> a(5, 7, 2.5);
Matrix<double> b = a + 0.1;

Also, using the arithmetic and assignment operators with the Matrix class is similar than with the Vector class. For instance, to assign by sum with another Matrix we can write

Matrix<double> a(1, 2, 1.0);
Matrix<double> b(1, 2, 0.5);

a += b;

The not equal to operator with another Matrix can be used in the following way,

Matrix<string> a(1, 1, "hello");
Matrix<string> b(1, 1, "good bye");

bool is_not_equal_to = (a != b);

        

The use of the greater than operator with a scalar is listed below

Matrix<double> a(2, 3, 0.0);
bool is_greater_than = (a > 1.0);        

Methods

As it happens for the Vector class, the Matrix class implements get and set methods for all the members. The get_rows_number() and get_columns_number() methods are very useful.

Matrix<int> m(4, 2);

size_t rows_number = m.get_rows_number();
size_t columns_number = m.get_columns_number();

In order to set a new number of rows or columns to a Matrix object, the set_rows_number() or set_columns_number() methods are used.

Matrix<int> m(4, 2);

size_t rows_number = m.get_rows_number();
size_t columns_number = m.get_columns_number();

A Matrix can be initialized with a given value, at random with an uniform distribution or at random with a normal distribution,

Matrix<double> m(4, 2);

m.initialize(0.0);
m.randomize_uniform(-0.2, 0.4);
m.randomize_normal(-1.0, 0.25);

A set of mathematical methods are also implemented for convenience. For instance, the dot() method computes the dot product of this Matrix with a Vector or with another Matrix.

Matrix<double> m(4, 2, 1.0);
Vector<double> v(4, 2.0);

Vector<double> dot_product = m.dot(v);

Finally, string serializing, printing, saving or loading utility methods are also implemented. For example, the use of the print() method or print_preview() is as follows.

Matrix<bool> m(1, 3, false);

m.print();
m.print_preview();

Bibliography