LIMA
Libre Multilingual Analyzer — C++ API
Loading...
Searching...
No Matches
lemmatization_eigen_inference_impl.h
Go to the documentation of this file.
1// Copyright 2002-2021 CEA LIST
2// SPDX-FileCopyrightText: 2022 CEA LIST <gael.de-chalendar@cea.fr>
3//
4// SPDX-License-Identifier: MIT
5
6#ifndef DEEPLIMA_LEMMATIZATION_EIGEN_INFERENCE_IMPL_H
7#define DEEPLIMA_LEMMATIZATION_EIGEN_INFERENCE_IMPL_H
8
9#include <eigen3/Eigen/Dense>
10
11#include "bilstm.h"
12#include "bilstm_and_dense.h"
13#include "lstm_beam_decoder.h"
14
15#include "embd_dict.h"
16
19
20//#define LEMM_INFERENCE_PROFILE
21
22#ifdef LEMM_INFERENCE_PROFILE
23#include <chrono>
24#endif
25
26namespace deeplima
27{
28namespace lemmatization
29{
30namespace eigen_impl
31{
32
33#ifdef WIN32
34#ifdef LEMM_EXPORTING
35 #define LEMM_EXPORT __declspec(dllexport)
36#else
37 #define LEMM_EXPORT __declspec(dllimport)
38#endif
39#else
40 #define LEMM_EXPORT
41#endif
42
43
46{
47public:
49
51
52 virtual void load(const std::string& fn) override
53 {
54 try
55 {
56 convert_from_torch(fn);
57 }
58 catch (const std::runtime_error& e)
59 {
60 throw;
61 }
62 }
63
64 virtual size_t init_new_worker(size_t input_len, bool precomputed_input=false) override
65 {
66 assert(Parent::m_wb.size() > 0);
67 assert(Parent::m_ops.size() > 0);
68 assert(Parent::m_ops.size() == Parent::m_params.size());
69
70 size_t new_worker_idx = Parent::m_wb[0].size();
71 for (size_t i = 0; i < Parent::m_ops.size(); i++)
72 {
73 assert(Parent::m_wb[i].size() == new_worker_idx);
74 assert(nullptr != Parent::m_params[i]);
75 Parent::m_wb[i].push_back(Parent::m_ops[i]->create_workbench(input_len, Parent::m_params[i], precomputed_input));
76 }
77
78 m_workbenches.push_back(std::make_shared<workbench_t>());
79
80 return new_worker_idx;
81 }
82
83 virtual size_t get_precomputed_dim() const
84 {
85 auto p_params = std::dynamic_pointer_cast<typename deeplima::eigen_impl::Op_BiLSTM<Eigen::MatrixXf, Eigen::VectorXf, float>::params_t>(Parent::m_params[0]);
86
87 assert(p_params->layers.size() > 0);
88 const auto& layer = p_params->layers[0];
89 size_t hidden_size = layer.fw.weight_ih.rows() + layer.bw.weight_ih.rows();
90 return hidden_size;
91 }
92
93 virtual void precompute_inputs(
94 const Eigen::MatrixXf& inputs,
95 Eigen::MatrixXf& outputs,
96 int64_t input_size
97 ) override
98 {
99 auto p_op = std::dynamic_pointer_cast<deeplima::eigen_impl::Op_BiLSTM<Eigen::MatrixXf, Eigen::VectorXf, float>>(Parent::m_ops[0]);
100
101 p_op->precompute_inputs(Parent::m_params[0], inputs, outputs, input_size);
102 }
103
104 virtual void predict(
105 size_t /*worker_id*/,
106 const Eigen::MatrixXf& /*inputs*/,
107 int64_t /*input_begin*/,
108 int64_t /*input_end*/,
109 int64_t /*output_begin*/,
110 int64_t /*output_end*/,
111 std::shared_ptr< StdMatrix<uint8_t> >& /*output*/,
112 const std::vector<std::string>& /*outputs_names*/
113 ) override
114 {
115 assert(false);
116 }
117
119 {
122 Eigen::VectorXf fw_h, fw_c, bw_h, bw_c; // encoder's output
123 Eigen::VectorXf encoder_state; // too bad: this is a copy of previous things
124 Eigen::VectorXf decoder_initial_h, decoder_initial_c;
125 };
126
127 virtual void predict(
128 size_t worker_id,
129 const Eigen::MatrixXf& inputs,
130 const Eigen::MatrixXf& input_feats,
131 int64_t input_len,
132 int64_t output_max_len,
133 int64_t /*beam_size*/,
134 std::vector< uint32_t >& output,
135 const std::vector<std::string>& /*output_names*/
136 )
137 {
138 assert(Parent::m_wb.size() > 0);
139 assert(worker_id < Parent::m_wb[0].size());
140 assert(m_workbenches.size() > worker_id);
141 workbench_t& wb = *(m_workbenches[worker_id]);
142
143#ifdef LEMM_INFERENCE_PROFILE
144 using clock = std::chrono::system_clock;
145 using ms = std::chrono::duration<double, std::milli>;
146#endif
147
148 // Features encoders
149 // for encoder
150 auto p_linear_feats_enc = std::dynamic_pointer_cast<deeplima::eigen_impl::Op_Linear<Eigen::MatrixXf, Eigen::VectorXf, float>>(Parent::m_ops[5]);
151
152#ifdef LEMM_INFERENCE_PROFILE
153 const auto before = clock::now();
154#endif
155
156 p_linear_feats_enc->execute(Parent::m_wb[5][worker_id],
157 input_feats,
158 Parent::m_params[5],
160
161#ifdef LEMM_INFERENCE_PROFILE
162 const auto exec1 = clock::now();
163#endif
164
165 // for decoder
166 auto p_linear_feats_dec = std::dynamic_pointer_cast<deeplima::eigen_impl::Op_Linear<Eigen::MatrixXf, Eigen::VectorXf, float>>(Parent::m_ops[3]);
167
168 p_linear_feats_dec->execute(Parent::m_wb[3][worker_id],
169 input_feats,
170 Parent::m_params[3],
172#ifdef LEMM_INFERENCE_PROFILE
173 const auto exec2 = clock::now();
174#endif
175 auto p_encoder = std::dynamic_pointer_cast<deeplima::eigen_impl::Op_BiLSTM<Eigen::MatrixXf, Eigen::VectorXf, float>>(Parent::m_ops[0]);
176
177 auto p_decoder = std::dynamic_pointer_cast<deeplima::eigen_impl::Op_LSTM_Beam_Decoder<Eigen::MatrixXf, Eigen::VectorXf, float>>(Parent::m_ops[4]);
178
179 auto enc_mutlilayer_bilstm
180 = std::dynamic_pointer_cast<const deeplima::eigen_impl::params_multilayer_bilstm_t<Eigen::MatrixXf, Eigen::VectorXf>>(Parent::m_params[0]);
181 size_t hidden_size = enc_mutlilayer_bilstm->layers[0].fw.weight_ih.rows() / 4;
182
183 if (true)
184 {
185 // layout of encoded_feats_for_encoder:
186 //
187 // encoder_init_state_ = forward module=fc_cat2encoder input=categories_enc_embd
188 // encoder_init_state = reshape input=encoder_init_state_ dims=2,-1,(encoder_input_size / 2)
189 wb.fw_h = wb.encoded_feats_for_encoder.head(hidden_size);
190 wb.fw_c = wb.fw_h;
191 wb.bw_h = wb.encoded_feats_for_encoder.tail(hidden_size);
192 wb.bw_c = wb.bw_h;
193 }
194
195#ifdef LEMM_INFERENCE_PROFILE
196 std::cerr << "inputs.cols()=" << inputs.cols() << std::endl;
197 std::cerr << "inputs.rows()=" << inputs.rows() << std::endl;
198
199 const auto exec3 = clock::now();
200#endif
201
202 p_encoder->execute(Parent::m_wb[0][worker_id],
203 inputs, Parent::m_params[0],
204 0, input_len, wb.fw_h, wb.fw_c, wb.bw_h, wb.bw_c);
205
206#ifdef LEMM_INFERENCE_PROFILE
207 const auto exec4 = clock::now();
208#endif
209
210 if (wb.encoder_state.rows() == 0)
211 {
212 wb.encoder_state = Eigen::VectorXf(hidden_size * 4 + wb.encoded_feats_for_decoder.rows());
213 }
214 wb.encoder_state << wb.fw_h, wb.fw_c, wb.bw_h, wb.bw_c, wb.encoded_feats_for_decoder;
215
216 auto p_linear_h = std::dynamic_pointer_cast<deeplima::eigen_impl::Op_Linear<Eigen::MatrixXf, Eigen::VectorXf, float>>(Parent::m_ops[1]);
217 auto p_linear_c = std::dynamic_pointer_cast<deeplima::eigen_impl::Op_Linear<Eigen::MatrixXf, Eigen::VectorXf, float>>(Parent::m_ops[2]);
218
219#ifdef LEMM_INFERENCE_PROFILE
220 const auto exec5 = clock::now();
221#endif
222
223 p_linear_h->execute(Parent::m_wb[1][worker_id], wb.encoder_state, Parent::m_params[1], wb.decoder_initial_h);
224
225#ifdef LEMM_INFERENCE_PROFILE
226 const auto exec6 = clock::now();
227#endif
228
229 p_linear_c->execute(Parent::m_wb[2][worker_id], wb.encoder_state, Parent::m_params[2], wb.decoder_initial_c);
230
231#ifdef LEMM_INFERENCE_PROFILE
232 const auto exec7 = clock::now();
233#endif
234
235 const EmbdUInt64Float& decoder_embd = Parent::m_input_uint_dicts[1];
236 p_decoder->execute(Parent::m_wb[4][worker_id], decoder_embd,
238 Parent::m_params[4], 0x10FFFE, 0x10FFFF, 9, output, output_max_len);
239
240#ifdef LEMM_INFERENCE_PROFILE
241 const auto exec8 = clock::now();
242
243 std::cerr << "feats for enc : " << (exec1 - before).count() << std::endl;
244 std::cerr << "feats for dec : " << (exec2 - exec1).count() << std::endl;
245
246 std::cerr << "copy : " << (exec3 - exec2).count() << std::endl;
247 std::cerr << "encoder : " << (exec4 - exec3).count() << std::endl;
248 std::cerr << "copy : " << (exec5 - exec4).count() << std::endl;
249
250 std::cerr << "prep h : " << (exec6 - exec5).count() << std::endl;
251 std::cerr << "prep c : " << (exec7 - exec6).count() << std::endl;
252 std::cerr << "decoder : " << (exec8 - exec7).count() << std::endl;
253 throw;
254#endif
255 }
256
257 const std::vector<std::vector<std::string>>& get_classes() const
258 {
259 return m_classes;
260 }
261
262 const std::vector<std::string>& get_class_names() const
263 {
264 return m_class_names;
265 }
266
268 {
269 return m_morph_model;
270 }
271
272 inline const std::string& get_embd_fn(size_t idx) const
273 {
274 return m_embd_fn[idx];
275 }
276
277 const std::vector<size_t>& get_fixed_upos() const
278 {
279 return m_fixed_upos;
280 }
281
282protected:
283 std::vector<std::string> m_class_names;
284 std::vector<std::vector<std::string>> m_classes;
285 std::vector<std::string> m_embd_fn;
287 std::vector<size_t> m_fixed_upos;
288
289 std::vector<std::shared_ptr<workbench_t>> m_workbenches;
290
291 virtual void convert_from_torch(const std::string& fn) override;
292};
293
294
295} // namespace eigen_impl
296} // namespace lemmatization
297} // namespace deeplima
298
299#endif // DEEPLIMA_LEMMATIZATION_EIGEN_INFERENCE_IMPL_H
300
virtual void predict(size_t, const Eigen::MatrixXf &, int64_t, int64_t, int64_t, int64_t, std::shared_ptr< StdMatrix< uint8_t > > &, const std::vector< std::string > &) override
virtual size_t init_new_worker(size_t input_len, bool precomputed_input=false) override
virtual void predict(size_t worker_id, const Eigen::MatrixXf &inputs, const Eigen::MatrixXf &input_feats, int64_t input_len, int64_t output_max_len, int64_t, std::vector< uint32_t > &output, const std::vector< std::string > &)
virtual void precompute_inputs(const Eigen::MatrixXf &inputs, Eigen::MatrixXf &outputs, int64_t input_size) override
Helper class for morphology data (upos, features) binarization.
Definition morph_model.h:93