《PyTorch 深度学习实践 》-刘二大人 第十一讲
CNN用于图像识别
最后accuracy on test set:98%
1 import torch 2 import torch.nn as nn 3 from torchvision import transforms 4 from torchvision import datasets 5 from torch.utils.data import DataLoader 6 import torch.nn.functional as F 7 import torch.optim as optim 8 9 # prepare dataset 10 batch_size = 64 11 transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))]) # 归一化,均值和方差 12 13 train_dataset = datasets.MNIST(root='../dataset/mnist/', train=True, download=True, transform=transform) 14 train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size) 15 test_dataset = datasets.MNIST(root='../dataset/mnist/', train=False, download=True, transform=transform) 16 test_loader = DataLoader(test_dataset, shuffle=False, batch_size=batch_size) 17 18 19 # design model using class 20 class InceptionA(nn.Module): 21 def __init__(self, in_channels): 22 super(InceptionA, self).__init__() 23 self.branch1x1 = nn.Conv2d(in_channels, 16, kernel_size=1) 24 25 self.branch5x5_1 = nn.Conv2d(in_channels, 16, kernel_size=1) 26 self.branch5x5_2 = nn.Conv2d(16, 24, kernel_size=5, padding=2) 27 28 self.branch3x3_1 = nn.Conv2d(in_channels, 16, kernel_size=1) 29 self.branch3x3_2 = nn.Conv2d(16, 24, kernel_size=3, padding=1) 30 self.branch3x3_3 = nn.Conv2d(24, 24, kernel_size=3, padding=1) 31 32 self.branch_pool = nn.Conv2d(in_channels, 24, kernel_size=1) 33 34 def forward(self, x): 35 branch1x1 = self.branch1x1(x) 36 37 branch5x5 = self.branch5x5_1(x) 38 branch5x5 = self.branch5x5_2(branch5x5) 39 40 branch3x3 = self.branch3x3_1(x) 41 branch3x3 = self.branch3x3_2(branch3x3) 42 branch3x3 = self.branch3x3_3(branch3x3) 43 44 branch_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1) 45 branch_pool = self.branch_pool(branch_pool) 46 47 outputs = [branch1x1, branch5x5, branch3x3, branch_pool] 48 return torch.cat(outputs, dim=1) # b,c,w,h c对应的是dim=1 49 50 51 class Net(nn.Module): 52 def __init__(self): 53 super(Net, self).__init__() 54 self.conv1 = nn.Conv2d(1, 10, kernel_size=5) 55 self.conv2 = nn.Conv2d(88, 20, kernel_size=5) # 88 = 24x3 + 16 56 57 self.incep1 = InceptionA(in_channels=10) # 与conv1 中的10对应 58 self.incep2 = InceptionA(in_channels=20) # 与conv2 中的20对应 59 60 self.mp = nn.MaxPool2d(2) 61 self.fc = nn.Linear(1408, 10) 62 63 def forward(self, x): 64 in_size = x.size(0) 65 x = F.relu(self.mp(self.conv1(x))) 66 x = self.incep1(x) 67 x = F.relu(self.mp(self.conv2(x))) 68 x = self.incep2(x) 69 x = x.view(in_size, -1) 70 x = self.fc(x) 71 72 return x 73 model = Net() 74 #使用GPU 75 device = torch.device("cuda" if torch.cuda.is_available() else "cpu") 76 model.to(device) 77 78 # construct loss and optimizer 79 criterion = torch.nn.CrossEntropyLoss() 80 optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5) 81 82 83 # training cycle forward, backward, update 84 def train(epoch): 85 running_loss = 0.0 86 for batch_idx, data in enumerate(train_loader, 0): 87 inputs, target = data 88 inputs, target = inputs.to(device), target.to(device) 89 optimizer.zero_grad() 90 91 outputs = model(inputs) 92 loss = criterion(outputs, target) 93 loss.backward() 94 optimizer.step() 95 96 running_loss += loss.item() 97 if batch_idx % 300 == 299: 98 print('[%d, %5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 300)) 99 running_loss = 0.0 100 101 102 def hehe(): 103 correct = 0 104 total = 0 105 with torch.no_grad(): 106 for data in test_loader: 107 images, labels = data 108 images, labels = images.to(device), labels.to(device) 109 outputs = model(images) 110 _, predicted = torch.max(outputs.data, dim=1) 111 total += labels.size(0) 112 correct += (predicted == labels).sum().item() 113 print('accuracy on test set: %d %% ' % (100 * correct / total)) 114 115 116 if __name__ == '__main__': 117 for epoch in range(10): 118 train(epoch) 119 hehe()
加入Residual,解决梯度消失的问题,即在网络里面加入了跳连接,H(x) = F(x) + x,张量维度必须一样,加完后再激活。
(Residual是华人何凯明和他的团队提出来的,简直就是华人之光啊~)
最后accuracy on test set:99%
1 import torch 2 import torch.nn as nn 3 from torchvision import transforms 4 from torchvision import datasets 5 from torch.utils.data import DataLoader 6 import torch.nn.functional as F 7 import torch.optim as optim 8 9 # prepare dataset 10 batch_size = 64 11 #ToTensor()将shape为(H, W, C)的nump.ndarray或img转为shape为(C, H, W)的tensor 12 # transforms.Normalize()将每一个数值归一化到[0,1],0.1307,0.3081是MNIST数据集的均值和方差 13 transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))]) # 归一化,均值和方差 14 15 train_dataset = datasets.MNIST(root='../dataset/mnist/', train=True, download=True, transform=transform) 16 train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size) 17 test_dataset = datasets.MNIST(root='../dataset/mnist/', train=False, download=True, transform=transform) 18 test_loader = DataLoader(test_dataset, shuffle=False, batch_size=batch_size) 19 20 21 # design model using class 22 class ResidualBlock(nn.Module): 23 def __init__(self, channels): 24 super(ResidualBlock, self).__init__() 25 self.channels = channels 26 self.conv1 = nn.Conv2d(channels, channels, kernel_size=3, padding=1) 27 self.conv2 = nn.Conv2d(channels, channels, kernel_size=3, padding=1) 28 29 def forward(self, x): 30 y = F.relu(self.conv1(x)) 31 y = self.conv2(y) 32 return F.relu(x + y) 33 34 35 class Net(nn.Module): 36 def __init__(self): 37 super(Net, self).__init__() 38 self.conv1 = nn.Conv2d(1, 16, kernel_size=5) 39 self.conv2 = nn.Conv2d(16, 32, kernel_size=5) # 88 = 24x3 + 16 40 41 self.rblock1 = ResidualBlock(16) 42 self.rblock2 = ResidualBlock(32) 43 44 self.mp = nn.MaxPool2d(2) 45 self.fc = nn.Linear(512, 10) # 暂时不知道1408咋能自动出来的 46 47 def forward(self, x): 48 in_size = x.size(0) 49 50 x = self.mp(F.relu(self.conv1(x))) 51 x = self.rblock1(x) 52 x = self.mp(F.relu(self.conv2(x))) 53 x = self.rblock2(x) 54 55 x = x.view(in_size, -1) 56 x = self.fc(x) 57 return x 58 59 60 model = Net() 61 #使用GPU 62 device = torch.device("cuda" if torch.cuda.is_available() else "cpu") 63 model.to(device) 64 65 # construct loss and optimizer 66 criterion = torch.nn.CrossEntropyLoss() 67 optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5) 68 69 70 # training cycle forward, backward, update 71 def train(epoch): 72 running_loss = 0.0 73 for batch_idx, data in enumerate(train_loader, 0): 74 inputs, target = data 75 inputs, target = inputs.to(device), target.to(device) 76 optimizer.zero_grad() 77 78 outputs = model(inputs) 79 loss = criterion(outputs, target) 80 loss.backward() 81 optimizer.step() 82 83 running_loss += loss.item() 84 if batch_idx % 300 == 299: 85 print('[%d, %5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 300)) 86 running_loss = 0.0 87 88 89 def hehe(): 90 correct = 0 91 total = 0 92 with torch.no_grad(): 93 for data in test_loader: 94 images, labels = data 95 images, labels = images.to(device), labels.to(device) 96 outputs = model(images) 97 _, predicted = torch.max(outputs.data, dim=1) 98 total += labels.size(0) 99 correct += (predicted == labels).sum().item() 100 print('accuracy on test set: %d %% ' % (100 * correct / total)) 101 102 103 if __name__ == '__main__': 104 for epoch in range(10): 105 train(epoch) 106 hehe()
accuracy on test set: 98 %
[9, 300] loss: 0.025
[9, 600] loss: 0.025
[9, 900] loss: 0.022
accuracy on test set: 98 %
[10, 300] loss: 0.021
[10, 600] loss: 0.021
[10, 900] loss: 0.023
accuracy on test set: 99 %