LIMA
Libre Multilingual Analyzer — C++ API
Loading...
Searching...
No Matches
deep_biaffine_attn_decoder.h
Go to the documentation of this file.
1// Copyright 2021 CEA LIST
2// SPDX-FileCopyrightText: 2022 CEA LIST <gael.de-chalendar@cea.fr>
3//
4// SPDX-License-Identifier: MIT
5
6#ifndef DEEPLIMA_SRC_INFERENCE_EIGEN_DEEP_BIAFFINE_ATTN_DECODER_H
7#define DEEPLIMA_SRC_INFERENCE_EIGEN_DEEP_BIAFFINE_ATTN_DECODER_H
8
9#include <eigen3/Eigen/Dense>
10#include "op_base.h"
12
13namespace deeplima
14{
15namespace eigen_impl
16{
17
18template<class M=Eigen::MatrixXf, class V=Eigen::VectorXf>
29
30template<class M, class V, class T>
32{
33protected:
35 {
37 {
38 }
39 virtual ~workbench_t() {}
40
42 };
43
44public:
45 typedef V Vector;
47
48 virtual std::shared_ptr<Op_Base::workbench_t> create_workbench([[maybe_unused]] uint32_t input_size,
49 [[maybe_unused]] const std::shared_ptr<param_base_t> params,
50 bool /*precomputed_input=false*/) const override
51 {
52 assert(input_size > 0);
53 assert(nullptr != params);
54 // TODO should it be used
55 // const params_deep_biaffine_attn_decoder_t<M, V>& layer = *static_cast<const params_t*>(params);
56
57 return std::make_shared<workbench_t>();
58 }
59
60 virtual size_t execute([[maybe_unused]] std::shared_ptr<Op_Base::workbench_t> pwb,
61 const M& input_matrix,
62 const std::shared_ptr<param_base_t> params,
63 const size_t input_begin,
64 const size_t input_end,
65 std::vector<uint32_t>& output)
66 {
67 // std::cerr << "Op_DeepBiaffineAttnDecoder::execute input begin=" << input_begin << ", end=" << input_end
68 // << ", output size=" << output.size()
69 // << std::endl;
70 assert(nullptr != pwb);
71 assert(nullptr != params);
72 auto layer = std::dynamic_pointer_cast<const params_t>(params);
73 // TODO check if layer is empty, signaling that the cast failed
74 // TODO should it be used?
75 // auto wb = std::dynamic_pointer_cast<workbench_t>(pwb);
76
77 const M input = input_matrix.block(0, 0, input_matrix.rows(), input_end - input_begin);
78
79 M arc_head = ((layer->m_weight_head * input).colwise() + layer->m_bias_head).transpose();
80 elu_inplace(arc_head);
81 M arc_dep = (layer->m_weight_dep * input).colwise() + layer->m_bias_dep;
82 elu_inplace(arc_dep);
83
84 // Head bias: (arc_head * m_u2) depends only on the head, so it is the same
85 // for every dependent column. Compute it once and broadcast, instead of
86 // recomputing the identical matrix-vector product for every column.
87 const V head_bias = arc_head * layer->m_u2; // [n_head]
88
89 M logits = (arc_head * layer->m_U1) * arc_dep;
90 logits.colwise() += head_bias;
91
92 for (Eigen::Index i = 0; i < logits.rows(); ++i)
93 {
94 Eigen::Index idx = 0;
95 /*typename M::Scalar v = */ logits.row(i).maxCoeff(&idx);
96 assert(idx >= 0);
97 assert(idx < std::numeric_limits<uint32_t>::max());
98 output[input_begin + i] = (uint32_t) idx;
99 // std::cerr << i << "\t" << idx << std::endl;
100 }
101 // std::cerr << std::endl;
102
103 // TODO comment out that and output
104 arborescence<M, uint32_t, typename M::Scalar>(logits, output, input_begin);
105
106 return 0;
107 }
108
109protected:
110 inline void elu_inplace(M& m)
111 {
112 for (Eigen::Index r = 0; r < m.rows(); ++r)
113 {
114 for (Eigen::Index c = 0; c < m.cols(); ++c)
115 {
116 if (m(r,c) < 0)
117 {
118 m(r,c) = expf(m(r,c)) - 1;
119 }
120 }
121 }
122 }
123};
124
125} // namespace eigen_impl
126} // namespace deeplima
127
128#endif
params_deep_biaffine_attn_decoder_t< M, V > params_t
virtual std::shared_ptr< Op_Base::workbench_t > create_workbench(uint32_t input_size, const std::shared_ptr< param_base_t > params, bool) const override
virtual size_t execute(std::shared_ptr< Op_Base::workbench_t > pwb, const M &input_matrix, const std::shared_ptr< param_base_t > params, const size_t input_begin, const size_t input_end, std::vector< uint32_t > &output)