Create batch of image from list of images

Kenzo: <p>Im trying to create a batch of images from a list of images. However, sometimes the batch goes longer than the batch_size that I defined. For example, I defined the batch_size to 15, but when I get the len(), I have 17 images sometimes instead of 15. Any help would be appreciated!</p>
<p>Here is my code that I’m trying to create the batch of images:</p>
<pre><code class="lang-auto">    def _to_batch(self, imgs: List[torch.Tensor], device) -&gt; torch.Tensor:
        batch_list = [x.unsqueeze(0) for x in imgs]
        if self.batch_size &gt; len(batch_list):
            fill_size = self.batch_size - len(batch_list)
            batch_list.append(torch.zeros([fill_size, 3, self._img_size[0], self._img_size[1]]).to(device))
        batch = torch.cat(batch_list, 0).half()
        return batch

</code></pre>
<p>I know I have to check if my total list of images is more than my batch_size as well and keep those images for the next batch, but cannot find the logic to do it <img src="https://discuss.pytorch.org/images/emoji/apple/expressionless.png?v=12" title=":expressionless:" class="emoji" alt=":expressionless:" loading="lazy" width="20" height="20"></p>

ParGG: <aside class="quote no-group quote-modified" data-username="Kenzo" data-post="1" data-topic="156188">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/kenzo/48/10615_2.png" class="avatar"> Kenzo:</div>
<blockquote>
<p>I know I have to check if my total list of images is more than my batch_size as well and keep those images for the next batch but cannot find the logic to do it <img src="https://discuss.pytorch.org/images/emoji/apple/expressionless.png?v=12" title=":expressionless:" class="emoji" alt=":expressionless:" loading="lazy" width="20" height="20"></p>
</blockquote>
</aside>
<p>It’s good that you found that issue.</p>
<p>To keep the images for the next batch, just define <code>self.batch_list = []</code> in your model. Inside your function <code>_to_batch</code>, extend your list with <code>self.batch_list.extend([x.unsqueeze(0) for x in imgs])</code>. Then pretty much the remaining part of the code is the same. You just need to substitute the use of <code>batch_list</code> with <code>self.batch_list</code> and update its content before concatenation (slice and store the remainder in <code>self.batch_list</code>, whilst assign the selection to another variable that will be used for <code>torch.cat</code>).</p>
<p>I hope this could help you. If you need further help I can write you the code. <img src="https://discuss.pytorch.org/images/emoji/apple/slightly_smiling_face.png?v=12" title=":slightly_smiling_face:" class="emoji" alt=":slightly_smiling_face:" loading="lazy" width="20" height="20"></p>

Kenzo: <p><a class="mention" href="/u/pargg">@ParGG</a> Thanks for the help. I tried but still cannot keep the images for the next batch. Can you elaborate more?</p>

ParGG: <p>Here I subclass your class to give you an example and have overridden your <code>_to_batch</code> implementation. I wrote some comments for you to understand the different steps. Let me know if it works for you or have any question.</p>
<pre><code class="lang-auto">class MyClass(YourClass):
    def __init__(*args, **kwargs):
        super().__init__(*args, **kwargs)
        # define the container for your tensors to be batched
        self.batch_list = []
 
    def _to_batch(self, imgs: List[torch.Tensor], device) -&gt; torch.Tensor:
        # extend the list with the new loaded tensors
        self.batch_list.extend([x.unsqueeze(0) for x in imgs])
        
        # if the list has a length smaller than the batch size
        if (fill_size := self.batch_size - len(self.batch_list)) &gt; 0:
            # fill the list to the desired length with zeroed tensors
            self.batch_list.append(torch.zeros([fill_size, 3, self._img_size[0], self._img_size[1]]).to(device))

        # here the list is of at least `batch_size` elements
        # take the first `batch_size` elements and
        # put them in a variable that you will use for concatenation
        batch_list = self.batch_list[:self.batch_size]

        # take the remaining tensors and propagate them to the next call
        self.batch_list = self.batch_list[self.batch_size:]
       
        # concatenate the selected tensors and return them as a batch
        return torch.cat(batch_list, 0).half()

</code></pre>

Kenzo: <p>Hey <a class="mention" href="/u/pargg">@ParGG</a>, Thanks for completing the code and explanations. Well, it doesn’t work completely okay. Getting these errors sometimes:</p>
<pre><code class="lang-auto">list index out of range
list index out of range
list index out of range
list index out of range
tile cannot extend outside image
tile cannot extend outside image
list index out of range
list index out of range

</code></pre>

ParGG: <p>Those errors could come from other parts of your code, can you check the traceback? To see if the code works, just put a breakpoint in the function and see if everything works as expected.</p>