在FASHION-MNIST上訓練CNN


案例源碼鏈接 http://studyai.com/pytorch-1.2/beginner/fanshionmnist_tutorial.html

PyTorch環境配置Pycharm使用參考我博客。

1、打開PyCharm,創建項目,新建python文件,hello.py

從上到下依次粘貼鏈接的代碼,注意修改如下:

① 添加代碼,其后的所有代碼必須縮進  if __name__ == "__main__":

② transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

改為

transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])

因為處理的是單通道的灰度圖,而不是三通道。為什么是這兩個數,點擊參考?

2、下載FASHION-MNIST數據,放到項目目錄..\PycharmProjects\untitled4\data\fashiomnist\FashionMNIST\raw,運行程序會自動解壓的。

 3、運行程序

【全部程序如下】

import matplotlib.pyplot as plt
import numpy as np
import torch
import torchvision
import torchvision.transforms as transforms

print("PyTorch Version: ", torch.__version__)
print("Torchvision Version: ", torchvision.__version__)

# 忽略 warnings
import warnings
warnings.filterwarnings("ignore")

if __name__ == "__main__":

    ############################### 1 使用 torchvision 加載和規范訓練和測試數據集

    batch_size = 16

    #transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
    transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])

    trainset = torchvision.datasets.FashionMNIST(root='./data/fashiomnist', train=True, download=True, transform=transform)
    trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size, shuffle=True, num_workers=2)

    testset = torchvision.datasets.FashionMNIST(root='./data/fashiomnist', train=False, download=True, transform=transform)
    testloader = torch.utils.data.DataLoader(testset, batch_size=batch_size, shuffle=False, num_workers=2)

    classes = ('T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot')

    print("訓練集大小:", len(trainloader) * batch_size)
    print("測試集大小:", len(testloader) * batch_size)


    ########################################## 展示訓練集中的圖片
    # 用於顯示一張圖像的函數
    def imshow(img):
        img = img / 2 + 0.5  # 去歸一化
        npimg = img.numpy()
        plt.imshow(np.transpose(npimg, (1, 2, 0)))


    # 獲取一個批次的圖像,一次迭代取出batch_size張圖片
    dataiter = iter(trainloader)
    images, labels = dataiter.next()

    # 顯示一個批次的圖像
    imshow(torchvision.utils.make_grid(images))
    # 輸出 對應批次圖像的標簽
    print(' '.join('%5s' % classes[labels[j]] for j in range(batch_size)))

    ######################################## 定義網絡模型
    import torch.nn as nn
    import torch.nn.functional as F


    class Net1(nn.Module):
        def __init__(self):
            super(Net1, self).__init__()
            self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
            self.conv2 = nn.Conv2d(10, 20, kernel_size=5)
            self.conv2_drop = nn.Dropout2d()
            self.fc1 = nn.Linear(320, 50)
            self.fc2 = nn.Linear(50, 10)
            self.bn = nn.BatchNorm2d(20)

        def forward(self, x):
            x = F.max_pool2d(self.conv1(x), 2)
            x = F.relu(x) + F.relu(-x)
            x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))
            x = self.bn(x)
            x = x.view(-1, 320)
            x = F.relu(self.fc1(x))
            x = F.dropout(x, training=self.training)
            x = self.fc2(x)
            x = F.softmax(x, dim=1)
            return x


    class Net2(nn.Module):
        def __init__(self):
            super(Net2, self).__init__()
            self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
            self.conv2 = nn.Conv2d(10, 20, kernel_size=5)
            self.conv2_drop = nn.Dropout2d()
            self.fc1 = nn.Linear(320, 50)
            self.fc2 = nn.Linear(50, 10)

        def forward(self, x):
            x = F.relu(F.max_pool2d(self.conv1(x), 2))
            x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))
            x = x.view(-1, 320)
            x = F.relu(self.fc1(x))
            x = F.dropout(x, training=self.training)
            x = self.fc2(x)
            x = F.log_softmax(x, dim=1)
            return x


    class Net3(nn.Module):
        """ Simple network"""

        def __init__(self):
            super().__init__()
            self.features = nn.Sequential(
                nn.Conv2d(1, 32, kernel_size=3, padding=1),  # 28
                nn.ReLU(inplace=True),
                nn.MaxPool2d(kernel_size=2, stride=2),  # 14

                nn.Conv2d(32, 64, kernel_size=3, padding=1),
                nn.ReLU(inplace=True),
                nn.MaxPool2d(kernel_size=2, stride=2)  # 7
            )
            self.classifier = nn.Sequential(
                nn.Dropout(),
                nn.Linear(64 * 7 * 7, 128),
                nn.ReLU(inplace=True),
                nn.Linear(128, 10)
            )

        def forward(self, x):
            x = self.features(x)
            x = x.view(x.size(0), 64 * 7 * 7)
            x = self.classifier(x)
            return x

    ################################### 將模型寫入文件並用TensorBoard查看
    from tensorboardX import SummaryWriter

    # 無意義輸入,與MNIST的一個batch數據的shape相同
    dummy_input = torch.autograd.Variable(torch.rand(batch_size, 1, 28, 28))

    model1 = Net1()
    print(model1)
    with SummaryWriter(comment='_fashionmnist_net1') as w:
        w.add_graph(model1, (dummy_input,))

    model2 = Net2()
    print(model2)
    with SummaryWriter(comment='_fashionmnist_net2') as w:
        w.add_graph(model2, (dummy_input,))

    model3 = Net3()
    print(model3)
    with SummaryWriter(comment='_fashionmnist_net3') as w:
        w.add_graph(model3, (dummy_input,))

    ################################## 定義損失函數和優化器
    import torch.optim as optim

    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    print(device)

    # 選擇上面定義的任意一個模型 model1,model2,model3,...
    net = model3.to(device)  # or = model2

    loss = nn.CrossEntropyLoss()
    optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

    writer = SummaryWriter(comment='_fashionmnist_logs')

    ########################################################### 計算初始網絡的准確率
    correct = 0
    total = 0
    with torch.no_grad():
        for data in testloader:
            images, labels = data[0].to(device), data[1].to(device)
            outputs = net(images)
            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()

    print('Accuracy of the network on the 10000 test images: %d %%' % (100 * correct / total))

    ##開始訓練
    num_epochs = 10
    num_batches = len(trainloader)
    for epoch in range(num_epochs):
        running_loss = 0.0
        for step, data in enumerate(trainloader):
            n_iter = epoch * num_batches + step
            images, labels = data[0].to(device), data[1].to(device)
            # 將梯度清零
            optimizer.zero_grad()
            # 向前傳遞
            out = net(images)
            # 計算損失
            loss_value = loss(out, labels)
            # 向后傳遞
            loss_value.backward()
            # 優化
            optimizer.step()
            # 記錄日志
            writer.add_scalar('loss', loss_value.item(), n_iter)
            running_loss += loss_value.item()

            if step % 500 == 499:  # 每 500 個 mini-batches 就輸出一次訓練信息
                print('[%d, %5d] loss: %.3f' % (epoch + 1, step + 1, running_loss / 500))
                running_loss = 0.0

    writer.close()
    print('Finished Training')

    ############################################################ 開始測試
    correct = 0
    total = 0
    with torch.no_grad():
        for data in testloader:
            images, labels = data[0].to(device), data[1].to(device)
            outputs = net(images)
            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()

    print('Accuracy of the network on the 10000 test images: %d %%' % (100 * correct / total))

    ############################################################ 展示每個樣本上的准確率
    num_classes = len(classes)
    class_correct = list(0. for i in range(num_classes))
    class_total = list(0. for i in range(num_classes))
    with torch.no_grad():
        for data in testloader:
            images, labels = data[0].to(device), data[1].to(device)
            outputs = net(images)
            _, predicted = torch.max(outputs, 1)
            c = (predicted == labels).squeeze()
            for i in range(batch_size):
                label = labels[i]
                class_correct[label] += c[i].item()
                class_total[label] += 1

    for i in range(num_classes):
        print('Accuracy of %5s : %2d %%' % (classes[i], 100 * class_correct[i] / class_total[i]))

    ############################################ 展示測試樣本、真實標簽和測試標簽
    dataiter = iter(testloader)
    images, labels = dataiter.next()

    # print images
    imshow(torchvision.utils.make_grid(images))
    print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(batch_size)))

    outputs = net(images.to(device))
    _, predicted = torch.max(outputs, 1)

    print('Predicted: ', ' '.join('%5s' % classes[predicted[j]] for j in range(batch_size)))

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM