神经网络----猫狗识别

1、数据集的准备

自己制作数据集比较麻烦,这里我们直接去网上找就行了
百度网盘可以得到数据:
链接: https://pan.baidu.com/s/12e1UTyERkZ9eZt4I9W7ZaA
提取码: rt7g
里面包含了训练集和测试集,需要的自行去获取

2、对数据进行resize

这里就直接上代码了,resize比较简单
我们用PLIL创建一个画布,画布的大小实际上就是我们需要的尺寸大小,然后等比例缩放原图,把resize后的图像融合到画布,这样就得到了我们需要的相同尺寸的图像
具体代码如下:

from PIL import Image
import os

def resize_img(img_path):
    img = Image.open(img_path)
    img_w, img_h = img.size
    # 计算压缩比例:
    ratio = min(100/img_w, 100/img_h)
    new_w = int(img_w * ratio)
    new_h = int(img_h * ratio)
    # 等比例压缩图像
    resized_img = img.resize((new_w, new_h), Image.ANTIALIAS)
    # resized_img.show()
    # 创建一个画布
    canvas = Image.new('RGB', (100, 100), (255, 255, 255))
    # 在画布上居中放置压缩好的图像
    offset = ((100 - new_w) // 2, (100 - new_h) // 2)
    # 融合在一起
    canvas.paste(resized_img, offset)
    return canvas

if __name__ == '__main__':

    cat_root = r"原本猫的数据路径"
    dog_root = r"原本狗的数据路径"
    count = 1
    for path in os.listdir(cat_root):
    	# 图像的具体路径
        img_path = os.path.join(cat_root, path)
        img = resize_img(img_path)
        # 保存在我们当前项目的根目录下
        img.save(rf"data\test\0\{path}")

3、对神经网络的具体构建

这里是我们需要的包
代码:

import torch
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader
import os
import cv2
import numpy as np
import tqdm

在构建模型的时候,我们的神经网络是必不可少的,往往我们的神经网络的构建会决定后面模型的好坏程度,当然!不是全部原因
代码如下:

import torch
import torch.nn as nn
# 继承了nn.Module,这是构建PyTorch模型的基类
class Net_V1(nn.Module):
    def __init__(self):
        super().__init__()
        
        # 定义神经网络的层结构
        self.layer = nn.Sequential(
        	# in_features是输入特征数, out_features是输出特征数,
        	# 1 * 100 * 100 是我们图像的尺寸大小与通道数,后面的自行定义特征数,
        	# nn.LeakyRelu() 是我们的激活函数
            nn.Linear(in_features=1 * 100 * 100, out_features=1024), nn.LeakyReLU(),
            nn.Linear(in_features=1024, out_features=516), nn.LeakyReLU(),
            nn.Linear(in_features=516, out_features=256), nn.LeakyReLU(),
            nn.Linear(in_features=256, out_features=128), nn.LeakyReLU(),
            nn.Linear(in_features=128, out_features=128), nn.LeakyReLU(),
            nn.Linear(in_features=128, out_features=128), nn.LeakyReLU(),
            nn.Linear(in_features=128, out_features=128), nn.LeakyReLU(),
            nn.Linear(in_features=128, out_features=64), nn.LeakyReLU(),
            nn.Linear(in_features=64, out_features=32), nn.LeakyReLU(),
            nn.Linear(in_features=32, out_features=16), nn.LeakyReLU(),
            # 最后的输出必须与我们需要的类别数相同,即二分类我们就是2
            nn.Linear(in_features=16, out_features=2),  # 最后一层输出2个值
            nn.Sigmoid()  # 最后一层的激活函数使用 Sigmoid
        )

    def forward(self, x):
        # 前向传播函数,用于计算模型的输出
        return self.layer(x)

4、对数据集的处理

我们自定义数据集。需要继承torch.utils.data.Dataset
在这一步我们会对数据的完整路径进行获取,包括标签,还会定义一个获取每个数据的函数
代码部分:

class MNIST_Dataset(Dataset):
    def __init__(self, root, train=True):
        # 父类的构造函数先实现
        super().__init__()
        self.dataset = []
        # 判断是训练集还是测试集
        train_or_test = "train" if train else "test"
        path = f"{root}//{train_or_test}"
        for label in os.listdir(path):  # [0123456789]
            img_path = f"{path}//{label}"
            for img_name in os.listdir(img_path):
                # 图片完整路径
                img = f"{img_path}//{img_name}"
                # 图片路径,标签[01]
                self.dataset.append((img, label))

    def __len__(self):
        return len(self.dataset)
    # 获取数据集中的一条数据
    def __getitem__(self, index):
        data = self.dataset[index]
        img = cv2.imread(data[0], 0)
        # 对图像进行展平,因为我们的图像是HWC,而我们的神经网络是 NV
        img = img.reshape(-1)
        # 归一化
        img = img / 255
        # 标签[01]
        one_hot = np.zeros(2)
        # 对应的位置赋值为 1
        one_hot[int(data[1])] = 1
        return np.float32(img), np.float32(one_hot)


5、进行训练和测试的实现

定义一个训练类,在初始化的时候会准备许多东西,之后就是训练和测试的函数实现
代码如下:

class Trainer:
    # 初始化
    def __init__(self):
    	# 创建一个Net_V1的神经网络实例
        self.net = Net_V1()
        # 根据是否有可用的GPU,选择在cuda或cpu上运行
        self.device = "cuda" if torch.cuda.is_available() else "cpu"
        # 将网络模型移动到所选的设备(GPU或CPU)
        self.net.to(self.device)
        # 创建用于训练的MNIST数据集实例,指定数据集路径和训练标志为True
        self.train_dataset = MNIST_Dataset(r"D:\work\cat_dog\data", train=True)
        # 创建用于训练数据的数据加载器,设置批量大小为100,随机打乱数据
        self.train_loader = DataLoader(self.train_dataset, batch_size=100, shuffle=True)
        # 创建用于测试的MNIST数据集实例,指定数据集路径和训练标志为False
        self.test_dataset = MNIST_Dataset(r"D:\work\cat_dog\data", train=False)
        # 创建用于测试数据的数据加载器,设置批量大小为100,随机打乱数据
        self.test_loader = DataLoader(self.test_dataset, batch_size=100, shuffle=True)
        # 优化器: Adam,优化神经网络模型的参数
        self.opt = torch.optim.Adam(self.net.parameters())

    # 训练
    def train(self):
        # 1轮次:20000张
        for epoch in range(1, 20000):
            sum_loss = 0.0
            # 分批次batch_size训练
            # tqdm.tqdm() 这个是在循环中显示进度的
            # for i, (img, label) in enumerate(tqdm.tqdm(self.train_loader)):
            for i, (img, label) in enumerate(self.train_loader):
                # img.shape == 100, 784
                # 开启训练模式
                self.net.train()  # dropout()
                # GPU
                img, label = img.to(self.device), label.to(self.device)
                # 数据放入网络,前向计算,得到结果。
                out = self.net(img)
                # 标签与计算结果之间求损失
                # 均方差
                loss = torch.mean((label - out) ** 2)
                # 损失,优化器,反向跟新
                self.opt.zero_grad()  # 清空梯度
                loss.backward()  # 梯度跟新
                self.opt.step()
                sum_loss = sum_loss + loss.item()
                # 60000 100
            # 计算平均损失
            avg_loss = sum_loss / len(self.train_loader)
            print(f"第{epoch}轮的损失是{avg_loss}")
            # 保存结果:权重
            torch.save(self.net.state_dict(), f"params//{epoch}.pt")

    # 测试
    def test(self):
        # 10000 9800 98%
        # 加载权重测试
        # 循环自己保存的pt文件
        for j in range(30, 130):
            self.net.load_state_dict(torch.load(rf"params//{j}.pt"))
            for epoch in range(1, 2):
                sum_score = 0.0
                for i, (img, label) in enumerate(tqdm.tqdm(self.test_loader)):
                    # 测试模式 不执行dropout
                    self.net.eval()
                    img, label = img.to(self.device), label.to(self.device)
                    # img.shape == [100, 784]
                    out = self.net(img)
                    # out.shape == [100, 10]
                    # out和label作比较,最大值的索引,比较eq,int(),sum()
                    x = torch.argmax(out, dim=1)
                    y = torch.argmax(label, dim=1)
                    # 得分
                    score = torch.sum(torch.eq(x, y).float())
                    sum_score = sum_score + score.item()
                # 平均得分
                avg_score = sum_score / len(self.test_loader)
                print(f"第{j}轮的测试精度{avg_score}")

在主函数中进行对象实例化,并且调用我们的训练和测试

if __name__ == '__main__':
	# 创建对象
    trainer = Trainer()
    # trainer.train()
    trainer.test()

上面就是我们猫狗识别的基本流程:包含了全部的代码,需要的话,自己组合一下吧
感觉这个猫狗识别没什么太大的难度,也就没有详细的讲解其中的内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值