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:


浙公网安备 33010602011771号