A singular Riemannian geometry approach to Deep Neural Networks.
matrix_utils.h
1 //------------------------------------------------------------------------------
2 //
3 // MATRIX UTILS
4 // Utils to work with Eigen::MatrixXd
5 //
6 //------------------------------------------------------------------------------
7 
8 
9 #ifndef MATRIX_UTILS_H
10 #define MATRIX_UTILS_H
11 
12 //Eigen libs
13 #include"Eigen/Dense"
14 #include"Eigen/Core"
15 
16 //OpenMP libs
17 #include"omp.h"
18 
19 //------------------------------------------------------------------------------
20 // Functions to work with reduced form of the jacobians.
21 // The jacobians of the layers map are sparse matrices
22 // with the same number of (consecutive) non-zero entries
23 // in each row (See the documentation).
24 // The following functions allow to convert
25 // a standard matrix from/to reduced form and implement
26 // mutliplications between different forms of matrices
27 //------------------------------------------------------------------------------
28 
29 //Multiplication between a reduced matrix and a standard one
30 inline Eigen::MatrixXd reduced_standard_mul(Eigen::MatrixXd &red, Eigen::MatrixXd &std)
31 {
32  int rows_red = red.rows();
33  int non_null_per_row = rows_red*(red.cols());
34  int rows_std = std.rows();
35  int cols_std = std.cols();
36  Eigen::MatrixXd result(rows_red,cols_std);
37  #pragma omp parallel for collapse(2) shared(red,std,result,rows_red,non_null_per_row,rows_std,cols_std)
38  for (int i = 0; i < rows_red; i++)
39  {
40  for (int j = 0; j < cols_std; j++)
41  {
42  #pragma omp simd
43  for (int k = 0; k < rows_std; k++)
44  {
45  result(i,j) = red(i,k)*std(k*non_null_per_row,j);
46  }
47  }
48  }
49  return result;
50 }
51 //------------------------------------------------------------------------------
52 //Multiplication between a standard matrix and a reduced one
53 inline Eigen::MatrixXd standard_reduced_mul(Eigen::MatrixXd &std, Eigen::MatrixXd &red)
54 {
55  int rows_std = std.rows();
56  int cols_std = std.cols();
57  int rows_red = red.rows();
58  int cols_red = red.cols();
59  int non_null_per_row = red.cols();
60  Eigen::MatrixXd result(rows_std,cols_red*rows_red);
61  result = move(Eigen::MatrixXd::Zero(rows_std,cols_red*rows_red));
62  for (int i = 0; i < rows_std; i++)
63  {
64  for (int j = 0; j < cols_std; j++)
65  {
66  #pragma omp simd
67  for (int k = 0; k < non_null_per_row; k++)
68  {
69  result(i,j*non_null_per_row+k) = std(i,j)*red(j,k);
70  }
71  }
72  }
73  return result;
74 }
75 //------------------------------------------------------------------------------
76 //Conversion from reduced form to standard form
77 inline Eigen::MatrixXd reduced_to_standard(Eigen::MatrixXd &a)
78 {
79 
80  int rows_a = a.rows();
81  int cols_a = a.cols();
82  int a_non_null_per_row = cols_a;
83  int cols_res = rows_a*a_non_null_per_row;
84  Eigen::MatrixXd result;
85  result = move(Eigen::MatrixXd::Zero(rows_a,cols_res));
86  #pragma omp parallel for shared(a,result,rows_a,cols_a,a_non_null_per_row)
87  for (int i = 0; i < rows_a; i++)
88  {
89  #pragma omp simd
90  for (int j = 0; j < cols_a; j++)
91  {
92  result(i,i*a_non_null_per_row+j) = a(i,j);
93  }
94 
95  }
96  //cout << "OK!" << endl;
97  return result;
98 }
99 //------------------------------------------------------------------------------
100 //Conversion from standard form to reduced form
101 inline Eigen::MatrixXd standard_to_reduced(Eigen::MatrixXd &a)
102 {
103  int rows_a = a.rows();
104  int cols_a = a.cols();
105  int a_non_null_per_row = cols_a/rows_a;
106  int cols_res = a_non_null_per_row;
107  Eigen::MatrixXd result(rows_a,cols_res);
108  #pragma omp parallel for shared(a,result,rows_a,cols_a,a_non_null_per_row,cols_res)
109  for (int i = 0; i < rows_a; i++)
110  {
111  #pragma omp simd
112  for (int j = 0; j < cols_res; j++)
113  {
114  result(i,j) = a(i,i*a_non_null_per_row+j);
115  }
116  }
117  return result;
118 }
119 //------------------------------------------------------------------------------
120 
121 
122 //------------------------------------------------------------------------------
123 // Operations on generic matrices
124 //------------------------------------------------------------------------------
125 
126 //Compute the Frobenius norm of a matrix
127 inline double Frobenius_norm(Eigen::MatrixXd &mat)
128 {
129  const int rows = mat.rows();
130  const int cols = mat.cols();
131  double result = 0.;
132  #pragma omp parallel for collapse(2) shared(mat) reduction(+: result)
133  for (int i = 0; i < rows; i++)
134  {
135  for (int j = 0; j < cols; j++)
136  {
137 
138  result += mat(i,j)*mat(i,j);
139  }
140  }
141  result = sqrt(result);
142  return result;
143 }
144 //------------------------------------------------------------------------------
145 
146 //------------------------------------------------------------------------------
147 // Write a matrix to file
148 //------------------------------------------------------------------------------
149 
150 //Write a matrix to file
151 inline void write_eigen_matrixxf_to_file(string filename, char separating_char, Eigen::MatrixXd &mat)
152 {
153  std::ofstream file;
154  file.open(filename);
155  const int nrows = mat.rows();
156  const int ncols = mat.cols();
157  for (int i = 0; i < nrows; i++)
158  {
159  for (int j = 0; j < ncols; j++)
160  {
161  file << mat(i,j);
162  file << separating_char;
163  }
164  file << endl;
165  }
166  file.close();
167 }
168 #endif /* MATRIX_UTILS_H */