XDU深度学习Fashion-MNIST(包含python源码)

1. 题目要求&目的

本次实验的主要目的是巩固和应用卷积神经网络(CNN)的理论知识。通过编写代码实现这一深度学习模型,旨在达到理论与实践相结合的“知行合一”的学习效果。此外,实验还旨在加深对神经网络在图像识别任务中应用的理解。

1.1 实验目标

  • 数据集:使用公认的Fashion-MNIST数据集进行实验。
  • 任务描述:在Fashion-MNIST数据集上,利用卷积神经网络对10种不同类别的服装图像进行分类。
  • 性能目标:实现的模型需达到至少90%的分类正确率

2. 数据预处理

在此部分主要完成了对数据的导入以及标准化等处理,在此次实验中使用了Pytorch框架进行实验。下面是此部分的对应代码:

transform = transforms.Compose([  
    transforms.ToTensor(),  
    transforms.Normalize((0.5,), (0.5,))  
])  
  
train_dataset = datasets.FashionMNIST(root='./data', train=True, download=True, transform=transform)  
test_dataset = datasets.FashionMNIST(root='./data', train=False, download=True, transform=transform)  
  
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)  
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)
  • 数据加载与转换: 首先,使用了torchvision库中的datasets模块来加载Fashion-MNIST数据集。通过设置train=Truetrain=False,分别加载了训练集和测试集。此外,所有图像数据在加载过程中都应用了两个转换操作,确保它们能以适当的格式供神经网络使用。

  • 数据转换流程: 这里定义了一个转换流程,并且使用了transforms.Compose来组合两个主要的转换操作:

  1. ToTensor:此转换将图像数据从PIL格式或NumPy ndarray转换为FloatTensor格式,并自动将图像的像素值从[0, 255]缩放到[0.0, 1.0]的范围,这是为了适配PyTorch的处理方式。
  2. Normalize:我们对数据进行了标准化处理,设置均值为0.5和标准差为0.5。这个操作进一步将像素值从[0.0, 1.0]转换到[-1.0, 1.0],有助于模型训练时的数值稳定性和收敛速度。
  • 数据加载器: 使用DataLoader来封装数据集,这样可以更方便的批量处理图像数据,还可以随机打乱训练数据(通过shuffle=True),以避免模型过拟合。训练集和测试集的批处理大小均设置为64,这意味着每次迭代训练和评估模型时,网络将接收64张图像。

3. 模型设计

此部分为模型的搭建,主要还是使用了pytorch中的一些内置函数以及父类,具体的代码为:

class FashionCNN(nn.Module):  
    def __init__(self):  
        super(FashionCNN, self).__init__()  
        self.layer1 = nn.Sequential(  
            nn.Conv2d(1, 32, kernel_size=3, padding=1),  
            nn.BatchNorm2d(32),  
            nn.ReLU(),  
            nn.MaxPool2d(kernel_size=2, stride=2)  
        )  
        self.layer2 = nn.Sequential(  
            nn.Conv2d(32, 64, kernel_size=3, padding=1),  
            nn.BatchNorm2d(64),  
            nn.ReLU(),  
            nn.MaxPool2d(kernel_size=2, stride=2)  
        )  
        self.fc1 = nn.Linear(64 * 7 * 7, 1000)  
        self.drop = nn.Dropout2d(0.25)  
        self.fc2 = nn.Linear(1000, 10)  
  
    def forward(self, x):  
        out = self.layer1(x)  
        out = self.layer2(out)  
        out = out.view(out.size(0), -1)  # Flatten the output  
        out = self.fc1(out)  
        out = self.drop(out)  
        out = self.fc2(out)  
        return out

如上述代码可以发现,我在此次实验中一共为网络定义了几个模块,他们具体解释以及作用为:

  • 卷积层:
    模型包含两个卷积层序列,每个序列中都包含卷积层、批量归一化层、ReLU激活函数和最大池化层,具体配置如下:

    • 第一层(Layer1)
      • 卷积层:使用nn.Conv2d,配置为接收1个通道的输入(单色图像),输出32个通道,核大小为3,边缘填充为1。
      • 批量归一化:对32个输出通道进行归一化,以加速训练过程并提高模型稳定性。
      • ReLU激活函数:增加非线性处理,有助于捕捉复杂特征。
      • 最大池化层:使用nn.MaxPool2d,核大小为2,步幅为2,用于降低特征维度并提取主要特征。
    • 第二层(Layer2)
      • 类似于第一层,但是此层的卷积层输出通道增加到64,以捕获更细致的特征。
  • 全连接层:

    • Flatten操作:在传递给全连接层之前,将特征图展平成一维向量。
    • 第一个全连接层(fc1):将展平的特征连接到1000个神经元,这一层大幅增加模型的学习能力。
    • Dropout层:采用25%的丢弃率,用于减少过拟合,增强模型的泛化能力。
    • 第二个全连接层(fc2):最终的输出层,将1000个神经元连接到10个输出类别,对应于Fashion-MNIST的10种服装类别。
  • 模型输出:
    模型的最终输出是一个10维向量,每个维度对应一个服装类别的预测概率。

值得一提的是如何计算卷积后图像输出形状,它的公式为:
W out  = ⌊ W in  − F + 2 P S ⌋ + 1 H out  = ⌊ H in  − F + 2 P S ⌋ + 1 \begin{aligned} & W_{\text {out }}=\left\lfloor\frac{W_{\text {in }}-F+2 P}{S}\right\rfloor+1 \\ & H_{\text {out }}=\left\lfloor\frac{H_{\text {in }}-F+2 P}{S}\right\rfloor+1 \end{aligned} Wout =SWin F+2P+1Hout =SHin F+2P+1

这些模块一同构成下图所示的模型网络结构:
在这里插入图片描述

model = FashionCNN()  
criterion = nn.CrossEntropyLoss()  
optimizer = optim.Adam(model.parameters(), lr=0.001)

模型实例化,并使用pytorch库中的交叉熵损失作为损失函数,优化器采用Adam。

4. 模型训练

def train_model(num_epochs):  
    model.train()  
    for epoch in range(num_epochs):  
        for images, labels in train_loader:  
            optimizer.zero_grad()  
            outputs = model(images)  
            loss = criterion(outputs, labels)  
            loss.backward()  
            optimizer.step()  
        print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')  
  
train_model(50)
  • 初始化训练

    • 模型状态:首先,通过调用model.train()确保模型处于训练模式。
  • 训练循环
    训练过程包括多个周期(epoch),每个周期都会处理整个训练集一次。本次实验中,设置训练周期为50次。具体步骤如下:

  • 循环每一个周期:使用for epoch in range(num_epochs):来迭代指定次数。

    • 数据加载:通过train_loader加载批次数据,每个批次包含图像及其对应的标签。

    • 梯度初始化:在每次批处理前,使用optimizer.zero_grad()清除旧的梯度信息,防止梯度累积影响当前批次的更新。

    • 前向传播:将图像数据images输入模型,计算预测输出outputs

    • 计算损失:使用损失函数criterion(outputs, labels)计算预测输出与实际标签之间的差异。

    • 反向传播:调用loss.backward()对模型参数进行梯度计算。

    • 参数更新:执行optimizer.step()根据计算得到的梯度更新模型参数。

  • 监控训练进度

    • 打印损失:在每个训练周期结束时,输出当前周期的损失值。

5. 模型评估和结果

def evaluate_model():  
    model.eval()  
    total = 0  
    correct = 0  
    with torch.no_grad():  
        for images, labels in test_loader:  
            outputs = model(images)  
            _, predicted = torch.max(outputs.data, 1)  
            total += labels.size(0)  
            correct += (predicted == labels).sum().item()  
    accuracy = 100 * correct / total  
    print(f'Accuracy: {accuracy:.2f}%')  
  
evaluate_model()
  • 模型评估设置

    • 评估模式:首先,通过调用model.eval()将模型设置为评估模式。这是必要的步骤,因为某些网络层(例如Dropout和BatchNorm)在训练和评估时的行为是不同的。评估模式下,这些层会表现出与训练时不同的特性,例如不再随机丢弃神经元。

    • 禁用梯度计算:使用torch.no_grad()环境,确保在评估过程中不会计算梯度。

  • 性能计算

    • 测试数据遍历:通过test_loader逐批加载测试数据集的图像和标签。对每批数据执行以下步骤:

      • 模型预测:将图像输入模型,获取输出结果outputs

      • 确定预测类别:使用torch.max(outputs.data, 1)提取每个图像的预测类别。这个函数返回每行(每个图像)最大值的索引,即模型认为最可能的类别。

    • 统计正确预测:累计测试集中总图像数total和正确预测的图像数correct。比较预测类别predicted与真实标签labels,通过(predicted == labels).sum().item()计算匹配的数量。

  • 计算准确率

    • 计算并打印准确率:最后,计算准确率accuracy = 100 * correct / total,将正确预测的比例转换为百分比形式,并打印结果,如Accuracy: {accuracy:.2f}%

(这里图片之前在本地的markdown里写了不小心删了,但这是没调任何参的第一次运行结果,调好了会再高可能1%)
达到90.34%的正确率,完成了既定的任务。

6. 总结

这次实验通过构建和训练一个卷积神经网络模型,在Fashion-MNIST数据集上进行图像分类,取得了90.34%的正确率。证明了CNN的强大性能。下面是在此次实验中的个人感想(略)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

End!ess

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值