KerasModel.cxx
Go to the documentation of this file.
2 
3 #include <iostream>
4 #include <fstream>
5 #include <algorithm>
6 #include <math.h>
7 
8 using namespace std;
9 
10 
11 std::vector<float> keras::read_1d_array(std::ifstream &fin, int cols) {
12  vector<float> arr;
13  float tmp_float;
14  char tmp_char;
15  fin >> tmp_char; // for '['
16  for(int n = 0; n < cols; ++n) {
17  fin >> tmp_float;
18  arr.push_back(tmp_float);
19  }
20  fin >> tmp_char; // for ']'
21  return arr;
22 }
23 
25  ifstream fin(fname.c_str());
26  fin >> m_depth >> m_rows >> m_cols;
27 
28  for(int d = 0; d < m_depth; ++d) {
29  vector<vector<float> > tmp_single_depth;
30  for(int r = 0; r < m_rows; ++r) {
31  vector<float> tmp_row = keras::read_1d_array(fin, m_cols);
32  tmp_single_depth.push_back(tmp_row);
33  }
34  data.push_back(tmp_single_depth);
35  }
36  fin.close();
37 }
38 
39 
40 void keras::LayerConv2D::load_weights(std::ifstream &fin) {
41  char tmp_char = ' ';
42  string tmp_str = "";
43  float tmp_float;
44  bool skip = false;
45  fin >> m_kernels_cnt >> m_depth >> m_rows >> m_cols >> m_border_mode;
46  if (m_border_mode == "[") { m_border_mode = "valid"; skip = true; }
47 
48  // reading kernel weights
49  for(int k = 0; k < m_kernels_cnt; ++k) {
50  vector<vector<vector<float> > > tmp_depths;
51  for(int d = 0; d < m_depth; ++d) {
52  vector<vector<float> > tmp_single_depth;
53  for(int r = 0; r < m_rows; ++r) {
54  if (!skip) { fin >> tmp_char; } // for '['
55  else { skip = false; }
56  vector<float> tmp_row;
57  for(int c = 0; c < m_cols; ++c) {
58  fin >> tmp_float;
59  tmp_row.push_back(tmp_float);
60  }
61  fin >> tmp_char; // for ']'
62  tmp_single_depth.push_back(tmp_row);
63  }
64  tmp_depths.push_back(tmp_single_depth);
65  }
66  m_kernels.push_back(tmp_depths);
67  }
68  // reading kernel biases
69  fin >> tmp_char; // for '['
70  for(int k = 0; k < m_kernels_cnt; ++k) {
71  fin >> tmp_float;
72  m_bias.push_back(tmp_float);
73  }
74  fin >> tmp_char; // for ']'
75 
76 }
77 
79  fin >> m_activation_type;
80 }
81 
83  fin >> m_pool_x >> m_pool_y;
84 }
85 
86 void keras::LayerDense::load_weights(std::ifstream &fin) {
87  fin >> m_input_cnt >> m_neurons;
88  float tmp_float;
89  char tmp_char = ' ';
90  for(int i = 0; i < m_input_cnt; ++i) {
91  vector<float> tmp_n;
92  fin >> tmp_char; // for '['
93  for(int n = 0; n < m_neurons; ++n) {
94  fin >> tmp_float;
95  tmp_n.push_back(tmp_float);
96  }
97  fin >> tmp_char; // for ']'
98  m_weights.push_back(tmp_n);
99  }
100  fin >> tmp_char; // for '['
101  for(int n = 0; n < m_neurons; ++n) {
102  fin >> tmp_float;
103  m_bias.push_back(tmp_float);
104  }
105  fin >> tmp_char; // for ']'
106 
107 }
108 
109 keras::KerasModel::KerasModel(const string &input_fname) {
110  load_weights(input_fname);
111 }
112 
113 
115  vector<vector<vector<float> > > im = dc->get_3d();
116 
117  size_t csize = im[0].size();
118  size_t rsize = im[0][0].size();
119  size_t size = im.size() * csize * rsize;
121  float * y_ret = out->get_1d_rw().data();
122  for(size_t i = 0, dst = 0; i < im.size(); ++i) {
123  for(size_t j = 0; j < csize; ++j) {
124  float * row = im[i][j].data();
125  for(size_t k = 0; k < rsize; ++k) {
126  y_ret[dst++] = row[k];
127  }
128  }
129  }
130 
131  return out;
132 }
133 
134 
136  vector<vector<vector<float> > > im = dc->get_3d();
137  vector<vector<vector<float> > > y_ret;
138  for(unsigned int i = 0; i < im.size(); ++i) {
139  vector<vector<float> > tmp_y;
140  for(unsigned int j = 0; j < (unsigned int)(im[0].size()/m_pool_x); ++j) {
141  tmp_y.push_back(vector<float>((int)(im[0][0].size()/m_pool_y), 0.0));
142  }
143  y_ret.push_back(tmp_y);
144  }
145  for(unsigned int d = 0; d < y_ret.size(); ++d) {
146  for(unsigned int x = 0; x < y_ret[0].size(); ++x) {
147  unsigned int start_x = x*m_pool_x;
148  unsigned int end_x = start_x + m_pool_x;
149  for(unsigned int y = 0; y < y_ret[0][0].size(); ++y) {
150  unsigned int start_y = y*m_pool_y;
151  unsigned int end_y = start_y + m_pool_y;
152 
153  vector<float> values;
154  for(unsigned int i = start_x; i < end_x; ++i) {
155  for(unsigned int j = start_y; j < end_y; ++j) {
156  values.push_back(im[d][i][j]);
157  }
158  }
159  y_ret[d][x][y] = *max_element(values.begin(), values.end());
160  }
161  }
162  }
164  out->set_data(y_ret);
165  return out;
166 }
167 
168 void keras::missing_activation_impl(const string &act) {
169  cout << "Activation " << act << " not defined!" << endl;
170  cout << "Please add its implementation before use." << endl;
171  exit(1);
172 }
173 
175 
176  if (dc->get_data_dim() == 3) {
177  vector<vector<vector<float> > > y = dc->get_3d();
178  if(m_activation_type == "relu") {
179  for(unsigned int i = 0; i < y.size(); ++i) {
180  for(unsigned int j = 0; j < y[0].size(); ++j) {
181  for(unsigned int k = 0; k < y[0][0].size(); ++k) {
182  if(y[i][j][k] < 0) y[i][j][k] = 0;
183  }
184  }
185  }
187  out->set_data(y);
188  return out;
189  } else {
190  keras::missing_activation_impl(m_activation_type);
191  }
192  } else if (dc->get_data_dim() == 1) { // flat data, use 1D
193  vector<float> y = dc->get_1d();
194  if(m_activation_type == "relu") {
195  for(unsigned int k = 0; k < y.size(); ++k) {
196  if(y[k] < 0) y[k] = 0;
197  }
198  } else if(m_activation_type == "softmax") {
199  float sum = 0.0;
200  for(unsigned int k = 0; k < y.size(); ++k) {
201  y[k] = exp(y[k]);
202  sum += y[k];
203  }
204  for(unsigned int k = 0; k < y.size(); ++k) {
205  y[k] /= sum;
206  }
207  } else if(m_activation_type == "sigmoid") {
208  for(unsigned int k = 0; k < y.size(); ++k) {
209  y[k] = 1/(1+exp(-y[k]));
210  }
211  } else {
212  keras::missing_activation_impl(m_activation_type);
213  }
214 
216  out->set_data(y);
217  return out;
218  } else { throw "data dim not supported"; }
219 
220  return dc;
221 }
222 
223 
224 // with border mode = valid
225 std::vector< std::vector<float> > keras::conv_single_depth_valid(
226  std::vector< std::vector<float> > const & im,
227  std::vector< std::vector<float> > const & k)
228 {
229  unsigned int st_x = (k.size() - 1) >> 1;
230  unsigned int st_y = (k[0].size() - 1) >> 1;
231 
232  std::vector< std::vector<float> > y;
233  for(unsigned int i = 0; i < im.size()-2*st_x; ++i) {
234  y.emplace_back(vector<float>(im[0].size()-2*st_y, 0.0));
235  }
236  for(unsigned int i = st_x; i < im.size()-st_x; ++i) {
237  for(unsigned int j = st_y; j < im[0].size()-st_y; ++j) {
238  for(unsigned int k1 = 0; k1 < k.size(); ++k1) {
239  for(unsigned int k2 = 0; k2 < k[0].size(); ++k2) {
240  y[i-st_x][j-st_y] += k[k.size()-k1-1][k[0].size()-k2-1] * im[i-st_x+k1][j-st_y+k2];
241  }
242  }
243  }
244  }
245  return y;
246 }
247 
248 
249 // with border mode = same
250 std::vector< std::vector<float> > keras::conv_single_depth_same(
251  std::vector< std::vector<float> > const & im,
252  std::vector< std::vector<float> > const & k)
253 {
254  unsigned int st_x = (k.size() - 1) / 2;
255  unsigned int st_y = (k[0].size() - 1) / 2;
256 
257  std::vector< std::vector<float> > y;
258  for(unsigned int i = 0; i < im.size(); ++i) {
259  y.emplace_back(vector<float>(im[0].size(), 0.0));
260  }
261  for(unsigned int i = 0; i < im.size(); ++i) {
262  for(unsigned int j = 0; j < im[0].size(); ++j) {
263  for(unsigned int k1 = 0; k1 < k.size(); ++k1) {
264  for(unsigned int k2 = 0; k2 < k[0].size(); ++k2) {
265  if(i+k1 < st_x) continue;
266  if(i-st_x+k1 > im.size()-1) continue;
267  if(j+k2 < st_y) continue;
268  if(j-st_y+k2 > im[0].size()-1) continue;
269  y[i][j] += k[k.size()-k1-1][k[0].size()-k2-1] * im[i-st_x+k1][j-st_y+k2];
270  }
271  }
272  }
273  }
274  return y;
275 }
276 
277 
279 
280  unsigned int st_x = (m_kernels[0][0].size()-1)/2;
281  unsigned int st_y = (m_kernels[0][0][0].size()-1)/2;
282  vector< vector< vector<float> > > y_ret;
283  auto const & im = dc->get_3d();
284 
285  size_t size_x = (m_border_mode == "valid")? im[0].size() - 2 * st_x : im[0].size();
286  size_t size_y = (m_border_mode == "valid")? im[0][0].size() - 2 * st_y: im[0][0].size();
287  for(unsigned int i = 0; i < m_kernels.size(); ++i) { // depth
288  vector<vector<float> > tmp;
289  tmp.reserve(size_x);
290  for(unsigned int j = 0; j < size_x; ++j) { // rows
291  tmp.emplace_back(vector<float>(size_y, 0.0));
292  }
293  y_ret.push_back(tmp);
294  }
295 
296  for(unsigned int j = 0; j < m_kernels.size(); ++j) { // loop over kernels
297  for(unsigned int m = 0; m < im.size(); ++m) { // loope over image depth
298 
299  vector<vector<float> > tmp_w = (m_border_mode == "valid")?
300  keras::conv_single_depth_valid(im[m], m_kernels[j][m]) :
301  keras::conv_single_depth_same(im[m], m_kernels[j][m]);
302 
303  for(unsigned int x = 0; x < tmp_w.size(); ++x) {
304  for(unsigned int y = 0; y < tmp_w[0].size(); ++y) {
305  y_ret[j][x][y] += tmp_w[x][y];
306  }
307  }
308  }
309 
310  for(unsigned int x = 0; x < y_ret[0].size(); ++x) {
311  for(unsigned int y = 0; y < y_ret[0][0].size(); ++y) {
312  y_ret[j][x][y] += m_bias[j];
313  }
314  }
315  }
316 
318  out->set_data(y_ret);
319  return out;
320 }
321 
323  size_t size = m_weights[0].size();
324  size_t size8 = size >> 3;
325  keras::DataChunkFlat *out = new DataChunkFlat(size, 0);
326  float * y_ret = out->get_1d_rw().data();
327  auto const & im = dc->get_1d();
328 
329  for (size_t j = 0; j < m_weights.size(); ++j) { // iter over input
330  const float * w = m_weights[j].data();
331  float p = im[j];
332  size_t k = 0;
333  for (size_t i = 0; i < size8; ++i) { // iter over neurons
334  y_ret[k] += w[k] * p; // vectorize if you can
335  y_ret[k+1] += w[k+1] * p;
336  y_ret[k+2] += w[k+2] * p;
337  y_ret[k+3] += w[k+3] * p;
338  y_ret[k+4] += w[k+4] * p;
339  y_ret[k+5] += w[k+5] * p;
340  y_ret[k+6] += w[k+6] * p;
341  y_ret[k+7] += w[k+7] * p;
342  k += 8;
343  }
344  while (k < size) { y_ret[k] += w[k] * p; ++k; }
345  }
346  for (size_t i = 0; i < size; ++i) { // add biases
347  y_ret[i] += m_bias[i];
348  }
349 
350  return out;
351 }
352 
353 
355 
356  keras::DataChunk *inp = dc;
357  keras::DataChunk *out = 0;
358  for(int l = 0; l < (int)m_layers.size(); ++l) {
359  out = m_layers[l]->compute_output(inp);
360 
361  if(inp != dc) delete inp;
362  //delete inp;
363  inp = 0L;
364  inp = out;
365  }
366 
367  out->show_values();
368 
369  std::vector<float> flat_out = out->get_1d();
370  delete out;
371 
372  return flat_out;
373 }
374 
375 void keras::KerasModel::load_weights(const string &input_fname) {
376  ifstream fin(input_fname.c_str());
377  string layer_type = "";
378  string tmp_str = "";
379  int tmp_int = 0;
380 
381  fin >> tmp_str >> m_layers_cnt;
382 
383  for(int layer = 0; layer < m_layers_cnt; ++layer) { // iterate over layers
384  fin >> tmp_str >> tmp_int >> layer_type;
385 
386  Layer *l = 0L;
387  if(layer_type == "Convolution2D") {
388  l = new LayerConv2D();
389  } else if(layer_type == "Activation") {
390  l = new LayerActivation();
391  } else if(layer_type == "MaxPooling2D") {
392  l = new LayerMaxPooling();
393  } else if(layer_type == "Flatten") {
394  l = new LayerFlatten();
395  } else if(layer_type == "Dense") {
396  l = new LayerDense();
397  } else if(layer_type == "Dropout") {
398  continue; // we dont need dropout layer in prediciton mode
399  }
400  if(l == 0L) {
401  cout << "Layer is empty, maybe it is not defined? Cannot define network." << endl;
402  return;
403  }
404  l->load_weights(fin);
405  m_layers.push_back(l);
406  }
407 
408  fin.close();
409 }
410 
412  for(int i = 0; i < (int)m_layers.size(); ++i) {
413  delete m_layers[i];
414  }
415 }
416 
418 {
419  int i = m_layers.size() - 1;
420  while ((i > 0) && (m_layers[i]->get_output_units() == 0)) --i;
421  return m_layers[i]->get_output_units();
422 }
TString fin
Definition: Style.C:24
void load_weights(std::ifstream &fin)
Definition: KerasModel.cxx:40
KerasModel(const std::string &input_fname)
keras::DataChunk * compute_output(keras::DataChunk *)
Definition: KerasModel.cxx:278
std::vector< std::vector< float > > conv_single_depth_same(std::vector< std::vector< float > > const &im, std::vector< std::vector< float > > const &k)
Definition: KerasModel.cxx:250
const char * p
Definition: xmltok.h:285
int get_output_length() const
Definition: KerasModel.cxx:417
virtual void set_data(std::vector< std::vector< std::vector< float > > > const &)
Definition: KerasModel.h:38
char * dst
Definition: lz4.h:458
void load_weights(const std::string &input_fname)
Definition: KerasModel.cxx:416
virtual void load_weights(std::ifstream &fin)=0
Float_t tmp
Definition: plot.C:36
virtual std::vector< std::vector< std::vector< float > > > const & get_3d() const
Definition: KerasModel.h:37
virtual size_t get_data_dim(void) const
Definition: KerasModel.h:35
virtual void show_values()=0
keras::DataChunk * compute_output(keras::DataChunk *)
Definition: KerasModel.cxx:322
keras::DataChunk * compute_output(keras::DataChunk *)
Definition: KerasModel.cxx:114
std::vector< float > compute_output(keras::DataChunk *dc)
Definition: KerasModel.cxx:354
const XML_Char const XML_Char * data
Definition: expat.h:268
const int cols[3]
static constexpr double L
void read_from_file(const std::string &fname)
Definition: KerasModel.cxx:24
fvar< T > exp(const fvar< T > &x)
Definition: exp.hpp:10
Float_t d
Definition: plot.C:236
const double j
Definition: BetheBloch.cxx:29
keras::DataChunk * compute_output(keras::DataChunk *)
Definition: KerasModel.cxx:174
void missing_activation_impl(const std::string &act)
Definition: KerasModel.cxx:176
std::vector< std::vector< float > > conv_single_depth_valid(std::vector< std::vector< float > > const &im, std::vector< std::vector< float > > const &k)
Definition: KerasModel.cxx:225
void load_weights(std::ifstream &fin)
Definition: KerasModel.cxx:86
OStream cout
Definition: OStream.cxx:6
::xsd::cxx::tree::string< char, simple_type > string
Definition: Database.h:154
keras::DataChunk * compute_output(keras::DataChunk *)
Definition: KerasModel.cxx:135
exit(0)
std::vector< float > & get_1d_rw()
Definition: KerasModel.h:89
TRandom3 r(0)
Double_t sum
Definition: plot.C:31
void load_weights(std::ifstream &fin)
Definition: KerasModel.cxx:78
void load_weights(std::ifstream &fin)
Definition: KerasModel.cxx:82
Float_t w
Definition: plot.C:20
virtual std::vector< float > const & get_1d() const
Definition: KerasModel.h:36
std::vector< float > read_1d_array(std::ifstream &fin, int cols)
Definition: KerasModel.cxx:11