CNN训练前的准备:pytorch处理自己的图像数据(Dataset和Dataloader)

CNN训练前的准备:pytorch处理自己的图像数据(Dataset和Dataloader)pytorch的torchvision给我们提供了很多已经封装好的数据集,但是我们经常得使用自己找到的数据集,因此,想要得到一个好的训练结果,合理的数据处理是必不可少的。

大家好,又见面了,我是你们的朋友全栈君。

链接:cnn-dogs-vs-cats

  pytorch给我们提供了很多已经封装好的数据集,但是我们经常得使用自己找到的数据集,因此,想要得到一个好的训练结果,合理的数据处理是必不可少的。我们以1400张猫狗图片来进行分析。

  1. 分析数据:
    在这里插入图片描述
    在这里插入图片描述

训练集包含500张狗的图片以及500张猫的图片,测试接包含200张狗的图片以及200张猫的图片。

  1. 数据预处理:得到一个包含所有图片文件名(包含路径)和标签(狗1猫0)的列表:
def init_process(path, lens):
    data = []
    name = find_label(path)
    for i in range(lens[0], lens[1]):
        data.append([path % i, name])
        
    return data

  现有数据的命名都是有序号的,训练集中数据编号为0-499,测试集中编号为1000-1200,因此我们可以根据这个规律来读取文件名,比如参数传入:

path1 = 'cnn_data/data/training_data/cats/cat.%d.jpg'
data1 = init_process(path1, [0, 500])

data1就是一个包含五百个文件名以及标签的列表。find_label来判断标签是dog还是cat:

def find_label(str):
    first, last = 0, 0
    for i in range(len(str) - 1, -1, -1):
        if str[i] == '%' and str[i - 1] == '.':
            last = i - 1
        if (str[i] == 'c' or str[i] == 'd') and str[i - 1] == '/':
            first = i
            break

    name = str[first:last]
    if name == 'dog':
        return 1
    else:
        return 0

dog返回1,cat返回0。
  有了上面两个函数之后,我们经过四次操作,就可以得到四个列表:

path1 = 'cnn_data/data/training_data/cats/cat.%d.jpg'
data1 = init_process(path1, [0, 500])
path2 = 'cnn_data/data/training_data/dogs/dog.%d.jpg'
data2 = init_process(path2, [0, 500])
path3 = 'cnn_data/data/testing_data/cats/cat.%d.jpg'
data3 = init_process(path3, [1000, 1200])
path4 = 'cnn_data/data/testing_data/dogs/dog.%d.jpg'
data4 = init_process(path4, [1000, 1200])

随便输出一个列表的前五个:

[['cnn_data/data/testing_data/dogs/dog.1000.jpg', 1], ['cnn_data/data/testing_data/dogs/dog.1001.jpg', 1], ['cnn_data/data/testing_data/dogs/dog.1002.jpg', 1], ['cnn_data/data/testing_data/dogs/dog.1003.jpg', 1], ['cnn_data/data/testing_data/dogs/dog.1004.jpg', 1]]
  1. 利用PIL包的Image处理图片:
def Myloader(path):
    return Image.open(path).convert('RGB')
  1. 重写pytorch的Dataset类:
class MyDataset(Dataset):
    def __init__(self, data, transform, loder):
        self.data = data
        self.transform = transform
        self.loader = loder
    def __getitem__(self, item):
        img, label = self.data[item]
        img = self.loader(img)
        img = self.transform(img)
        return img, label

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

里面有2个比较重要的函数:

  • __getitem__是真正读取数据的地方,迭代器通过索引来读取数据集中数据,因此只需要这一个方法中加入读取数据的相关功能即可。在这个函数里面,我们对第二步处理得到的列表进行索引,接着利用第三步定义的Myloader来对每一个路径进行处理,最后利用pytorch的transforms对RGB数据进行处理,将其变成Tensor数据。
    transform为:
transform = transforms.Compose([
        transforms.CenterCrop(224),
        transforms.Resize((224, 224)),
        transforms.ToTensor(),
        transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5))  # 归一化
    ])

对上面四个操作做一些解释:
1)、transforms.CenterCrop(224),从图像中心开始裁剪图像,224为裁剪大小
2)、transforms.Resize((224, 224)),重新定义图像大小
3)、 transforms.ToTensor(),很重要的一步,将图像数据转为Tensor
4)、transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5)),归一化

  • __len__中提供迭代器索引的范围。

因此我们只需要:

train_data = data1 + data2 + data3[0:150] + data4[0:150]
train = MyDataset(train_data, transform=transform, loder=Myloader)
test_data = data3[150:200] + data4[150:200]
test= MyDataset(test_data, transform=transform, loder=Myloader)

就可以得到处理好的Dataset,其中训练集我给了1300张图片,测试集只给了100张。

  1. 通过pytorch的DataLoader对第四步得到的Dataset进行shuffle以及mini-batch操作,分成一个个小的数据集:
train_data = DataLoader(dataset=train, batch_size=5, shuffle=True, num_workers=0, pin_memory=True)
test_data = DataLoader(dataset=test, batch_size=1, shuffle=True, num_workers=0, pin_memory=True)

最后我们只要给定义好的神经网络模型喂数据就OK了!!!
完整代码:

# -*- coding: utf-8 -*-
""" @Time : 2020/8/18 9:11 @Author :KI @File :CNN.py @Motto:Hungry And Humble """
import torch
from torch import optim
import torch.nn as nn
from torch.autograd import Variable
from torchvision import transforms
from torch.utils.data import Dataset, DataLoader
from PIL import Image

def Myloader(path):
    return Image.open(path).convert('RGB')

#得到一个包含路径与标签的列表
def init_process(path, lens):
    data = []
    name = find_label(path)
    for i in range(lens[0], lens[1]):
        data.append([path % i, name])

    return data

class MyDataset(Dataset):
    def __init__(self, data, transform, loder):
        self.data = data
        self.transform = transform
        self.loader = loder
    def __getitem__(self, item):
        img, label = self.data[item]
        img = self.loader(img)
        img = self.transform(img)
        return img, label

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


def find_label(str):
    first, last = 0, 0
    for i in range(len(str) - 1, -1, -1):
        if str[i] == '%' and str[i - 1] == '.':
            last = i - 1
        if (str[i] == 'c' or str[i] == 'd') and str[i - 1] == '/':
            first = i
            break

    name = str[first:last]
    if name == 'dog':
        return 1
    else:
        return 0

def load_data():
    transform = transforms.Compose([
        #transforms.RandomHorizontalFlip(p=0.5),
        #transforms.RandomVerticalFlip(p=0.5),
        transforms.CenterCrop(224),
        transforms.Resize((224, 224)),
        transforms.ToTensor(),
        transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5))  # 归一化
    ])
    path1 = 'cnn_data/data/training_data/cats/cat.%d.jpg'
    data1 = init_process(path1, [0, 500])
    path2 = 'cnn_data/data/training_data/dogs/dog.%d.jpg'
    data2 = init_process(path2, [0, 500])
    path3 = 'cnn_data/data/testing_data/cats/cat.%d.jpg'
    data3 = init_process(path3, [1000, 1200])
    path4 = 'cnn_data/data/testing_data/dogs/dog.%d.jpg'
    data4 = init_process(path4, [1000, 1200])

    train_data = data1 + data2 + data3[0:150] + data4[0:150]

    train = MyDataset(train_data, transform=transform, loder=Myloader)

    test_data = data3[150:200] + data4[150:200]
    test= MyDataset(test_data, transform=transform, loder=Myloader)

    train_data = DataLoader(dataset=train, batch_size=5, shuffle=True, num_workers=0, pin_memory=True)
    test_data = DataLoader(dataset=test, batch_size=1, shuffle=True, num_workers=0, pin_memory=True)

    return train_data, test_data

train_data以及test_data就是我们最终需要得到的数据。

对猫狗数据分类的具体实现请见:CNN简单实战:pytorch搭建CNN对猫狗图片进行分类

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/130066.html原文链接:https://javaforall.net

(0)
上一篇 2022年4月27日 下午4:20
下一篇 2022年4月27日 下午4:40


相关推荐

  • mysql长轮询_ajax的轮询和长轮询

    mysql长轮询_ajax的轮询和长轮询概念:轮询(polling):客户端按规定时间定时像服务端发送ajax请求,服务器接到请求后马上返回响应信息并关闭连接。概念总是枯燥的,只有代码方能解心头之快前段代码:index.html:vargetting={url:’server.php’,dataType:’json’,success:function(res){console.log(res);}};//关键在这里,Ajax定时…

    2022年10月9日
    3
  • eclipse Maven配置[通俗易懂]

    eclipse Maven配置[通俗易懂]简述:现需要在Eclipse中配置Maven插件,同时安装maven应用,配置Maven环境变量,建立Maven管理的工程,并用Maven导入Gson包,编写简易Json输出程序步骤:1.首先到EclipseMarketplace中下载MavenIntegrationforEclipseWTP,如下,之后查看是否成功下载,Win

    2022年5月17日
    38
  • rider 激活 csdn【中文破解版】

    (rider 激活 csdn)2021最新分享一个能用的的激活码出来,希望能帮到需要激活的朋友。目前这个是能用的,但是用的人多了之后也会失效,会不定时更新的,大家持续关注此网站~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月30日
    66
  • Qt 垂直布局 (QVBoxLayout)

    Qt 垂直布局 (QVBoxLayout)Qt垂直布局(QVBoxLayout)上一节说了水平布局:https://blog.csdn.net/weixin_42837024/article/details/82114258QVBoxLayout:在垂直的方向上排列控件上下排列QVBoxLayout*pLayout=newQVBoxLayout();//水平布局QPushButton*p…

    2022年6月15日
    35
  • 超强汇总!110 道 Python 面试笔试题

    超强汇总!110 道 Python 面试笔试题

    2021年11月5日
    41
  • navicat 激活码【2021免费激活】

    (navicat 激活码)这是一篇idea技术相关文章,由全栈君为大家提供,主要知识点是关于2021JetBrains全家桶永久激活码的内容IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.htmlS32PGH0SQB-eyJsa…

    2022年3月26日
    97

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号