Pytorch模型训练-----------数据集加载之ImageFolder之全过程

数据集加载之ImageFolder

ImageFolder一个通用的数据加载器,数据集中的数据以以下方式组织

函数如下

ImageFolder(root, transform``=``None``, target_transform``=``None``, loader``=``default_loader)

参数解释

  • root 指定路径加载图片

  • transform:对PIL Image进行的转换操作,transform的输入是使用loader读取图片的返回对象

  • target_transform:对label的转换

  • loader:给定路径后如何读取图片,默认读取为RGB格式的PIL Image对象

label是按照文件夹名顺序排序后存成字典,即{类名:类序号(从0开始)},一般来说最好直接将文件夹命名为从0开始的数字,这样会和ImageFolder实际的label一致,如果不是这种命名规范,建议看看self.class_to_idx属性以了解label和文件夹名的映射关系

img

可见分成了cat和dog两类

import torchvision.datasets as dset
dataset = dset.ImageFolder('./data/dogcat_2') #没有transform,先看看取得的原始图像数据
print(dataset.classes)  #根据分的文件夹的名字来确定的类别
print(dataset.class_to_idx) #按顺序为这些类别定义索引为0,1...
print(dataset.imgs) #返回从所有文件夹中得到的图片的路径以及其类别

返回

['cat', 'dog']
{'cat': 0, 'dog': 1}
[('./data/dogcat_2/cat/cat.12484.jpg', 0), ('./data/dogcat_2/cat/cat.12485.jpg', 0), ('./data/dogcat_2/cat/cat.12486.jpg', 0), ('./data/dogcat_2/cat/cat.12487.jpg', 0), ('./data/dogcat_2/dog/dog.12496.jpg', 1), ('./data/dogcat_2/dog/dog.12497.jpg', 1), ('./data/dogcat_2/dog/dog.12498.jpg', 1), ('./data/dogcat_2/dog/dog.12499.jpg', 1)]

查看得到的图片数据:

#从返回结果可见得到的数据仍是PIL Image对象
print(dataset[0])
print(dataset[0][0])
print(dataset[0][1]) #得到的是类别0,即cat

返回:

(<PIL.Image.Image image mode=RGB size=497x500 at 0x11D99A9B0>, 0)
<PIL.Image.Image image mode=RGB size=497x500 at 0x11DD24278>
0

再通过transform变成张量

 data_transform = {
        "train": transforms.Compose([transforms.RandomResizedCrop(224),
                                     transforms.RandomHorizontalFlip(),
                                     transforms.ToTensor()
                                     ]),
        "val": transforms.Compose([transforms.Resize((224, 224)),  # cannot 224, must (224, 224)
                                   transforms.ToTensor()
                                   ])}

    train_dataset = datasets.ImageFolder(root=os.path.join(data_root, "train"),
                                         transform=data_transform["train"])
    
    print(train_dataset[0])
	print(train_dataset[0][0])
	print(train_dataset[0][1]) #得到的是类别0,即cat

得到

(tensor([[[0.3765, 0.3765, 0.3765,  ..., 0.3765, 0.3765, 0.3765],
         [0.3765, 0.3765, 0.3765,  ..., 0.3765, 0.3765, 0.3765],
         [0.3804, 0.3804, 0.3804,  ..., 0.3765, 0.3765, 0.3765],
         ...,
         [0.4941, 0.4941, 0.4902,  ..., 0.3804, 0.3765, 0.3765],
         [0.5098, 0.5098, 0.5059,  ..., 0.3804, 0.3765, 0.3765],
         [0.5098, 0.5098, 0.5059,  ..., 0.3804, 0.3765, 0.3765]],

        [[0.5686, 0.5686, 0.5686,  ..., 0.5843, 0.5804, 0.5804],
         [0.5686, 0.5686, 0.5686,  ..., 0.5843, 0.5804, 0.5804],
         [0.5725, 0.5725, 0.5725,  ..., 0.5843, 0.5804, 0.5804],
         ...,
         [0.5686, 0.5686, 0.5686,  ..., 0.5961, 0.5922, 0.5922],
         [0.5686, 0.5686, 0.5686,  ..., 0.5961, 0.5922, 0.5922],
         [0.5686, 0.5686, 0.5686,  ..., 0.5961, 0.5922, 0.5922]],

        [[0.4824, 0.4824, 0.4824,  ..., 0.4902, 0.4902, 0.4902],
         [0.4824, 0.4824, 0.4824,  ..., 0.4902, 0.4902, 0.4902],
         [0.4863, 0.4863, 0.4863,  ..., 0.4902, 0.4902, 0.4902],
         ...,
         [0.3647, 0.3686, 0.3804,  ..., 0.4824, 0.4784, 0.4784],
         [0.3451, 0.3490, 0.3608,  ..., 0.4824, 0.4784, 0.4784],
         [0.3451, 0.3490, 0.3608,  ..., 0.4824, 0.4784, 0.4784]]]), 0)
         
         省略
         图像Tensor [........]
         标签Tensor [0]

可以知道train_dataset[0]是一个tuple里面一个是张量一个是标量

    print(train_dataset[0][0].shape)
    print(train_dataset[0][1])

返回

torch.Size([3, 224, 224])
0

DataLoader产生批训练数据

for epoch in range(epoch_num):
        for image, label in train_loader:
			print("label: ", labels, labels.dtype)
            print("imges: ", images, images.dtype)

返回

label:  tensor([0]) torch.int64
    
imges:  tensor([[[[0.2275, 0.2275, 0.2235,  ..., 0.2196, 0.2196, 0.2196],
          [0.2275, 0.2275, 0.2235,  ..., 0.2196, 0.2196, 0.2196],
          [0.2235, 0.2235, 0.2235,  ..., 0.2157, 0.2157, 0.2157],
          ...,
          [0.2392, 0.2392, 0.2392,  ..., 0.2235, 0.2235, 0.2235],
          [0.2353, 0.2353, 0.2353,  ..., 0.2235, 0.2275, 0.2275],
          [0.2353, 0.2353, 0.2353,  ..., 0.2235, 0.2275, 0.2275]],

         [[0.2392, 0.2392, 0.2353,  ..., 0.2275, 0.2275, 0.2275],
          [0.2392, 0.2392, 0.2353,  ..., 0.2275, 0.2275, 0.2275],
          [0.2353, 0.2353, 0.2353,  ..., 0.2235, 0.2235, 0.2235],
          ...,
          [0.2275, 0.2275, 0.2314,  ..., 0.2196, 0.2196, 0.2196],
          [0.2235, 0.2235, 0.2275,  ..., 0.2196, 0.2196, 0.2196],
          [0.2235, 0.2235, 0.2275,  ..., 0.2196, 0.2196, 0.2196]],

         [[0.1961, 0.1961, 0.1961,  ..., 0.1765, 0.1765, 0.1765],
          [0.1961, 0.1961, 0.1961,  ..., 0.1765, 0.1765, 0.1765],
          [0.1922, 0.1922, 0.1922,  ..., 0.1725, 0.1725, 0.1725],
          ...,
          [0.1529, 0.1529, 0.1529,  ..., 0.1686, 0.1686, 0.1686],
          [0.1490, 0.1490, 0.1490,  ..., 0.1686, 0.1686, 0.1686],
          [0.1490, 0.1490, 0.1490,  ..., 0.1686, 0.1686, 0.1686]]]]) torch.float32

enumerate加载

enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。

可以用这个循环加载batchsize下面的每一元组,来得到相应的图片及标签

多元素赋值

当Python检测到等号左边是多个变量,右边是list或者是tuple之后,会自动执行list和tuple的解压,将它依次赋值给对应的元素

l = [1, 2]
a, b = l

所以可以

for step, data in enumerate(train_bar):
            images, labels = data

最后nn.CrossEntropyLoss()计算loss回归

nn.CrossEntropyLoss()nn.logSoftmax()nn.NLLLoss()的整合,可以直接使用它来替换网络中的这两个操作。下面我们来看一下计算过程。

img

其中x是网络的输出向量,class是真实标签

举个例子,一个三分类网络对某个输入样本的输出为[-0.7715, -0.6205,-0.2562],该样本的真实标签为0,则用nn.CrossEntropyLoss()计算的损失为

img

参考链接讲的很好

参考二

  • 6
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
好的,我可以用PyTorch框架完成这个任务。首先需要下载tiny-imagenet数据集并准备数据。接着,我们可以按照以下步骤进行训练和预测: 1. 加载数据集 我们需要使用PyTorch的Dataset和DataLoader类来加载tiny-imagenet数据集。在加载数据集时,我们需要进行数据增强(如随机剪裁、水平翻转等)以提高模型的泛化能力。 ```python import torch import torchvision.transforms as transforms import torchvision.datasets as datasets # 定义数据增强 train_transforms = transforms.Compose([ transforms.RandomResizedCrop(64), transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)) ]) test_transforms = transforms.Compose([ transforms.Resize(64), transforms.CenterCrop(64), transforms.ToTensor(), transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)) ]) # 加载数据集 train_dataset = datasets.ImageFolder('/path/to/tiny-imagenet/train', transform=train_transforms) test_dataset = datasets.ImageFolder('/path/to/tiny-imagenet/val', transform=test_transforms) # 定义DataLoader train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=64, shuffle=True) test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=32, shuffle=False) ``` 2. 定义模型 我们可以使用预训练的ResNet-18模型,并将其最后一层替换为一个全连接层以适应tiny-imagenet数据集。 ```python import torchvision.models as models import torch.nn as nn # 加载训练的ResNet-18模型 model = models.resnet18(pretrained=True) # 替换最后一层为一个全连接层,并使用xavier初始化权重 model.fc = nn.Linear(512, 200) nn.init.xavier_uniform_(model.fc.weight) # 将模型移动到GPU上 device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model = model.to(device) ``` 3. 定义损失函数和优化器 我们可以使用交叉熵损失函数来训练模型,并使用随机梯度下降(SGD)优化器进行参数优化。 ```python import torch.optim as optim criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(model.parameters(), lr=0.1, momentum=0.9, weight_decay=1e-4) ``` 4. 训练模型 我们可以使用以下代码来训练模型: ```python # 定义训练函数 def train(model, device, train_loader, criterion, optimizer, epoch): model.train() running_loss = 0.0 for batch_idx, (data, target) in enumerate(train_loader): data, target = data.to(device), target.to(device) optimizer.zero_grad() output = model(data) loss = criterion(output, target) loss.backward() optimizer.step() running_loss += loss.item() * data.size(0) train_loss = running_loss / len(train_loader.dataset) print('Train Epoch: {} \t Loss: {:.6f}'.format(epoch, train_loss)) # 训练模型 for epoch in range(1, 21): train(model, device, train_loader, criterion, optimizer, epoch) ``` 5. 测试模型 我们可以使用以下代码来测试模型: ```python # 定义测试函数 def test(model, device, test_loader): model.eval() correct = 0 with torch.no_grad(): for data, target in test_loader: data, target = data.to(device), target.to(device) output = model(data) pred = output.argmax(dim=1, keepdim=True) correct += pred.eq(target.view_as(pred)).sum().item() acc = 100. * correct / len(test_loader.dataset) print('Test Accuracy: {:.2f}%'.format(acc)) # 测试模型 test(model, device, test_loader) ``` 6. 预测新图片 我们可以使用以下代码来预测新图片: ```python import PIL.Image as Image # 定义类别名称 class_names = train_dataset.classes # 加载图片并进行预处理 img = Image.open('/path/to/image.jpg') img_transforms = test_transforms(img).unsqueeze(0) # 将图片移动到GPU上 img_transforms = img_transforms.to(device) # 预测图片的类别 output = model(img_transforms) pred = output.argmax(dim=1, keepdim=True).item() # 打印预测结果 print('Predicted Class:', class_names[pred]) ``` 这样,我们就完成了对tiny-imagenet的训练过程和分类预测。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值