pytorch-day06(CNN)

1、什么是卷积

    

 

                    

 

         

 

 感受野(局部相关性,一次感受一个视野(一个小方块))

      

 参数变小(参数总数:每个小方块的参数总数,权值共享

  

  卷积操作:(小方块)相乘再相累加的操作

    

    


2、卷积神经网络

  

  

 

  

 

   


3、池化层(降维)

 Max pooling:

    

 同样还有Avg pooling等

 

   

   

      

   

     


 

 4、inplace=True

 inplace=True的意思是进行原地操作,例如x=x+5,对x就是一个原地操作,y=x+5,x=y,完成了与x=x+5同样的功能但是不是原地操作,上面LeakyReLU中的inplace=True的含义是一样的,是对于Conv2d这样的上层网络传递下来的tensor直接进行修改,好处就是可以节省运算内存,不用多储存变量y。


5、BatchNorm

    

 

   

 

   

    

     

   

     

 

    

 

    

 

    

 

     

 

    

  优点:收敛速度快、性能更好、健壮(稳定、可以设置更大的学习率)


6、经典神经网络

 LeNet5:

  

 实现:

 

import torch
from torch import nn
from torch.nn import functional as F


class ResBlk(nn.Module):
    """
    resnet block
    """

    def __init__(self, ch_in, ch_out, stride=1):
        """

        :param ch_in:
        :param ch_out:
        """
        super(ResBlk, self).__init__()

        # we add stride support for resbok, which is distinct from tutorials.
        self.conv1 = nn.Conv2d(ch_in, ch_out, kernel_size=3, stride=stride, padding=1)
        self.bn1 = nn.BatchNorm2d(ch_out)
        self.conv2 = nn.Conv2d(ch_out, ch_out, kernel_size=3, stride=1, padding=1)
        self.bn2 = nn.BatchNorm2d(ch_out)

        self.extra = nn.Sequential()
        if ch_out != ch_in:
            # [b, ch_in, h, w] => [b, ch_out, h, w]
            self.extra = nn.Sequential(
                nn.Conv2d(ch_in, ch_out, kernel_size=1, stride=stride),  # 1x1卷积核的作用
                nn.BatchNorm2d(ch_out)
            )

    def forward(self, x):
        """

        :param x: [b, ch, h, w]
        :return:
        """
        out = F.relu(self.bn1(self.conv1(x)))
        out = self.bn2(self.conv2(out))
        # short cut.
        # extra module: [b, ch_in, h, w] => [b, ch_out, h, w]
        # element-wise add:
        out = self.extra(x) + out
        out = F.relu(out)

        return out


class ResNet18(nn.Module):

    def __init__(self):
        super(ResNet18, self).__init__()

        self.conv1 = nn.Sequential(
            nn.Conv2d(3, 64, kernel_size=3, stride=3, padding=0),
            nn.BatchNorm2d(64)
        )
        # followed 4 blocks
        # [b, 64, h, w] => [b, 128, h ,w]
        self.blk1 = ResBlk(64, 128, stride=2)
        # [b, 128, h, w] => [b, 256, h, w]
        self.blk2 = ResBlk(128, 256, stride=2)
        # # [b, 256, h, w] => [b, 512, h, w]
        self.blk3 = ResBlk(256, 512, stride=2)
        # # [b, 512, h, w] => [b, 1024, h, w]
        self.blk4 = ResBlk(512, 512, stride=2)

        self.outlayer = nn.Linear(512 * 1 * 1, 10)

    def forward(self, x):
        """

        :param x:
        :return:
        """
        x = F.relu(self.conv1(x))

        # [b, 64, h, w] => [b, 1024, h, w]
        x = self.blk1(x)
        x = self.blk2(x)
        x = self.blk3(x)
        x = self.blk4(x)

        # print('after conv:', x.shape) #[b, 512, 2, 2]
        # [b, 512, h, w] => [b, 512, 1, 1]
        x = F.adaptive_avg_pool2d(x, [1, 1])
        # print('after pool:', x.shape)
        x = x.view(x.size(0), -1)
        x = self.outlayer(x)

        return x


def main():
    blk = ResBlk(64, 128, stride=4)
    tmp = torch.randn(2, 64, 32, 32)
    out = blk(tmp)
    print('block:', out.shape)

    x = torch.randn(2, 3, 32, 32)
    model = ResNet18()
    out = model(x)
    print('resnet:', out.shape)


if __name__ == '__main__':
    main()

 main函数:

 1 import torch
 2 from torch.utils.data import DataLoader
 3 from torchvision import datasets
 4 from torchvision import transforms
 5 from torch import nn, optim
 6 
 7 from lenet5 import Lenet5
 8 from resnet import ResNet18
 9 
10 
11 def main():
12     batchsz = 128
13 
14     cifar_train = datasets.CIFAR10('cifar', True, transform=transforms.Compose([
15         transforms.Resize((32, 32)),
16         transforms.ToTensor(),
17         transforms.Normalize(mean=[0.485, 0.456, 0.406],
18                              std=[0.229, 0.224, 0.225])
19     ]), download=True)
20     cifar_train = DataLoader(cifar_train, batch_size=batchsz, shuffle=True)
21 
22     cifar_test = datasets.CIFAR10('cifar', False, transform=transforms.Compose([
23         transforms.Resize((32, 32)),
24         transforms.ToTensor(),
25         transforms.Normalize(mean=[0.485, 0.456, 0.406],
26                              std=[0.229, 0.224, 0.225])
27     ]), download=True)
28     cifar_test = DataLoader(cifar_test, batch_size=batchsz, shuffle=True)
29 
30     x, label = iter(cifar_train).next()
31     print('x:', x.shape, 'label:', label.shape)
32 
33     device = torch.device('cuda')
34     # model = Lenet5().to(device)
35     model = ResNet18().to(device)
36 
37     criteon = nn.CrossEntropyLoss().to(device)
38     optimizer = optim.Adam(model.parameters(), lr=1e-3)
39     print(model)
40 
41     for epoch in range(1000):
42 
43         model.train()
44         for batchidx, (x, label) in enumerate(cifar_train):
45             # [b, 3, 32, 32]
46             # [b]
47             x, label = x.to(device), label.to(device)
48 
49             logits = model(x)
50             # logits: [b, 10]
51             # label:  [b]
52             # loss: tensor scalar
53             loss = criteon(logits, label)
54 
55             # backprop
56             optimizer.zero_grad()
57             loss.backward()
58             optimizer.step()
59 
60         print(epoch, 'loss:', loss.item())
61 
62         model.eval() # 例如设置Dropout=0
63         with torch.no_grad(): # 不需要返现传播,即不需要backward(),即不需要计算梯度
64             # test
65             total_correct = 0
66             total_num = 0
67             for x, label in cifar_test:
68                 # [b, 3, 32, 32]
69                 # [b]
70                 x, label = x.to(device), label.to(device)
71 
72                 # [b, 10]
73                 logits = model(x)
74                 # [b]
75                 pred = logits.argmax(dim=1)
76                 # [b] vs [b] => scalar tensor
77                 correct = torch.eq(pred, label).float().sum().item()
78                 total_correct += correct
79                 total_num += x.size(0)
80                 # print(correct)
81 
82             acc = total_correct / total_num
83             print(epoch, 'test acc:', acc)
84 
85 
86 if __name__ == '__main__':
87     main()

 

 AlexNet:

  

 VGG:

  

 注意:1 x 1卷积核的作用

    1、更少的计算(1x1的卷积核比3x3的运算更少,但是也完成了卷积运算)

    2、维度的改变,如下

      

 GoogleNet:

  

  


7、ResNet(深度残差网络)

  

 

  

  

  实现:

  1 import torch
  2 from torch import nn
  3 from torch.nn import functional as F
  4 
  5 
  6 class ResBlk(nn.Module):
  7     """
  8     resnet block
  9     """
 10 
 11     def __init__(self, ch_in, ch_out, stride=1):
 12         """
 13 
 14         :param ch_in:
 15         :param ch_out:
 16         """
 17         super(ResBlk, self).__init__()
 18 
 19         # we add stride support for resbok, which is distinct from tutorials.
 20         self.conv1 = nn.Conv2d(ch_in, ch_out, kernel_size=3, stride=stride, padding=1)
 21         self.bn1 = nn.BatchNorm2d(ch_out)
 22         self.conv2 = nn.Conv2d(ch_out, ch_out, kernel_size=3, stride=1, padding=1)
 23         self.bn2 = nn.BatchNorm2d(ch_out)
 24 
 25         self.extra = nn.Sequential()
 26         if ch_out != ch_in:
 27             # [b, ch_in, h, w] => [b, ch_out, h, w]
 28             self.extra = nn.Sequential(
 29                 nn.Conv2d(ch_in, ch_out, kernel_size=1, stride=stride),  # 1x1卷积核的作用
 30                 nn.BatchNorm2d(ch_out)
 31             )
 32 
 33     def forward(self, x):
 34         """
 35 
 36         :param x: [b, ch, h, w]
 37         :return:
 38         """
 39         out = F.relu(self.bn1(self.conv1(x)))
 40         out = self.bn2(self.conv2(out))
 41         # short cut.
 42         # extra module: [b, ch_in, h, w] => [b, ch_out, h, w]
 43         # element-wise add:
 44         out = self.extra(x) + out
 45         out = F.relu(out)
 46 
 47         return out
 48 
 49 
 50 class ResNet18(nn.Module):
 51 
 52     def __init__(self):
 53         super(ResNet18, self).__init__()
 54 
 55         self.conv1 = nn.Sequential(
 56             nn.Conv2d(3, 64, kernel_size=3, stride=3, padding=0),
 57             nn.BatchNorm2d(64)
 58         )
 59         # followed 4 blocks
 60         # [b, 64, h, w] => [b, 128, h ,w]
 61         self.blk1 = ResBlk(64, 128, stride=2)
 62         # [b, 128, h, w] => [b, 256, h, w]
 63         self.blk2 = ResBlk(128, 256, stride=2)
 64         # # [b, 256, h, w] => [b, 512, h, w]
 65         self.blk3 = ResBlk(256, 512, stride=2)
 66         # # [b, 512, h, w] => [b, 1024, h, w]
 67         self.blk4 = ResBlk(512, 512, stride=2)
 68 
 69         self.outlayer = nn.Linear(512 * 1 * 1, 10)
 70 
 71     def forward(self, x):
 72         """
 73 
 74         :param x:
 75         :return:
 76         """
 77         x = F.relu(self.conv1(x))
 78 
 79         # [b, 64, h, w] => [b, 1024, h, w]
 80         x = self.blk1(x)
 81         x = self.blk2(x)
 82         x = self.blk3(x)
 83         x = self.blk4(x)
 84 
 85         # print('after conv:', x.shape) #[b, 512, 2, 2]
 86         # [b, 512, h, w] => [b, 512, 1, 1]
 87         x = F.adaptive_avg_pool2d(x, [1, 1])
 88         # print('after pool:', x.shape)
 89         x = x.view(x.size(0), -1)
 90         x = self.outlayer(x)
 91 
 92         return x
 93 
 94 
 95 def main():
 96     blk = ResBlk(64, 128, stride=4)
 97     tmp = torch.randn(2, 64, 32, 32)
 98     out = blk(tmp)
 99     print('block:', out.shape)
100 
101     x = torch.randn(2, 3, 32, 32)
102     model = ResNet18()
103     out = model(x)
104     print('resnet:', out.shape)
105 
106 
107 if __name__ == '__main__':
108     main()

 main函数:

 1 import torch
 2 from torch.utils.data import DataLoader
 3 from torchvision import datasets
 4 from torchvision import transforms
 5 from torch import nn, optim
 6 
 7 from lenet5 import Lenet5
 8 from resnet import ResNet18
 9 
10 
11 def main():
12     batchsz = 128
13 
14     cifar_train = datasets.CIFAR10('cifar', True, transform=transforms.Compose([
15         transforms.Resize((32, 32)),
16         transforms.ToTensor(),
17         transforms.Normalize(mean=[0.485, 0.456, 0.406],
18                              std=[0.229, 0.224, 0.225])
19     ]), download=True)
20     cifar_train = DataLoader(cifar_train, batch_size=batchsz, shuffle=True)
21 
22     cifar_test = datasets.CIFAR10('cifar', False, transform=transforms.Compose([
23         transforms.Resize((32, 32)),
24         transforms.ToTensor(),
25         transforms.Normalize(mean=[0.485, 0.456, 0.406],
26                              std=[0.229, 0.224, 0.225])
27     ]), download=True)
28     cifar_test = DataLoader(cifar_test, batch_size=batchsz, shuffle=True)
29 
30     x, label = iter(cifar_train).next()
31     print('x:', x.shape, 'label:', label.shape)
32 
33     device = torch.device('cuda')
34     # model = Lenet5().to(device)
35     model = ResNet18().to(device)
36 
37     criteon = nn.CrossEntropyLoss().to(device)
38     optimizer = optim.Adam(model.parameters(), lr=1e-3)
39     print(model)
40 
41     for epoch in range(1000):
42 
43         model.train()
44         for batchidx, (x, label) in enumerate(cifar_train):
45             # [b, 3, 32, 32]
46             # [b]
47             x, label = x.to(device), label.to(device)
48 
49             logits = model(x)
50             # logits: [b, 10]
51             # label:  [b]
52             # loss: tensor scalar
53             loss = criteon(logits, label)
54 
55             # backprop
56             optimizer.zero_grad()
57             loss.backward()
58             optimizer.step()
59 
60         print(epoch, 'loss:', loss.item())
61 
62         model.eval()
63         with torch.no_grad():
64             # test
65             total_correct = 0
66             total_num = 0
67             for x, label in cifar_test:
68                 # [b, 3, 32, 32]
69                 # [b]
70                 x, label = x.to(device), label.to(device)
71 
72                 # [b, 10]
73                 logits = model(x)
74                 # [b]
75                 pred = logits.argmax(dim=1)
76                 # [b] vs [b] => scalar tensor
77                 correct = torch.eq(pred, label).float().sum().item()
78                 total_correct += correct
79                 total_num += x.size(0)
80                 # print(correct)
81 
82             acc = total_correct / total_num
83             print(epoch, 'test acc:', acc)
84 
85 
86 if __name__ == '__main__':
87     main()

 

 DenseNet:

  


 

posted @ 2020-07-29 10:41  小吴的日常  阅读(127)  评论(0)    收藏  举报