def gen_batches(self, batch_size: int, data_type: str = '<STR_LIT:train>',<EOL>shuffle: bool = None, return_indexes: bool = False) -> Iterator[tuple]:
if shuffle is None:<EOL><INDENT>shuffle = self.shuffle<EOL><DEDENT>data = self.data[data_type]<EOL>if shuffle:<EOL><INDENT>random.shuffle(data)<EOL><DEDENT>lengths = [len(x[<NUM_LIT:0>]) for x in data]<EOL>indexes = np.argsort(lengths)<EOL>L = len(data)<EOL>if batch_size < <NUM_LIT:0>:<EOL><INDENT>batch_size = L<EOL><DEDENT>for start in range(<NUM_LIT:0>, L, batch_size):<EOL><INDENT>indexes_to_yield = indexes[start:start+batch_size]<EOL>data_to_yield = tuple(list(x) for x in zip(*([data[i] for i in indexes_to_yield])))<EOL>if return_indexes:<EOL><INDENT>yield indexes_to_yield, data_to_yield<EOL><DEDENT>else:<EOL><INDENT>yield data_to_yield<EOL><DEDENT><DEDENT>
Generate batches of inputs and expected output to train neural networks

        Args:
            batch_size: number of samples in batch
            data_type: can be either 'train', 'test', or 'valid'
            shuffle: whether to shuffle dataset before batching
            return_indexes: whether to return indexes of batch elements in initial dataset

        Yields:
            a tuple of a batch of inputs and a batch of expected outputs.
            If `return_indexes` is True, also yields indexes of batch elements.