iterate over tasks and provide a random batch per task in each mini-batch
| 6 | taken from https://github.com/bomri/code-for-posts |
| 7 | ''' |
| 8 | class BatchSchedulerSampler(torch.utils.data.sampler.Sampler): |
| 9 | """ |
| 10 | iterate over tasks and provide a random batch per task in each mini-batch |
| 11 | """ |
| 12 | def __init__(self, dataset, batch_size): |
| 13 | self.dataset = dataset |
| 14 | self.batch_size = batch_size |
| 15 | self.number_of_datasets = len(dataset.datasets) |
| 16 | self.largest_dataset_size = max([len(cur_dataset) for cur_dataset in dataset.datasets]) |
| 17 | |
| 18 | def __len__(self): |
| 19 | return self.batch_size * math.ceil(self.largest_dataset_size / self.batch_size) * len(self.dataset.datasets) |
| 20 | |
| 21 | def __iter__(self): |
| 22 | samplers_list = [] |
| 23 | sampler_iterators = [] |
| 24 | for dataset_idx in range(self.number_of_datasets): |
| 25 | cur_dataset = self.dataset.datasets[dataset_idx] |
| 26 | sampler = RandomSampler(cur_dataset) |
| 27 | samplers_list.append(sampler) |
| 28 | cur_sampler_iterator = sampler.__iter__() |
| 29 | sampler_iterators.append(cur_sampler_iterator) |
| 30 | |
| 31 | push_index_val = [0] + self.dataset.cumulative_sizes[:-1] |
| 32 | step = self.batch_size * self.number_of_datasets |
| 33 | samples_to_grab = self.batch_size |
| 34 | # for this case we want to get all samples in dataset, this force us to resample from the smaller datasets |
| 35 | epoch_samples = self.largest_dataset_size * self.number_of_datasets |
| 36 | |
| 37 | final_samples_list = [] # this is a list of indexes from the combined dataset |
| 38 | for _ in range(0, epoch_samples, step): |
| 39 | for i in range(self.number_of_datasets): |
| 40 | cur_batch_sampler = sampler_iterators[i] |
| 41 | cur_samples = [] |
| 42 | for _ in range(samples_to_grab): |
| 43 | try: |
| 44 | cur_sample_org = cur_batch_sampler.__next__() |
| 45 | cur_sample = cur_sample_org + push_index_val[i] |
| 46 | cur_samples.append(cur_sample) |
| 47 | except StopIteration: |
| 48 | # got to the end of iterator - restart the iterator and continue to get samples |
| 49 | # until reaching "epoch_samples" |
| 50 | sampler_iterators[i] = samplers_list[i].__iter__() |
| 51 | cur_batch_sampler = sampler_iterators[i] |
| 52 | cur_sample_org = cur_batch_sampler.__next__() |
| 53 | cur_sample = cur_sample_org + push_index_val[i] |
| 54 | cur_samples.append(cur_sample) |
| 55 | final_samples_list.extend(cur_samples) |
| 56 | |
| 57 | return iter(final_samples_list) |