预期的batch_size()与目标batch_size()pytorch不相同

gr8qqesn  于 2023-08-05  发布在  其他
关注(0)|答案(1)|浏览(126)

我写了一个代码,把卫星图像分成七个区域(城市、森林、水……)。问题是,当我执行脚本时,我得到了以下错误:
Traceback(最近的呼叫最后一次):文件"/Users/.../pytorch_test。py ",第215行,在model = train_model中(model,train_dataloader,val_dataloader,loss_fn,optimizer,device,num_epochs)^^File "/Users/./pytorch_test。py",第179行,in train_model train_loss = train(model,train_dataloader,loss_fn,optimizer,device)^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^/pytorch_test。py",line 134,in train loss = loss_fn(outputs,labels)^^framework/Versions/3.11/lib/python3.11/site-packages/torch/nn/modules/module. py",line 1501,in_call_impl return forward_call(* args,**kwargs)^framework/Versions/3.11/lib/python3.11/site-packages/torch/nn/modules/loss. py”,第1174行,在前向返回F中。cross_entropy(input,target,weight = self.权重,^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^framework/Versions/3.11/lib/python3.11/site-packages/torch/nn/functional. py”,第3029行,在cross_entropy返回 Torch 中。_C._nn. cross_entropy_loss(input,target,weight,_Reduction. get_enum(reduction),ignore_index,标签_平滑)^^^^输入batch_size(3)应与目标batch_size(9)匹配。
问题是,当我改变batch_size时,我每次都得到目标batch_size的三倍,但我找不到bug。我觉得我搜索了整个互联网,但什么也没找到。我希望你们中的一些人能帮助我!
这是我的代码:

import torch
import torch.nn as nn
import torchvision.transforms as transforms
from torch.utils.data import Dataset, DataLoader
from PIL import Image
import os
from PIL import ImageEnhance

class SatelliteDataset(Dataset):
    def __init__(self, image_folder, label_folder, transform=None):
        self.image_folder = image_folder
        self.label_folder = label_folder
        self.transform = transform

        self.image_paths = sorted([os.path.join(image_folder, filename) for filename in os.listdir(image_folder)])
        self.label_paths = sorted([os.path.join(label_folder, filename) for filename in os.listdir(label_folder)])

    def __len__(self):
        return len(self.image_paths)

    def __getitem__(self, idx):
        image_path = self.image_paths[idx]
        label_path = self.label_paths[idx]

        image = Image.open(image_path)
        label = Image.open(label_path)

        image = self.adjust_brightness(image, brightness_factor=1.8)

        # Resize images to 512x512
        image = image.resize((512, 512), Image.BILINEAR)
        label = label.resize((512, 512), Image.NEAREST)

        # Apply transformations if specified
        if self.transform:
            image = self.transform(image)
            label = self.transform(label)

        return image, label

    def adjust_brightness(self, image, brightness_factor=1.0):
        enhancer = ImageEnhance.Brightness(image)
        enhanced_image = enhancer.enhance(brightness_factor)
        return enhanced_image

# Define paths to the folders containing satellite images and corresponding labels
image_folder = "/Users/.../train_data/images"
label_folder = "/Users/.../train_data/masks"

# Define transformations for normalization and scaling
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]),
])

# Create an instance of the SatelliteDataset
dataset = SatelliteDataset(image_folder, label_folder, transform=transform)

# Create DataLoader for training
def collate_fn(batch):
    images, labels = zip(*batch)
    images = torch.stack(images)
    labels = torch.stack(labels)
    return images, labels

batch_size = 3
train_dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True, collate_fn=collate_fn)

# cnn
class CNN(nn.Module):
    def __init__(self, in_channels, out_channels):
        super(CNN, self).__init__()

        self.conv1 = nn.Conv2d(in_channels, 64, kernel_size=3, stride=1, padding=1)
        self.relu1 = nn.ReLU()
        self.maxpool1 = nn.MaxPool2d(kernel_size=2, stride=2)

        self.conv2 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
        self.relu2 = nn.ReLU()
        self.maxpool2 = nn.MaxPool2d(kernel_size=2, stride=2)

        self.conv3 = nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1)
        self.relu3 = nn.ReLU()
        self.maxpool3 = nn.MaxPool2d(kernel_size=2, stride=2)

        self.conv4 = nn.Conv2d(256, 512, kernel_size=3, stride=1, padding=1)
        self.relu4 = nn.ReLU()

        self.conv5 = nn.Conv2d(512, out_channels=7, kernel_size=1, stride=1)

    def forward(self, x):
        x = self.conv1(x)
        x = self.relu1(x)
        x = self.maxpool1(x)

        x = self.conv2(x)
        x = self.relu2(x)
        x = self.maxpool2(x)

        x = self.conv3(x)
        x = self.relu3(x)
        x = self.maxpool3(x)

        x = self.conv4(x)
        x = self.relu4(x)

        x = self.conv5(x)

        x = torch.softmax(x, dim=1)  # add Softmax layer
        return x

# Training loop
def train(model, dataloader, loss_fn, optimizer, device):
    model.train()  # Set the model to training mode

    running_loss = 0.0

    for images, labels in dataloader:
        images = images.to(device)
        labels = labels.to(device)

        optimizer.zero_grad()

        # Forward pass
        outputs = model(images)

        # Reshape labels dimensions
        labels = labels.view(-1, 512, 512)
        labels = labels.long()

        # Calculate loss
        loss = loss_fn(outputs, labels)

        # Backward pass and weight update
        loss.backward()
        optimizer.step()

        running_loss += loss.item() * images.size(0)

    epoch_loss = running_loss / len(dataloader.dataset)

    return epoch_loss

# Validation
def evaluate(model, dataloader, loss_fn, device):
    model.eval()  # Set the model to evaluation mode

    running_loss = 0.0

    with torch.no_grad():
        for images, labels in dataloader:
            images = images.to(device)
            labels = labels.to(device)

            # Forward pass
            outputs = model(images)

            # Calculate loss
            loss = loss_fn(outputs, labels)

            running_loss += loss.item() * images.size(0)

    epoch_loss = running_loss / len(dataloader.dataset)
    return epoch_loss

# Perform training
def train_model(model, train_dataloader, val_dataloader, loss_fn, optimizer, device, num_epochs):
    best_val_loss = float('inf')
    best_model_weights = None
    for epoch in range(num_epochs):
        print(f"Epoch {epoch+1}/{num_epochs}")

        # Training step
        train_loss = train(model, train_dataloader, loss_fn, optimizer, device)
        print(f"Train Loss: {train_loss}")

        # Validation step
        val_loss = evaluate(model, val_dataloader, loss_fn, device)
        print(f"Val Loss: {val_loss}")

        # Check for improvement in validation loss
        if val_loss < best_val_loss:
            best_val_loss = val_loss
            best_model_weights = model.state_dict()

    # Return the best model
    model.load_state_dict(best_model_weights)
    return model


# Example usage of the model
model = CNN(in_channels=3, out_channels=7)

# Select device (CPU)
device = torch.device("cpu")

# Loss function
loss_fn = nn.CrossEntropyLoss()

# Optimizer
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9)

Number of epochs (adjust as needed)
num_epochs = 10

# Create a separate DataLoader for validation with batch_size=3
val_dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True, collate_fn=collate_fn)

# Perform training
model = train_model(model, train_dataloader, val_dataloader, loss_fn, optimizer, device, num_epochs)

字符串
顺便说一下,我在MacOS和VSC上编程

    • 我试过了:**我把所有的错误信息都复制到了谷歌上,并阅读了几乎所有关于这个问题的文章。尽管如此,我还是无法解决这个问题。我尝试改变批量大小(我有804张图片来训练模型),并改变了数据加载器。我还问了ChatGPT,虽然它很好地解释了这个问题,并给出了解决这个问题的几个想法,但它没有帮助。
7xllpg7q

7xllpg7q1#

有一条线labels = labels.view(-1, 512, 512)正在更改标签的尺寸。从你的数据加载器,似乎你的标签是图像。如果它有3个通道(RGB),那么这条尺寸变化线基本上会使批量大小增加三倍。

相关问题