MachineIntelligenceCore:Algorithms
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Matrix.hpp
Go to the documentation of this file.
1 
23 #ifndef SRC_TYPES_MATRIX_HPP_
24 #define SRC_TYPES_MATRIX_HPP_
25 
26 #include <Eigen/Dense>
27 #include <random>
28 #include <memory> // std::shared_ptr
29 
30 #include <boost/serialization/serialization.hpp>
31 // include this header to serialize vectors
32 #include <boost/serialization/vector.hpp>
33 // include this header to serialize arrays
34 #include <boost/serialization/array.hpp>
35 #include <boost/serialization/version.hpp>
36 
37 // Forward declaration of class boost::serialization::access
38 namespace boost {
39 namespace serialization {
40 class access;
41 }//: serialization
42 }//: access
43 
44 namespace mic {
45 namespace types {
46 
47 // Forward declaration of a class Tensor.
48 template<typename T>
49 class Tensor;
50 
51 // Forward declaration of a class Vector.
52 //template<typename T>
53 //class Vector;
54 
63 template<typename T>
64 class Matrix : public Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> {
65 public:
66 
70  EIGEN_STRONG_INLINE
71  Matrix() :
72  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>() {
73  }
74 
80  EIGEN_STRONG_INLINE
81  Matrix(int Rows_, int Cols_) :
82  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>(Rows_, Cols_) {
83  this->setZero();
84  }
85 
90  EIGEN_STRONG_INLINE
91  Matrix(const Eigen::Matrix<T, Eigen::Dynamic, 1>& vector_) :
92  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>(vector_.size(), 1)
93  {
94  // Copy the whole vector block.
95  memcpy(this->data(), vector_.data(), vector_.size() * sizeof(T));
96  }
97 
102  EIGEN_STRONG_INLINE
103  Matrix(const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& matrix_) :
104  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>(matrix_.rows(), matrix_.cols())
105  {
106  // Copy the whole vector block.
107  memcpy(this->data(), matrix_.data(), matrix_.size() * sizeof(T));
108  }
109 
115  EIGEN_STRONG_INLINE
117  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>(tensor_.dim(1), tensor_.dim(0))
118  {
119  // Tensor must be 2D!
120  assert(tensor_.dims().size() == 2);
121  // Copy the whole block.
122  memcpy(this->data(), tensor_.data(), tensor_.size() * sizeof(T));
123  }
124 
125  /*
126  * Overloaded assignment operator - calls base operator.
127  * @param mat_ Input matrix
128  * @return An exact copy of the input matrix.
129  */
130 /* EIGEN_STRONG_INLINE
131  const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& operator =(const mic::types::Matrix<T>& mat_) {
132  // Using base EIGEN operator =
133  return Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>::operator=(mat_);
134  }*/
135 
136 
137 /* EIGEN_STRONG_INLINE
138  const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& operator =(const Eigen::Matrix<T, Eigen::Dynamic, 1>& vector_) {
139  // Using base EIGEN operator =
140  return Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>::operator=(vector_);
141  }*/
142 
148  EIGEN_STRONG_INLINE
149  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& operator =(const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& mat_) {
150  // Using base EIGEN operator =
151  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>::operator=(mat_);
152  return *this;
153  }
154 
155 
161  EIGEN_STRONG_INLINE
162  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> operator *(const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& mat_) {
163  // Calling base EIGEN operator *
164  //printf("Calling base EIGEN operator *\n");
165  return Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>::operator*(mat_);
166  }
167 
168 
173  void setValue(T value_) {
174  // Get access to data.
175  T* data_ptr = this->data();
176 
177 #pragma omp parallel for
178  for (size_t i = 0; i < (size_t) (this->rows() * this->cols()); i++)
179  data_ptr[i] = value_;
180  }
181 
185  void enumerate() {
186  // Get access to data.
187  T* data_ptr = this->data();
188 
189 #pragma omp parallel for
190  for (size_t i = 0; i < (size_t)this->size(); i++)
191  data_ptr[i] = i;
192  }
193 
199  void randn(T mean = 0, T stddev = 1) {
200 
201  // Initialize random number generator with normal distribution.
202  std::random_device rd;
203  std::mt19937 mt(rd());
204  std::normal_distribution<T> dist(mean, stddev);
205 
206  // Get access to data.
207  T* data_ptr = this->data();
208 
209 #pragma omp parallel for
210  for (size_t i = 0; i < (size_t) (this->rows() * this->cols()); i++) {
211  data_ptr[i] = (T)dist(mt);
212  }
213  }
214 
221  void rand(T min = 0, T max = 1) {
222 
223  // Initialize random number generator with normal distribution.
224  std::random_device rd;
225  std::mt19937 mt(rd());
226  std::uniform_real_distribution<T> dist(min, max);
227 
228  // Get access to data.
229  T* data_ptr = this->data();
230 
231 #pragma omp parallel for
232  for (size_t i = 0; i < (size_t) (this->rows() * this->cols()); i++) {
233  data_ptr[i] = (T)dist(rd);
234  }
235  }
236 
237 
242  void elementwiseFunction(T (*func)(T)) {
243 
244  // Get access to data.
245  T* data_ptr = this->data();
246 
247  // Apply function to all elements.
248 #pragma omp parallel for
249  for (size_t i = 0; i < (size_t) (this->rows() * this->cols()); i++) {
250  data_ptr[i] = (*func)(data_ptr[i]);
251  } //: for i
252  }
253 
259  void elementwiseFunctionScalar(T (*func)(T, T), T scalar_) {
260 
261  // Get access to data.
262  T* data_ptr = this->data();
263 
264  // Apply function to all elements.
265 #pragma omp parallel for
266  for (size_t i = 0; i < (size_t) (this->rows() * this->cols()); i++) {
267  data_ptr[i] = (*func)(data_ptr[i], scalar_);
268  } //: for i
269  }
270 
276  void elementwiseFunctionMatrix(T (*func)(T, T), Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> & mat_) {
277 
278  // Check dimensions.
279  if ((this->rows() != mat_.rows()) || (this->cols() != mat_.cols()))
280  printf("elementwiseFunctionMatrix: dimensions mismatch!\n");
281 
282  // Get access to data.
283  T* data_ptr = this->data();
284  T* m_data_ptr = mat_.data();
285 
286  // Apply function to all elements.
287 #pragma omp parallel for
288  for (size_t i = 0; i < (size_t) (this->rows() * this->cols()); i++) {
289  data_ptr[i] = (*func)(data_ptr[i], m_data_ptr[i]);
290  }//: for i
291 
292  }
293 
299  void matrixColumnVectorFunction(T (*func)(T, T),
300  Eigen::Matrix<T, Eigen::Dynamic, 1>& v_) {
301 
302  if (this->rows() != v_.cols())
303  printf("matrixColumnVectorFunction: dimensions mismatch\n");
304 
305  // Get access to data.
306  //float* data_ptr = data();
307  //int rows = this->rows();
308  //int cols = this->cols();
309  //float* vector_data_ptr = v_.data();
310 
311 #pragma omp parallel for
312  for (size_t x = 0; x < (size_t)this->cols(); x++) {
313  for (size_t y = 0; y < (size_t)this->rows(); y++) {
314  //data_ptr[x + y*cols] = (*func)(data_ptr[x + y*cols], vector_data_ptr[x]);
315  (*this)(y, x) = (*func)((*this)(y, x), v_(y));
316  }//: for y
317  }//: for x
318  }
319 
325  void matrixRowVectorFunction(T (*func)(T, T), Eigen::Matrix<T, Eigen::Dynamic, 1>& v_) {
326 
327  if (this->cols() != v_.cols())
328  printf("matrixRowVectorFunction: dimensions mismatch\n");
329 
330  // Get access to data.
331  /*float* data_ptr = data();
332  int rows = this->rows();
333  int cols = this->cols();
334  float* vector_data_ptr = v_.data();*/
335 
336 #pragma omp parallel for
337  for (size_t x = 0; x < (size_t)this->cols(); x++) {
338  for (size_t y = 0; y < (size_t)this->rows(); y++) {
339  //h(y,x) += c(x);
340  //(*this)(y,x) += v_(x);
341  (*this)(y, x) = (*func)((*this)(y, x), v_(x));
342  //data_ptr[x + y*cols] = (*func)(data_ptr[x + y*cols], vector_data_ptr[y]);
343  }//: for y
344  }//: for x
345  }
346 
347 
352  void repeatVector(Eigen::Matrix<T, Eigen::Dynamic, 1> &in) {
353 #pragma omp parallel for
354  for (size_t x = 0; x < (size_t)this->cols(); x++) {
355  for (size_t y = 0; y < (size_t)this->rows(); y++) {
356 
357  (*this)(y, x) = in(y);
358  }//: y
359  }//: x
360  }
361 
366  Eigen::Matrix<T, Eigen::Dynamic, 1> colwiseReturnMaxIndices() {
367 
368  Eigen::Matrix<T, Eigen::Dynamic, 1> indices((*this).cols());
369 
370  for (size_t i = 0; i < (size_t)(*this).cols(); i++) {
371 
372  T current_max_val;
373  T index;
374 
375  for (size_t j = 0; j < (size_t)(*this).rows(); j++) {
376 
377  if (j == 0 || (*this)(j, i) > current_max_val) {
378 
379  index = j;
380  current_max_val = (*this)(j, i);
381  }
382 
383  indices(i) = index;
384 
385  }
386  }
387 
388  return indices;
389  }
390 
396  T calculateCrossEntropy(Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& targets_) {
397 
398  T ce = 0.0;
399  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> error(this->rows(), this->cols());
400 
401  //check what has happened and get information content for that event
402  error.array() = - (this->unaryExpr(std::ptr_fun(::logf)).array() * targets_.array());
403 
404  // Sum the errors.
405  ce = error.sum();
406 
407  return ce;
408  }
409 
410  /****************** ARMADILLO COMPATIBILITY *********************************/
411 
415  void zeros (){
416  this->setZero();
417  }
418 
419  T& operator [](int idx) {
420  return this->data()[idx];
421  }
422 
423  T operator [](int idx) const {
424  return this->data()[idx];
425  }
426 
427 private:
428 
429  // Friend class - required for using boost serialization.
431 
437  template<class Archive>
438  void save(Archive & ar, const unsigned int version) const {
439  size_t rows, cols;
440  rows = this->rows();
441  cols = this->cols();
442  ar & rows;
443  ar & cols;
444  // Save elements.
445  size_t elements = (size_t)(this->rows() * this->cols());
446  T* data_ptr = (T*)this->data();
447  ar & boost::serialization::make_array<T>(data_ptr, elements);
448  }
449 
455  template<class Archive>
456  void load(Archive & ar, const unsigned int version) {
457  size_t rows, cols;
458  ar & rows;
459  ar & cols;
460  // Allocate memory - resize.
461  this->resize(rows, cols);
462  // Load elements
463  size_t elements = (size_t)(this->rows() * this->cols());
464  T* data_ptr = this->data();
465  ar & boost::serialization::make_array<T>(data_ptr, elements);
466  }
467 
468  // The serialization must be splited as load requires to allocate the memory.
469  BOOST_SERIALIZATION_SPLIT_MEMBER()
470 
471 };
472 
473 
478 template<typename T>
479 using MatrixPtr = typename std::shared_ptr< mic::types::Matrix<T> >;
480 
481 }//: namespace types
482 }//: namespace mic
483 
484 
485 
486 // Just in the case that something important will change in the matrix class - set version.
487 BOOST_CLASS_VERSION(mic::types::Matrix<bool>, 1)
488 BOOST_CLASS_VERSION(mic::types::Matrix<short>, 1)
489 BOOST_CLASS_VERSION(mic::types::Matrix<int>, 1)
490 BOOST_CLASS_VERSION(mic::types::Matrix<long>, 1)
491 BOOST_CLASS_VERSION(mic::types::Matrix<float>, 1)
492 BOOST_CLASS_VERSION(mic::types::Matrix<double>, 1)
493 
494 #endif /* SRC_TYPES_MATRIX_HPP_ */
T & operator[](int idx)
Definition: Matrix.hpp:419
void randn(T mean=0, T stddev=1)
Definition: Matrix.hpp:199
EIGEN_STRONG_INLINE Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > operator*(const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &mat_)
Definition: Matrix.hpp:162
void load(Archive &ar, const unsigned int version)
Definition: Matrix.hpp:456
EIGEN_STRONG_INLINE Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > & operator=(const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &mat_)
Definition: Matrix.hpp:149
EIGEN_STRONG_INLINE Matrix(const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &matrix_)
Definition: Matrix.hpp:103
EIGEN_STRONG_INLINE Matrix(mic::types::Tensor< T > &tensor_)
Definition: Matrix.hpp:116
T calculateCrossEntropy(Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &targets_)
Definition: Matrix.hpp:396
void elementwiseFunctionMatrix(T(*func)(T, T), Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &mat_)
Definition: Matrix.hpp:276
void setValue(T value_)
Definition: Matrix.hpp:173
void save(Archive &ar, const unsigned int version) const
Definition: Matrix.hpp:438
EIGEN_STRONG_INLINE Matrix()
Definition: Matrix.hpp:71
Eigen::Matrix< T, Eigen::Dynamic, 1 > colwiseReturnMaxIndices()
Definition: Matrix.hpp:366
void rand(T min=0, T max=1)
Definition: Matrix.hpp:221
void matrixRowVectorFunction(T(*func)(T, T), Eigen::Matrix< T, Eigen::Dynamic, 1 > &v_)
Definition: Matrix.hpp:325
typename std::shared_ptr< mic::types::Matrix< T > > MatrixPtr
Typedef for a shared pointer to template-typed dynamic matrices.
Definition: Matrix.hpp:479
void elementwiseFunctionScalar(T(*func)(T, T), T scalar_)
Definition: Matrix.hpp:259
EIGEN_STRONG_INLINE Matrix(int Rows_, int Cols_)
Definition: Matrix.hpp:81
EIGEN_STRONG_INLINE Matrix(const Eigen::Matrix< T, Eigen::Dynamic, 1 > &vector_)
Definition: Matrix.hpp:91
void matrixColumnVectorFunction(T(*func)(T, T), Eigen::Matrix< T, Eigen::Dynamic, 1 > &v_)
Definition: Matrix.hpp:299
void repeatVector(Eigen::Matrix< T, Eigen::Dynamic, 1 > &in)
Definition: Matrix.hpp:352
friend class boost::serialization::access
Definition: Matrix.hpp:430
Template class representing an nD (n-Dimensional) tensor. Tensor is row-major, i.e. first dimension is height (rows), second is width (cols), third is depth (channels) etc.
Definition: Matrix.hpp:49
void elementwiseFunction(T(*func)(T))
Definition: Matrix.hpp:242
Template-typed Matrix of dynamic size. Uses OpenBLAS if found by CMAKE - overloaded, specializations of * operator for types: float, double.
Definition: Matrix.hpp:64
std::vector< size_t > dims()
Definition: Tensor.hpp:308