我尝试制作一个 Unet 模型。 这是我的代码:
import torch
import torch.nn as nn
import torch.optim as optim
import albumentations as A
from albumentations.pytorch import ToTensorV2
from tqdm import tqdm
from model import Unet
from utils import get_loaders
import numpy as np
import random
# Hyperparameters
LEARNING_RATE = 1e-8
BATCH_SIZE = 8
NUM_EPOCH = 2
NUM_WORKERS = 2
PIN_MEMORY = True
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
print(DEVICE)
TRAIN_IMG_DIR = "./dataset/train_img_dir"
TRAIN_MASK_DIR = "./dataset/train_mask_dir"
VAL_IMG_DIR = "./dataset/val_img_dir"
VAL_MASK_DIR = "./dataset/val_mask_dir"
IMAGE_HEIGHT = 160
IMAGE_WIDTH = 240
train_losses = []
val_acc = []
val_dice = []
# 设置随机种子
seed = random.randint(1, 100)
torch.manual_seed(seed)
torch.cuda.manual_seed(seed)
torch.cuda.manual_seed_all(seed) # 如果你使用多个GPU
np.random.seed(seed)
random.seed(seed)
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
def train_fn(loader, model, loss_fn, optimizer, scaler):
loop = tqdm(loader)
total_loss = 0.0
for index, (data, target) in enumerate(loop):
data = data.to(DEVICE)
target = target.unsqueeze(1).float().to(DEVICE)
with torch.cuda.amp.autocast():
predict = model(data)
loss = loss_fn(predict, target)
optimizer.zero_grad()
scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()
total_loss += loss.item()
loop.set_postfix(loss=loss.item())
return total_loss / len(loader)
def check_accuracy(loader, model, DEVICE="cuda"):
num_correct = 0
num_pixels = 0
dice_score = 0
model.eval()
with torch.no_grad():
for x, y in loader:
x = x.to(DEVICE)
y = y.unsqueeze(1).to(DEVICE)
predictions = torch.sigmoid(model(x))
predictions = (predictions > 0.5).float()
num_correct += (predictions == y).sum()
num_pixels += torch.numel(predictions)
dice_score += (2 * (predictions * y).sum()) / (2 * (predictions * y).sum()+((predictions*y)<1).sum())
accuracy = round(float(num_correct / num_pixels), 4)
dice = round(float(dice_score/len(loader)), 4)
print(f"Got {num_correct}/{num_pixels} with acc {num_correct/num_pixels * 100 :.2f}")
print(f"Dice Score:{dice_score/len(loader)}")
model.train()
return accuracy, dice
def main():
train_transform = A.Compose(
[
A.Resize(height=IMAGE_HEIGHT, width=IMAGE_WIDTH),
A.Rotate(limit=35, p=1.0),
A.HorizontalFlip(p=0.5),
A.VerticalFlip(p=0.1),
A.Normalize(
mean=[0.0, 0.0, 0.0],
std=[1.0, 1.0, 1.0],
max_pixel_value=255.0,
),
ToTensorV2(),
],)
val_transform = A.Compose(
[
A.Resize(height=IMAGE_HEIGHT, width=IMAGE_WIDTH),
A.Normalize(
mean=[0.0, 0.0, 0.0],
std=[1.0, 1.0, 1.0],
max_pixel_value=255.0,
),
ToTensorV2(),
], )
train_loader, val_loader = get_loaders(TRAIN_IMG_DIR, TRAIN_MASK_DIR, VAL_IMG_DIR, VAL_MASK_DIR,
train_transform, val_transform,
BATCH_SIZE, NUM_WORKERS, PIN_MEMORY)
model = Unet(in_channel=3, out_channel=1).to(device=DEVICE)
loss_fn = nn.BCEWithLogitsLoss()
optimizer = optim.Adam(model.parameters(), lr=LEARNING_RATE)
scaler = torch.cuda.amp.GradScaler()
for index in range(NUM_EPOCH):
print("Current Epoch: ", index)
train_loss = train_fn(train_loader, model, loss_fn, optimizer, scaler)
train_losses.append(train_loss)
accuracy, dice = check_accuracy(val_loader, model, DEVICE=DEVICE)
val_acc.append(accuracy)
val_dice.append(dice)
if __name__ == "__main__":
main()
我得到了这个错误:
D:\anaconda3\envs\Unet\python.exe C:\Users\xxx\PycharmProjects\Study\pythonProject3\train.py 库达 当前纪元:0 0it [00:00, ?it/s] 回溯(最近一次调用最后一次): 文件“C:\Users\xxx\PycharmProjects\Study\pythonProject3\train.py”,第 142 行,位于 主要的() 文件“C:\Users\xxx\PycharmProjects\Study\pythonProject3\train.py”,第 133 行,在 main 中 train_loss = train_fn(train_loader、模型、loss_fn、优化器、缩放器) 文件“C:\Users\xxx\PycharmProjects\Study\pythonProject3\train.py”,第 50 行,在 train_fn 中 对于枚举(循环)中的索引(数据,目标): 文件“D:\anaconda3\envs\Unet\lib\site-packages\tqdm\std.py”,第 1181 行,在 iter for obj in iterable 中: 文件“D:\anaconda3\envs\Unet\lib\site-packages\torch\utils\data\dataloader.py”,第 435 行, iter return self._get_iterator() 文件“D:\anaconda3\envs\Unet\lib\site-packages\torch\utils\data\dataloader.py”,第 381 行,在 _get_iterator 中 返回 _MultiProcessingDataLoaderIter(self) 文件“D:\anaconda3\envs\Unet\lib\site-packages\torch\utils\data\dataloader.py”,第 1072 行,in init self._reset(loader,first_iter=True) 文件“D:\anaconda3\envs\Unet\lib\site-packages\torch\utils\data\dataloader.py”,第 1105 行,在 _reset 中 self._try_put_index() 文件“D:\anaconda3\envs\Unet\lib\site-packages\torch\utils\data\dataloader.py”,第 1339 行,位于 _try_put_index 中 索引 = self._next_index() 文件“D:\anaconda3\envs\Unet\lib\site-packages\torch\utils\data\dataloader.py”,第 618 行,在 _next_index 中 return next(self._sampler_iter) # 可能会引发 StopIteration 文件“D:\anaconda3\envs\Unet\lib\site-packages\torch\utils\data\sampler.py”,第 254 行,in iter for self.sampler 中的 idx: 文件“D:\anaconda3\envs\Unet\lib\site-packages\torch\utils\data\sampler.py”,第 76 行,in iter return iter(range(len(self.data_source) )) 文件“C:\Users\xxx\PycharmProjects\Study\pythonProject3\dataset.py”,第 15 行,in len return len(self.image) AttributeError:“CarvanaDataset”对象没有属性“image” 进程已完成,退出代码为 1
我该如何解决此问题?
错误信息 "AttributeError: 'CarvanaDataset' object has no attribute 'image'" 表明正在尝试访问
CarvanaDataset
类中不存在的
image
属性。这个错误出现在尝试获取数据集长度时,这意味着问题出在的
CarvanaDataset
类的
__len__
函数中。
需要确保在
CarvanaDataset
类中正确定义了
self.image
。它应该在
__init__
方法中初始化,并且存储图像路径的列表或图像数据本身。
以下是修复此错误的步骤以及改进代码的建议:
1. 检查
CarvanaDataset
类:
-
确保在
utils.py
文件中定义了CarvanaDataset
类。 -
验证
__init__
方法是否正确初始化了self.image
,并将其设置为图像路径列表或图像数据。
```python class CarvanaDataset(Dataset): def init (self, image_dir, mask_dir, transform=None): self.image_dir = image_dir self.mask_dir = mask_dir self.transform = transform self.images = os.listdir(image_dir) # 获取所有图像文件名
def __len__(self):
return len(self.images)
def __getitem__(self, index):
img_path = os.path.join(self.image_dir, self.images[index])
mask_path = os.path.join(self.mask_dir, self.images[index].replace('.jpg', '_mask.gif'))
# 假设掩码文件名与图像文件名相关
image = np.array(Image.open(img_path).convert("RGB"))
mask = np.array(Image.open(mask_path).convert("L"), dtype=np.float32)
# 将掩码转换为单通道
if self.transform is not None:
augmentations = self.transform(image=image, mask=mask)
image = augmentations["image"]
mask = augmentations["mask"]
return image, mask
```
2. 检查
get_loaders
函数:
-
确保
get_loaders
函数在创建DataLoader
实例时正确地实例化了CarvanaDataset
类。
```python def get_loaders( train_dir, train_maskdir, val_dir, val_maskdir, train_transform, val_transform, batch_size, num_workers=4, pin_memory=True, ): train_ds = CarvanaDataset( image_dir=train_dir, mask_dir=train_maskdir, transform=train_transform, )
train_loader = DataLoader(
train_ds,
batch_size=batch_size,
num_workers=num_workers,
pin_memory=pin_memory,
shuffle=True,
)
val_ds = CarvanaDataset(
image_dir=val_dir,
mask_dir=val_maskdir,
transform=val_transform,
)
val_loader = DataLoader(
val_ds,
batch_size=batch_size,
num_workers=num_workers,
pin_memory=pin_memory,
shuffle=False,
)
return train_loader, val_loader
```
通过进行这些更改,应该能够解决 "AttributeError: 'CarvanaDataset' object has no attribute 'image'" 错误并继续进行 U-Net 模型的训练。
标签:python,unet-neural-network From: 78845269