PyTorch 会抛出除 1 之外的任何值的批量大小错误

问题描述 投票:0回答:1

我用PyTorch制作了一个神经网络模型,它有点类似于vgg19模型。每次我输入批量大小的值时,我都会收到错误:

ValueError: Expected input batch_size (1) to match target batch_size (16).

批量大小值为 1 时不会发生这种情况,它会开始训练,没有任何复杂性。

我只是想改变批量大小而不会出现任何错误。

我自己无法找到(或理解)这个问题的解决方案。我提供下面的模型脚本。

注意:在模型的 train() 方法中,批量大小的默认值为 16。使用此配置,它会抛出错误,如我上面所示,当我调用此方法时,我将批量大小值设置为 1,并且它工作正常。

import os
import glob

import numpy as np
import pandas as pd

import matplotlib.pyplot as plt

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import DataLoader

from torchvision import datasets, transforms

class ICModel(nn.Module):

    def __init__(self):
        super().__init__()
        # CNN
        self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=2)
        self.conv2 = nn.Conv2d(64, 128, kernel_size=3, stride=2)
        self.conv3 = nn.Conv2d(128, 256, kernel_size=3, stride=2)
        self.conv4 = nn.Conv2d(256, 512, kernel_size=3, stride=2)

        # FULLY CONNECTED LAYERS
        self.fc1 = nn.Linear(61952, 256)
        self.fc2 = nn.Linear(256, 64)
        self.out = nn.Linear(64, 2)
    def forward(self, x):
        # CONV - 1
        x = F.relu(self.conv1(x))
        x = F.max_pool2d(x, kernel_size=3, stride=1)
        # CONV - 2
        x = F.relu(self.conv2(x))
        x = F.max_pool2d(x, kernel_size=3, stride=1)
        # CONV - 3
        x = F.relu(self.conv3(x))
        x = F.max_pool2d(x, kernel_size=3, stride=1)
        # CONV - 4
        x = F.relu(self.conv4(x))

        flattened_size = x.shape[0] * x.shape[1] * x.shape[2] * x.shape[3]

        x = x.view(-1, flattened_size)
        # FULLY CONNECTED LAYERS
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.out(x)

        return F.log_softmax(x, dim=1)

    def train(self, dataset_dir='', epochs=5, batch_size=16, seed=35, learning_rate=0.001, model_weights_path=''):
        if dataset_dir == '':
            raise Exception("Please enter a valid dataset directory path!")

        train_correct = []
        train_losses = []

        torch.manual_seed(seed)

        # CRITERION AND OPTIMIZER SETUP
        criterion = nn.CrossEntropyLoss()
        optimizer = torch.optim.Adam(self.parameters(), lr=learning_rate)

        optim_width, optim_height = 224, 224

        data_transforms = transforms.Compose([
            transforms.Resize((optim_width, optim_height)),  # Resize images to average dimensions
            transforms.ToTensor(),  # Convert images to PyTorch tensors
            transforms.Normalize(mean=[0.456, 0.456, 0.456], std=[0.456, 0.456, 0.456])  # Normalize images
        ])

        dataset = datasets.ImageFolder(root=dataset_dir, transform=data_transforms)
        train_loader = DataLoader(dataset=dataset, batch_size=batch_size, shuffle=True)

        for epoch in range(epochs):
            trn_corr = 0

            for b, (X_train, y_train) in enumerate(train_loader):
                b += 1
                y_pred = self(X_train)
                loss = criterion(y_pred, y_train)

                predicted = torch.max(y_pred, dim=1)[1]
                batch_corr = (predicted == y_train).sum()

                trn_corr += batch_corr.item()

                optimizer.zero_grad()
                loss.backward()
                optimizer.step()

                if b % 4 == 0:
                    print(f'Epoch: {epoch}  Batch: {b}  Loss: {loss.item()}')

        train_losses.append(loss)
        train_correct.append(trn_corr)

        if (model_weights_path != '') & os.path.exists(model_weights_path) & os.path.isdir(model_weights_path):
            torch.save({
                'model_state_dict': self.state_dict(),
                'optimizer_state_dict': optimizer.state_dict()
            }, model_weights_path)

    def test(self, dataset_dir='', batch_size=16):
        if dataset_dir == '':
            raise Exception("Please enter a valid dataset directory path!")

        optim_width, optim_height = 224, 224
        test_losses = []
        tst_crr = 0

        criterion = nn.CrossEntropyLoss()

        data_transforms = transforms.Compose([
            transforms.Resize((optim_width, optim_height)),  # Resize images to average dimensions
            transforms.Grayscale(),
            transforms.ToTensor(),  # Convert images to PyTorch tensors
            transforms.Normalize(mean=[0.456], std=[0.456])  # Normalize images
        ])

        dataset = datasets.ImageFolder(root=dataset_dir, transform=data_transforms)
        test_loader = DataLoader(dataset=dataset, batch_size=batch_size, shuffle=True)

        with torch.no_grad():
            for b, (X_test, y_test) in enumerate(test_loader):
                y_val = self(X_test)
                predicted = torch.max(y_val.data, dim=1)[1]
                tst_crr += (predicted == y_test).sum()

            loss = criterion(y_val, y_test)
            test_losses.append(loss.item())

            test_results = {
                'true_positive': tst_crr,
                'false_positive': len(dataset.imgs) - tst_crr
            }

        return test_results, test_losses


这是错误的完整回溯:

Traceback (most recent call last):
  File "/Users/eaidy/Repos/ML/inclination-classification-pytorch/src/main.py", line 12, in <module>
    ic_model.train(dataset_dir=train_dataset_absolute_path, epochs=1, batch_size=16, learning_rate=1e-5)
  File "/Users/eaidy/Repos/ML/inclination-classification-pytorch/src/models/cnn_model.py", line 94, in train
    loss = criterion(y_pred, y_train)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/eaidy/Repos/ML/inclination-classification-pytorch/.venv/lib/python3.11/site-packages/torch/nn/modules/module.py", line 1511, in _wrapped_call_impl
    return self._call_impl(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/eaidy/Repos/ML/inclination-classification-pytorch/.venv/lib/python3.11/site-packages/torch/nn/modules/module.py", line 1520, in _call_impl
    return forward_call(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/eaidy/Repos/ML/inclination-classification-pytorch/.venv/lib/python3.11/site-packages/torch/nn/modules/loss.py", line 1179, in forward
    return F.cross_entropy(input, target, weight=self.weight,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/eaidy/Repos/ML/inclination-classification-pytorch/.venv/lib/python3.11/site-packages/torch/nn/functional.py", line 3059, in cross_entropy
    return torch._C._nn.cross_entropy_loss(input, target, weight, _Reduction.get_enum(reduction), ignore_index, label_smoothing)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: Expected input batch_size (1) to match target batch_size (16).
python machine-learning pytorch neural-network
1个回答
0
投票

问题就在这里

flattened_size = x.shape[0] * x.shape[1] * x.shape[2] * x.shape[3]

x = x.view(-1, flattened_size)

x
的形状为
(batch_size, channels, height, width)
。您计算
flattened_size = batch_size * channels * height * width
- 错误包括批次维度。这意味着当您计算
x = x.view(-1, flattened_size)
时,输出
x
将始终具有大小
(1, flattened_size)

在损失计算中,您尝试计算

loss(x,y)
,其中
x
具有形状
(1, flattened_size)
y
具有形状
(bs,)
,从而导致错误。

展平时应保留批次尺寸:

x = x.view(x.shape[0], -1)

您还需要调整第一个全连接层的输入大小。

© www.soinside.com 2019 - 2024. All rights reserved.