pytorch 猫狗数据集识别(一)

一 、猫狗数据集预处理

该项目从数据预处理–网络构建–训练–测试这几个部分讲解。读完该部分代码希望能对你有所帮助。 猫狗数据集下载地址链接:https://pan.baidu.com/s/1OBDj51wp0TMRZK_ve-n3fA
提取码:rift

1、数据预处理中加载的模块

import torch
import os
import numpy as np
from PIL import Image
from torch.utils.data import Dataset, DataLoader

2、数据预处理代码

class MyDataSet(Dataset):
    def __init__(self, path):
        """根据路径获得数据集"""
        self.path = path
        
        """读取路径下的所有文件"""
        self.dataset = os.listdir(self.path)
        
        # 均值和方差的求解过程下面会交代
        self.mean = [0.4878, 0.4545, 0.4168]
        self.std = [0.2623, 0.2555, 0.2577]

    def __len__(self):
        """获取数据集的长度"""
        return len(self.dataset)

    def __getitem__(self, index):
        """根据索引获得数据集"""
        # 获得数据的标签
        name = self.dataset[index]

        # 数据集的文件名为i.j.jpeg, 这个标签的第i个位置如果是0表示猫,1则表示狗,第j个位置是图片的个数
        name_list = name.split(".")
        target = int(name_list[0])
        
       # 这里需要注意,tensor(target) 和Tensor([target])的区别,否则在one-hot解码的时候会出现错误
        target = torch.tensor(target)

        """数据预处理"""
        # 打开图片
        img = Image.open(os.path.join(self.path, name))
       
        # 设置图片大小
        # img = np.resize(img, (3, 10, 10))
       
        # 归一化,先将图片转化为一个矩阵,然后除以255
        img = np.array(img) / 255

        # # 去均值
        img = (img - self.mean) / self.std

        # 换轴 H W C 转换为 C H W ,这里需要注意下,其实我们可以不这么处理,在前面设置图片大小的时候设置为3 * 100 * 100 的就可以。
        train_data = torch.tensor(img, dtype=torch.float32).permute(2, 0, 1)
        return train_data, target

3、 数据预处理中均值的求解步骤:

if __name__ == '__main__':
    """注意:求均值和标准差时,首先把上面去均值的那一行代码注释了"""
    dataset = MyDataSet(r'C:\Users\admin\Desktop\cat_dog\cat_dog\img')
    
    # 求均值,将DataLoader进行打包,这里batch_size的数量应该是训练图片的总数
    data_loader = DataLoader(dataset= dataset, batch_size=12000, shuffle=True)
    
    # 将data_loader作为一个迭代器进行运算,这里面包含了输入数据和标签,所以后面取第0个位置的数,也就是取输入数据
    data = next(iter(data_loader))[0]

    # 这里图片N(每批的数量) C(通道数) H(高)  W(宽) 几个维度,求的.0是通道层面的均值,所以dim=(0, 2, 3)
    mean = torch.mean(data, dim=(0, 2, 3))
    std = torch.std(data, dim=(0, 2, 3))

二、网络构建

import torch.nn as nn
class MyNetwork(nn.Module):
    def __init__(self):
        super(MyNetwork, self).__init__()
        
        """
        nn.Sequential:一个有序的容器,神经网络模块将按照在传入构造器的顺序依次被添加到计算图中执行
        
        """
        self.line = nn.Sequential(
            nn.Linear(in_features=3 * 100 * 100, out_features=512),
            nn.ReLU(),
            nn.Linear(in_features=512, out_features=256),
            nn.ReLU(),
            nn.Linear(in_features=256, out_features=128),
            nn.ReLU(),
            nn.Linear(in_features=128, out_features=256),
            nn.ReLU(),
            nn.Linear(in_features=256, out_features=512),
            nn.ReLU(),
            nn.Linear(in_features=512, out_features=256),
            nn.ReLU(),
            nn.Linear(in_features=256, out_features=2),
        )

    def forward(self, parse):
        data = torch.reshape(parse, shape=(-1, 3 * 100 * 100))
        return self.line(data)

三、模型的训练

class Train(object):
    def __init__(self, path):
        self.path = path
        self.test_dataset = MyDataSet(os.path.join(self.path, "test_img"))
        self.train_dataset = MyDataSet(os.path.join(self.path, "train_img"))
        self.criterion = torch.nn.MSELoss()
        self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
        self.net = MyNetwork().to(self.device)
        self.optimize = torch.optim.Adam(self.net.parameters())

    def dataLoader(self, batch):
        train_data_loader = DataLoader(dataset=self.train_dataset, batch_size=batch, shuffle=True)
        test_data_loader = DataLoader(dataset=self.test_dataset, batch_size=batch, shuffle=True)
        return train_data_loader, test_data_loader

    def trainNet(self, batch, epoch):
        train_data_loader, test_data_loader = self.dataLoader(batch)
        losses = []
        accuracy = []
        for i in range(epoch):
            for j, (Input, target) in enumerate(train_data_loader):
                Input = Input.to(self.device)
                out_put = self.net(Input)
                """
                one - hot 编码:
                torch.scatter(self, dim, index, value)
                该代码表示把value按照index根据dim的方向填入self中
                Example:
                    index = torch.tensor([0, 2, 4, 1])
                    src = torch.zeros(4, 5)
                    print(src.shape)
                    out = torch.scatter(src, dim=1, index=index.view(-1, 1), value=1)
                    print(out)
                
                """
                target = torch.zeros(target.size(0), 2).scatter_(1, target.view(-1, 1), 1).to(self.device)
                loss = self.criterion(out_put, target)
                losses.append(loss.item())
                
                """ 梯度清零"""
                self.optimize.zero_grad()
                loss.backward()
                self.optimize.step()
                if j % 5 == 0:
                    print("训练轮次:epoch{}/{},迭代次数:iteration{}/{}".format(i, epoch, j, len(train_data_loader)))
                    acc = torch.mean((out_put.argmax(1) == target.argmax(1)), dtype=torch.float32)
                    accuracy.append(acc.item())
                    print("训练准确率为:accuracy = %s , loss值为:%s" % (acc.item(), loss.item()))
                    plt.clf()
                    plt.ion()
                    """加载loss曲线"""
                    plt.subplot(2, 1, 1)
                    plt.tight_layout(2)
                    plt.plot(losses, label="loss")
                    plt.legend(loc='best')

                    """加载accuracy曲线"""
                    plt.subplot(2, 1, 2)
                   
                    """设置图像之间的距离"""
                    plt.tight_layout(2)
                    plt.plot(accuracy, label="accuracy")
                    """显示图例"""
                    plt.legend(loc='best')
                    plt.pause(0.2)
                    plt.show()
            torch.save(self.net, "model/net.pth")

四、模型的测试

  # 测试
  class Test(object):
    def __init__(self, path):
        self.path = path
        self.test_dataset = MyDataSet(os.path.join(self.path, "test_img"))
        self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    def Test(self, batch):
        train_data_loader, test_data_loader = self.dataLoader(batch)
        plt.ion()
        for k, (In, tgt) in enumerate(test_data_loader):
            print(k)
            In = In.to(self.device)
            """加载测试图片"""
            # 加载训练好的网络
            test_Net = torch.load('model/net.pth')
            
            # 这是可视化训练图片的第一步,进行反算(Input * 标准差+均值)*255
            # 这里输入In的维度是(batch, 3, 100, 100 ),std 和mean是矩阵,所以给它转换维度才能与输入做运算
            img = (In.cpu().data.numpy() * np.array(self.train_dataset.std).reshape(1, 3, 1, 1) + np.array(self.train_dataset.mean).reshape(1, 3, 1, 1)) * 255
            img = np.resize(img, (100, 100))

            """显示测试结果"""
            if 0 < k <= batch:
                plt.subplot(3, 2, k)
                plt.tight_layout(1)
                plt.imshow(img)
                predict = test_Net(In)
                # print("predict", torch.argmax((predict[k])).item())
                predict_result = "cat" if torch.argmax(predict[k-1]).item() == 0 else "dog"
                plt.title(predict_result)
                plt.axis('off')
                plt.pause(1)
                plt.show()
                plt.savefig("result.jpg")
            elif k == 0:
                continue
            else:
                print("图片测试完毕,请查看!")
                break

五、执行代码

if __name__ == '__main__':
    path = r"数据集路径"
    # 训练
    t = Train(path)
    
    # 测试
    # t.Test(batch=6)
Pytorch是一种流行的深度学习框架,可以使用它来识别。然而在使用Pytorch进行这个任务之前,需要了解识别数据集的格式要求。在本文中,我们将详细介绍这些要求。 首先,识别数据集应该包含两个子文件夹,一个是训练集(Training Set),一个是验证集(Validation Set)。其中,训练集文件夹应该包含所有用于模型训练的图像文件,而验证集文件夹应该包含用于模型验证的图像文件。这两个文件夹中的图像应该是随机分配的,不能出现任何重复。 其次,每个图像文件应该被命名为“类别.编号.jpg”,其中“类别”是的名字,编号是一个整数,用于标识不同的图像。例如,的图像文件名可以是“cat.1.jpg”,而的图像文件名可以是“dog.1.jpg”。 第三,为了使用Pytorch进行识别,需要添加一个数据增强(Data Augmentation)的组件,用于增加数据集的多样性。常见的数据增强方式包括随机旋转、水平或垂直翻转、随机裁剪和随机缩放等。 最后,识别数据集中的图像大小应该一致。Pytorch会自动对图像进行缩放以适应模型输入。因此,最好将所有图像缩放到相同的大小,例如224 x 224。这样可以确保图像的一致性,避免出现不必要的模型错误。 总之,Pytorch识别数据集的格式要求是十分严格的,需要遵循以上四个要求。其目的是为了确保数据集的质量和可用性,以实现准确的识别
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值