《深度學習框架PyTorch入門與實踐》示例——利用LeNet進行CIFAR-10分類
阿新 • • 發佈:2020-11-23
平臺及框架:python3 + anaconda + pytorch + pycharm
我主要是根據陳雲的《深度學習框架PyTorch入門與實踐》來學習的,書中第二章的一個示例是利用卷積神經網路LeNet進行CIFAR-10分類。
原書中的程式碼是在IPython或Jupyter Notebook中寫的,在pycharm中寫的時候遇到一些問題,在程式碼中有註釋。
下面附上LeNet進行CIFAR-10分類的python程式碼:
import torch as t from torch.autograd import Variable import torch.nn as nn import torch.nn.functional as Fimport torchvision as tv import torchvision.transforms as transforms from torchvision.transforms import ToPILImage from torch import optim show = ToPILImage() # 資料預處理 transform = transforms.Compose([ transforms.ToTensor(), # 轉為Tensor transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),# 資料歸一化 # ToTensor()能夠把灰度範圍從0-255變換到0-1之間,而後面的transform.Normalize()則把0-1變換到(-1,1) # image=(image-mean)/std # 其中mean和std分別通過(0.5,0.5,0.5)和(0.5,0.5,0.5)進行指定。原來的0-1最小值0則變成(0-0.5)/0.5=-1,而最大值1則變成(1-0.5)/0.5=1 # 前面的(0.5,0.5,0.5)是RGB三個通道上的均值, 後面(0.5, 0.5, 0.5)是三個通道的標準差 ]) if __name__ == '__main__': #輸出4張圖片時,返回多執行緒出錯的解決方法 # 訓練集 trainset = tv.datasets.CIFAR10(root='E:/pycharm projects/book1/data', train=True, download=True, transform=transform) trainloader = t.utils.data.DataLoader( trainset, batch_size=4, shuffle=True, num_workers=2 ) # 測試集 testset = tv.datasets.CIFAR10( 'E:/pycharm projects/book1/data', train=False, download=True, transform=transform ) testloader = t.utils.data.DataLoader( testset, batch_size=4, shuffle=False, num_workers=2 ) classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck') # (data, label) = trainset[100] # print(classes[label]) # show((data + 1) / 2).resize((100, 100)).show() # 按照書中不加.show()無法打印出圖片 # dataiter = iter(trainloader) # images, labels = dataiter.next() # print(' '.join('%11s' % classes[labels[j]] for j in range(4))) # show(tv.utils.make_grid((images + 1) / 2)).resize((400, 100)).show() # 定義網路 class Net(nn.Module): def __init__(self): # 執行父類的建構函式 super(Net, self).__init__() # '1':輸入圖片為單通道 # '6':輸出通道數 # '5':卷積核5*5 # 輸入層 self.conv1 = nn.Conv2d(3, 6, 5) # ‘3’表示三通道彩圖 # 卷積層 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 = F.max_pool2d(F.relu(self.conv1(x)), (2, 2)) x = F.max_pool2d(F.relu(self.conv2(x)), 2) # reshape, "-1"表示自適應 x = x.view(x.size()[0], -1) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = self.fc3(x) return x net = Net() # 定義損失函式和優化器 criterion = nn.CrossEntropyLoss() # 交叉熵損失函式 optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) for epoch in range(2): running_loss = 0.0 for i, data in enumerate(trainloader, 0): # 輸入資料 inputs, labels = data inputs, labels = Variable(inputs), Variable(labels) # 梯度清零 optimizer.zero_grad() # 前向傳播+反向傳播 outputs = net(inputs) loss = criterion(outputs, labels) loss.backward() # 更新引數 optimizer.step() running_loss += loss.data if i % 2000 == 1999: print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 2000)) running_loss = 0.0 print('Finished Training') # 測試資料集 # dataiter = iter(testloader) # images, labels = dataiter.next() # print('實際的label:', ' '.join('%08s' % classes[labels[j]] for j in range(4))) # # show(tv.utils.make_grid(images / 2 - 0.5)).resize((400, 100)).show() # # outputs = net(Variable(images)) # _, predicted = t.max(outputs.data, 1) # print('預測結果:', ' '.join('%5s' % classes[predicted[j]] for j in range(4))) correct = 0 total = 0 for data in testloader: images, labels = data outputs = net(Variable(images)) _, predicted = t.max(outputs, 1) total += labels.size(0) correct += (predicted == labels).sum() print('10000張測試集中的準確率為: %d %%' % (100 * t.true_divide(correct, total))) # tensor和int之間的除法不能直接用'/',需要用t.true_divide(correct, total)
測試結果如下: