def _preprocess_data(self, X, Y=None, idxs=None, train=False):
C, F = X<EOL>if issparse(F):<EOL><INDENT>F = np.array(F.todense(), dtype=np.float32)<EOL><DEDENT>if Y is not None:<EOL><INDENT>Y = np.array(Y).astype(np.float32)<EOL><DEDENT>if not hasattr(self, "<STR_LIT>"):<EOL><INDENT>self.word_dict = SymbolTable()<EOL>arity = len(C[<NUM_LIT:0>])<EOL>for i in range(arity):<EOL><INDENT>list(map(self.word_dict.get, ["<STR_LIT>" + str(i), str(i) + "<STR_LIT>"]))<EOL><DEDENT><DEDENT>seq_data = []<EOL>for candidate in C:<EOL><INDENT>cand_idx = []<EOL>for i in range(len(candidate)):<EOL><INDENT>args = [<EOL>(<EOL>candidate[i].context.get_word_start_index(),<EOL>candidate[i].context.get_word_end_index(),<EOL>i,<EOL>)<EOL>]<EOL>s = mark_sentence(mention_to_tokens(candidate[i]), args)<EOL>f = self.word_dict.get if train else self.word_dict.lookup<EOL>cand_idx.append(list(map(f, s)))<EOL><DEDENT>seq_data.append(cand_idx)<EOL><DEDENT>if idxs is None:<EOL><INDENT>if Y is not None:<EOL><INDENT>return [[seq_data[i], F[i]] for i in range(len(seq_data))], Y<EOL><DEDENT>else:<EOL><INDENT>return [[seq_data[i], F[i]] for i in range(len(seq_data))]<EOL><DEDENT><DEDENT>if Y is not None:<EOL><INDENT>return [[seq_data[i], F[i]] for i in idxs], Y[idxs]<EOL><DEDENT>else:<EOL><INDENT>return [[seq_data[i], F[i]] for i in idxs]<EOL><DEDENT>
Preprocess the data:
1. Convert sparse feature matrix to dense matrix for pytorch operation.
2. Make sentence with mention into sequence data for LSTM.
3. Select subset of the input if idxs exists.

:param X: The input data of the model.
:type X: pair with candidates and corresponding features
:param Y: The labels of input data (optional).
:type Y: list or numpy.array
:param idxs: The selected indexs of input data.
:type idxs: list or numpy.array
:param train: An indicator for word dictionary to extend new words.
:type train: bool
:return: Preprocessed data.
:rtype: list of (candidate, features) pairs