大家好,欢迎来到IT知识分享网。
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=True
和train=False
,分别加载了训练集和测试集。此外,所有图像数据在加载过程中都应用了两个转换操作,确保它们能以适当的格式供神经网络使用。 - 数据转换流程: 这里定义了一个转换流程,并且使用了
transforms.Compose
来组合两个主要的转换操作:
- ToTensor:此转换将图像数据从PIL格式或NumPy ndarray转换为FloatTensor格式,并自动将图像的像素值从[0, 255]缩放到[0.0, 1.0]的范围,这是为了适配PyTorch的处理方式。
- 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,以捕获更细致的特征。
- 第一层(Layer1):
- 全连接层:
- 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}%
。
- 计算并打印准确率:最后,计算准确率
6. 总结
这次实验通过构建和训练一个卷积神经网络模型,在Fashion-MNIST数据集上进行图像分类,取得了90.34%的正确率。证明了CNN的强大性能。下面是在此次实验中的个人感想(略)
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/151213.html