How can I handle sklearn.Kfold with ImageFolder?

username: Maryam_M
cooked: <p>I am trying to use Kfold on image classification task<br>
/data/<br>
class1/ image1<br>
/image2<br>
…<br>
class2/image1<br>
/image2<br>
…<br>
…<br>
class6/image1<br>
/image2<br>
…<br>
My code is as follows</p>
<blockquote>
<pre><code>dsets = torchvision.datasets.ImageFolder(data_dir)

for i_fold, (train_idx, valid_idx) in enumerate(folds.split(dsets))
   dataset_train = Subset(dsets, train_idx,transforms = transforms_train)
   dataset_valid = Subset(dsets, valid_idx,transforms=transforms_valid )
 ` trainloader = torch.utils.data.DataLoader( train, batch_size = batch_size, shuffle =True)`

 ` testloader = torch.utils.data.DataLoader(test, batch_size=batch_size,
     shuffle=True)`
</code></pre>
</blockquote>
<p>for the subset  I copied a new Subset to keep the transform in the Subset (not the parent).</p>
<p>the error i m getting is :<br>
<strong>RecursionError: maximum recursion depth exceeded</strong></p>
<p>the labels are the names of the folders</p>
<p>can someone please tell me what s wrong with my code?</p>

username: Nikronic
cooked: <p>Hi,</p>
<p>I ran your code and it works just fine. But I have changed few things that I cannot have a clear thought on them:</p>
<ol>
<li>Is <code>Subset</code> the classes from <code>torch.utils.data.Subset</code> or you have created your own class?</li>
<li>In 2 last lines, you have passed <code>train</code> and <code>test</code> as datasets to data loaders. Is it typo?</li>
</ol>
<aside class="quote no-group quote-modified" data-username="Maryam_M" data-post="1" data-topic="86005">
<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/maryam_m/48/25766_2.png" class="avatar"> Maryam_M:</div>
<blockquote>
<pre><code class="lang-auto">trainloader = torch.utils.data.DataLoader( train ###??, batch_size = batch_size, shuffle =True)
testloader = torch.utils.data.DataLoader(test ###?, batch_size=batch_size, shuffle=True)
</code></pre>
</blockquote>
</aside>
<p>Here is the code I ran:</p>
<pre><code class="lang-auto">
from sklearn.model_selection import KFold

!wget https://download.microsoft.com/download/3/E/1/3E1C3F21-ECDB-4869-8368-6DEBA77B919F/kagglecatsanddogs_3367a.zip
!unzip kagglecatsanddogs_3367a.zip

folds = KFold(shuffle=True)
dsets = torchvision.datasets.ImageFolder('PetImages')

for i_fold, (train_idx, valid_idx) in enumerate(folds.split(dsets)):
    dataset_train = data.Subset(dsets, train_idx)
    dataset_valid = data.Subset(dsets, valid_idx)
    trainloader = torch.utils.data.DataLoader(dataset_train, batch_size=256, shuffle =True)
    testloader = torch.utils.data.DataLoader(dataset_valid, batch_size=256, shuffle=True)
</code></pre>
<p>bests</p>

username: Maryam_M
cooked: <p>I realised that the code is fine it needed just to re-run to work.<br>
Yes I used a new class of Subset that I found in the solutions here <a href="https://stackoverflow.com/questions/51782021/how-to-use-different-data-augmentation-for-subsets-in-pytorch" rel="noopener nofollow ugc">subset</a><br>
Unfortunatly I got another issue this time with this loop</p>
<blockquote>
<p>for i_fold, (train_idx, valid_idx) in enumerate(folds.split(dsets)):<br>
…<br>
trainloader = torch.utils.data.DataLoader( train, batch_size = batch_size, shuffle =True)<br>
for epoch in range(N_EPOCHS):<br>
for i, data in enumerate(trainloader , 0):<br>
# get the inputs<br>
inputs, labels = data</p>
</blockquote>
<p>with the error<br>
<strong>AssertionError: force_apply must have bool or int type</strong></p>
<p>if you have a clue on why this accures</p>
<p>thanks you for your response</p>

username: Nikronic
cooked: <p>Could you share the stack trace of error and codes corresponding those errors?</p>

username: Maryam_M
cooked: <p>the fonction i am calling for each fold is  :</p>
<blockquote>
<pre><code> def train_one_fold(i_fold, model, criterion, optimizer, dataloader_train, dataloader_valid):    
        train_fold_results = []
        for epoch in range(N_EPOCHS):
        
        model.train()
        tr_loss = 0    

        for i, data in enumerate(dataloader_train, 0):
                 # get the inputs 
                 inputs, labels = data

                if use_gpu:
                          inputs, labels = Variable(inputs.cuda()), Variable(labels.cuda(non_blocking=True))
                else:
                          inputs, labels = Variable(inputs), Variable(labels)

                outputs = model(inputs)
                loss = criterion(outputs, labels)                

                 loss.backward()

                 tr_loss += loss.item()

                 optimizer.step()
                 optimizer.zero_grad()

         # Validate
         model.eval()
         val_loss = 0
         val_preds = None
         val_labels = None

        for i, data in enumerate(dataloader_valid, 0):
                images, labels = data

                if use_gpu:
                        images, labels = (images.cuda()), (labels.cuda(async=True))
                else:
                      images, labels = Variable(images), Variable(labels)
                 
                with torch.no_grad():
                     outputs = model(images)

               loss = criterion(outputs, labels)
                val_loss += loss.item()
                preds = torch.softmax(outputs, dim=1).data.cpu()

               if val_preds is None:
                    val_preds = preds
               else:
                   val_preds = torch.cat((val_preds, preds), dim=0) 
    return val_preds
</code></pre>
</blockquote>
<p>so here is the trace of error</p>
<hr>
<p>AssertionError                            Traceback (most recent call last)</p>
<p> in ()<br>
24     optimizer = optim.Adam(plist, lr=5e-5)<br>
25<br>
—&gt; 26     val_preds, train_fold_results = train_one_fold(i_fold, model, criterion, optimizer, trainloader, testloader)<br>
27     oof_preds[valid_idx, :] = val_preds.numpy()<br>
28</p>
<p>---------------------------------------------------6 frames-------------------------------------------------------</p>
<p> in train_one_fold(i_fold, model, criterion, optimizer, dataloader_train, dataloader_valid)<br>
12         tr_loss = 0<br>
13<br>
—&gt; 14         for i, data in enumerate(dataloader_train, 0):<br>
15             # get the inputs<br>
16</p>
<p>/usr/local/lib/python3.6/dist-packages/torch/utils/data/dataloader.py in _ <em>next</em>_(self)<br>
343<br>
344     def _ <em>next</em>_(self):<br>
 → 345         data = self._next_data()<br>
346         self._num_yielded += 1<br>
347         if self._dataset_kind == _DatasetKind.Iterable and \</p>
<p>/usr/local/lib/python3.6/dist-packages/torch/utils/data/dataloader.py in _next_data(self)<br>
383     def _next_data(self):<br>
384         index = self._next_index()  # may raise StopIteration<br>
 → 385         data = self._dataset_fetcher.fetch(index)  # may raise StopIteration<br>
386         if self._pin_memory:<br>
387             data = _utils.pin_memory.pin_memory(data)</p>
<p>/usr/local/lib/python3.6/dist-packages/torch/utils/data/_utils/fetch.py in fetch(self, possibly_batched_index)<br>
42     def fetch(self, possibly_batched_index):<br>
43         if self.auto_collation:<br>
—&gt; 44             data = [self.dataset[idx] for idx in possibly_batched_index]<br>
45         else:<br>
46             data = self.dataset[possibly_batched_index]</p>
<p>/usr/local/lib/python3.6/dist-packages/torch/utils/data/_utils/fetch.py in (.0)<br>
42     def fetch(self, possibly_batched_index):<br>
43         if self.auto_collation:<br>
—&gt; 44             data = [self.dataset[idx] for idx in possibly_batched_index]<br>
45         else:<br>
46             data = self.dataset[possibly_batched_index]</p>
<p> in _ <em>getitem</em>_(self, idx)<br>
14     def _ <em>getitem</em>_(self, idx):<br>
15         im, labels = self.dataset[self.indices[idx]]<br>
—&gt; 16         return self.transform(im), labels<br>
17<br>
18     def _ <em>len</em>_(self):</p>
<p>/usr/local/lib/python3.6/dist-packages/albumentations/core/composition.py in _ <em>call</em>_(self, force_apply, **data)<br>
162<br>
163     def _ <em>call</em>_(self, force_apply=False, **data):<br>
 → 164         assert isinstance(force_apply, (bool, int)), “force_apply must have bool or int type”<br>
165         need_to_run = force_apply or random.random() &lt; self.p<br>
166         for p in self.processors.values():</p>
<p>AssertionError: force_apply must have bool or int type</p>

username: ptrblck
cooked: <p>It seems that the error is raised by <code>albumations</code>, so you might need to check the transformations you are using.<br>
Maybe you are trying to pass multiple values to one transformation and the second argument is accidentally interpreted as the <code>force_apply</code> argument.</p>