【第二周】卷积神经网络

【第二周】卷积神经网络

学习专知课程《卷积神经网络》,主要内容包括:

  • CNN的基本结构:卷积、池化、全连接
  • 典型的网络结构:AlexNet、VGG、GoogleNet、ResNet

1.代码练习

  • MNIST 数据集分类:构建简单的CNN对 mnist 数据集进行分类。同时,还会在实验中学习池化与卷积操作的基本作用。访问链接
  • CIFAR10 数据集分类:使用 CNN 对 CIFAR10 数据集进行分类,访问链接
  • 使用 VGG16 对 CIFAR10 分类,访问链接

1.1MNIST 数据集分类

1.1.1加载数据

PyTorch里包含了 MNIST, CIFAR10 等常用数据集,调用 torchvision.datasets 即可把这些数据由远程下载到本地,下面给出MNIST的使用方法:

torchvision.datasets.MNIST(root, train=True, transform=None, target_transform=None, download=False)

  • root 为数据集下载到本地后的根目录,包括 training.pt 和 test.pt 文件
  • train,如果设置为True,从training.pt创建数据集,否则从test.pt创建。
  • download,如果设置为True, 从互联网下载数据并放到root文件夹下
  • transform, 一种函数或变换,输入PIL图片,返回变换之后的数据。
  • target_transform 一种函数或变换,输入目标,进行变换。

另外值得注意的是,DataLoader是一个比较重要的类,提供的常用操作有:batch_size(每个batch的大小), shuffle(是否进行随机打乱顺序的操作), num_workers(加载数据的时候使用几个子进程)

1.1.2创建网络

然后创建两个网络,分别为全连接神经网络和卷积神经网络

class FC2Layer(nn.Module):def __init__(self, input_size, n_hidden, output_size):# nn.Module子类的函数必须在构造函数中执行父类的构造函数# 下式等价于nn.Module.__init__(self)super(FC2Layer, self).__init__()self.input_size = input_size# 这里直接用 Sequential 就定义了网络,注意要和下面 CNN 的代码区分开self.network = nn.Sequential(nn.Linear(input_size, n_hidden),nn.ReLU(),nn.Linear(n_hidden, n_hidden),nn.ReLU(),nn.Linear(n_hidden, output_size),nn.LogSoftmax(dim=1))def forward(self, x):# view一般出现在model类的forward函数中,用于改变输入或输出的形状# x.view(-1, self.input_size) 的意思是多维的数据展成二维# 代码指定二维数据的列数为 input_size=784,行数 -1 表示我们不想算,电脑会自己计算对应的数字# 在 DataLoader 部分,我们可以看到 batch_size 是64,所以得到 x 的行数是64# 大家可以加一行代码:print(x.cpu().numpy().shape)# 训练过程中,就会看到 (64, 784) 的输出,和我们的预期是一致的# forward 函数的作用是,指定网络的运行过程,这个全连接网络可能看不啥意义,# 下面的CNN网络可以看出 forward 的作用。x = x.view(-1, self.input_size)return self.network(x)class CNN(nn.Module):def __init__(self, input_size, n_feature, output_size):# 执行父类的构造函数,所有的网络都要这么写super(CNN, self).__init__()# 下面是网络里典型结构的一些定义,一般就是卷积和全连接# 池化、ReLU一类的不用在这里定义self.n_feature = n_featureself.conv1 = nn.Conv2d(in_channels=1, out_channels=n_feature, kernel_size=5)self.conv2 = nn.Conv2d(n_feature, n_feature, kernel_size=5)self.fc1 = nn.Linear(n_feature*4*4, 50)self.fc2 = nn.Linear(50, 10)# 下面的 forward 函数,定义了网络的结构,按照一定顺序,把上面构建的一些结构组织起来# 意思就是,conv1, conv2 等等的,可以多次重用def forward(self, x, verbose=False):x = self.conv1(x)x = F.relu(x)x = F.max_pool2d(x, kernel_size=2)x = self.conv2(x)x = F.relu(x)x = F.max_pool2d(x, kernel_size=2)x = x.view(-1, self.n_feature*4*4)x = self.fc1(x)x = F.relu(x)x = self.fc2(x)x = F.log_softmax(x, dim=1)return x

定义网络要继承于nn.Module,在构造函数中执行父类的构造函数,以及写明网络中具有可学习参数的层,并用forward函数来定义了网络结构。

然后是训练和测试函数,其中optimizer.zero_grad()用于清除累计的梯度,上个实验中也有提到。

# 训练函数
def train(model):model.train()# 主里从train_loader里,64个样本一个batch为单位提取样本进行训练for batch_idx, (data, target) in enumerate(train_loader):# 把数据送到GPU中data, target = data.to(device), target.to(device)optimizer.zero_grad()output = model(data)loss = F.nll_loss(output, target)loss.backward()optimizer.step()if batch_idx % 100 == 0:print('Train: [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(batch_idx * len(data), len(train_loader.dataset),100. * batch_idx / len(train_loader), loss.item()))def test(model):model.eval()test_loss = 0correct = 0for data, target in test_loader:# 把数据送到GPU中data, target = data.to(device), target.to(device)# 把数据送入模型,得到预测结果output = model(data)# 计算本次batch的损失,并加到 test_loss 中test_loss += F.nll_loss(output, target, reduction='sum').item()# get the index of the max log-probability,最后一层输出10个数,# 值最大的那个即对应着分类结果,然后把分类结果保存在 pred 里pred = output.data.max(1, keepdim=True)[1]# 将 pred 与 target 相比,得到正确预测结果的数量,并加到 correct 中# 这里需要注意一下 view_as ,意思是把 target 变成维度和 pred 一样的意思                                                correct += pred.eq(target.data.view_as(pred)).cpu().sum().item()test_loss /= len(test_loader.dataset)accuracy = 100. * correct / len(test_loader.dataset)print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(test_loss, correct, len(test_loader.dataset),accuracy))

1.1.3在小型全连接网络上训练

n_hidden = 8 # number of hidden unitsmodel_fnn = FC2Layer(input_size, n_hidden, output_size)
model_fnn.to(device)
optimizer = optim.SGD(model_fnn.parameters(), lr=0.01, momentum=0.5)
print('Number of parameters: {}'.format(get_n_params(model_fnn)))train(model_fnn)
test(model_fnn)

其中n_hidden是一个超参数,为每个隐层的神经元个数,

在colab上运行结果如下,可以看到模型参数为6442.

在这里插入图片描述

1.1.4 在卷积神经网络上训练

# Training settings 
n_features = 6 # number of feature mapsmodel_cnn = CNN(input_size, n_features, output_size)
model_cnn.to(device)
optimizer = optim.SGD(model_cnn.parameters(), lr=0.01, momentum=0.5)
print('Number of parameters: {}'.format(get_n_params(model_cnn)))train(model_cnn)
test(model_cnn)

n_features为特征图的数量,决定了网络中卷积层输出的通道数,也可以理解为卷积核的数量。

运行结果如下,可以发现在参数量相同的情况下,CNN表现更好。

在这里插入图片描述

1.1.5.打乱像素顺序再次在两个网络上训练与测试

将图像进行打乱,再测试两种网络的识别表现

在这里插入图片描述

全连接神经网络:
在这里插入图片描述

CNN:

在这里插入图片描述

全连接网络的性能基本上没有发生变化,但是卷积神经网络的性能明显下降。

这是因为对于卷积神经网络,会利用像素的局部关系,但是打乱顺序以后,这些像素间的关系将无法得到利用。

通过对图像进行像素打乱操作,会破坏图像的空间局部性特征。说明卷积神经网络的卷积和池化操作,能够对具有局部特征的图像取得更好的分类效果。

1.1.6这个实验对我的一点小启发:

我:

经过打乱后,我已经很难分辨手写数字的图像原本的类别了,但是神经网络却还能有较高的识别能力,这是为什么呢?我不能识别但神经网络能识别,这是一种什么现象?这跟可解释性差有联系吗?

ChatGPT:

确实,当像素顺序被打乱后,图像的外观会发生较大变化,难以被人类视觉系统轻易识别。然而,神经网络在某些情况下可能仍然能够对打乱后的图像进行分类。

这可以归因于神经网络具有一定的模式识别和特征提取能力,它可以通过学习和调整模型的参数来适应不同的输入变化。神经网络通过多个层次的非线性变换和权重优化,可以学习到在输入数据中存在的隐含模式和特征

然而,对于人类视觉系统而言,像素顺序的打乱会破坏图像的空间局部性和连续性,使得我们很难准确地识别图像的类别。这与神经网络的工作方式不同,神经网络并不直接依赖于具体的空间位置和像素顺序。

这种现象与神经网络的可解释性有一定的关系。神经网络的内部表示和决策过程通常是复杂和抽象的,难以直接解释和理解。神经网络可能会学习到一些抽象的特征和模式,而不仅仅依赖于输入数据的直观特征。因此,即使在像素顺序打乱的情况下,神经网络可能仍然能够通过学习到的抽象特征来进行分类。

1.2 CIFAR10 数据集分类

对于视觉数据,PyTorch 创建了一个叫做 totchvision 的包,该包含有支持加载类似Imagenet,CIFAR10,MNIST 等公共数据集的数据加载模块 torchvision.datasets 和支持加载图像数据数据转换模块 torch.utils.data.DataLoader。

下面将使用CIFAR10数据集,它包含十个类别:‘airplane’, ‘automobile’, ‘bird’, ‘cat’, ‘deer’, ‘dog’, ‘frog’, ‘horse’, ‘ship’, ‘truck’。CIFAR-10 中的图像尺寸为3x32x32,也就是RGB的3层颜色通道,每层通道内的尺寸为32*32。

1.2.1加载数据

首先,加载并归一化 CIFAR10 使用 torchvision 。torchvision 数据集的输出是范围在[0,1]之间的 PILImage,我们将他们转换成归一化范围为[-1,1]之间的张量 Tensors。

import torch
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim# 使用GPU训练,可以在菜单 "代码执行工具" -> "更改运行时类型" 里进行设置
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])# 注意下面代码中:训练的 shuffle 是 True,测试的 shuffle 是 false
# 训练时可以打乱顺序增加多样性,测试是没有必要
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64,shuffle=True, num_workers=2)testset = torchvision.datasets.CIFAR10(root='./data', train=False,download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=8,shuffle=False, num_workers=2)classes = ('plane', 'car', 'bird', 'cat','deer', 'dog', 'frog', 'horse', 'ship', 'truck')

下面展示 CIFAR10 里面的一些图片,pytorch版本不同导致有些代码需要小改一下。

def imshow(img):plt.figure(figsize=(8,8))img = img / 2 + 0.5     # 转换到 [0,1] 之间npimg = img.numpy()plt.imshow(np.transpose(npimg, (1, 2, 0)))plt.show()# 得到一组图像
dataiter=iter(trainloader)
images, labels = next(dataiter)
# 展示图像
imshow(torchvision.utils.make_grid(images))
# 展示第一行图像的标签
for j in range(8):print(classes[labels[j]])

在这里插入图片描述

1.2.2网络的定义和结构

接下来是网络的定义和结构,

class Net(nn.Module):def __init__(self):super(Net, self).__init__()self.conv1 = nn.Conv2d(3, 6, 5)self.pool = nn.MaxPool2d(2, 2)self.conv2 = nn.Conv2d(6, 16, 5)self.fc1 = nn.Linear(16 * 5 * 5, 120)self.fc2 = nn.Linear(120, 84)self.fc3 = nn.Linear(84, 10)def forward(self, x):x = self.pool(F.relu(self.conv1(x)))x = self.pool(F.relu(self.conv2(x)))x = x.view(-1, 16 * 5 * 5)x = F.relu(self.fc1(x))x = F.relu(self.fc2(x))x = self.fc3(x)return x

1.2.3训练代码及过程

# 网络放到GPU上
net = Net().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters(), lr=0.001)
for epoch in range(10):  # 重复多轮训练for i, (inputs, labels) in enumerate(trainloader):inputs = inputs.to(device)labels = labels.to(device)# 优化器梯度归零optimizer.zero_grad()# 正向传播 + 反向传播 + 优化 outputs = net(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()# 输出统计信息if i % 100 == 0:   print('Epoch: %d Minibatch: %5d loss: %.3f' %(epoch + 1, i + 1, loss.item()))print('Finished Training')
Epoch: 1 Minibatch:     1 loss: 2.302
Epoch: 1 Minibatch:   101 loss: 1.879
Epoch: 1 Minibatch:   201 loss: 1.736
Epoch: 1 Minibatch:   301 loss: 1.723
Epoch: 1 Minibatch:   401 loss: 1.844
Epoch: 1 Minibatch:   501 loss: 1.569
Epoch: 1 Minibatch:   601 loss: 1.596
Epoch: 1 Minibatch:   701 loss: 1.519
Epoch: 2 Minibatch:     1 loss: 1.557
Epoch: 2 Minibatch:   101 loss: 1.269
Epoch: 2 Minibatch:   201 loss: 1.283
Epoch: 2 Minibatch:   301 loss: 1.544
Epoch: 2 Minibatch:   401 loss: 1.702
Epoch: 2 Minibatch:   501 loss: 1.398
Epoch: 2 Minibatch:   601 loss: 1.222
Epoch: 2 Minibatch:   701 loss: 1.175
Epoch: 3 Minibatch:     1 loss: 1.268
Epoch: 3 Minibatch:   101 loss: 1.269
Epoch: 3 Minibatch:   201 loss: 1.133
Epoch: 3 Minibatch:   301 loss: 0.968
Epoch: 3 Minibatch:   401 loss: 1.141
Epoch: 3 Minibatch:   501 loss: 1.130
Epoch: 3 Minibatch:   601 loss: 1.415
Epoch: 3 Minibatch:   701 loss: 1.236
Epoch: 4 Minibatch:     1 loss: 1.047
Epoch: 4 Minibatch:   101 loss: 1.026
Epoch: 4 Minibatch:   201 loss: 1.082
Epoch: 4 Minibatch:   301 loss: 1.314
Epoch: 4 Minibatch:   401 loss: 0.839
Epoch: 4 Minibatch:   501 loss: 1.268
Epoch: 4 Minibatch:   601 loss: 1.243
Epoch: 4 Minibatch:   701 loss: 0.982
Epoch: 5 Minibatch:     1 loss: 1.143
Epoch: 5 Minibatch:   101 loss: 0.970
Epoch: 5 Minibatch:   201 loss: 0.779
Epoch: 5 Minibatch:   301 loss: 0.957
Epoch: 5 Minibatch:   401 loss: 0.955
Epoch: 5 Minibatch:   501 loss: 1.166
Epoch: 5 Minibatch:   601 loss: 0.823
Epoch: 5 Minibatch:   701 loss: 0.956
Epoch: 6 Minibatch:     1 loss: 1.096
Epoch: 6 Minibatch:   101 loss: 1.052
Epoch: 6 Minibatch:   201 loss: 1.136
Epoch: 6 Minibatch:   301 loss: 1.098
Epoch: 6 Minibatch:   401 loss: 1.002
Epoch: 6 Minibatch:   501 loss: 0.886
Epoch: 6 Minibatch:   601 loss: 0.841
Epoch: 6 Minibatch:   701 loss: 1.063
Epoch: 7 Minibatch:     1 loss: 0.926
Epoch: 7 Minibatch:   101 loss: 0.988
Epoch: 7 Minibatch:   201 loss: 0.894
Epoch: 7 Minibatch:   301 loss: 1.018
Epoch: 7 Minibatch:   401 loss: 1.180
Epoch: 7 Minibatch:   501 loss: 0.857
Epoch: 7 Minibatch:   601 loss: 0.971
Epoch: 7 Minibatch:   701 loss: 1.221
Epoch: 8 Minibatch:     1 loss: 0.680
Epoch: 8 Minibatch:   101 loss: 0.996
Epoch: 8 Minibatch:   201 loss: 0.908
Epoch: 8 Minibatch:   301 loss: 0.888
Epoch: 8 Minibatch:   401 loss: 1.050
Epoch: 8 Minibatch:   501 loss: 0.822
Epoch: 8 Minibatch:   601 loss: 1.084
Epoch: 8 Minibatch:   701 loss: 1.010
Epoch: 9 Minibatch:     1 loss: 0.897
Epoch: 9 Minibatch:   101 loss: 0.861
Epoch: 9 Minibatch:   201 loss: 0.956
Epoch: 9 Minibatch:   301 loss: 0.869
Epoch: 9 Minibatch:   401 loss: 0.883
Epoch: 9 Minibatch:   501 loss: 0.873
Epoch: 9 Minibatch:   601 loss: 0.911
Epoch: 9 Minibatch:   701 loss: 0.856
Epoch: 10 Minibatch:     1 loss: 0.925
Epoch: 10 Minibatch:   101 loss: 1.085
Epoch: 10 Minibatch:   201 loss: 0.793
Epoch: 10 Minibatch:   301 loss: 1.021
Epoch: 10 Minibatch:   401 loss: 0.917
Epoch: 10 Minibatch:   501 loss: 0.961
Epoch: 10 Minibatch:   601 loss: 1.039
Epoch: 10 Minibatch:   701 loss: 0.661
Finished Training

1.2.4测试结果

网络在整个数据集上的表现仅有63%

correct = 0
total = 0for data in testloader:images, labels = dataimages, labels = images.to(device), labels.to(device)outputs = net(images)_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()print('Accuracy of the network on the 10000 test images: %d %%' % (100 * correct / total))
Accuracy of the network on the 10000 test images: 63 %

1.3 使用 VGG16 对 CIFAR10 分类

VGG是由Simonyan 和Zisserman在文献《Very Deep Convolutional Networks for Large Scale Image Recognition》中提出卷积神经网络模型,其名称来源于作者所在的牛津大学视觉几何组(Visual Geometry Group)的缩写。

该模型参加2014年的 ImageNet图像分类与定位挑战赛,取得了优异成绩:在分类任务上排名第二,在定位任务上排名第一。

VGG16示意图

1.3.1 定义 dataloader

import torch
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim# 使用GPU训练,可以在菜单 "代码执行工具" -> "更改运行时类型" 里进行设置device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")transform_train = transforms.Compose([transforms.RandomCrop(32, padding=4),transforms.RandomHorizontalFlip(),transforms.ToTensor(),transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))])transform_test = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))])trainset = torchvision.datasets.CIFAR10(root='./data', train=True,  download=True, transform=transform_train)
testset  = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform_test)trainloader = torch.utils.data.DataLoader(trainset, batch_size=128, shuffle=True, num_workers=2)
testloader = torch.utils.data.DataLoader(testset, batch_size=128, shuffle=False, num_workers=2)classes = ('plane', 'car', 'bird', 'cat','deer', 'dog', 'frog', 'horse', 'ship', 'truck')

两段代码中transform和dataloader相比:

第一段代码在训练和测试上使用了相同的transform对数据进行预处理操作。而第二段代码中在训练时使用了一些数据增强方式,包括随机裁剪和随机水平翻转。同时二者标准化的参数不同。

这些参数是经过计算得到的 CIFAR-10 数据集的像素通道均值和标准差。对于训练集和测试集,这些参数用于将图像的每个通道进行标准化,使其均值接近 0.5,标准差接近 0.2。

标准化的目的是将数据进行零均值化和单位方差化,以便更好地适应模型的训练。通过减去均值并除以标准差,可以将数据的分布调整为接近标准正态分布,这有助于模型更好地学习特征。

dataloader上,二者的batch_size不同。

1.3.2简化的VGG网络定义

class VGG(nn.Module):def __init__(self):super(VGG, self).__init__()self.cfg = [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M']self.features = self._make_layers(self.cfg)self.classifier = nn.Linear(512, 10)def forward(self, x):out = self.features(x)out = out.view(out.size(0), -1)out = self.classifier(out)return outdef _make_layers(self, cfg):layers = []in_channels = 3for x in cfg:if x == 'M':layers += [nn.MaxPool2d(kernel_size=2, stride=2)]else:layers += [nn.Conv2d(in_channels, x, kernel_size=3, padding=1),nn.BatchNorm2d(x),nn.ReLU(inplace=True)]in_channels = xlayers += [nn.AvgPool2d(kernel_size=1, stride=1)]return nn.Sequential(*layers)# 网络放到GPU上
net = VGG().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters(), lr=0.001)

1.3.3训练过程

Epoch: 1 Minibatch:     1 loss: 2.473
Epoch: 1 Minibatch:   101 loss: 1.563
Epoch: 1 Minibatch:   201 loss: 1.199
Epoch: 1 Minibatch:   301 loss: 1.172
Epoch: 2 Minibatch:     1 loss: 1.059
Epoch: 2 Minibatch:   101 loss: 1.030
Epoch: 2 Minibatch:   201 loss: 0.892
Epoch: 2 Minibatch:   301 loss: 0.874
Epoch: 3 Minibatch:     1 loss: 0.918
Epoch: 3 Minibatch:   101 loss: 0.718
Epoch: 3 Minibatch:   201 loss: 0.741
Epoch: 3 Minibatch:   301 loss: 0.681
Epoch: 4 Minibatch:     1 loss: 0.837
Epoch: 4 Minibatch:   101 loss: 0.818
Epoch: 4 Minibatch:   201 loss: 0.717
Epoch: 4 Minibatch:   301 loss: 0.582
Epoch: 5 Minibatch:     1 loss: 0.586
Epoch: 5 Minibatch:   101 loss: 0.616
Epoch: 5 Minibatch:   201 loss: 0.735
Epoch: 5 Minibatch:   301 loss: 0.536
Epoch: 6 Minibatch:     1 loss: 0.576
Epoch: 6 Minibatch:   101 loss: 0.459
Epoch: 6 Minibatch:   201 loss: 0.589
Epoch: 6 Minibatch:   301 loss: 0.466
Epoch: 7 Minibatch:     1 loss: 0.519
Epoch: 7 Minibatch:   101 loss: 0.512
Epoch: 7 Minibatch:   201 loss: 0.385
Epoch: 7 Minibatch:   301 loss: 0.453
Epoch: 8 Minibatch:     1 loss: 0.435
Epoch: 8 Minibatch:   101 loss: 0.477
Epoch: 8 Minibatch:   201 loss: 0.404
Epoch: 8 Minibatch:   301 loss: 0.474
Epoch: 9 Minibatch:     1 loss: 0.457
Epoch: 9 Minibatch:   101 loss: 0.325
Epoch: 9 Minibatch:   201 loss: 0.517
Epoch: 9 Minibatch:   301 loss: 0.429
Epoch: 10 Minibatch:     1 loss: 0.331
Epoch: 10 Minibatch:   101 loss: 0.244
Epoch: 10 Minibatch:   201 loss: 0.384
Epoch: 10 Minibatch:   301 loss: 0.367
Finished Training

1.3.4测试及结果

correct = 0
total = 0for data in testloader:images, labels = dataimages, labels = images.to(device), labels.to(device)outputs = net(images)_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()print('Accuracy of the network on the 10000 test images: %.2f %%' % (100 * correct / total))
Accuracy of the network on the 10000 test images: 83.03 %

相较于上一个网络,准确率有了较大的提升。

2.问题总结

2.1 dataloader 里面 shuffle 取不同值有什么区别?

shuffle为True时,可以在每个 epoch 中打乱数据顺序,增加样本的随机性,使模型更好的学到数据的各种特征。

shuffle为False时,dataloader会按照数据集中的顺序逐个加载样本。

一般在训练时shuffle取true,训练时取false。

2.2 transform 里,取了不同值,这个有什么区别?

像这次实验二和实验三中,transform里有不同的参数。transform主要用于数据的预处理,比如将数据转为张量和数据增强方法。实验三中针对CIFAR10数据集的像素通道均值和标准差,设定了标准化参数,实验二中可能就是一个初始的参数。实验三中还使用了随机裁剪和随机水平翻转的数据增强。

  • transforms.ToTensor():将 PIL 图像或 NumPy 数组转换为张量(Tensor),并将像素值从 [0, 255] 缩放到 [0, 1]。
  • transforms.Normalize(mean, std):对张量进行标准化操作,即减去均值并除以标准差。meanstd 是用于标准化的均值和标准差,可以根据数据集的特性进行设置。
  • transforms.Resize(size):调整图像大小,使其具有指定的尺寸。可以传入整数来调整图像的较小边的长度,或者传入一个元组来指定具体的尺寸。
  • transforms.CenterCrop(size):对图像进行中心裁剪,使其具有指定的尺寸。可以传入整数来指定裁剪的边长,或者传入一个元组来指定具体的尺寸。
  • transforms.RandomCrop(size, padding=None):对图像进行随机裁剪,使其具有指定的尺寸。可以传入整数来指定裁剪的边长,或者传入一个元组来指定具体的尺寸。可选的 padding 参数可以指定填充的大小。
  • transforms.RandomHorizontalFlip(p=0.5):以给定的概率进行随机水平翻转图像。默认概率为 0.5,即有一半的概率进行翻转。
  • 其他的预处理和增强操作,如旋转、亮度调整、对比度调整等。

2.3 epoch 和 batch 的区别?

epoch是训练时的轮数,应该是模型把所有的训练数据使用一遍进行学习的过程(一次完整的训练),算一个epoch;

batch是训练时,把所有的训练数据分成了多个批次,每一个批次取batchsize个训练样本进行训练,只学习这些样本。

2.4 1x1的卷积和 FC 有什么区别?主要起什么作用?

  • 1x1的卷积层在空间维度上进行局部感知,但不改变输入图像的空间尺寸,主要用于通道间的线性组合和特征变换。全连接层将输入特征映射到输出类别的分数,不保持空间结构。
  • 1x1的卷积层可以控制输出特征图的通道数,而全连接层的参数量随着输入特征的大小而增加。
  • 1x1的卷积层在深度卷积神经网络中常用于调整通道数、特征整合和非线性变换,而全连接层通常用于分类任务的最后一层。

综上所述,1x1的卷积层和全连接层在神经网络中有着不同的作用和应用场景,可以根据任务需求和模型结构来选择使用。

1x1的卷积可以用来调整通道数,起到降维和升维的作用。

2.5 residual leanring 为什么能够提升准确率?

residual basic structure

在此模型中,由于x直接连接到下一层,没有任何参数,即网络学习到的是F(x)。

缓解梯度消失问题:深度神经网络存在梯度消失问题,导致在训练过程中难以有效地更新较早层的参数。通过引入跳跃连接,残差学习允许信息在网络中直接传播,减少了梯度在深层传播过程中逐渐消失的情况,使得更深的网络可以更好地学习特征。

提高网络收敛速度:由于跳跃连接的引入,残差学习可以使网络在初始训练阶段更快地收敛。在初始训练阶段,模型还没有很好地学习到有效的特征表示,但通过跳跃连接,网络可以直接传递输入信息到后续层,从而减少了训练初始阶段的信息丢失。

网络深度的有效利用:残差学习允许通过跳跃连接将信息直接传递到后续层,使得网络可以更好地利用深层的特征表示。网络可以选择性地学习残差,将前面层的特征与后面层的特征相加,从而更充分地利用网络的深度。

总的来说残差的结构可以帮助解决网络退化问题,通过允许信息在网络中直接传播来缓解梯度消失,同时能更充分地利用网络的深度。

2.6 代码练习二里,网络和1989年 Lecun 提出的 LeNet 有什么区别?

代码二:

class Net(nn.Module):def __init__(self):super(Net, self).__init__()self.conv1 = nn.Conv2d(3, 6, 5)self.pool = nn.MaxPool2d(2, 2)self.conv2 = nn.Conv2d(6, 16, 5)self.fc1 = nn.Linear(16 * 5 * 5, 120)self.fc2 = nn.Linear(120, 84)self.fc3 = nn.Linear(84, 10)def forward(self, x):x = self.pool(F.relu(self.conv1(x)))x = self.pool(F.relu(self.conv2(x)))x = x.view(-1, 16 * 5 * 5)x = F.relu(self.fc1(x))x = F.relu(self.fc2(x))x = self.fc3(x)return x

LeNet:

class LeNet5(nn.Module):def __init__(self):super().__init__()self.conv1 = nn.Conv2d(1,6,5,padding=2)self.pool1 = nn.AvgPool2d(2)self.conv2 = nn.Conv2d(6,16,5)self.pool2 = nn.AvgPool2d(2)self.fc1 = nn.Linear(16*5*5,120)self.fc2 = nn.Linear(120,84)self.fc3 = nn.Linear(84,10)def forward(self,x):x = torch.tanh(self.conv1(x))x = self.pool1(x)x = torch.tanh(self.conv2(x))x = self.pool2(x)x = x.view(-1,16*5*5)x = self.fc1(x)x = self.fc2(x)x = self.fc3(x)return x

池化层不同,LeNet使用的是平均池化;

起初LeNet处理灰度图,第一个卷积的输入通道数不同。

2.7 代码练习二里,卷积以后feature map 尺寸会变小,如何应用 Residual Learning?

在网络中添加跳跃连接,将输入特征图直接添加到相应的层的输出特征图中。在正向传播过程中,通过在相应位置将残差添加到输出特征上,实现残差学习的效果。

2.8 有什么方法可以进一步提升准确率?

增加数据集的数据量或者使用数据增强,来增加可用的样本;

尝试不同的网络结构或调整一些参数,使之能够更好发现图像的特征。

尝试不同的激活函数、损失函数、优化器;

用预训练的模型进行微调;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/16755.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

failed to load response

原因: 因为后端没有把跨域的相关信息写到Header,导致前端无法加载数据。 分析: 1、首先先查看项目中有没有配跨域相关的配置,然后发现有配。 2、这个应该是在执行controller的时候返回才会加上。 3、因为我们项目做了个拦截器…

前端请求failed to load response解决方案

情况是这样的,vue写的一个前端页面,写了一个上传图片的功能,在生产环境上是可以使用的,但在测试环境上不可用,所以开始找原因。 第一步 打开浏览器,查看网页代码,走到network页面开始抓包。 …

任务一 唐诗赏析软件

(1)TextView控件详解 在Android中,文本框使用TextView表示,作用是在界面上显示文本。TextView提供了大量的XML属性,通过这些属性值的设置可以控制其显示内容的外观。表2-1显示了TextView常见的XML属性说明。TextView的…

若依框架 项目运行报错问题

前端项目启动报错 Syntax Error: TypeError: eslint.CLIEngine is not a constructor stackoverflow上的解决方法 1)升级webstorm 到2019版本 2)降级eslint 到5 我选择 2) 代码如下 npm install --save-dev eslint5安装报错 1、npm audit fix 2、npm a…

大爆发还是大崩盘?亿万富翁Bankman-Fried解读NFT

iNFTnews.com消息,在接受CNBC采访时,加密衍生品交易所 FTX 的首席执行官 Sam Bankman-Fried 表示NFT几乎比他见过的任何东西都更快地成为主流。他还指出:“快速采用一种新趋势既让人兴奋,也存在风险。” “Visa刚刚宣布他们购买了…

AI工具究竟是帮手还是对手?

本文概要 近日育碧开发了人工智能工具 Ghostwriter,可以一键生成游戏NPC对话。不少游戏开发者担心AI写手工具的出现会让自己“饭碗”不保,但Swanson表示这个工具只是为了提供第一稿的 barks来减少对话生成工作的繁琐度。AI工具究竟是帮手还是对手&#x…

【自然语言处理】【大模型】DeepMind的大模型Gopher

DeepMind的大模型Gopher 《Scaling Language Models: Methods, Analysis & Insights from Training Gopher》 论文:https://arxiv.org/pdf/2112.11446.pdf 相关博客 【自然语言处理】【大模型】CodeGeeX:用于代码生成的多语言预训练模型 【自然语言处…

一文读懂“大语言模型”

1、背景 本文基于谷歌云的官方视频:《Introduction to Large Language Models》 ,使用 ChatGPT4 整理而成,希望对大家入门大语言模型有帮助。 本课程主要包括以下 4 方面的内容: 大语言模型的定义描述大语言模型的用例解释提示…

Azure OpenAI 官方指南04|Codex的模型结构和应用场景

Codex 是 OpenAI 公司推出的 GPT-3(Generative Pre-trained Transformer – 3)的多个派生模型之一。它是基于GPT语言模型,使用代码数据进行 Fine-Tune(微调)而训练出的专门用于代码生成/文档生成的模型。Codex 模型参数…

[论文] LIMA: Less Is More for Alignment

文章目录 概要内容关键方法高质量样本获取模型评估方法 结论思考 Meta新模型LIMA,基于LLaMa-65B,精选1000个微调样本进行训练,对比GPT-4/Bard/DaVinci003,表现出强大的性能。 结果表明,大语言模型中的几乎所有知识都是…

ChatGpt万能公式以及详细使用方法(实时更新最新方法)

万能公式: 1. 我希望你 / 我想让你 充当 / 担任 / 扮演( 设定角色) 2. 我将为你提供 (关键信息) 3. 你的工作 / 任务是 (工作内容) 4. 我的第一个要求是(输出目标) 例如: 我希望你充当一名广告商。您将创建…

九类AI应用和五个简单LLM的Prompt技巧

文章目录 一、九类AI应用二、五个提示词技巧三、MidJourney的prompt使用举例Reference 一、九类AI应用 AI艺术:造梦日记、MidJourney、Stable Diffusion、Adobe、Stability、Remove AI聊天:ChatGPT、Discord、文心一言、Google Bard、星火、Character.…

使用 ChatGPT 和 React 创建一个惊艳的3D卡片(二)

在上一篇文章中,我们一起使用 ChatGPT 和 React 构建了一个基本的卡片布局,效果如下图所示。如果您还没有看过上一篇文章,可以通过这个链接快速查看《使用 ChatGPT 和 React 创建一个惊艳的3D卡片(一)》。 在此基础上&…

【Figma技巧】根据JSON文件自动生成色标图例

最近工作中有个需求,就是根据json文件里的参数,在figma中做出色标图例。 由于要素很多,不同的要素的色标配置文件都不同,如果手动一个颜色一个颜色去复制粘贴很费时间,所以我让chatGPT去帮我实现。但是我用的是GPT-3&…

ChatGPT加持下的微软New Bing 错误频出,别只骂谷歌的Bard了

文|李星漩、丁博生、赵若辰、谢耀赓、邴立东 源|机器之心 这些天看下来,在与谷歌 Bard 加持的搜索引擎较量中,微软基于 ChatGPT 的新必应似乎完全占据了上风。但仍不禁要问,新必应的搜索结果真的无懈可击吗&#xff1f…

ChatGPT时代情感分析还存在吗?一份真实调查

深度学习自然语言处理 原创作者:qazw 引言 最近几年,GPT-3、PaLM和GPT-4等LLM刷爆了各种NLP任务,特别是在zero-shot和few-shot方面表现出它们强大的性能。因此,情感分析(SA)领域也必然少不了LLM的影子,但是哪种LLM适用…

【精妙绝伦】写出查询所有用户的第2笔订单sql!!!

叹为观止的sql语句 SELECT user_id, order_id, order_date, amount FROM orders WHERE (SELECT COUNT(*) FROM orders o WHERE o.user_id orders.user_id AND o.order_date < orders.order_date ) 1 ORDER BY user_id, order_date阿里渣渣研发组群主分享

chatgpt赋能python:探索Python:如何找出大于5的数

探索Python&#xff1a;如何找出大于5的数 在Python编程中&#xff0c;我们常常需要对一系列数字进行操作和筛选。例如&#xff0c;我们需要找出一个列表中所有大于5的数字。本文将详细说明如何使用Python找出大于5的数&#xff0c;并讨论在实际应用中可能遇到的问题和解决方案…

利用chatgpt+低代码技术搭建进销存系统

1 前言 在当今数字化时代&#xff0c;企业管理系统已经成为各行各业不可或缺的一部分。而进销存系统更是企业管理中的重要组成部分&#xff0c;它可以帮助企业实现产品库存管理、采购管理、销售管理等多个方面的自动化管理。 然而&#xff0c;搭建一个高质量的进销存系统需要…

吴恩达联手OpenAI的免费课程笔记—面向开发人员的 ChatGPT 提示工程

目录 前言一、大语言模型介绍二、提示指南2-0、导入API key和相关的python库2-1、写清楚的、具体的提示2-1-1、使用分隔符清楚的指示输入的不同部分2-1-2、要求结构化的输出2-1-3、按照指定的条件输出2-1-4、少样本学习 2-2、给模型时间去思考2-2-1、指定完成任务所需要的具体步…