深度学习-第五周

BP实战猫狗分类数据集

1,准备和任务

                (1)下载猫狗图片

                https://www.microsoft.com/en-us/download/confirmation.aspx?id=54765

                 (2)准备好目录

                       

                  (3)测试读取,路径

                        

import numpy as np
import torch
# 数据准备
# 由于下载的图片大小不一,需要统一大小为 224 * 224
from PIL import Image
import os
#尝试读取(绝对路径)
img = Image.open("D:\\pytorch\\pytorch_study\\第五周\\train\\cat\\0.jpg")  # " \ "要双
print(img)
print(type(img))
# img.show()

#图像类型转为numpy类型
num_img = np.asarray( img )
print(num_img)
print(num_img.shape) # 375(gao) * 500(kuan)  3:通道
print(type(num_img))

# 模型里面不认字符,因此需要把标签改成数字
cls = "cat"
if cls == "cat":
    label = 0
else
    label = 1

运行结果

         

2,实战

        1数据的准备:

        

class mydataset(Dataset):
    def __init__(self, data_root, data_label):
        self.data_root = data_root  # 路径
        self.data_label = data_label  # 标签
        self.path = os.path.join(data_root, data_label)  # 把路径和标签联系起来
        self.img_path = os.listdir(self.path)  # 转为列表类型
        self.transform = transforms.Compose([
            transforms.Resize((224, 224)),  # 变大小
            transforms.ToTensor()
        ])
        # img转为tensor类型

    def __getitem__(self, item):
        img_name = self.img_path[item]  # 第item个图像
        img_item_path = os.path.join(self.path, img_name)  # 图像路径
        img = Image.open(img_item_path)
        img = self.transform(img)

        if self.data_label == "cat":
            label = 1
        else:
            label = 0
        return img, label

    def __len__(self):
        lenth = len(self.img_path)
        return lenth

  

  • 定义了mydataset类继承自Dataset---用于处理和加载图像数据。
  • 这个类将图像转换为224x224像素大小,然后转换为PyTorch的Tensor格式。
  • 数据集被分为catdog

         2构建BP模型:

class BPnetwork(torch.nn.Module):
    def __init__(self):
        super(BPnetwork, self).__init__()
        self.linear1 = torch.nn.Linear(224 * 224 * 3, 128)
        self.ReLU1 = torch.nn.ReLU()

        self.linear2 = torch.nn.Linear(128, 64)
        self.ReLU2 = torch.nn.ReLU()

        self.linear3 = torch.nn.Linear(64, 32)
        self.ReLU3 = torch.nn.ReLU()

        self.linear4 = torch.nn.Linear(32, 10)
        self.ReLU4 = torch.nn.ReLU()

        self.linear5 = torch.nn.Linear(10, 2)
        self.softmax = torch.nn.LogSoftmax(dim=1)
  • 输入层接收224x224x3的图像像素值(RGB),经过多个全连接层(linear1linear5)和ReLU激活函数,最后通过Softmax函数输出两个类别的预测概率。

         3数据加载:

trainloader = torch.utils.data.DataLoader(train_dataset, batch_size=16, shuffle=True)
testloader = torch.utils.data.DataLoader(test_dataset, batch_size=16, shuffle=True)

Batch Size(批大小)是机器学习和深度学习中的一个重要超参数,它指的是在每次迭代(iteration)中用于训练模型的样本集合的大小。在训练过程中,模型不会一次性处理整个数据集,而是分成若干个批次(batch)进行学习,每个批次包含特定数量的样本。Batch Size的选择直接影响到模型的训练速度、内存使用、梯度估计的准确性以及最终的模型性能 

  • 使用DataLoadertrain_datasettest_dataset加载数据,设置batch_size为16。

        4模型训练

model = BPnetwork()
criterion = torch.nn.NLLLoss()  # loss函数
optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)  # 优化器

eopchs = 35
for i in range(eopchs):
    sumloss = 0
    # print(1)
    for images, lables in trainloader:
        # 前向传播-预测值
        # print(1)
        ypre = model(images)
        # 计算loss
        loss = criterion(ypre, lables)
        # 反向传播
        loss.backward()
        # 更新权重
        optimizer.step()

        optimizer.zero_grad()
        # 损失累加
        sumloss += loss.item()
    print("Epoch {}, Loss: {}".format(i + 1, sumloss / len(trainloader)))
  • 损失函数(NLLLoss)。NLLLoss 的计算等价于计算交叉熵损失,但不包括 Softmax 层,因此在使用 NLLLoss 时,需要确保输入是经过 Softmax 处理的
  • 优化器SGD。PyTorch中实现随机梯度下降(SGD)优化算法的类,根据损失函数相对于模型参数的梯度来更新这些参数,model.parameters:这是一个迭代器,包含模型中所有需要训练的参数。momentum:动量(Momentum)因子,用于加速梯度下降并减少震荡。动量通过累积梯度信息来更新参数,类似于物理中的动量效应。
  • 35个周期(eopchs)训练模型,每轮遍历所有训练数据,计算loss,进行反向传播和权重更新,损失累加。

        5模型测试 :

examples = enumerate(testloader)
batch, (images, lables) = next(examples)

fig = plt.figure()
for i in range(16):
    t = torch.unsqueeze(images[i], dim=0)  # 增加一个维度,使t的形状与模型期望的形状相匹配
    logps = model(t)

    probab = list(logps.detach().numpy()[0])  # logps.detach()从计算图中分离出logps,确保后续的操作不会影响到模型的梯度。
    pred_label = probab.index(max(probab))

    if pred_label == 1:
        label = "猫"
    else:
        label = "狗"
        # 接着,.numpy()将张量转换为NumPy数组。[0]取出第一个元素(因为t是一个批次大小为1的数据),
        # 最后list()将这个元素转换为一个列表。此时,probab是一个包含所有类别概率的列表。
        # 找出probab列表中概率最大的元素的索引,这个索引即代表模型预测的类别标签。
    img = torch.squeeze(images[i])  # 移除大小为1的维度,让它回到原来的形状
    img1 = img.permute(1, 2, 0)  # 将图像的维度从(channels, height, width)调整为(height, width, channels)
    img1 = img1.numpy()

    plt.subplot(4, 4, i + 1)  # 创建一个2*2的子图网格,并选择第i+1个子图作为当前绘图区域
    plt.tight_layout()  # 自动调整子图参数,使之填充整个图像区域并尽量减少重叠
    plt.imshow(img1, cmap='gray', interpolation='none')
    plt.title(f"预测值:{label}")
    plt.xticks([])  # 设置x轴和y轴的刻度标签为空
    plt.yticks([])
plt.show()
  • 通过testloader取出一个批次的数据,对图像预测,展示预测结果。返回数据集中的样本和标签
  • enumerate函数来迭代testloader数据加载器。返回的每个元素是一个元组,包含当前样本的索引和样本本身
  • next函数来获取examples迭代器的下一个元素。元组,包含索引和数据。在这个元组中,batch变量接收索引值,而(images, labels)变量接收数据和标签。imageslabels分别代表当前批次的输入图像和标签
  • 使用matplotlib库可视化测试图像的预测结果,显示其预测类别(猫或狗)。

完整代码:

import numpy as np
import torch
# 数据准备
# 由于下载的图片大小不一,需要统一大小为 224 * 224
from PIL import Image
import os
from torch.utils.data import Dataset
from torchvision.transforms import transforms
from matplotlib import pyplot as plt
import matplotlib

matplotlib.rcParams['font.sans-serif'] = ['KaiTi']


# 构造
class mydataset(Dataset):
    def __init__(self, data_root, data_label):
        self.data_root = data_root  # 路径
        self.data_label = data_label  # 标签
        self.path = os.path.join(data_root, data_label)  # 把路径和标签联系起来
        self.img_path = os.listdir(self.path)  # 转为列表类型
        self.transform = transforms.Compose([
            transforms.Resize((224, 224)),  # 变大小
            transforms.ToTensor()
        ])
        # img转为tensor类型

    def __getitem__(self, item):
        img_name = self.img_path[item]  # 第item个图像
        img_item_path = os.path.join(self.path, img_name)  # 图像路径
        img = Image.open(img_item_path)
        img = self.transform(img)

        if self.data_label == "cat":
            label = 1
        else:
            label = 0
        return img, label

    def __len__(self):
        lenth = len(self.img_path)
        return lenth


# 2,构建BP模型
class BPnetwork(torch.nn.Module):
    def __init__(self):
        super(BPnetwork, self).__init__()
        self.linear1 = torch.nn.Linear(224 * 224 * 3, 128)
        self.ReLU1 = torch.nn.ReLU()

        self.linear2 = torch.nn.Linear(128, 64)
        self.ReLU2 = torch.nn.ReLU()

        self.linear3 = torch.nn.Linear(64, 32)
        self.ReLU3 = torch.nn.ReLU()

        self.linear4 = torch.nn.Linear(32, 10)
        self.ReLU4 = torch.nn.ReLU()

        self.linear5 = torch.nn.Linear(10, 2)
        self.softmax = torch.nn.LogSoftmax(dim=1)

    def forward(self, x):
        x = x.reshape(x.shape[0], -1)
        x = self.linear1(x)
        x = self.ReLU1(x)
        x = self.linear2(x)
        x = self.ReLU2(x)
        x = self.linear3(x)
        x = self.ReLU3(x)
        x = self.linear4(x)
        x = self.ReLU4(x)
        x = self.linear5(x)
        x = self.softmax(x)
        return x


data_root = "第五周/train"
test_dir = "第五周/train"

data_label_cat = "cat"
data_label_dog = "dog"

catdataset = mydataset(data_root, data_label_cat)
dogdataset = mydataset(data_root, data_label_dog)
train_dataset = catdataset + dogdataset

cat_test = mydataset(test_dir, data_label_cat)
dog_test = mydataset(test_dir, data_label_dog)
test_dataset = cat_test + dog_test

# 数据加载器
trainloader = torch.utils.data.DataLoader(train_dataset, batch_size=16, shuffle=True)
testloader = torch.utils.data.DataLoader(test_dataset, batch_size=16, shuffle=True)

# 训练模型
model = BPnetwork()
criterion = torch.nn.NLLLoss()  # loss函数
optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)  # 优化器

eopchs = 35
for i in range(eopchs):
    sumloss = 0
    # print(1)
    for images, lables in trainloader:
        # 前向传播-预测值
        # print(1)
        ypre = model(images)
        # 计算loss
        loss = criterion(ypre, lables)
        # 反向传播
        loss.backward()
        # 更新权重
        optimizer.step()

        optimizer.zero_grad()
        # 损失累加
        sumloss += loss.item()
    print("Epoch {}, Loss: {}".format(i + 1, sumloss / len(trainloader)))

# 测试模型
print(1)
examples = enumerate(testloader)
batch, (images, lables) = next(examples)

fig = plt.figure()
for i in range(16):
    t = torch.unsqueeze(images[i], dim=0)  # 增加一个维度,使t的形状与模型期望的形状相匹配
    logps = model(t)

    probab = list(logps.detach().numpy()[0])  # logps.detach()从计算图中分离出logps,确保后续的操作不会影响到模型的梯度。
    pred_label = probab.index(max(probab))

    if pred_label == 1:
        label = "猫"
    else:
        label = "狗"
        # 接着,.numpy()将张量转换为NumPy数组。[0]取出第一个元素(因为t是一个批次大小为1的数据),
        # 最后list()将这个元素转换为一个列表。此时,probab是一个包含所有类别概率的列表。
        # 找出probab列表中概率最大的元素的索引,这个索引即代表模型预测的类别标签。
    img = torch.squeeze(images[i])  # 移除大小为1的维度,让它回到原来的形状
    img1 = img.permute(1, 2, 0)  # 将图像的维度从(channels, height, width)调整为(height, width, channels)
    img1 = img1.numpy()

    plt.subplot(4, 4, i + 1)  # 创建一个2*2的子图网格,并选择第i+1个子图作为当前绘图区域
    plt.tight_layout()  # 自动调整子图参数,使之填充整个图像区域并尽量减少重叠
    plt.imshow(img1, cmap='gray', interpolation='none')
    plt.title(f"预测值:{label}")
    plt.xticks([])  # 设置x轴和y轴的刻度标签为空
    plt.yticks([])
plt.show()

运行结果:

 

  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值