Text: Setting sort_within_batch of pool to True when called in the method create_batches of BucketIterator?

Created on 14 Nov 2019  路  1Comment  路  Source: pytorch/text

Hi,

I am working with torchtext and I had a question about the pool function in the iterator module.

I have a train_dataset, valid_dataset and test_dataset. I want to create a train iterator with minibatches of similar lengths, with random internal order, and eventually shuffle the order of the minibatches. For the valid and test set, I want to keep their initial orders and create batches sequentially, based on that order.

I found the splits / __init__ method of _BucketIterator_ rather counterintuitive to use and I agree with this post:

While Torchtext is brilliant, it鈥檚 sort_key based batching leaves a little to be desired. Often the sentences aren鈥檛 of the same length at all, and you end up feeding a lot of padding into your network

I'm a bit confused with why the argument sort_within_batch of _pool_ is set to self.sort_within_batch when pool is called in the method create_batches of _BucketIterator_.
My issue is that if I want to effectively create minibatches of similar lengths, I have to set sort_within_batch to True when I call data.BucketIterator.splits.

train_iterator, valid_iterator, test_iterator = data.BucketIterator.splits((train_dataset, 
                                                                            valid_dataset,
                                                                            test_dataset), 
                                                                            batch_sizes=(train_batch_size,
                                                                                         valid_batch_size,
                                                                                         test_batch_size), 
                                                                            sort_key=lambda x: len(x.text),
                                                                            sort=False,
                                                                            sort_within_batch=True)

But then, in addition to sort the samples in the chunks / buckets, it will also sort the samples in the created minibatches (in __iter__), which is not needed. As a side effect it will also sort both the chunks / buckets and the minibatches in the validation and test iterators, which I don't want.

Wouldn't it be more intuitive to set the argument _sort_within_batch_ of pool to True when called in the method create_batches of _BucketIterator_?
In that case, if you don't want to reorder the samples in the minibatches of the train, validation nor test set, you would do

train_iterator, valid_iterator, test_iterator = data.BucketIterator.splits((train_dataset, 
                                                                            valid_dataset,
                                                                            test_dataset), 
                                                                            batch_sizes=(train_batch_size,
                                                                                         valid_batch_size,
                                                                                         test_batch_size), 
                                                                            sort_key=lambda x: len(x.text),
                                                                            sort=False,
                                                                            sort_within_batch=False)

If you want to sort the samples in the minibatches of the validation and test set, you would do

train_iterator, valid_iterator, test_iterator = data.BucketIterator.splits((train_dataset, 
                                                                            valid_dataset,
                                                                            test_dataset), 
                                                                            batch_sizes=(train_batch_size,
                                                                                         valid_batch_size,
                                                                                         test_batch_size), 
                                                                            sort_key=lambda x: len(x.text))

And if you want to sort the samples in the minibatches of the train, validation and test set, you would do

train_iterator, valid_iterator, test_iterator = data.BucketIterator.splits((train_dataset, 
                                                                            valid_dataset,
                                                                            test_dataset), 
                                                                            batch_sizes=(train_batch_size,
                                                                                         valid_batch_size,
                                                                                         test_batch_size), 
                                                                            sort_key=lambda x: len(x.text),
                                                                            sort_within_batch=True)

Besides, you may want to let the factor 100 (for the chunk / bucket size) as a paremeter because it can be useful to tune it when working with toy datasets.

Please tell me if I am missing something.

Thanks.

Most helpful comment

@mttk I think this is a good example to decouple those functionals.

@LeoLaugier If you don't want to sort valid/test dataset, can you pass them separately to data.BucketIterator.splits()

>All comments

@mttk I think this is a good example to decouple those functionals.

@LeoLaugier If you don't want to sort valid/test dataset, can you pass them separately to data.BucketIterator.splits()

Was this page helpful?
0 / 5 - 0 ratings