/jml/neural/auto_encoder_stack.cc

https://gitlab.com/max-crow/rtbkit-p · C++ · 480 lines · 376 code · 84 blank · 20 comment · 32 complexity · 11a51fbebff07409dae4a1d6ec264267 MD5 · raw file

  1. /* auto_encoder_stack.cc -*- C++ -*-
  2. Jeremy Barnes, 11 November 2009
  3. Copyright (c) 2009 Jeremy Barnes. All rights reserved.
  4. Implementation of a stack of auto-encoders.
  5. */
  6. #undef NDEBUG
  7. #include "auto_encoder_stack.h"
  8. #include "jml/boosting/registry.h"
  9. #include "layer_stack_impl.h"
  10. #include "jml/utils/check_not_nan.h"
  11. using namespace std;
  12. namespace ML {
  13. /*****************************************************************************/
  14. /* AUTO_ENCODER_STACK */
  15. /*****************************************************************************/
  16. /** A stack of auto-encoders, that acts as a whole like an auto-encoder. */
  17. Auto_Encoder_Stack::
  18. Auto_Encoder_Stack()
  19. {
  20. }
  21. Auto_Encoder_Stack::
  22. Auto_Encoder_Stack(const std::string & name)
  23. : layers_(name)
  24. {
  25. }
  26. Auto_Encoder_Stack::
  27. Auto_Encoder_Stack(const Auto_Encoder_Stack & other, Deep_Copy_Tag)
  28. : Auto_Encoder(other),
  29. layers_(other.layers_, Deep_Copy_Tag())
  30. {
  31. update_parameters();
  32. }
  33. void
  34. Auto_Encoder_Stack::
  35. swap(Auto_Encoder_Stack & other)
  36. {
  37. Auto_Encoder::swap(other);
  38. layers_.swap(other.layers_);
  39. }
  40. void
  41. Auto_Encoder_Stack::
  42. clear()
  43. {
  44. layers_.clear();
  45. update_parameters();
  46. }
  47. void
  48. Auto_Encoder_Stack::
  49. add(Auto_Encoder * layer)
  50. {
  51. layers_.add(layer);
  52. Layer::init(name(), layers_.inputs(), layers_.outputs());
  53. update_parameters();
  54. }
  55. void
  56. Auto_Encoder_Stack::
  57. add(std::shared_ptr<Auto_Encoder> layer)
  58. {
  59. layers_.add(layer);
  60. Layer::init(name(), layers_.inputs(), layers_.outputs());
  61. update_parameters();
  62. }
  63. std::string
  64. Auto_Encoder_Stack::
  65. print() const
  66. {
  67. return layers_.print();
  68. }
  69. std::string
  70. Auto_Encoder_Stack::
  71. class_id() const
  72. {
  73. return "Auto_Encoder_Stack";
  74. }
  75. void
  76. Auto_Encoder_Stack::
  77. serialize(DB::Store_Writer & store) const
  78. {
  79. store << (char)1 // version
  80. << layers_;
  81. }
  82. void
  83. Auto_Encoder_Stack::
  84. reconstitute(DB::Store_Reader & store)
  85. {
  86. char version;
  87. store >> version;
  88. if (version != 1)
  89. throw Exception("Auto_Encoder_Stack::reconstitute(): invalid version");
  90. store >> layers_;
  91. //cerr << "reconstituted auto encoder stack; layers_.inputs() = "
  92. // << layers_.inputs() << endl;
  93. Layer::init(name(), layers_.inputs(), layers_.outputs());
  94. update_parameters();
  95. }
  96. void
  97. Auto_Encoder_Stack::
  98. add_parameters(Parameters & params)
  99. {
  100. layers_.add_parameters(params);
  101. }
  102. void
  103. Auto_Encoder_Stack::
  104. apply(const float * input, float * output) const
  105. {
  106. return layers_.apply(input, output);
  107. }
  108. void
  109. Auto_Encoder_Stack::
  110. apply(const double * input, double * output) const
  111. {
  112. return layers_.apply(input, output);
  113. }
  114. size_t
  115. Auto_Encoder_Stack::
  116. fprop_temporary_space_required() const
  117. {
  118. return layers_.fprop_temporary_space_required();
  119. }
  120. void
  121. Auto_Encoder_Stack::
  122. fprop(const float * inputs,
  123. float * temp_space, size_t temp_space_size,
  124. float * outputs) const
  125. {
  126. layers_.fprop(inputs, temp_space, temp_space_size, outputs);
  127. }
  128. void
  129. Auto_Encoder_Stack::
  130. fprop(const double * inputs,
  131. double * temp_space, size_t temp_space_size,
  132. double * outputs) const
  133. {
  134. layers_.fprop(inputs, temp_space, temp_space_size, outputs);
  135. }
  136. void
  137. Auto_Encoder_Stack::
  138. bprop(const float * inputs,
  139. const float * outputs,
  140. const float * temp_space, size_t temp_space_size,
  141. const float * output_errors,
  142. float * input_errors,
  143. Parameters & gradient,
  144. double example_weight) const
  145. {
  146. layers_.bprop(inputs, outputs, temp_space, temp_space_size,
  147. output_errors, input_errors, gradient, example_weight);
  148. }
  149. void
  150. Auto_Encoder_Stack::
  151. bprop(const double * inputs,
  152. const double * outputs,
  153. const double * temp_space, size_t temp_space_size,
  154. const double * output_errors,
  155. double * input_errors,
  156. Parameters & gradient,
  157. double example_weight) const
  158. {
  159. layers_.bprop(inputs, outputs, temp_space, temp_space_size,
  160. output_errors, input_errors, gradient, example_weight);
  161. }
  162. std::pair<float, float>
  163. Auto_Encoder_Stack::
  164. itargets(float maximum) const
  165. {
  166. if (layers_.empty())
  167. throw Exception("itargets(): no layers");
  168. return layers_.back().itargets(maximum);
  169. }
  170. bool
  171. Auto_Encoder_Stack::
  172. supports_missing_outputs() const
  173. {
  174. if (layers_.empty())
  175. throw Exception("itargets(): no layers");
  176. return layers_.back().supports_missing_outputs();
  177. }
  178. void
  179. Auto_Encoder_Stack::
  180. iapply(const float * output, float * input) const
  181. {
  182. iapply<float>(output, input);
  183. }
  184. void
  185. Auto_Encoder_Stack::
  186. iapply(const double * output, double * input) const
  187. {
  188. iapply<double>(output, input);
  189. }
  190. template<typename F>
  191. void
  192. Auto_Encoder_Stack::
  193. iapply(const F * output, F * input) const
  194. {
  195. F tmp[layers_.max_internal_width()];
  196. for (int l = layers_.size() - 1; l >= 0; --l) {
  197. F * i = (l == 0 ? input : tmp);
  198. const F * o = (l == layers_.size() - 1 ? output : tmp);
  199. layers_[l].iapply(o, i);
  200. }
  201. }
  202. size_t
  203. Auto_Encoder_Stack::
  204. ifprop_temporary_space_required() const
  205. {
  206. // We need: inputs of all layers except the first,
  207. // temporary space of all layers in between.
  208. //
  209. // +-----------+-------+-------------+--------+---...
  210. // | l0 tmp | l0 out| l1 tmp | l1 out| l2 tmp
  211. // +-----------+-------+-------------+--------+---...
  212. size_t result = 0;
  213. for (unsigned i = 0; i < size(); ++i) {
  214. if (i != 0) result += layers_[i].inputs();
  215. result += layers_[i].ifprop_temporary_space_required();
  216. }
  217. return result;
  218. }
  219. void
  220. Auto_Encoder_Stack::
  221. ifprop(const float * outputs,
  222. float * temp_space, size_t temp_space_size,
  223. float * inputs) const
  224. {
  225. ifprop<float>(outputs, temp_space, temp_space_size, inputs);
  226. }
  227. void
  228. Auto_Encoder_Stack::
  229. ifprop(const double * outputs,
  230. double * temp_space, size_t temp_space_size,
  231. double * inputs) const
  232. {
  233. ifprop<double>(outputs, temp_space, temp_space_size, inputs);
  234. }
  235. template<typename F>
  236. void
  237. Auto_Encoder_Stack::
  238. ifprop(const F * outputs,
  239. F * temp_space, size_t temp_space_size,
  240. F * inputs) const
  241. {
  242. F * temp_space_start = temp_space;
  243. F * temp_space_end = temp_space_start + temp_space_size;
  244. const F * curr_outputs = outputs;
  245. for (int i = size() - 1; i >= 0; --i) {
  246. int layer_temp_space_size
  247. = layers_[i].ifprop_temporary_space_required();
  248. F * curr_inputs
  249. = (i == 0
  250. ? inputs
  251. : temp_space + layer_temp_space_size);
  252. layers_[i].ifprop(curr_outputs, temp_space, layer_temp_space_size,
  253. curr_inputs);
  254. curr_outputs = curr_inputs;
  255. temp_space += layer_temp_space_size;
  256. if (i != 0) temp_space += layers_[i].inputs();
  257. if (temp_space > temp_space_end
  258. || (i == 0 && temp_space != temp_space_end))
  259. throw Exception("temp space out of sync");
  260. }
  261. }
  262. void
  263. Auto_Encoder_Stack::
  264. ibprop(const float * outputs,
  265. const float * inputs,
  266. const float * temp_space, size_t temp_space_size,
  267. const float * input_errors,
  268. float * output_errors,
  269. Parameters & gradient,
  270. double example_weight) const
  271. {
  272. ibprop<float>(outputs, inputs, temp_space, temp_space_size,
  273. input_errors, output_errors, gradient, example_weight);
  274. }
  275. void
  276. Auto_Encoder_Stack::
  277. ibprop(const double * outputs,
  278. const double * inputs,
  279. const double * temp_space, size_t temp_space_size,
  280. const double * input_errors,
  281. double * output_errors,
  282. Parameters & gradient,
  283. double example_weight) const
  284. {
  285. ibprop<double>(outputs, inputs, temp_space, temp_space_size,
  286. input_errors, output_errors, gradient, example_weight);
  287. }
  288. template<typename F>
  289. void
  290. Auto_Encoder_Stack::
  291. ibprop(const F * outputs,
  292. const F * inputs,
  293. const F * temp_space, size_t temp_space_size,
  294. const F * input_errors,
  295. F * output_errors,
  296. Parameters & gradient,
  297. double example_weight) const
  298. {
  299. int ni = this->inputs(), no = this->outputs();
  300. CHECK_NOT_NAN_N(outputs, no);
  301. CHECK_NOT_NAN_N(inputs, ni);
  302. CHECK_NOT_NAN_N(input_errors, ni);
  303. const F * temp_space_start = temp_space;
  304. const F * temp_space_end = temp_space_start + temp_space_size;
  305. const F * curr_temp_space = temp_space_end;
  306. const F * curr_inputs = inputs;
  307. // Storage for the errors kept between the layers
  308. F error_storage[layers_.max_internal_width()];
  309. for (int i = 0; i < layers_.size(); ++i) {
  310. int layer_temp_space_size
  311. = layers_[i].ifprop_temporary_space_required();
  312. curr_temp_space -= layer_temp_space_size;
  313. const F * curr_outputs
  314. = (i == size() - 1
  315. ? outputs
  316. : curr_temp_space - layers_[i].outputs());
  317. const F * curr_input_errors
  318. = (i == 0 ? input_errors : error_storage);
  319. F * curr_output_errors
  320. = (i == size() - 1 ? output_errors : error_storage);
  321. //cerr << "i = " << i << endl;
  322. layers_[i].ibprop(curr_outputs, curr_inputs, curr_temp_space,
  323. layer_temp_space_size, curr_input_errors,
  324. curr_output_errors,
  325. gradient.subparams(i, layers_[i].name()),
  326. example_weight);
  327. if (curr_temp_space < temp_space_start)
  328. throw Exception("Layer temp space was out of sync");
  329. curr_inputs = curr_outputs;
  330. if (i != layers_.size() - 1) curr_temp_space -= layers_[i].outputs();
  331. }
  332. if (curr_temp_space != temp_space_start)
  333. throw Exception("Layer_Stack::bprop(): out of sync");
  334. }
  335. void
  336. Auto_Encoder_Stack::
  337. random_fill(float limit, Thread_Context & context)
  338. {
  339. layers_.random_fill(limit, context);
  340. }
  341. void
  342. Auto_Encoder_Stack::
  343. zero_fill()
  344. {
  345. layers_.zero_fill();
  346. }
  347. size_t
  348. Auto_Encoder_Stack::
  349. parameter_count() const
  350. {
  351. return layers_.parameter_count();
  352. }
  353. std::pair<float, float>
  354. Auto_Encoder_Stack::
  355. targets(float maximum) const
  356. {
  357. return layers_.targets(maximum);
  358. }
  359. bool
  360. Auto_Encoder_Stack::
  361. supports_missing_inputs() const
  362. {
  363. return layers_.supports_missing_inputs();
  364. }
  365. Auto_Encoder_Stack *
  366. Auto_Encoder_Stack::
  367. make_copy() const
  368. {
  369. return new Auto_Encoder_Stack(*this);
  370. }
  371. Auto_Encoder_Stack *
  372. Auto_Encoder_Stack::
  373. deep_copy() const
  374. {
  375. return new Auto_Encoder_Stack(*this, Deep_Copy_Tag());
  376. }
  377. bool
  378. Auto_Encoder_Stack::
  379. equal_impl(const Layer & other) const
  380. {
  381. if (typeid(*this) != typeid(other)) return false;
  382. return layers_.equal_impl(other);
  383. }
  384. bool
  385. Auto_Encoder_Stack::
  386. operator == (const Auto_Encoder_Stack & other) const
  387. {
  388. return layers_.operator == (other.layers_);
  389. }
  390. namespace {
  391. Register_Factory<Layer, Auto_Encoder_Stack>
  392. AES_REGISTER("Auto_Encoder_Stack");
  393. } // file scope
  394. template class Layer_Stack<Auto_Encoder>;
  395. } // namespace ML