1.结构

  • 以识别手写数字为例,有些地方是简化版

这个图是图片数据的特征维度经过一层一层的变化。
image.png
这个图是每一层的核的size,包括输入输出通道的个数
image.png

  • 第一卷积层,卷积核的size(5 * 5)

输入通道:1
输出通道:6

  • 第一层池化层,核的size(2 * 2)

(经过池化层,输入输出通道数没改变)

  • 第二卷积层 ,卷积核的size(5 * 5)

输入通道:6
输出通道:16

  • 第二层池化层,核的size(2 * 2)

图片数据的特征维度变化:
(2828)——>6(1414)——>6(1010)——>16(55)——>165*5——>84——>10
参数:

  • 人为设置一部分

    代码实现

  1. class Reshape(torch.nn.Module):
  2. def forward(self,x):
  3. #为什么用view???
  4. return x.view(-1,1,28,28)
  5. net=torch.nn.Sequential(
  6. Reshape(),
  7. #1:输入通道数 6:输出通道数
  8. nn.Conv2d(1,6,kernel_size=5,padding=2),nn.Sigmoid(),
  9. nn.AvgPool2d(kernel_size=2, stride=2),
  10. #为什么输出后特征维度变成16*10*10
  11. nn.Conv2d(6, 16, kernel_size=5), nn.Sigmoid(),
  12. nn.AvgPool2d(kernel_size=2, stride=2),
  13. #????flatten()全部展平???
  14. nn.Flatten(),
  15. #第一个参数:输入特征维度,,,第二个参数:输出特征维度
  16. nn.Linear(16 * 5 * 5, 120), nn.Sigmoid(),
  17. nn.Linear(120, 84), nn.Sigmoid(),
  18. nn.Linear(84, 10))
  1. #1,1分别代表?
  2. #打印每个层的结构
  3. X=torch.randn(size=(1,1,28,28),dtype=torch.float32)
  4. for layer in net:
  5. X=layer(X)
  6. print(layer.__class__.__name__,'output shape:\t',X.shape)
  1. batch_size = 128
  2. train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size=batch_size)
  1. #在模型使用 GPU 计算数据集之前,我们需要将其复制到显卡
  2. def evaluate_accuracy_gpu(net,data_iter,device=None):
  3. """使用gpu"""
  4. if isinstance(net,torch.nn.Module):
  5. net.eval()
  6. if not device:
  7. device=next(iter(net.parameters())).device
  8. metric=d2l.Accumulator(2)
  9. for X,y in data_iter:
  10. if isinstance(X,list):
  11. X=[x.to(device) for x in X]
  12. else:
  13. X=X.to(device)
  14. y=y.to(device)
  15. metric.add(d2l.accuracy(net(X),y),y.numel())
  16. return metric[0]/metric[1]
  1. #训练数据
  2. def train_ch6(net,train_iter,test_iter,num_epochs,lr,device):
  3. def init_weights(m):
  4. if type(m)==nn.Linear or type(m)==nn.Conv2d:
  5. nn.init.xavier_uniform_(m.weight)
  6. net.apply(init_weights)
  7. print('training on',device)
  8. net.to(device)
  9. optimizer=torch.optim.SGD(net.parameters(),lr=lr)
  10. loss=nn.CrossEntropyLoss()
  11. animator=d2l.Animator(xlabel='epoch',xlim=[1,num_epochs],
  12. legend=['train loss','train acc','test acc'])
  13. timer,num_batches=d2l.Timer()
  14. for epoch in range(num_epochs):
  15. # 训练损失之和,训练准确率之和,范例数
  16. metric=d2l.Accumulator(3)
  17. net.train()
  18. for i,(X,y) in enumerate(train_iter):
  19. timer.start()
  20. optimizer.zero_grad()
  21. X,y=X.to(device),y.to(device)
  22. y_hat=net(X)
  23. l=loss(y_hat,y)
  24. l.backward()
  25. optimizer.step()
  26. with torch.no_grad():
  27. metric.add(l*X.shape[0],d2l.accuracy(y_hat,y),X.shape[0])
  28. timer.stop()
  29. train_l=metric[0]/metric[1]
  30. train_acc=metric[1]/metric[2]
  31. if (i+1)%(num_batches//5)==0 or i==num_batches-1:
  32. animator.add(epoch+(i+1)/num_batches,(train_l,train_acc,None))
  33. test_acc=evaluate_accuracy_gpu(net,test_iter)
  34. animator.add(epoch+1,(None,None,test_acc))
  35. print(f'loss {train_l:.3f}, train acc {train_acc:.3f}, '
  36. f'test acc {test_acc:.3f}')
  37. print(f'{metric[2] * num_epochs / timer.sum():.1f} examples/sec '
  38. f'on {str(device)}')
  1. lr, num_epochs = 0.9, 10
  2. train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())