ImageFolder does not properly read the target variables

ianweb100: <p>Hi all,</p>
<p>Following advice from Patrick, I finally manage to load the data using the data loader. I am trying to classify images that are [1x256,256] simply. I separate my images into three folders ‘data/1/’ two and three. Using the data loader all worked fine. However, when I loop to start training, I get the following error. I think is something to do on my load, the data loader bring in the labels but does not transform to a long format.</p>
<pre><code>if input.size(0) != target.size(0):

IndexError: dimension specified as 0 but tensor has no dimensions
</code></pre>
<p>My Loading code is below:</p>
<h1>Data transforms</h1>
<h1></h1>
<pre><code>data_transforms = transforms.Compose([
transforms.Grayscale(num_output_channels=1),
transforms.Resize(256),
transforms.CenterCrop(256),
transforms.ToTensor()])


data_path = "C:/Users/JOBS/Desktop/comp 8420 NN/Assignment_2/data/"
train_dataset = torchvision.datasets.ImageFolder(
root="C:/Users/JOBS/Desktop/comp 8420 NN/Assignment_2/data/",
transform = data_transforms)

loader = DataLoader(
train_dataset,
batch_size=32,
num_workers=0,
shuffle=False)

trainloader, val_loader = torch.utils.data.random_split(loader.dataset, (153, 39))

print(trainloader, val_loader)
</code></pre>
<h4>The looping:</h4>
<pre><code>for epoch in tqdm(range(1, EPOCHS+1)):  # loop over the dataset multiple times

running_loss = 0.0
for i, data in enumerate(trainloader, 0):
    # get the inputs; data is a list of [inputs, labels]
    inputs, labels = data
    print(labels)
    
    inputs = inputs.unsqueeze(0)
    # zero the parameter gradients
    optimizer.zero_grad()

    # forward + backward + optimize
    outputs = net(inputs)
    print(outputs)
    loss = criterion(outputs, labels)  ## THE ERROR HAPPENS HERE I THINK
    loss.backward()
    optimizer.step()

    # print statistics
    running_loss += loss.item()
    if i % 2000 == 1999:    # print every 2000 mini-batches
        print('[%d, %5d] loss: %.3f' %
              (epoch + 1, i + 1, running_loss / 2000))
        running_loss = 0.0

print('Finished Training')
</code></pre>
<h4>Note:</h4>
<p>I also printed the shape of the inputs and the label itself ( S I guess the target should be long, but I don’t know what to do here)</p>
<p>torch.Size([1, 256, 256]) 1<br>
torch.Size([1, 256, 256]) 2<br>
torch.Size([1, 256, 256]) 1<br>
torch.Size([1, 256, 256]) 2</p>
<h4>My output look like this:</h4>
<p>tensor([[-0.0917, -0.1215, -0.0545]], grad_fn=)0</p>
<p>Thank you,</p>
<p>Ian</p>

ptrblck: <p>Did you print the shape of the <code>data</code> tensor as well as the <code>labels</code> inside the training loop?<br>
Based on your setup, you should see a batch size of 32, while it seems both tensors miss the batch dimension.</p>

ianweb100: <p>Hi Patrick,</p>
<p>I figure it out the error, it turns out when you use the data. random split the train loader becomes a dataset. The elegant solution is to pass these datasets into the loaders again. By doing this, there are 2 gains, first, you can enjoy the benefits of data loader rather than do iterations because the datasets don’t carry the batch information. Please see below my transformation, followed by the reload. Hopefully, it can help others with the same issue. On a side note, the image classification did not result in very good accuracy. Also as usual, thanks for taking the time to help.</p>
<h3>Here the data is split - it loses all the goodies of the data loader</h3>
<p>train loader, val_loader = torch.utils.data.random_split(loader.dataset, (153, 39))</p>
<h3>But as a test I put back into data loader and worked really well</h3>
<pre><code>## Create a Image folder
#
train_dataset = torchvision.datasets.ImageFolder(
root= data_path,
transform = data_transforms,
target_transform=None)

## Load into a older
#
loader = DataLoader(
train_dataset,
batch_size=32,
num_workers=0,
shuffle=True)

## Split randomly
#
</code></pre>
<p>trainloader, valloader = torch.utils.data.random_split(loader.dataset, (153, 39))<br>
type(trainloader)</p>
<pre><code>## Load back into data loaders as train and val sets
#
train_loader = DataLoader(
trainloader,
batch_size=1000,
num_workers=0,
shuffle=True)

val_loader = DataLoader(
valloader,
batch_size=1,
num_workers=0,
shuffle=False)</code></pre>