You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

282 lines
7.2 KiB

4 years ago
  1. from libc.stdint cimport int16_t, int32_t, uint64_t
  2. from preshed.maps cimport MapStruct
  3. from libcpp.vector cimport vector
  4. from libc.stdlib cimport malloc, calloc, free, realloc
  5. from libc.string cimport memcpy, memset
  6. from murmurhash.mrmr cimport real_hash64 as hash64
  7. from .typedefs cimport len_t, idx_t, atom_t, weight_t
  8. from .linalg cimport VecVec
  9. include "compile_time_constants.pxi"
  10. ctypedef vector[weight_t] vector_weight_t
  11. ctypedef void (*do_update_t)(
  12. weight_t* weights,
  13. weight_t* gradient,
  14. len_t nr,
  15. const ConstantsC* hp,
  16. ) nogil
  17. ctypedef void (*do_feed_fwd_t)(
  18. weight_t** fwd,
  19. const weight_t* W,
  20. const len_t* shape,
  21. int nr_layer,
  22. int nr_batch,
  23. const ConstantsC* hp
  24. ) nogil
  25. ctypedef void (*do_feed_bwd_t)(
  26. weight_t* G,
  27. weight_t** bwd,
  28. const weight_t* W,
  29. const weight_t* const* fwd,
  30. const len_t* shape,
  31. int nr_layer,
  32. int nr_batch,
  33. const ConstantsC* hp
  34. ) nogil
  35. # Alias this, so that it matches our naming scheme
  36. ctypedef MapStruct MapC
  37. cdef struct ConstantsC:
  38. weight_t a
  39. weight_t b
  40. weight_t c
  41. weight_t d
  42. weight_t e
  43. weight_t g
  44. weight_t h
  45. weight_t i
  46. weight_t j
  47. weight_t k
  48. weight_t l
  49. weight_t m
  50. weight_t n
  51. weight_t o
  52. weight_t p
  53. weight_t q
  54. weight_t r
  55. weight_t s
  56. weight_t t
  57. weight_t u
  58. weight_t w
  59. weight_t x
  60. weight_t y
  61. weight_t z
  62. cdef struct EmbedC:
  63. MapC** weights
  64. MapC** gradients
  65. weight_t** defaults
  66. weight_t** d_defaults
  67. idx_t* offsets
  68. len_t* lengths
  69. len_t nr
  70. int nr_support
  71. cdef struct NeuralNetC:
  72. do_feed_fwd_t feed_fwd
  73. do_feed_bwd_t feed_bwd
  74. do_update_t update
  75. len_t* widths
  76. weight_t* weights
  77. weight_t* gradient
  78. EmbedC* embed
  79. len_t nr_layer
  80. len_t nr_weight
  81. len_t nr_node
  82. ConstantsC hp
  83. cdef extern from "stdlib.h":
  84. int posix_memalign(void **memptr, size_t alignment, size_t size) nogil
  85. void* valloc (size_t size) nogil
  86. cdef struct ExampleC:
  87. int* is_valid
  88. weight_t* costs
  89. uint64_t* atoms
  90. FeatureC* features
  91. weight_t* scores
  92. int nr_class
  93. int nr_atom
  94. int nr_feat
  95. cdef cppclass MinibatchC:
  96. weight_t** _fwd
  97. weight_t** _bwd
  98. FeatureC** _feats
  99. len_t* _nr_feat
  100. weight_t* _costs
  101. int* _is_valid
  102. uint64_t* signatures
  103. len_t* widths
  104. int i
  105. int nr_layer
  106. int batch_size
  107. __init__(len_t* widths, int nr_layer, int batch_size) nogil:
  108. this.i = 0
  109. this.nr_layer = nr_layer
  110. this.batch_size = batch_size
  111. this.widths = <len_t*>calloc(nr_layer, sizeof(len_t))
  112. this._fwd = <weight_t**>calloc(nr_layer, sizeof(weight_t*))
  113. this._bwd = <weight_t**>calloc(nr_layer, sizeof(weight_t*))
  114. for i in range(nr_layer):
  115. this.widths[i] = widths[i]
  116. this._fwd[i] = <weight_t*>calloc(this.widths[i] * batch_size, sizeof(weight_t))
  117. this._bwd[i] = <weight_t*>calloc(this.widths[i] * batch_size, sizeof(weight_t))
  118. this._feats = <FeatureC**>calloc(batch_size, sizeof(void*))
  119. this._nr_feat = <len_t*>calloc(batch_size, sizeof(len_t))
  120. this._is_valid = <int*>calloc(batch_size * widths[nr_layer-1], sizeof(int))
  121. this._costs = <weight_t*>calloc(batch_size * widths[nr_layer-1], sizeof(weight_t))
  122. this.signatures = <uint64_t*>calloc(batch_size, sizeof(uint64_t))
  123. __dealloc__() nogil:
  124. free(this.widths)
  125. for i in range(this.nr_layer):
  126. free(this._fwd[i])
  127. free(this._bwd[i])
  128. for i in range(this.i):
  129. free(this._feats[i])
  130. free(this._fwd)
  131. free(this._bwd)
  132. free(this._feats)
  133. free(this._nr_feat)
  134. free(this._is_valid)
  135. free(this._costs)
  136. free(this.signatures)
  137. void reset() nogil:
  138. for i in range(this.nr_layer):
  139. memset(this._fwd[i],
  140. 0, sizeof(this._fwd[i][0]) * this.batch_size * this.widths[i])
  141. memset(this._bwd[i],
  142. 0, sizeof(this._bwd[i][0]) * this.batch_size * this.widths[i])
  143. memset(this._nr_feat, 0, sizeof(this._nr_feat[0]) * this.batch_size)
  144. memset(this.signatures, 0, sizeof(this.signatures[0]) * this.batch_size)
  145. memset(this._costs,
  146. 0, sizeof(this._costs[0]) * this.nr_out() * this.batch_size)
  147. memset(this._is_valid,
  148. 0, sizeof(this._is_valid[0]) * this.nr_out() * this.batch_size)
  149. for i in range(this.i):
  150. free(this._feats[i])
  151. this._feats[i] = NULL
  152. this.i = 0
  153. int nr_in() nogil:
  154. return this.widths[0]
  155. int nr_out() nogil:
  156. return this.widths[this.nr_layer - 1]
  157. int push_back(const FeatureC* feats, int nr_feat,
  158. const weight_t* costs, const int* is_valid, uint64_t key) nogil:
  159. # Hash the features, to see if the batch has a matching input.
  160. # If it does, just update the gradient for it.
  161. if key != 0:
  162. for i in range(this.i):
  163. if this.signatures[i] == key:
  164. VecVec.add_i(this.costs(i),
  165. costs, 1.0, this.nr_out())
  166. return 0
  167. if this.i >= this.batch_size:
  168. this.reset()
  169. this.i = 0 # This is done in reset() --- but make it obvious
  170. this.signatures[this.i] = key
  171. this._nr_feat[this.i] = nr_feat
  172. this._feats[this.i] = <FeatureC*>calloc(nr_feat, sizeof(FeatureC))
  173. memcpy(this._feats[this.i],
  174. feats, nr_feat * sizeof(this._feats[this.i][0]))
  175. memcpy(this.costs(this.i),
  176. costs, this.nr_out() * sizeof(costs[0]))
  177. if is_valid is not NULL:
  178. memcpy(this.is_valid(this.i),
  179. is_valid, this.nr_out() * sizeof(is_valid[0]))
  180. else:
  181. for i in range(this.nr_out()):
  182. this.is_valid(this.i)[i] = 1
  183. this.i += 1
  184. return this.i >= this.batch_size
  185. FeatureC* features(int i) nogil:
  186. return this._feats[i]
  187. int nr_feat(int i) nogil:
  188. return this._nr_feat[i]
  189. weight_t* fwd(int i, int j) nogil:
  190. return this._fwd[i] + (j * this.widths[i])
  191. weight_t* bwd(int i, int j) nogil:
  192. return this._bwd[i] + (j * this.widths[i])
  193. weight_t* scores(int i) nogil:
  194. return this.fwd(this.nr_layer-1, i)
  195. weight_t* losses(int i) nogil:
  196. return this.bwd(this.nr_layer-1, i)
  197. weight_t* costs(int i) nogil:
  198. return this._costs + (i * this.nr_out())
  199. int* is_valid(int i) nogil:
  200. return this._is_valid + (i * this.nr_out())
  201. int guess(int i) nogil:
  202. return VecVec.arg_max_if_true(this.scores(i), this.is_valid(i), this.nr_out())
  203. int best(int i) nogil:
  204. return VecVec.arg_max_if_zero(this.scores(i), this.costs(i), this.nr_out())
  205. cdef packed struct SparseArrayC:
  206. int32_t key
  207. weight_t val
  208. cdef struct FeatureC:
  209. int i
  210. uint64_t key
  211. weight_t value
  212. cdef struct SparseAverageC:
  213. SparseArrayC* curr
  214. SparseArrayC* mom1
  215. SparseArrayC* mom2
  216. SparseArrayC* avgs
  217. SparseArrayC* times
  218. SparseArrayC* penalties
  219. weight_t penalty
  220. cdef struct TemplateC:
  221. int[MAX_TEMPLATE_LEN] indices
  222. int length
  223. atom_t[MAX_TEMPLATE_LEN] atoms