def forward(self, word_inputs, tag_inputs, arc_targets=None, rel_targets=None):
is_train = autograd.is_training()<EOL>def flatten_numpy(ndarray):<EOL><INDENT>"""<STR_LIT>"""<EOL>return np.reshape(ndarray, (-<NUM_LIT:1>,), '<STR_LIT:F>')<EOL><DEDENT>batch_size = word_inputs.shape[<NUM_LIT:1>]<EOL>seq_len = word_inputs.shape[<NUM_LIT:0>]<EOL>mask = np.greater(word_inputs, self._vocab.ROOT).astype(np.float32)<EOL>num_tokens = int(np.sum(mask))  <EOL>if is_train or arc_targets is not None:<EOL><INDENT>mask_1D = flatten_numpy(mask)<EOL>mask_1D_tensor = nd.array(mask_1D)<EOL><DEDENT>unked_words = np.where(word_inputs < self._vocab.words_in_train, word_inputs, self._vocab.UNK)<EOL>word_embs = self.word_embs(nd.array(unked_words, dtype='<STR_LIT:int>'))<EOL>if self.pret_word_embs:<EOL><INDENT>word_embs = word_embs + self.pret_word_embs(nd.array(word_inputs))<EOL><DEDENT>tag_embs = self.tag_embs(nd.array(tag_inputs))<EOL>emb_inputs = nd.concat(word_embs, tag_embs, dim=<NUM_LIT:2>)  <EOL>top_recur = biLSTM(self.f_lstm, self.b_lstm, emb_inputs, batch_size,<EOL>dropout_x=self.dropout_lstm_input if is_train else <NUM_LIT:0>)<EOL>top_recur = nd.Dropout(data=top_recur, axes=[<NUM_LIT:0>], p=self.dropout_mlp)<EOL>W_dep, b_dep = self.mlp_dep_W.data(), self.mlp_dep_b.data()<EOL>W_head, b_head = self.mlp_head_W.data(), self.mlp_head_b.data()<EOL>dep, head = leaky_relu(nd.dot(top_recur, W_dep.T) + b_dep), leaky_relu(nd.dot(top_recur, W_head.T) + b_head)<EOL>dep, head = nd.Dropout(data=dep, axes=[<NUM_LIT:0>], p=self.dropout_mlp), nd.Dropout(data=head, axes=[<NUM_LIT:0>],<EOL>p=self.dropout_mlp)<EOL>dep, head = nd.transpose(dep, axes=[<NUM_LIT:2>, <NUM_LIT:0>, <NUM_LIT:1>]), nd.transpose(head, axes=[<NUM_LIT:2>, <NUM_LIT:0>, <NUM_LIT:1>])<EOL>dep_arc, dep_rel = dep[:self.mlp_arc_size], dep[self.mlp_arc_size:]<EOL>head_arc, head_rel = head[:self.mlp_arc_size], head[self.mlp_arc_size:]<EOL>W_arc = self.arc_W.data()<EOL>arc_logits = bilinear(dep_arc, W_arc, head_arc, self.mlp_arc_size, seq_len, batch_size, num_outputs=<NUM_LIT:1>,<EOL>bias_x=True, bias_y=False)<EOL>flat_arc_logits = reshape_fortran(arc_logits, (seq_len, seq_len * batch_size))<EOL>arc_preds = arc_logits.argmax(<NUM_LIT:0>)<EOL>if is_train or arc_targets is not None:<EOL><INDENT>correct = np.equal(arc_preds.asnumpy(), arc_targets)<EOL>arc_correct = correct.astype(np.float32) * mask<EOL>arc_accuracy = np.sum(arc_correct) / num_tokens<EOL>targets_1D = flatten_numpy(arc_targets)<EOL>losses = self.softmax_loss(flat_arc_logits, nd.array(targets_1D))<EOL>arc_loss = nd.sum(losses * mask_1D_tensor) / num_tokens<EOL><DEDENT>if not is_train:<EOL><INDENT>arc_probs = np.transpose(<EOL>np.reshape(nd.softmax(flat_arc_logits, axis=<NUM_LIT:0>).asnumpy(), (seq_len, seq_len, batch_size), '<STR_LIT:F>'))<EOL><DEDENT>W_rel = self.rel_W.data()<EOL>rel_logits = bilinear(dep_rel, W_rel, head_rel, self.mlp_rel_size, seq_len, batch_size,<EOL>num_outputs=self._vocab.rel_size, bias_x=True, bias_y=True)<EOL>flat_rel_logits = reshape_fortran(rel_logits, (seq_len, self._vocab.rel_size, seq_len * batch_size))<EOL>_target_vec = nd.array(targets_1D if is_train else flatten_numpy(arc_preds.asnumpy())).reshape(<EOL>seq_len * batch_size, <NUM_LIT:1>)<EOL>_target_mat = _target_vec * nd.ones((<NUM_LIT:1>, self._vocab.rel_size))<EOL>partial_rel_logits = nd.pick(flat_rel_logits, _target_mat.T, axis=<NUM_LIT:0>)<EOL>if is_train or arc_targets is not None:<EOL><INDENT>rel_preds = partial_rel_logits.argmax(<NUM_LIT:0>)<EOL>targets_1D = flatten_numpy(rel_targets)<EOL>rel_correct = np.equal(rel_preds.asnumpy(), targets_1D).astype(np.float32) * mask_1D<EOL>rel_accuracy = np.sum(rel_correct) / num_tokens<EOL>losses = self.softmax_loss(partial_rel_logits, nd.array(targets_1D))<EOL>rel_loss = nd.sum(losses * mask_1D_tensor) / num_tokens<EOL><DEDENT>if not is_train:<EOL><INDENT>rel_probs = np.transpose(np.reshape(nd.softmax(flat_rel_logits.transpose([<NUM_LIT:1>, <NUM_LIT:0>, <NUM_LIT:2>]), axis=<NUM_LIT:0>).asnumpy(),<EOL>(self._vocab.rel_size, seq_len, seq_len, batch_size), '<STR_LIT:F>'))<EOL><DEDENT>if is_train or arc_targets is not None:<EOL><INDENT>loss = arc_loss + rel_loss<EOL>correct = rel_correct * flatten_numpy(arc_correct)<EOL>overall_accuracy = np.sum(correct) / num_tokens<EOL><DEDENT>if is_train:<EOL><INDENT>return arc_accuracy, rel_accuracy, overall_accuracy, loss<EOL><DEDENT>outputs = []<EOL>for msk, arc_prob, rel_prob in zip(np.transpose(mask), arc_probs, rel_probs):<EOL><INDENT>msk[<NUM_LIT:0>] = <NUM_LIT:1.><EOL>sent_len = int(np.sum(msk))<EOL>arc_pred = arc_argmax(arc_prob, sent_len, msk)<EOL>rel_prob = rel_prob[np.arange(len(arc_pred)), arc_pred]<EOL>rel_pred = rel_argmax(rel_prob, sent_len)<EOL>outputs.append((arc_pred[<NUM_LIT:1>:sent_len], rel_pred[<NUM_LIT:1>:sent_len]))<EOL><DEDENT>if arc_targets is not None:<EOL><INDENT>return arc_accuracy, rel_accuracy, overall_accuracy, outputs<EOL><DEDENT>return outputs<EOL>
Run decoding

        Parameters
        ----------
        word_inputs : mxnet.ndarray.NDArray
            word indices of seq_len x batch_size
        tag_inputs : mxnet.ndarray.NDArray
            tag indices of seq_len x batch_size
        arc_targets : mxnet.ndarray.NDArray
            gold arc indices of seq_len x batch_size
        rel_targets : mxnet.ndarray.NDArray
            gold rel indices of seq_len x batch_size
        Returns
        -------
        tuple
            (arc_accuracy, rel_accuracy, overall_accuracy, loss) when training, else if given gold target
        then return arc_accuracy, rel_accuracy, overall_accuracy, outputs, otherwise return outputs, where outputs is a
        list of (arcs, rels).