的研究详情)
目录1. 研究目的2. 研究准备3. 研究内容3.1 多层感知机模型选择、欠拟合和过拟合3.2 练习4. 研究体会1. 研究目的理解块的网络结构比较块的网络与传统浅层网络的性能差异探究块的网络深度与性能之间的关系研究块的网络在不同任务上的适用性。2. 研究准备根据GPU安装对应版本的PyTorch以实现GPU加速运行研究代码配置环境用于运行Python、Jupyter Notebook及相关库。3. 研究内容启动Jupyter Notebook使用新增的PyTorch环境新建ipynb文件。为检查环境配置是否合理输入import torch及torch.cuda.is_available()。若返回True则说明研究环境配置正确若返回False但能正确导入torch则说明PyTorch配置成功但研究运行在CPU上进行。结果如下3.1使用块的网络VGG1使用Jupyter Notebook新增的PyTorch环境新建ipynb文件完成基本数据操作的研究代码与练习结果如下VGG块import torch from torch import nn from d2l import torch as d2l def vgg_block(num_convs, in_channels, out_channels): layers [] for _ in range(num_convs): layers.append(nn.Conv2d(in_channels, out_channels, kernel_size3, padding1)) layers.append(nn.ReLU()) in_channels out_channels layers.append(nn.MaxPool2d(kernel_size2,stride2)) return nn.Sequential(*layers)VGG网络conv_arch ((1, 64), (1, 128), (2, 256), (2, 512), (2, 512)) def vgg(conv_arch): conv_blks [] in_channels 1 # 卷积层部分 for (num_convs, out_channels) in conv_arch: conv_blks.append(vgg_block(num_convs, in_channels, out_channels)) in_channels out_channels return nn.Sequential( *conv_blks, nn.Flatten(), # 全连接层部分 nn.Linear(out_channels * 7 * 7, 4096), nn.ReLU(), nn.Dropout(0.5), nn.Linear(4096, 4096), nn.ReLU(), nn.Dropout(0.5), nn.Linear(4096, 10)) net vgg(conv_arch) X torch.randn(size(1, 1, 224, 224)) for blk in net: X blk(X) print(blk.class.name,output shape:\t,X.shape)训练模型ratio 4 small_conv_arch [(pair[0], pair[1] // ratio) for pair in conv_arch] net vgg(small_conv_arch) lr, num_epochs, batch_size 0.05, 10, 128 train_iter, test_iter d2l.load_data_fashion_mnist(batch_size, resize224) d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())3.2练习1.打印层的尺寸时我们只看到8个结果而不是11个结果。剩余的3层信息去哪了在VGG网络中最后三个全连接层nn.Linear的输出尺寸没有被打印出来。这是因为在for循环中只遍历了卷积层部分的模块而没有遍历全连接层部分的模块。为了打印出全连接层的输出尺寸可以将全连接层的模块添加到一个列表中然后在遍历网络的时候也打印出这些模块的输出尺寸。以下是修改后的代码import torch import torch.nn as nn 定义 VGG 模型 def vgg(conv_arch): layers [] in_channels 1 for c, num_convs in conv_arch: layers.append(nn.Sequential( nn.Conv2d(in_channels, c, kernel_size3, padding1), nn.ReLU() )) in_channels c for _ in range(num_convs - 1): layers.append(nn.Sequential( nn.Conv2d(c, c, kernel_size3, padding1), nn.ReLU() )) layers.append(nn.MaxPool2d(kernel_size2, stride2)) return nn.Sequential(*layers) conv_arch ((1, 1), (2, 2), (4, 2), (8, 2), (16, 2)) net vgg(conv_arch) X torch.randn(size(1, 1, 224, 224)) for blk in net: X blk(X) print(blk.class.name, output shape:\t, X.shape) 获取卷积层的输出尺寸 _, channels, height, width X.shape 添加全连接层模块到列表中 fc_layers [ nn.Flatten(), nn.Linear(channels * height * width, 4096), nn.ReLU(), nn.Dropout(0.5), nn.Linear(4096, 4096), nn.ReLU(), nn.Dropout(0.5), nn.Linear(4096, 10) ] net nn.Sequential(*net, *fc_layers) 打印全连接层的输出尺寸 for blk in fc_layers: X blk(X) print(blk.class.name, output shape:\t, X.shape)2.与AlexNet相比VGG的计算要慢得多而且它还需要更多的显存。分析出现这种情况的原因。VGG相对于AlexNet而言计算速度更慢、显存需求更高的主要原因如下更深的网络结构 VGG网络相比AlexNet更深它使用了更多的卷积层和全连接层。VGG的网络结构包含了多个连续的卷积层导致了参数的数量增加和计算量的增加。相对于AlexNet的8层网络VGG网络有16或19层这导致了更多的计算和内存消耗。小尺寸的卷积核 VGG网络使用了较小的卷积核3x3大小而AlexNet则使用了更大的卷积核11x11和5x5大小。较小的卷积核意味着每个卷积层需要进行更多次的卷积运算来覆盖相同的感受野从而增加了计算量。更多的参数 VGG网络具有更多的参数量。由于每个卷积层都使用了较小的卷积核导致了更多的卷积核参数。此外由于网络更深全连接层的参数数量也更多。更多的参数需要更多的内存来存储并且在计算过程中需要更多的计算量。更高的内存需求 VGG网络的深度和参数量的增加导致了更高的内存需求。在训练过程中需要存储每一层的输出、梯度和参数这会消耗大量的显存。较大的显存需求可能导致无法一次性加载更多的数据和模型从而导致更多的显存读写操作和内存碎片化进而影响计算速度。3.尝试将Fashion-MNIST数据集图像的高度和宽度从224改为96。这对实验有什么影响将Fashion-MNIST数据集图像的高度和宽度从224改为96会对实验产生以下影响模型性能下降 缩小图像尺寸会导致图像的信息丢失和细节损失。VGG网络在设计时使用了较大的输入尺寸以便更好地捕捉图像的细节和纹理。通过将图像尺寸缩小为96x96模型可能无法有效地捕捉到原始图像中的细微特征从而导致性能下降。空间分辨率减小 图像尺寸从224x224缩小到96x96会导致空间分辨率的减小。较小的图像尺寸意味着每个像素代表的区域更大图像中的细节信息被压缩。这可能会导致模型在进行物体边界检测、纹理识别等任务时表现不佳。减少计算和内存需求 缩小图像尺寸可以减少模型的计算和内存需求。较小的输入图像尺寸意味着每个卷积层的特征图大小也会减小从而减少了参数数量和计算量。此外由于特征图大小减小模型所需的内存也会相应减少。训练速度加快 缩小图像尺寸可以加快训练速度。较小的输入图像尺寸意味着每个批次的数据量减少从而减少了每个训练步骤的计算量和内存消耗。这可能导致更快的训练速度和更高的训练效率。import torch from torch import nn from torchvision.transforms import ToTensor from torchvision.datasets import FashionMNIST from torch.utils.data import DataLoader 定义VGG块 def vgg_block(num_convs, in_channels, out_channels): layers [] for _ in range(num_convs): layers.append(nn.Conv2d(in_channels, out_channels, kernel_size3, padding1)) layers.append(nn.ReLU()) in_channels out_channels layers.append(nn.MaxPool2d(kernel_size2, stride2)) return nn.Sequential(*layers) 定义VGG网络 class VGG(nn.Module): def init(self, conv_arch): super(VGG, self).init() self.conv_blocks nn.Sequential() in_channels 1 for i, (num_convs, out_channels) in enumerate(conv_arch): self.conv_blocks.add_module(fvgg_block{i1}, vgg_block(num_convs, in_channels, out_channels)) in_channels out_channels self.fc_layers nn.Sequential( nn.Linear(out_channels * 3 * 3, 4096), nn.ReLU(), nn.Dropout(0.5), nn.Linear(4096, 4096), nn.ReLU(), nn.Dropout(0.5), nn.Linear(4096, 10) ) def forward(self, x): x self.conv_blocks(x) x torch.flatten(x, start_dim1) x self.fc_layers(x) return x 将Fashion-MNIST图像尺寸缩小为96x96 transform ToTensor() train_dataset FashionMNIST(root./data, trainTrue, downloadTrue, transformtransform) test_dataset FashionMNIST(root./data, trainFalse, downloadTrue, transformtransform) 创建数据加载器 batch_size 128 train_loader DataLoader(train_dataset, batch_sizebatch_size, shuffleTrue) test_loader DataLoader(test_dataset, batch_sizebatch_size, shuffleFalse) 定义VGG网络结构 conv_arch [(1, 64), (1, 128), (2, 256), (2, 512), (2, 512)] model VGG(conv_arch) 训练和测试 device torch.device(cuda if torch.cuda.is_available() else cpu) model.to(device) optimizer torch.optim.SGD(model.parameters(), lr0.05) criterion nn.CrossEntropyLoss() def train(model, train_loader, optimizer, criterion, device): model.train() train_loss 0.0 train_acc 0.0 for images, labels in train_loader: images images.to(device) labels labels.to(device) optimizer.zero_grad() outputs model(images) loss criterion(outputs, labels) loss.backward() optimizer.step() train_loss loss.item() * images.size(0) _, preds torch.max(outputs, 1) train_acc torch.sum(preds labels.data).item() train_loss / len(train_loader.dataset) train_acc / len(train_loader.dataset) return train_loss, train_acc def test(model, test_loader, criterion, device): model.eval() test_loss 0.0 test_acc 0.0 with torch.no_grad(): for images, labels in test_loader: images images.to(device) labels labels.to(device) outputs model(images) loss criterion(outputs, labels) test_loss loss.item() * images.size(0) _, preds torch.max(outputs, 1) test_acc torch.sum(preds labels.data).item() test_loss / len(test_loader.dataset) test_acc / len(test_loader.dataset) return test_loss, test_acc 训练模型 num_epochs 10 for epoch in range(num_epochs): train_loss, train_acc train(model, train_loader, optimizer, criterion, device) test_loss, test_acc test(model, test_loader, criterion, device) print(fEpoch {epoch1}/{num_epochs}, Train Loss: {train_loss:.4f}, Train Accuracy: {train_acc:.4f}, fTest Loss: {test_loss:.4f}, Test Accuracy: {test_acc:.4f}) 输出样例 print(Sample outputs:) model.eval() with torch.no_grad(): for images, labels in test_loader: images images.to(device) labels labels.to(device) outputs model(images) _, preds torch.max(outputs, 1) for i in range(images.size(0)): print(fPredicted: {preds[i].item()}, Ground Truth: {labels[i].item()}) break # 只输出一个批次的样例结果在上面的代码中定义了VGG网络结构并在Fashion-MNIST数据集上进行了训练和测试。通过将图像尺寸从224缩小为96可以看到模型的训练和推理速度可能会加快但模型的性能可能会下降因为图像的细节被压缩。这里使用了SGD优化器和交叉熵损失函数来训练模型并输出了训练和测试的损失和准确率。最后输出了一个样例的预测结果以查看模型的输出效果。请注意实际训练过程可能需要更多的迭代次数和调整超参数以获得更好的性能。4.请参考VGG论文 (Simonyan and Zisserman, 2014)中的表1构建其他常见模型如VGG-16或VGG-19。VGG-16:import torch from torch import nn from torchvision.transforms import ToTensor from torchvision.datasets import FashionMNIST from torch.utils.data import DataLoader 定义VGG块 def vgg_block(num_convs, in_channels, out_channels): layers [] for _ in range(num_convs): layers.append(nn.Conv2d(in_channels, out_channels, kernel_size3, padding1)) layers.append(nn.ReLU()) in_channels out_channels layers.append(nn.MaxPool2d(kernel_size2, stride2)) return nn.Sequential(*layers) 定义VGG-16网络 class VGG16(nn.Module): def init(self): super(VGG16, self).init() self.conv_blocks nn.Sequential( vgg_block(2, 3, 64), vgg_block(2, 64, 128), vgg_block(3, 128, 256), vgg_block(3, 256, 512), vgg_block(3, 512, 512) ) self.fc_layers nn.Sequential( nn.Linear(512 * 7 * 7, 4096), nn.ReLU(True), nn.Dropout(), nn.Linear(4096, 4096), nn.ReLU(True), nn.Dropout(), nn.Linear(4096, 10) ) def forward(self, x): x self.conv_blocks(x) x torch.flatten(x, start_dim1) x self.fc_layers(x) return x 将Fashion-MNIST图像转换为Tensor并进行数据加载 transform ToTensor() train_dataset FashionMNIST(root./data, trainTrue, downloadTrue, transformtransform) test_dataset FashionMNIST(root./data, trainFalse, downloadTrue, transformtransform) 创建数据加载器 batch_size 128 train_loader DataLoader(train_dataset, batch_sizebatch_size, shuffleTrue) test_loader DataLoader(test_dataset, batch_sizebatch_size, shuffleFalse) 创建VGG-16模型实例 model VGG16() 定义优化器和损失函数 optimizer torch.optim.SGD(model.parameters(), lr0.05) criterion nn.CrossEntropyLoss() 将模型移动到GPU如果可用 device torch.device(cuda if torch.cuda.is_available() else cpu) model.to(device) 训练模型 num_epochs 10 for epoch in range(num_epochs): model.train() train_loss 0.0 train_acc 0.0 for images, labels in train_loader: images images.to(device) labels labels.to(device) optimizer.zero_grad() outputs model(images) loss criterion(outputs, labels) loss.backward() optimizer.step() train_loss loss.item() * images.size(0) _, preds torch.max(outputs, 1) train_acc torch.sum(preds labels.data).item() train_loss / len(train_loader.dataset) train_acc / len(train_loader.dataset) # 在测试集上评估模型 model.eval() test_loss 0.0 test_acc 0.0 with torch.no_grad(): for images, labels in test_loader: images images.to(device) labels labels.to(device) outputs model(images) loss criterion(outputs, labels) test_loss loss.item() * images.size(0) _, preds torch.max(outputs, 1) test_acc torch.sum(preds labels.data).item() test_loss / len(test_loader.dataset) test_acc / len(test_loader.dataset) print(fEpoch {epoch1}/{num_epochs}, Train Loss: {train_loss:.4f}, Train Accuracy: {train_acc:.4f}, fTest Loss: {test_loss:.4f}, Test Accuracy: {test_acc:.4f}) 输出样例 print(Sample outputs:) model.eval() with torch.no_grad(): for images, labels in test_loader: images images.to(device) labels labels.to(device) outputs model(images) _, preds torch.max(outputs, 1) for i in range(images.size(0)): print(fPredicted: {preds[i].item()}, Ground Truth: {labels[i].item()}) break # 只输出一个批次的样例结果以上代码展示了包含数据加载和训练的完整代码使用VGG-16模型对Fashion-MNIST数据集进行了训练和测试。训练过程中模型在每个epoch中进行了训练和验证并输出了训练和验证集上的损失和准确率。最后展示了一个样例输出显示了模型在测试集上的预测结果。VGG-19:import torch from torch import nn from torchvision.transforms import ToTensor from torchvision.datasets import FashionMNIST from torch.utils.data import DataLoader 定义VGG块 def vgg_block(num_convs, in_channels, out_channels): layers [] for _ in range(num_convs): layers.append(nn.Conv2d(in_channels, out_channels, kernel_size3, padding1)) layers.append(nn.ReLU()) in_channels out_channels layers.append(nn.MaxPool2d(kernel_size2, stride2)) return nn.Sequential(*layers) 定义VGG-19网络 class VGG19(nn.Module): def init(self): super(VGG19, self).init() self.conv_blocks nn.Sequential( vgg_block(2, 3, 64), vgg_block(2, 64, 128), vgg_block(4, 128, 256), vgg_block(4, 256, 512), vgg_block(4, 512, 512) ) self.fc_layers nn.Sequential( nn.Linear(512 * 7 * 7, 4096), nn.ReLU(True), nn.Dropout(), nn.Linear(4096, 4096), nn.ReLU(True), nn.Dropout(), nn.Linear(4096, 10) ) def forward(self, x): x self.conv_blocks(x) x torch.flatten(x, start_dim1) x self.fc_layers(x) return x 将Fashion-MNIST图像转换为Tensor并进行数据加载 transform ToTensor() train_dataset FashionMNIST(root./data, trainTrue, downloadTrue, transformtransform) test_dataset FashionMNIST(root./data, trainFalse, downloadTrue, transformtransform) 创建数据加载器 batch_size 128 train_loader DataLoader(train_dataset, batch_sizebatch_size, shuffleTrue) test_loader DataLoader(test_dataset, batch_sizebatch_size, shuffleFalse) 创建VGG-19模型实例 model VGG19() 定义优化器和损失函数 optimizer torch.optim.SGD(model.parameters(), lr0.05) criterion nn.CrossEntropyLoss() 将模型移动到GPU如果可用 device torch.device(cuda if torch.cuda.is_available() else cpu) model.to(device) 训练模型 num_epochs 10 for epoch in range(num_epochs): model.train() train_loss 0.0 train_acc 0.0 for images, labels in train_loader: images images.to(device) labels labels.to(device) optimizer.zero_grad() outputs model(images) loss criterion(outputs, labels) loss.backward() optimizer.step() train_loss loss.item() * images.size(0) _, preds torch.max(outputs, 1) train_acc torch.sum(preds labels.data).item() train_loss / len(train_loader.dataset) train_acc / len(train_loader.dataset) # 在测试集上评估模型 model.eval() test_loss 0.0 test_acc 0.0 with torch.no_grad(): for images, labels in test_loader: images images.to(device) labels labels.to(device) outputs model(images) loss criterion(outputs, labels) test_loss loss.item() * images.size(0) _, preds torch.max(outputs, 1) test_acc torch.sum(preds labels.data).item() test_loss / len(test_loader.dataset) test_acc / len(test_loader.dataset) print(fEpoch {epoch1}/{num_epochs}, Train Loss: {train_loss:.4f}, Train Accuracy: {train_acc:.4f}, fTest Loss: {test_loss:.4f}, Test Accuracy: {test_acc:.4f}) 输出样例 print(Sample outputs:) model.eval() with torch.no_grad(): for images, labels in test_loader: images images.to(device) labels labels.to(device) outputs model(images) _, preds torch.max(outputs, 1) for i in range(images.size(0)): print(fPredicted: {preds[i].item()}, Ground Truth: {labels[i].item()}) break # 只输出一个批次的样例结果4. 研究体会在本次实验中我采用了块的网络结构具体来说是VGGVisual Geometry Group网络进行了深入的研究和分析。实验发现块的网络结构具有良好的模块化和复用性使得网络的设计和调整变得更加灵活和高效。通过将相同的卷积层和池化层堆叠在一起形成块我可以轻松地调整网络的深度和宽度而不需要对每一层都进行单独设计和调整。这种模块化的结构使得网络的搭建和调试更加高效节省了大量的时间和资源。