天天看點

Pytorch 最全入門介紹,Pytorch入門看這一篇就夠了

作者:閃念基因

本文通過詳細且實踐性的方式介紹了 PyTorch 的使用,包括環境安裝、基礎知識、張量操作、自動求導機制、神經網絡建立、資料處理、模型訓練、測試以及模型的儲存和加載。

1. Pytorch簡介

Pytorch 最全入門介紹,Pytorch入門看這一篇就夠了

在這一部分,我們将會對Pytorch做一個簡單的介紹,包括它的曆史、優點以及使用場景等。

1.1 Pytorch的曆史

PyTorch是一個由Facebook的人工智能研究團隊開發的開源深度學習架構。在2016年釋出後,PyTorch很快就因其易用性、靈活性和強大的功能而在科研社群中廣受歡迎。下面我們将詳細介紹PyTorch的發展曆程。

在2016年,Facebook的AI研究團隊(FAIR)公開了PyTorch,其旨在提供一個快速,靈活且動态的深度學習架構。PyTorch的設計哲學與Python的設計哲學非常相似:易讀性和簡潔性優于隐式的複雜性。PyTorch用Python語言編寫,是Python的一種擴充,這使得其更易于學習和使用。

PyTorch在設計上取了一些大膽的決定,其中最重要的一項就是選擇動态計算圖(Dynamic Computation Graph)作為其核心。動态計算圖與其他架構(例如TensorFlow和Theano)中的靜态計算圖有着本質的差別,它允許我們在運作時改變計算圖。這使得PyTorch在處理複雜模型時更具靈活性,并且對于研究人員來說,更易于了解和調試。

在釋出後的幾年裡,PyTorch迅速在科研社群中取得了廣泛的認可。在2019年,PyTorch釋出了1.0版本,引入了一些重要的新功能,包括支援ONNX、一個新的分布式包以及對C++的前端支援等。這些功能使得PyTorch在工業界的應用更加廣泛,同時也保持了其在科研領域的強勁勢頭。

到了近兩年,PyTorch已經成為全球最流行的深度學習架構之一。其在GitHub上的星标數量超過了50k,被用在了各種各樣的項目中,從最新的研究論文到大規模的工業應用。

綜上,PyTorch的發展曆程是一部充滿創新和挑戰的曆史,它從一個科研項目發展成為了全球最流行的深度學習架構之一。在未來,我們有理由相信,PyTorch将會在深度學習領域繼續發揮重要的作用。

1.2 Pytorch的優點

PyTorch不僅是最受歡迎的深度學習架構之一,而且也是最強大的深度學習架構之一。它有許多獨特的優點,使其在學術界和工業界都受到廣泛的關注和使用。接下來我們就來詳細地探讨一下PyTorch的優點。

1. 動态計算圖

PyTorch最突出的優點之一就是它使用了動态計算圖(Dynamic Computation Graphs,DCGs),與TensorFlow和其他架構使用的靜态計算圖不同。動态計算圖允許你在運作時更改圖的行為。這使得PyTorch非常靈活,在處理不确定性或複雜性時具有優勢,是以非常适合研究和原型設計。

2. 易用性

PyTorch被設計成易于了解和使用。其API設計的直覺性使得學習和使用PyTorch成為一件非常愉快的事情。此外,由于PyTorch與Python的深度內建,它在Python程式員中非常流行。

3. 易于調試

由于PyTorch的動态性和Python性質,調試PyTorch程式變得相當直接。你可以使用Python的标準調試工具,如PDB或PyCharm,直接檢視每個操作的結果和中間變量的狀态。

4. 強大的社群支援

PyTorch的社群非常活躍和支援。官方論壇、GitHub、Stack Overflow等平台上有大量的PyTorch使用者和開發者,你可以從中找到大量的資源和幫助。

5. 廣泛的預訓練模型

PyTorch提供了大量的預訓練模型,包括但不限于ResNet,VGG,Inception,SqueezeNet,EfficientNet等等。這些預訓練模型可以幫助你快速開始新的項目。

6. 高效的GPU利用

PyTorch可以非常高效地利用NVIDIA的CUDA庫來進行GPU計算。同時,它還支援分布式計算,讓你可以在多個GPU或伺服器上訓練模型。

綜上所述,PyTorch因其易用性、靈活性、豐富的功能以及強大的社群支援,在深度學習領域中備受歡迎。

1.3 Pytorch的使用場景

PyTorch的強大功能和靈活性使其在許多深度學習應用場景中都能夠發揮重要作用。以下是PyTorch在各種應用中的一些典型用例:

1. 計算機視覺

在計算機視覺方面,PyTorch提供了許多預訓練模型(如ResNet,VGG,Inception等)和工具(如TorchVision),可以用于圖像分類、物體檢測、語義分割和圖像生成等任務。這些預訓練模型和工具大大簡化了開發計算機視覺應用的過程。

2. 自然語言處理

在自然語言處理(NLP)領域,PyTorch的動态計算圖特性使得其非常适合處理變長輸入,這對于許多NLP任務來說是非常重要的。同時,PyTorch也提供了一系列的NLP工具和預訓練模型(如Transformer,BERT等),可以幫助我們處理文本分類、情感分析、命名實體識别、機器翻譯和問答系統等任務。

3. 生成對抗網絡

生成對抗網絡(GANs)是一種強大的深度學習模型,被廣泛應用于圖像生成、圖像到圖像的轉換、樣式遷移和資料增強等任務。PyTorch的靈活性使得其非常适合開發和訓練GAN模型。

4. 強化學習

強化學習是一種學習方法,其中智能體通過與環境的互動來學習如何執行任務。PyTorch的動态計算圖和易于使用的API使得其在實作強化學習算法時表現出極高的效率。

5. 時序資料分析

在處理時序資料的任務中,如語音識别、時間序列預測等,PyTorch的動态計算圖為處理可變長度的序列資料提供了便利。同時,PyTorch提供了包括RNN、LSTM、GRU在内的各種循環神經網絡模型。

總的來說,PyTorch憑借其強大的功能和極高的靈活性,在許多深度學習的應用場景中都能夠發揮重要作用。無論你是在研究新的深度學習模型,還是在開發實際的深度學習應用,PyTorch都能夠提供強大的支援。

2. Pytorch基礎

Pytorch 最全入門介紹,Pytorch入門看這一篇就夠了

在我們開始深入使用PyTorch之前,讓我們先了解一些基礎概念和操作。這一部分将涵蓋PyTorch的基礎,包括tensor操作、GPU加速以及自動求導機制。

2.1 Tensor操作

Tensor是PyTorch中最基本的資料結構,你可以将其視為多元數組或者矩陣。PyTorch tensor和NumPy array非常相似,但是tensor還可以在GPU上運算,而NumPy array則隻能在CPU上運算。下面,我們将介紹一些基本的tensor操作。

首先,我們需要導入PyTorch庫:

import torch
           

然後,我們可以建立一個新的tensor。以下是一些建立tensor的方法:

# 建立一個未初始化的5x3矩陣
x = torch.empty(5, 3)
print(x)

# 建立一個随機初始化的5x3矩陣
x = torch.rand(5, 3)
print(x)

# 建立一個5x3的零矩陣,類型為long
x = torch.zeros(5, 3, dtype=torch.long)
print(x)

# 直接從資料建立tensor
x = torch.tensor([5.5, 3])
print(x)
           

我們還可以對已有的tensor進行操作。以下是一些基本操作:

# 建立一個tensor,并設定requires_grad=True以跟蹤計算曆史
x = torch.ones(2, 2, requires_grad=True)
print(x)

# 對tensor進行操作
y = x + 2
print(y)

# y是操作的結果,是以它有grad_fn屬性
print(y.grad_fn)

# 對y進行更多操作
z = y * y * 3
out = z.mean()

print(z, out)
           

上述操作的結果如下:

tensor([[1., 1.],
        [1., 1.]], requires_grad=True)
tensor([[3., 3.],
        [3., 3.]], grad_fn=<AddBackward0>)
<AddBackward0 object at 0x7f36c0a7f1d0>
tensor([[27., 27.],
        [27., 27.]], grad_fn=<MulBackward0>) tensor(27., grad_fn=<MeanBackward0>)
           

在PyTorch中,我們可以使用.backward()方法來計算梯度。例如:

# 因為out包含一個标量,out.backward()等價于out.backward(torch.tensor(1.))
out.backward()

# 列印梯度 d(out)/dx
print(x.grad)
           

以上是PyTorch tensor的基本操作,我們可以看到PyTorch tensor操作非常簡單和直覺。在後續的學習中,我們将會使用到更多的tensor操作,例如索引、切片、數學運算、線性代數、随機數等等。

2.2 GPU加速

在深度學習訓練中,GPU(圖形處理器)加速是非常重要的一部分。GPU的并行計算能力使得其比CPU在大規模矩陣運算上更具優勢。PyTorch提供了簡單易用的API,讓我們可以很容易地在CPU和GPU之間切換計算。

首先,我們需要檢查系統中是否存在可用的GPU。在PyTorch中,我們可以使用torch.cuda.is_available()來檢查:

import torch

# 檢查是否有可用的GPU
if torch.cuda.is_available():
    print("There is a GPU available.")
else:
    print("There is no GPU available.")
           

如果存在可用的GPU,我們可以使用.to()方法将tensor移動到GPU上:

# 建立一個tensor
x = torch.tensor([1.0, 2.0])

# 移動tensor到GPU上
if torch.cuda.is_available():
    x = x.to('cuda')
           

我們也可以直接在建立tensor的時候就指定其裝置:

# 直接在GPU上建立tensor
if torch.cuda.is_available():
    x = torch.tensor([1.0, 2.0], device='cuda')
           

在進行模型訓練時,我們通常會将模型和資料都移動到GPU上:

# 建立一個簡單的模型
model = torch.nn.Linear(10, 1)

# 建立一些資料
data = torch.randn(100, 10)

# 移動模型和資料到GPU
if torch.cuda.is_available():
    model = model.to('cuda')
    data = data.to('cuda')
           

以上就是在PyTorch中進行GPU加速的基本操作。使用GPU加速可以顯著提高深度學習模型的訓練速度。但需要注意的是,資料在CPU和GPU之間的傳輸會消耗一定的時間,是以我們應該盡量減少資料的傳輸次數。

2.3 自動求導

在深度學習中,我們經常需要進行梯度下降優化。這就需要我們計算梯度,也就是函數的導數。在PyTorch中,我們可以使用自動求導機制(autograd)來自動計算梯度。

在PyTorch中,我們可以設定tensor.requires_grad=True來追蹤其上的所有操作。完成計算後,我們可以調用.backward()方法,PyTorch會自動計算和存儲梯度。這個梯度可以通過.grad屬性進行通路。

下面是一個簡單的示例:

import torch

# 建立一個tensor并設定requires_grad=True來追蹤其計算曆史
x = torch.ones(2, 2, requires_grad=True)

# 對這個tensor做一次運算:
y = x + 2

# y是計算的結果,是以它有grad_fn屬性
print(y.grad_fn)

# 對y進行更多的操作
z = y * y * 3
out = z.mean()

print(z, out)

# 使用.backward()來進行反向傳播,計算梯度
out.backward()

# 輸出梯度d(out)/dx
print(x.grad)
           

以上示例中,out.backward()等同于out.backward(torch.tensor(1.))。如果out不是一個标量,因為tensor是矩陣,那麼在調用.backward()時需要傳入一個與out同形的權重向量進行相乘。

例如:

x = torch.randn(3, requires_grad=True)

y = x * 2
while y.data.norm() < 1000:
    y = y * 2

print(y)

v = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float)
y.backward(v)

print(x.grad)
           

以上就是PyTorch中自動求導的基本使用方法。自動求導是PyTorch的重要特性之一,它為深度學習模型的訓練提供了極大的便利。

3. PyTorch 神經網絡

Pytorch 最全入門介紹,Pytorch入門看這一篇就夠了

在掌握了PyTorch的基本使用方法之後,我們将探索一些更為進階的特性和用法。這些進階特性包括神經網絡建構、資料加載以及模型儲存和加載等等。

3.1 建構神經網絡

PyTorch提供了torch.nn庫,它是用于建構神經網絡的工具庫。torch.nn庫依賴于autograd庫來定義和計算梯度。nn.Module包含了神經網絡的層以及傳回輸出的forward(input)方法。

以下是一個簡單的神經網絡的建構示例:

import torch
import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()

        # 輸入圖像channel:1,輸出channel:6,5x5卷積核
        self.conv1 = nn.Conv2d(1, 6, 5)
        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):
        # 使用2x2視窗進行最大池化
        x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
        # 如果視窗是方的,隻需要指定一個次元
        x = F.max_pool2d(F.relu(self.conv2(x)), 2)

        x = x.view(-1, self.num_flat_features(x))

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

        return x

    def num_flat_features(self, x):
        size = x.size()[1:]  # 擷取除了batch次元之外的其他次元
        num_features = 1
        for s in size:
            num_features *= s
        return num_features

net = Net()
print(net)
           

以上就是一個簡單的神經網絡的建構方法。我們首先定義了一個Net類,這個類繼承自nn.Module。然後在__init__方法中定義了網絡的結構,在forward方法中定義了資料的流向。在網絡的建構過程中,我們可以使用任何tensor操作。

需要注意的是,backward函數(用于計算梯度)會被autograd自動建立和實作。你隻需要在nn.Module的子類中定義forward函數。

在建立好神經網絡後,我們可以使用net.parameters()方法來傳回網絡的可學習參數。

3.2 資料加載和處理

在深度學習項目中,除了模型設計之外,資料的加載和處理也是非常重要的一部分。PyTorch提供了torch.utils.data.DataLoader類,可以幫助我們友善地進行資料的加載和處理。

3.2.1 DataLoader介紹

DataLoader類提供了對資料集的并行加載,可以有效地加載大量資料,并提供了多種資料采樣方式。常用的參數有:

  • dataset:加載的資料集(Dataset對象)
  • batch_size:batch大小
  • shuffle:是否每個epoch時都打亂資料
  • num_workers:使用多程序加載的程序數,0表示不使用多程序

以下是一個簡單的使用示例:

from torch.utils.data import DataLoader
from torchvision import datasets, transforms

# 資料轉換
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])

# 下載下傳并加載訓練集
trainset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
trainloader = DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2)

# 下載下傳并加載測試集
testset = datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)
testloader = DataLoader(testset, batch_size=4, shuffle=False, num_workers=2)
           

3.2.2 自定義資料集

除了使用内置的資料集,我們也可以自定義資料集。自定義資料集需要繼承Dataset類,并實作__len__和__getitem__兩個方法。

以下是一個自定義資料集的簡單示例:

from torch.utils.data import Dataset, DataLoader

class MyDataset(Dataset):
    def __init__(self, x_tensor, y_tensor):
        self.x = x_tensor
        self.y = y_tensor

    def __getitem__(self, index):
        return (self.x[index], self.y[index])

    def __len__(self):
        return len(self.x)

x = torch.arange(10)
y = torch.arange(10) + 1

my_dataset = MyDataset(x, y)
loader = DataLoader(my_dataset, batch_size=4, shuffle=True, num_workers=0)

for x, y in loader:
    print("x:", x, "y:", y)
           

這個例子中,我們建立了一個簡單的資料集,包含10個資料。然後我們使用DataLoader加載資料,并設定了batch大小和shuffle參數。

以上就是PyTorch中資料加載和處理的主要方法,通過這些方法,我們可以友善地對資料進行加載和處理。

3.3 模型的儲存和加載

在深度學習模型的訓練過程中,我們經常需要儲存模型的參數以便于将來重新加載。這對于中斷的訓練過程的恢複,或者用于模型的分享和部署都是非常有用的。

PyTorch提供了簡單的API來儲存和加載模型。最常見的方法是使用torch.save來儲存模型的參數,然後通過torch.load來加載模型的參數。

3.3.1 儲存和加載模型參數

以下是一個簡單的示例:

# 儲存
torch.save(model.state_dict(), PATH)

# 加載
model = TheModelClass(*args, **kwargs)
model.load_state_dict(torch.load(PATH))
model.eval()
           

在儲存模型參數時,我們通常使用.state_dict()方法來擷取模型的參數。.state_dict()是一個從參數名字映射到參數值的字典對象。

在加載模型參數時,我們首先需要執行個體化一個和原模型結構相同的模型,然後使用.load_state_dict()方法加載參數。

請注意,load_state_dict()函數接受一個字典對象,而不是儲存對象的路徑。這意味着在你傳入load_state_dict()函數之前,你必須反序列化你的儲存的state_dict。

在加載模型後,我們通常調用.eval()方法将dropout和batch normalization層設定為評估模式。否則,它們會在評估模式下保持訓練模式。

3.3.2 儲存和加載整個模型

除了儲存模型的參數,我們也可以儲存整個模型。

# 儲存
torch.save(model, PATH)

# 加載
model = torch.load(PATH)
model.eval()
           

儲存整個模型會将模型的結構和參數一起儲存。這意味着在加載模型時,我們不再需要手動建立模型執行個體。但是,這種方式需要更多的磁盤空間,并且可能在某些情況下導緻代碼的混亂,是以并不總是推薦的。

以上就是PyTorch中模型的儲存和加載的基本方法。适當的儲存和加載模型可以幫助我們更好地進行模型的訓練和評估。

4. PyTorch GPT加速

Pytorch 最全入門介紹,Pytorch入門看這一篇就夠了

掌握了PyTorch的基礎和進階用法之後,我們現在要探讨一些PyTorch的進階技巧,幫助我們更好地了解和使用這個強大的深度學習架構。

4.1 使用GPU加速

PyTorch支援使用GPU進行計算,這可以大大提高訓練和推理的速度。使用GPU進行計算的核心就是将Tensor和模型轉移到GPU上。

4.1.1 判斷是否支援GPU

首先,我們需要判斷目前的環境是否支援GPU。這可以通過torch.cuda.is_available()來實作:

print(torch.cuda.is_available())  # 輸出:True 或 False
           

4.1.2 Tensor在CPU和GPU之間轉移

如果支援GPU,我們可以使用.to(device)或.cuda()方法将Tensor轉移到GPU上。同樣,我們也可以使用.cpu()方法将Tensor轉移到CPU上:

# 判斷是否支援CUDA
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# 建立一個Tensor
x = torch.rand(3, 3)

# 将Tensor轉移到GPU上
x_gpu = x.to(device)

# 或者
x_gpu = x.cuda()

# 将Tensor轉移到CPU上
x_cpu = x_gpu.cpu()
           

4.1.3 将模型轉移到GPU上

類似的,我們也可以将模型轉移到GPU上:

model = Model()
model.to(device)
           

當模型在GPU上時,我們需要確定輸入的Tensor也在GPU上,否則會報錯。

注意,将模型轉移到GPU上後,模型的所有參數和緩沖區都會轉移到GPU上。

以上就是使用GPU進行計算的基本方法。通過合理的使用GPU,我們可以大大提高模型的訓練和推理速度。

4.2 使用torchvision進行圖像操作

torchvision是一個獨立于PyTorch的包,提供了大量的圖像資料集,圖像處理工具和預訓練模型等。

4.2.1 torchvision.datasets

torchvision.datasets子產品提供了各種公共資料集,如CIFAR10、MNIST、ImageNet等,我們可以非常友善地下載下傳和使用這些資料集。例如,下面的代碼展示了如何下載下傳和加載CIFAR10資料集:

from torchvision import datasets, transforms

# 資料轉換
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])

# 下載下傳并加載訓練集
trainset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2)

# 下載下傳并加載測試集
testset = datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=4, shuffle=False, num_workers=2)
           

4.2.2 torchvision.transforms

torchvision.transforms子產品提供了各種圖像轉換的工具,我們可以使用這些工具進行圖像預處理和資料增強。例如,上面的代碼中,我們使用了Compose函數來組合了兩個圖像處理操作:ToTensor(将圖像轉換為Tensor)和Normalize(标準化圖像)。

4.2.3 torchvision.models

torchvision.models子產品提供了預訓練的模型,如ResNet、VGG、AlexNet等。我們可以非常友善地加載這些模型,并使用這些模型進行遷移學習。

import torchvision.models as models

# 加載預訓練的resnet18模型
resnet18 = models.resnet18(pretrained=True)
           

以上就是torchvision的基本使用,它為我們提供了非常豐富的工具,可以大大提升我們處理圖像資料的效率。

4.3 使用TensorBoard進行可視化

TensorBoard 是一個可視化工具,它可以幫助我們更好地了解,優化,和調試深度學習模型。PyTorch 提供了對 TensorBoard 的支援,我們可以非常友善地使用 TensorBoard 來監控模型的訓練過程,比較不同模型的性能,可視化模型結構,等等。

4.3.1 啟動 TensorBoard

要啟動 TensorBoard,我們需要在指令行中運作 tensorboard --logdir=runs 指令,其中 runs 是儲存 TensorBoard 資料的目錄。

4.3.2 記錄資料

我們可以使用 torch.utils.tensorboard 子產品來記錄資料。首先,我們需要建立一個 SummaryWriter 對象,然後通過這個對象的方法來記錄資料。

from torch.utils.tensorboard import SummaryWriter

# 建立一個 SummaryWriter 對象
writer = SummaryWriter('runs/experiment1')

# 使用 writer 來記錄資料
for n_iter in range(100):
    writer.add_scalar('Loss/train', np.random.random(), n_iter)
    writer.add_scalar('Loss/test', np.random.random(), n_iter)
    writer.add_scalar('Accuracy/train', np.random.random(), n_iter)
    writer.add_scalar('Accuracy/test', np.random.random(), n_iter)

# 關閉 writer
writer.close()
           

4.3.3 可視化模型結構

我們也可以使用 TensorBoard 來可視化模型結構。

# 添加模型
writer.add_graph(model, images)
           

4.3.4 可視化高維資料

我們還可以使用 TensorBoard 的嵌入功能來可視化高維資料,如圖像特征、詞嵌入等。

# 添加嵌入
writer.add_embedding(features, metadata=class_labels, label_img=images)
           

以上就是 TensorBoard 的基本使用方法。通過使用 TensorBoard,我們可以更好地了解和優化我們的模型。

5. PyTorch實戰案例

Pytorch 最全入門介紹,Pytorch入門看這一篇就夠了

在這一部分中,我們将通過一個實戰案例來詳細介紹如何使用PyTorch進行深度學習模型的開發。我們将使用CIFAR10資料集來訓練一個卷積神經網絡(Convolutional Neural Network,CNN)。

5.1 資料加載和預處理

首先,我們需要加載資料并進行預處理。我們将使用torchvision包來下載下傳CIFAR10資料集,并使用transforms子產品來對資料進行預處理。

import torch
from torchvision import datasets, transforms

# 定義資料預處理操作
transform = transforms.Compose([
    transforms.RandomHorizontalFlip(),  # 資料增強:随機翻轉圖檔
    transforms.RandomCrop(32, padding=4),  # 資料增強:随機裁剪圖檔
    transforms.ToTensor(),  # 将PIL.Image或者numpy.ndarray資料類型轉化為torch.FloadTensor,并歸一化到[0.0, 1.0]
    transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))  # 标準化(這裡的均值和标準差是CIFAR10資料集的)
])

# 下載下傳并加載訓練資料集
trainset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True, num_workers=2)

# 下載下傳并加載測試資料集
testset = datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=64, shuffle=False, num_workers=2)
           

在這段代碼中,我們首先定義了一系列的資料預處理操作,然後使用datasets.CIFAR10來下載下傳CIFAR10資料集并進行預處理,最後使用torch.utils.data.DataLoader來建立資料加載器,它可以幫助我們在訓練過程中按照批次擷取資料。

5.2 定義網絡模型

接下來,我們定義我們的卷積神經網絡模型。在這個案例中,我們将使用兩個卷積層和兩個全連接配接層。

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)  # 輸入通道數3,輸出通道數6,卷積核大小5
        self.pool = nn.MaxPool2d(2, 2)  # 最大池化,核大小2,步長2
        self.conv2 = nn.Conv2d(6, 16, 5)  # 輸入通道數6,輸出通道數16,卷積核大小5
        self.fc1 = nn.Linear(16 * 5 * 5, 120)  # 全連接配接層,輸入次元16*5*5,輸出次元120
        self.fc2 = nn.Linear(120, 84)  # 全連接配接層,輸入次元120,輸出次元84
        self.fc3 = nn.Linear(84, 10)  # 全連接配接層,輸入次元84,輸出次元10(CIFAR10有10類)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))  # 第一層卷積+ReLU激活函數+池化
        x = self.pool(F.relu(self.conv2(x)))  # 第二層卷積+ReLU激活函數+池化
        x = x.view(-1, 16 * 5 * 5)  # 将特征圖展平
        x = F.relu(self.fc1(x))  # 第一層全連接配接+ReLU激活函數
        x = F.relu(self.fc2(x))  # 第二層全連接配接+ReLU激活函數
        x = self.fc3(x)  # 第三層全連接配接
        return x

# 建立網絡
net = Net()
           

在這個網絡模型中,我們使用nn.Module來定義我們的網絡模型,然後在__init__方法中定義網絡的層,最後在forward方法中定義網絡的前向傳播過程。

5.3 定義損失函數和優化器

現在我們已經有了資料和模型,下一步我們需要定義損失函數和優化器。損失函數用于衡量模型的預測與真實标簽的差距,優化器則用于優化模型的參數以減少損失。

在這個案例中,我們将使用交叉熵損失函數(Cross Entropy Loss)和随機梯度下降優化器(Stochastic Gradient Descent,SGD)。

import torch.optim as optim

# 定義損失函數
criterion = nn.CrossEntropyLoss()

# 定義優化器
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
           

在這段代碼中,我們首先使用nn.CrossEntropyLoss來定義損失函數,然後使用optim.SGD來定義優化器。我們需要将網絡的參數傳遞給優化器,然後設定學習率和動量。

5.4 訓練網絡

一切準備就緒後,我們開始訓練網絡。在訓練過程中,我們首先通過網絡進行前向傳播得到輸出,然後計算輸出與真實标簽的損失,接着通過後向傳播計算梯度,最後使用優化器更新模型參數。

for epoch in range(2):  # 在資料集上訓練兩遍

    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        # 擷取輸入資料
        inputs, labels = data

        # 梯度清零
        optimizer.zero_grad()

        # 前向傳播
        outputs = net(inputs)

        # 計算損失
        loss = criterion(outputs, labels)

        # 反向傳播
        loss.backward()

        # 更新參數
        optimizer.step()

        # 列印統計資訊
        running_loss += loss.item()
        if i % 2000 == 1999:  # 每2000個批次列印一次
            print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0

print('Finished Training')
           

在這段代碼中,我們首先對資料集進行兩輪訓練。在每輪訓練中,我們周遊資料加載器,擷取一批資料,然後通過網絡進行前向傳播得到輸出,計算損失,進行反向傳播,最後更新參數。我們還在每2000個批次後列印一次損失資訊,以便我們了解訓練過程。

5.5 測試網絡

訓練完成後,我們需要在測試集上測試網絡的性能。這可以讓我們了解模型在未見過的資料上的表現如何,以評估其泛化能力。

# 加載一些測試圖檔
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)

# 顯示預測的标簽
print('Predicted: ', ' '.join('%5s' % classes[predicted[j]] for j in range(4)))

# 在整個測試集上測試網絡
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('Accuracy of the network on the 10000 test images: %d %%' % (
    100 * correct / total))
           

在這段代碼中,我們首先加載一些測試圖檔,并列印出真實的标簽。然後我們讓網絡對這些圖檔做出預測,并列印出預測的标簽。最後,我們在整個測試集上測試網絡,并列印出網絡在測試集上的準确率。

5.6 儲存和加載模型

在訓練完網絡并且對其進行了測試後,我們可能希望儲存訓練好的模型,以便于将來使用,或者繼續訓練。

# 儲存模型
torch.save(net.state_dict(), './cifar_net.pth')
           

在這段代碼中,我們使用torch.save函數,将訓練好的模型參數(通過net.state_dict()獲得)儲存到檔案中。

當我們需要加載模型時,首先需要建立一個新的模型執行個體,然後使用load_state_dict方法将參數加載到模型中。

# 加載模型
net = Net()  # 建立新的網絡執行個體
net.load_state_dict(torch.load('./cifar_net.pth'))  # 加載模型參數
           

需要注意的是,load_state_dict方法加載的是模型的參數,而不是模型本身。是以,在加載模型參數之前,你需要先建立一個模型執行個體,這個模型需要與儲存的模型具有相同的結構。

6. 總結

這篇文章通過詳細且實踐性的方式介紹了 PyTorch 的使用,包括環境安裝、基礎知識、張量操作、自動求導機制、神經網絡建立、資料處理、模型訓練、測試以及模型的儲存和加載。

我們利用 PyTorch 從頭到尾完成了一個完整的神經網絡訓練流程,并在 CIFAR10 資料集上測試了網絡的性能。在這個過程中,我們深入了解了 PyTorch 提供的各種功能和工具。

希望這篇文章能對你學習 PyTorch 提供幫助,對于想要更深入了解 PyTorch 的讀者,我建議參考 PyTorch 的官方文檔以及各種開源教程。實踐是最好的學習方法,隻有通過大量的練習和實踐,才能真正掌握 PyTorch 和深度學習。

謝謝你的閱讀,希望你在深度學習的道路上越走越遠!

作者:TechLead

來源-微信公衆号:TechLead

出處:https://mp.weixin.qq.com/s/d2vnpXMCSbO7qEET2PNN8g