How to SubsetRandomSampler at run time

username: Deeply
cooked: <p>I’m doing some permutation testing experiments, that is; iterating <em>n</em> times over the the model. I would like thus to randomly sample <em>m</em> samples from the total available samples. One way to do this is define the loader as a function, something like:</p>
<pre><code class="lang-auto">def get_loader(dataset, my_sampler_size):
    loader = torch.utils.data.DataLoader(
            dataset,
            batch_size=100,         
            num_workers=4,             
            sampler = SubSetRandSampler(torch.randint(0, len(dataset), (my_sampler_size,)) ), # SubSetRandSampler(range(1000)),
            shuffle= False, 
            pin_memory=True)
    return loader
</code></pre>
<p>Clearly, this function needs to be called before each iteration (permutation).</p>
<p>I there a neater way to do this?</p>

username: ptrblck
cooked: <p>I think you could write a custom sampler by deriving or reusing the <a href="https://github.com/pytorch/pytorch/blob/3adc8f8cf76844741f403ffa6f3f10653776a1fd/torch/utils/data/sampler.py#L130-L147"><code>SubsetRandomSampler</code></a> and pass a <code>length</code> argument to it.<br>
In the <code>__iter__</code> method, you could use:</p>
<pre><code class="lang-python">torch.randperm(len(self.indices), generator=self.generator).tolist()[:self.length]
</code></pre>
<p>Let me know, if this would work for you or if I misunderstood your use case.</p>

username: Deeply
cooked: <p>My bad. What I’m trying to achieve is, for example, randomly selecting 5000 samples from a dataset that has 10000 samples. The sampler I showed above was working as intended.</p>
<pre><code class="lang-auto">'''unit-test'''
val_loader = get_loader(val_dataset)
for jj in range(5):    
    print('Iteration:', jj)
    for ii, (images, target) in enumerate(val_loader):        
        if ii&lt;2:
            plt.imshow(images[ii,:].permute(1, 2, 0)  ); plt.show() # to see the image
            print(target[ii].item())
            
            break
</code></pre>
<p>For some confusion, I thought I need to put <code>val_loader = get_loader(val_dataset)</code> after <code>for jj</code>  loop (could it be because I was doing this at 3AM in the morning! <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=9" title=":slight_smile:" class="emoji" alt=":slight_smile:"> )</p>
<p>But your idea seems very legit, yet I wouldn’t bother passing the <code>indices</code> and the <code>length</code>.  Hence, maybe the original <a href="https://github.com/pytorch/pytorch/blob/3adc8f8cf76844741f403ffa6f3f10653776a1fd/torch/utils/data/sampler.py#L130-L147" rel="noopener nofollow ugc"><code>SubsetRandomSampler</code></a>  should receive/generate the all <code>indices</code> of the dataset while it is invoked in the <a href="https://github.com/pytorch/pytorch/blob/master/torch/utils/data/dataloader.py" rel="noopener nofollow ugc">DataLoaderClass</a>; via <code>indices = torch.arange(0,len(self.dataset))</code>. The user then only passes the length to <a href="https://github.com/pytorch/pytorch/blob/3adc8f8cf76844741f403ffa6f3f10653776a1fd/torch/utils/data/sampler.py#L130-L147" rel="noopener nofollow ugc"><code>SubsetRandomSampler</code></a>; that is if the user did not pass the <code>indices</code>. Yet another better idea is to pass the <code>length</code> of the samples one wants to get to complement 'shuffle<code>; that is, adding another parameter to the </code>dataloder<code>called</code>length<code>; but if  </code>length` is not passed, shuffle works on the whole dataset.</p>