1. 程式人生 > >pytorch文件筆記4-訓練分類器

pytorch文件筆記4-訓練分類器

 

"""

    分類器:

    @在神經網路一節中,輸入資料都是隨機資料,這裡換為真實的資料進行一個簡單的訓練;一般資料分為影象、文字、音視訊等。

    對於影象,Pillow,OpenCV等軟體包很有用

    對於音訊,請使用scipy和librosa等軟體包

    對於文字,基於Python或Cython的原始載入,或者NLTK和SpaCy很有用

 

    @一般在c++中我們會使用opencv進行影象載入,至於載入的函式如loadimage或者imread都是由opencv提供的,在pytorch中也封裝了類似的

    包,在torchvision中。這個包基本上有最常見的資料載入器;其中最常見的資料載入器包括:

        torchvision.datasets和torch.utils.data.DataLoader;

    

    @訓練影象分類器常見步驟如下:

    使用以下命令載入和標準化CIFAR10訓練和測試資料集 torchvision

    定義卷積神經網路

    定義損失函式

    根據訓練資料訓練網路

    在測試資料上測試網路

"""

 

import torch

#包含了目前流行的資料集,模型結構和常用的圖片轉換工具

import torchvision

"""

transforms有以下幾個主要功能:

    Compose 組合多個功能步驟為一個步驟;

    CenterCrop 進行中心切割

    RandomCrop 進行隨機切割

    RandomHorizontalFlip 隨機水平翻轉

    RandomSizedCrop 隨機剪下及重設大小

    Pad 填充

    Normalize 正規化

    ToTensor 轉換為pytorch支援的Tensor

    ToPILImage 轉換為PIL影象

    Lambda 使用lambd轉換器

"""

import torchvision.transforms as transforms # 主要用於影象一些基本變換以及一些簡單格式封裝

 

"""

把一個取值範圍是[0,255]的PIL.Image或者shape為(H,W,C)的numpy.ndarray,轉換成形狀為[C,H,W],取值範圍是[0,1.0]的torch.FloadTensor;

給定均值:(R,G,B) 方差:(R,G,B),將會把Tensor正則化。即:Normalized_image=(image-mean)/std;

方差反應資料的偏離程度,標準差主要是利於我們肉眼檢視。

"""

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

 

# train為True表示訓練集,為False表示測試集;download表示是否從網際網路進行下載,transforms表示預處理方式,

# 主要目的是將這些如PIL形式資料轉成pytorch支援的;

trainset = torchvision.datasets.CIFAR10(root='./data',train=True,download=False,transform=transform)

 

#shuffle表示是否需要打亂資料。

trainloader = torch.utils.data.DataLoader(trainset,batch_size=4,shuffle=True,num_workers=0)

testset = torchvision.datasets.CIFAR10(root='./data',train=False,download=False,transform=transform)

testloader = torch.utils.data.DataLoader(testset,batch_size=4,shuffle=False,num_workers=0)

 

classes=('plane', 'car', 'bird', 'cat','deer', 'dog', 'frog', 'horse', 'ship', 'truck')

import matplotlib.pyplot as plt 

import numpy as np

def imshow(img):

    img = img/2+0.5

    npimg = img.numpy()

    plt.imshow(np.transpose(npimg,(1,2,0)))#進行軸對換

    plt.show()

 

dataiter = iter(trainloader)#執行到此步驟失敗,需要將之前的num_workers改為0

images,labels = dataiter.next()#這裡注意指向的是第一個元素並非下一個元素

imshow(torchvision.utils.make_grid(images))#網格顯示

print(' '.join('%5s'%classes[labels[j]] for j in range(4)))

 

#定義卷積神經網路

import torch.nn as nn

import torch.nn.functional as F


 

class Net(nn.Module):

    def __init__(self):

        super(Net, self).__init__()

        self.conv1 = nn.Conv2d(3, 6, 5)

        self.pool = nn.MaxPool2d(2, 2)

        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 = self.pool(F.relu(self.conv1(x)))

        x = self.pool(F.relu(self.conv2(x)))

        x = x.view(-1, 16 * 5 * 5)

        x = F.relu(self.fc1(x))

        x = F.relu(self.fc2(x))

        x = self.fc3(x)

        return x


 

net = Net()

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

print(device)

net.to(device)

#定義損失函式和優化器

import torch.optim as optim

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):# 0代表下標起始位置

        #inputs,labels = data #使用CPU

        inputs, labels = data[0].to(device), data[1].to(device)#  使用GPU

        optimizer.zero_grad()

        outputs = net(inputs)

        loss = criterion(outputs,labels)

        loss.backward()

        optimizer.step()

 

        running_loss += loss.item()

        if i % 2000 == 1999:

            print('[%d ,%5d] loss:%.3f'%(epoch+1,i+1,running_loss/2000))

            running_loss =0.0

print('trainning finished')

 

#測試網路

dataiter = iter(testloader)

images,labels = dataiter.next()

imshow(torchvision.utils.make_grid(images))

print('GroundTruth: ',' '.join('%5s'%classes[labels[j]] for j in range(4)))

 

outputs = net(images)

_,predicted = torch.max(outputs,1)#1代表返回最大元素在這一行的列索引

 

#整個資料集表現

correct = 0

total = 0

with torch.no_grad():

    for data in testloader:

        images,labels = data

        outputs = net(images)

        _,predicted = torch.max(outputs.data,1)

        total += labels.size(0)

        correct += (predicted==labels).sum().item()

print('正確率:%d %%'%(100*correct/total))

 

class_correct = list(0. for i in range(10))

class_total = list(0. for i in range(10))

with torch.no_grad():

    for data in testloader:

        images,labels = data

        outputs = net(images)

        _,predicted = torch.max(outputs,1)

        c = (predicted==labels).squeeze()#壓縮

        for i in range(4):

            label = labels[i]

            class_correct[label] += c[i].item()

            class_total[label] += 1

for i in range(10):

    print('%5s正確率:%2d %% '%(classes[i],100*class_correct[i]/class_total[i]))