代码先锋网 代码片段及技术文章聚合

pytorch: 自定义数据集加载

很多网络在数据加载方式

pytorch 的输入流水线的操作顺序是这样的:

    创建一个 Dataset 对象
    创建一个 DataLoader 对象
    不停的 循环 这个 DataLoader 对象

自己感觉:dataset只是负责一张图片以及它的label标签,dataloader负责调用dataset,使得输出batch_size的图片和他们的标签

dataset = MyDataset()
dataloader = DataLoader(dataset)
num_epoches = 100
for epoch in range(num_epoches):
    for data in dataloader:

其中里面的MyDataset()是继承torch.utils.data.Dataset类,这是一个抽象类,其他所有不管是公开的官方数据集还是自定义数据集都必须继承这个抽象类(比如MNIST数据集),继承这个抽象类的同时必须重写它的两个函数:__len__()  和    __getitem__()。

  • __len__():返回数据集的大小,比如我的数据集有500张图片,那么就返回500
  • __getitem__():返回一张图片

下面使用代码是自定义的数据加载方式。下面的是猫狗数据集里面的

class MyDataset(Dataset):


    def __init__(self, root_dir, transform=None):

        # os.listdir函数读取路径下所以文件的文件名,并组成一个列表并返回

        self.file = os.listdir(root_dir)

        self.root_dir = root_dir

        self.transform = transform

    def __len__(self):
        return len(self.file)  # 返回这给列表的大小

    def __getitem__(self, index):
        # 将传入路径和文件名组成一个新的地址,这个数据就是单个数据的具体地址,方便之后以地址读取该数据
        img_name = os.path.join(self.root_dir, self.file[index])
        # 从文件名中获取标签(我的数据标签在文件名中,比如一张狗的图片名:cat.4.jpg,4是序号,cat是
        # 标签)
        if img_name[13:16] == 'dog':
            label = 0
        else:
            label = 1
        # 根据上面获得的具体地址,读取这张图片
        image = Image.open(img_name)

        # 对图片进行处理
        image = self.transform(image)
        # print(image.shape)

        # numpy的三个维度顺序为:H * W * C
        # 而torch的张量维度顺序:C * H * W ,所以模型要处理它必须转换成torch的形式

        # 返回数据和标签
        return image, label

里面还使用了transform,如下面的代码可以看出来将上面的单个图片进行了预处理。Resize将读取图片的缩放到150。ToTenser()就比较重要了,这个函数的目的就是读取图片像素并且转化为0-1的数字。Normalize作为垫底的一步也很关键,主要用于把图片数据集的数值转化为标准差和均值都为0.5的数据集,这样数据值就从原来的0到1转变为-1到1。

# 数据预处理
transform = transforms.Compose([
    transforms.Resize(size=(150, 150)),
    transforms.ToTensor(),
    transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
])

猫狗大战中使用自定义数据读取方式代码

#coding=utf-8
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import Dataset  # 首先导入这个抽象类
from PIL import Image
import os


# 设置超参数
NUM_CLASSES = 2
BATCH_SIZE = 50
EPOCHS = 1
DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

# 数据预处理
transform = transforms.Compose([
    transforms.Resize(size=(150, 150)),
    transforms.ToTensor(),
    transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
])



class MyDataset(Dataset):


    def __init__(self, root_dir, transform=None):

        # os.listdir函数读取路径下所以文件的文件名,并组成一个列表并返回

        self.file = os.listdir(root_dir)

        self.root_dir = root_dir

        self.transform = transform

    def __len__(self):
        return len(self.file)  # 返回这给列表的大小

    def __getitem__(self, index):
        # 将传入路径和文件名组成一个新的地址,这个数据就是单个数据的具体地址,方便之后以地址读取该数据
        img_name = os.path.join(self.root_dir, self.file[index])
        # 从文件名中获取标签(我的数据标签在文件名中,比如一张狗的图片名:cat.4.jpg,4是序号,cat是
        # 标签)
        if img_name[13:16] == 'dog':
            label = 0
        else:
            label = 1
        # 根据上面获得的具体地址,读取这张图片
        image = Image.open(img_name)

        # 对图片进行处理
        image = self.transform(image)
        # print(image.shape)

        # numpy的三个维度顺序为:H * W * C
        # 而torch的张量维度顺序:C * H * W ,所以模型要处理它必须转换成torch的形式

        # 返回数据和标签
        return image, label

dataset_train = MyDataset(root_dir='kaggle/train/', transform=transform)
dataset_test = MyDataset(root_dir='kaggle/test1/', transform=transform)

# 导入数据
train_loader = torch.utils.data.DataLoader(dataset_train, batch_size=BATCH_SIZE, shuffle=True)
# test_loader = torch.utils.data.DataLoader(dataset_test, batch_size=BATCH_SIZE, shuffle=True)


# 定义网络
class ConvNet(nn.Module):
    def __init__(self):
        super(ConvNet, self).__init__()
        self.conv1 = nn.Conv2d(3, 32, 3)
        self.max_pool1 = nn.MaxPool2d(2)
        self.conv2 = nn.Conv2d(32, 64, 3)
        self.max_pool2 = nn.MaxPool2d(2)
        self.conv3 = nn.Conv2d(64, 128, 3)
        self.max_pool3 = nn.MaxPool2d(2)
        self.conv4 = nn.Conv2d(128, 128, 3)
        self.max_pool4 = nn.MaxPool2d(2)
        self.fc1 = nn.Linear(6272, 512)
        self.fc2 = nn.Linear(512, 1)

    def forward(self, x):
        in_size = x.size(0)
        x = self.conv1(x)
        x = F.relu(x)
        x = self.max_pool1(x)
        x = self.conv2(x)
        x = F.relu(x)
        x = self.max_pool2(x)
        x = self.conv3(x)
        x = F.relu(x)
        x = self.max_pool3(x)
        x = self.conv4(x)
        x = F.relu(x)
        x = self.max_pool4(x)
        # 展开
        x = x.view(in_size, -1)
        x = self.fc1(x)
        x = F.relu(x)
        x = self.fc2(x)
        x = torch.sigmoid(x)
        return x


# 实例化模型并且移动到GPU
model = ConvNet().to(DEVICE)
# 选择简单暴力的Adam优化器,学习率调低
optimizer = optim.Adam(model.parameters(), lr=1e-4)


# 定义训练过程
def train(model, device, train_loader, optimizer, epoch):
    model.train()
    for batch_idx, (data, target) in enumerate(train_loader):
        # print(data.shape)
        # print(target.shape)
        # print(target)

        data, target = data.to(device), target.to(device).float().reshape(50, 1)
        optimizer.zero_grad()
        output = model(data)
        loss = F.binary_cross_entropy(output, target)
        loss.backward()
        optimizer.step()
        if (batch_idx + 1) % 10 == 0:
            print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
                epoch, (batch_idx + 1) * len(data), len(train_loader.dataset),
                       100. * (batch_idx + 1) / len(train_loader), loss.item()))


# 定义测试过程
def test(model, device, test_loader):
    model.eval()
    test_loss = 0
    correct = 0
    with torch.no_grad():
        for data, target in test_loader:
            # data, target = data.to(device), target.to(device).float().reshape(50, 1)
            data, target = data.to(device), target.to(device)

            output = model(data)
            # print(output)
            test_loss += F.binary_cross_entropy(output, target).item()  # 将一批的损失相加
            pred = torch.tensor([[1] if num[0] >= 0.5 else [0] for num in output]).to(device)
            correct += pred.eq(target.long()).sum().item()
        print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
            test_loss, correct, len(test_loader.dataset),
            100. * correct / len(test_loader.dataset)))

# 训练
for epoch in range(1, EPOCHS + 1):
    train(model, DEVICE, train_loader, optimizer, epoch)
    # test(model, DEVICE, test_loader)

如果不使用自定义数据加载方式

dataset_train = datasets.ImageFolder(root + 'train', transform)

如果使用这个的话,需要将数据文件夹train分成两个子文件夹dog,cat。其实这个就是标签,需要下面的函数

import os
import shutil


def move(root, file_list, out_dog_path, out_cat_path):
    if not os.path.exists(out_dog_path):
        os.mkdir(out_dog_path)
    if not os.path.exists(out_cat_path):
        os.mkdir(out_cat_path)
    for file_name in file_list:
        print(file_name)
        file_path = os.path.join(root, file_name)
        index = file_name[:3]
        # print(index)
        if index == 'dog':
            shutil.move(file_path, out_dog_path)
        else:
            shutil.move(file_path, out_cat_path)

if __name__ == '__main__':
    #train
    root = 'kaggle/train/'
    file_list = os.listdir(root)
    out_dog_path = 'kaggle/train/dog/'
    out_cat_path = 'kaggle/train/cat/'
    move(root, file_list, out_dog_path, out_cat_path)

下面是训练的代码:

#coding=utf-8
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.autograd import Variable
from torchvision import datasets, transforms

# 设置超参数
BATCH_SIZE = 50
EPOCHS = 1
DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

# 数据预处理
transform = transforms.Compose([
    transforms.RandomResizedCrop(150),
    transforms.ToTensor(),
    transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
])

# 读取数据
root = 'kaggle/'
dataset_train = datasets.ImageFolder(root + 'train', transform)
# dataset_test = datasets.ImageFolder(root + 'test1', transform)

# 导入数据
train_loader = torch.utils.data.DataLoader(dataset_train, batch_size=BATCH_SIZE, shuffle=True)
# test_loader = torch.utils.data.DataLoader(dataset_test, batch_size=BATCH_SIZE, shuffle=True)


# 定义网络
class ConvNet(nn.Module):
    def __init__(self):
        super(ConvNet, self).__init__()
        self.conv1 = nn.Conv2d(3, 32, 3)
        self.max_pool1 = nn.MaxPool2d(2)
        self.conv2 = nn.Conv2d(32, 64, 3)
        self.max_pool2 = nn.MaxPool2d(2)
        self.conv3 = nn.Conv2d(64, 128, 3)
        self.max_pool3 = nn.MaxPool2d(2)
        self.conv4 = nn.Conv2d(128, 128, 3)
        self.max_pool4 = nn.MaxPool2d(2)
        self.fc1 = nn.Linear(6272, 512)
        self.fc2 = nn.Linear(512, 1)

    def forward(self, x):
        in_size = x.size(0)
        x = self.conv1(x)
        x = F.relu(x)
        x = self.max_pool1(x)
        x = self.conv2(x)
        x = F.relu(x)
        x = self.max_pool2(x)
        x = self.conv3(x)
        x = F.relu(x)
        x = self.max_pool3(x)
        x = self.conv4(x)
        x = F.relu(x)
        x = self.max_pool4(x)
        # 展开
        x = x.view(in_size, -1)
        x = self.fc1(x)
        x = F.relu(x)
        x = self.fc2(x)
        x = torch.sigmoid(x)
        return x


# 实例化模型并且移动到GPU
model = ConvNet().to(DEVICE)
# 选择简单暴力的Adam优化器,学习率调低
optimizer = optim.Adam(model.parameters(), lr=1e-4)


# 定义训练过程
def train(model, device, train_loader, optimizer, epoch):
    model.train()
    for batch_idx, (data, target) in enumerate(train_loader):
        # data, target = data.to(device), target.to(device).float().reshape(50, 1)
        data, target = data.to(device), target.to(device).float()
        # print(target.size())
        # print(data.size())
        # print(target)
        optimizer.zero_grad()
        output = model(data)
        # print(output)
        loss = F.binary_cross_entropy(output, target)
        loss.backward()
        optimizer.step()
        if (batch_idx + 1) % 10 == 0:
            print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
                epoch, (batch_idx + 1) * len(data), len(train_loader.dataset),
                       100. * (batch_idx + 1) / len(train_loader), loss.item()))


# 定义测试过程
def test(model, device, test_loader):
    model.eval()
    test_loss = 0
    correct = 0
    with torch.no_grad():
        for data, target in test_loader:
            data, target = data.to(device), target.to(device).float().reshape(50, 1)
            output = model(data)
            # print(output)
            test_loss += F.binary_cross_entropy(output, target, reduction='sum').item()  # 将一批的损失相加
            pred = torch.tensor([[1] if num[0] >= 0.5 else [0] for num in output]).to(device)
            correct += pred.eq(target.long()).sum().item()
        print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
            test_loss, correct, len(test_loader.dataset),
            100. * correct / len(test_loader.dataset)))

# 训练
for epoch in range(1, EPOCHS + 1):
    train(model, DEVICE, train_loader, optimizer, epoch)
    # test(model, DEVICE, test_loader)

 

版权声明:本文为pursuit_zhangyu原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/pursuit_zhangyu/article/details/95020567

智能推荐

pytorch自定义数据集

pytorch读取数据主要涉及到两个类:dataset和dataload,以读取图片为例子 dataset主要包括三个类: 首先初始化图片位置,一般写在初始化函数中 然后是根据图片位置去读取图片并返回读取的图片和标签: 最后返回数据集的长度,主要用于后续dataloader载入网络: 自定义数据集到这就初步完成了后续还有利用transform进行数据增强以及dataloader载入数据到网络中进行...

Pytorch自定义图片数据集

本篇博客旨在实现pytorch读取图片并自定义图片数据集 图像加载方法 主流的图像加载方法主要有三种 下表中xxx表示图片的路径 库 函数/方法 返回值 图像像素格式 像素值范围 图像矩阵表示 skimage io.imread(xxx) numpy.ndarray RGB [0, 255] (H X W X C) cv2 cv2.imread(xxx) numpy.ndarray BGR [0,...

使用Pytorch自定义数据集

使用Pytorch自定义数据集 参考:https://www.bilibili.com/video/BV1hE411t7RN?spm_id_from=333.999.0.0 蚂蚁蜜蜂/练手数据集:链接: https://pan.baidu.com/s/1jZoTmoFzaTLWh4lKBHVbEA 密码: 5suq Custom_dataset.py...

pytorch自定义数据集

在非练习的情况下,我们使用torch去做深度学习时首先面对的就是如何把未经处理的数据整合成torch能识别的tensor。为此,torch提供了抽象类Datasets。 要自定义数据集,首先要继承抽象类class torch.utils.data.Dataset,并且需要重载两个重要的函数:__len__ 和__getitem__,前者提供了数据集的大小,后者支持整数索引,范围从0到len(sel...

Pytorch自定义数据集 ImageNet

由于Pytorch不支持内置的ImageNet数据集,因此我们需要自定义数据集。有两种方式 1、使用ImageFolder ImageFolder需要数据集有良好的结构,train和test下分别包含相同类别的文件夹,每个文件夹存放一类图像,也就是这样 此时把.../ImageNet/train 或者 .../ImageNet/test/ 当作imagenet_root传入ImageFolder即...

猜你喜欢

Pytorch自定义数据集

自定义数据集的代码如下: 现在我们的自定义数据集即将做好了,然后使用dataloader模块打包数据集: 接下来就可以开始训练啦!!! train fuction的代码: test function的代码: 一共使用5个epoch。因此代码如下:...

PyTorch 入门:自定义数据加载

之前学习tensorflow时也学习了它的数据加载,不过在网上看了很多教程后还是有很多小问题,不知道为什么在别人电脑上可以运行但是我的就不行(把我头搞晕了),很烦,这时想起之前听导师说PyTorch容易入门上手,所以果断去学了PyTorch,写这篇博文的目的就是总结学到的,然后记录下来,也希望以后学到新的知识或技术能够用写博客的方式记录下来,这样有助于形成比较好的知识体系,也方便以后温故知新。 在...

pytorch自定义数据加载

实验环境:pytorch1.5 利用pytorch加载自定义数据集时,可利用pytorch自带的Dataset类进行。 只需要继承Dataset类,并实现其中的两个方法即可。 然后通过DataLoader类进行迭代即可。 DataLoader支持通过参数batch_size、drop_last和batch_sampler将单个获取的数据样本自动整理成批。 pytorch的自动微分: pytorch...

PyTorch 入门学习(六)————编写自定义数据集,数据加载器和转换

文章目录 编写自定义数据集,数据加载器和转换 一、使用ImageFolder数据集的格式时 1、只有train时的写法 2、有 train 和 val 时的写法 二、详细看看torchvision.datasets.ImageFolder这个类是怎么写的。 三、自定义自己的数据读取接口 编写自定义数据集,数据加载器和转换 解决任何机器学习问题都需要花费大量精力来准备数据。PyTorch提供了许多工...

TensorFlow&PyTorch加载自定义数据集并划分

PyTorch 导入需要的库 数据增强函数 导入数据并划分数据集 TensorFlow 导入需要的库 导入数据并划分数据集...