主頁 >  其他 > 到底什么是TORCH.NN?

到底什么是TORCH.NN?

2022-02-15 06:57:59 其他

該教程是在notebook上運行的,而不是腳本,下載notebook檔案,

PyTorch提供了設計優雅的模塊和類:torch.nn, torch.optim, Dataset, DataLoader,以創建和訓練神經完了過,為了充分利用其功能,并根據問題進行自定義,需要充分理解它們做的是什么,為了提高認知,我們首先在MNIST上訓練一個基礎的神經網路,而不使用這些模塊的任何特性;僅使用最基礎的PyTorch tensor函式初始化,然后,一次添加一個來自torch.nn, torch.optim, Dataset, DataLoader的特性,準確展示每個部分的功能,以及如何使代碼簡潔和更靈活,

該教程假設你已經安裝PyTorch,并且對tensor操作的基礎知識熟悉,

MNIST 資料設定

我們將使用經典的MNIST資料集,它是由手寫數字(0-9)的黑白圖片組成,

我們將使用pathlib(Python3標準庫的一部分)解決有關路徑的問題,并使用requests,我們只在使用他們時才匯入,這樣就可以準確地看到每一部分都在使用什么,

from pathlib import Path
import requests

DATA_PATH = Path('data')
PATH = DATA_PATH / "mnist"

PATH.mkdir(parents=True, exist_ok=True)

URL = "https://github.com/pytorch/tutorials/raw/master/_static/"
FILENAME = "mnist.pkl.gz"

if not (PATH / FILENAME).exits():
        content = requests.get(URL + FILENAME).content
        (PATH /  FILENAME).open('wb').write(content)

資料集是Numpy陣列格式,使用pickle(python中用于序列化資料的特定格式)保存,

import pickle
import gzip

with gzip.open((PATH / FILENAME).as_posix(), 'rb') as f:
        ((x_train, y_train), (x_valid, y_valid), _) = pickle.load(f, encoding='latin-1')

每個圖片的大小是28*28,被保存成展平的行,長度是784,查看其中一個,首先需要將其reshape至二維,

from matplotlib import pyplot
import numpy as np

pyplot.imshow(x_train[0].reshape((28, 28)), cmap = 'gray')
print(x_train.shape)

輸出:

(50000, 784)

PyTorch使用torch.tensor,而不是numpy陣列,所以我們進行資料轉換,

import torch

x_train, y_train, x_valid, y_valid = map(
    torch.tensor, (x_train, y_train, x_valid, y_valid)
)
n, c = x_train.shape
print(x_train, y_train)
print(x_train.shape)
print(y_train.min(), y_train.max())

輸出:

tensor([[0., 0., 0.,  ..., 0., 0., 0.],
        [0., 0., 0.,  ..., 0., 0., 0.],
        [0., 0., 0.,  ..., 0., 0., 0.],
        ...,
        [0., 0., 0.,  ..., 0., 0., 0.],
        [0., 0., 0.,  ..., 0., 0., 0.],
        [0., 0., 0.,  ..., 0., 0., 0.]]) tensor([5, 0, 4,  ..., 8, 4, 8])
torch.Size([50000, 784])
tensor(0) tensor(9)

從零開始的神經網路(不使用torch.nn)

首先僅使用PyTorch tensor操作創建模型,假設你已經對神經網路基礎知識熟悉,

PyTorch提供了創建隨機值或0值tensors的方法,可以用來為簡單的線性模型構建權重和偏置,這些只是常規的tensors,還有一個非常特殊的補充:告訴PyTorch它們需要梯度,使得PyTorch記錄發生在tensor上的所有操作,從而可以在自動反向傳播中計算梯度,

對于權重,我們在初始化之后設定 requires_grad,因為我們不想讓這個步驟包含在梯度更新中,(注意,PyTorch中,后綴_代表in-place操作),

注意:本文使用Xavier initialisation(乘以 1/sqrt(n) )初始化權重,

import math

weights = torch.randn(784, 10) / math.sqrt(784)
weights.requires_grad_()
bias = torch.zeros(10, requires_grad=True)

得益于PyTorch自動計算梯度的能力,我們可以使用任意標準Python函式(或呼叫物件)構建模型,所以這里寫了一個利用純矩陣乘法和廣播加法創建一個簡單的線性模型,還需要一個激活函式,所以我們將撰寫并使用log_softmax,記住:盡管PyTorch提供了大量寫好的損失函式,激活函式等,你依然使用純python撰寫它們,PyTorch甚至會自動為你的函式創建快速GPU或矢量化CPU代碼,

def log_softmax(X):
    return x - x.enp().sum(-1).log.unsqueeze(-1)

def model(xb):
    return log_softmax(xb @ weights + bias)

其中,@代表矩陣乘法,每個batch(本例64張圖片)都會呼叫我們的函式,這是一個前向傳遞,注意,在這個階段我們的預測不會比隨機更好,因為我們使用的是隨機初始化權重,

bs = 64 # batch size

xb = x_train[0:bs]    # a mini-batch from x
preds = model(xb)     # predictions

print(preds[0], preds.shape)

輸出:

tensor([-1.8235, -2.3674, -2.6933, -2.0418, -2.2708, -2.3946, -2.1448, -2.5031,
        -2.7917, -2.3786], grad_fn=<SelectBackward0>) torch.Size([64, 10])

正如你所見,predstensor不僅包含tensor數值,還有一個梯度函式,接下來我們將使用這個來做反向傳播,

現在來實作負對數似然函式作為損失函式(再一次,使用標準Python)

def nll(input, target):
    return -input[range(target.shape[0]), target].mean()

loss_func = nll

計算損失,這樣稍后在反向傳播后看到是否有所提升,

yb = y_train[0:bs]
print(loss_func(preds, yb))

輸出:

tensor(2.2979, grad_fn=<NegBackward0>)

使用一個函式計算模型準確率,對于每次預測,如果最大值的索引與目標值一致,則預測正確,

def accuracy(out, yb):
    preds = torch.argmax(out, dim=1)
    return (preds == yb).float().mean()

檢查模型準確率額,這樣就可以看到當loss提升時,準確率是否會提升

print(accuracy(preds, yb))

輸出:

tensor(0.1094)

我們現在可以運行一個訓練回圈了,對于每次回圈,包括:

  • 選擇一個mini-batch of data (of size bs)
  • 使用model預測
  • 計算損失
  • loss.backward()更新模型梯度,在此例中是weightsbias

現在使用梯度更新weights和bias,通過torch.no_grad()背景關系管理器,因為我們不想讓這些行為被記錄到下一次梯度計算中,你可以在here閱讀更多關于PyTorch的Autograd記錄操作,

接下來將梯度置0,準備好下一個回圈,否則,我們的梯度將會記錄所有已發生操作的運行記錄(即loss.backward()將梯度添加到已存盤的任何內容中,而不是替換它們),

TIP:你可以使用標準python中的除錯器單步除錯PyTroch代碼,允許你檢查每一步各種變數的值,取消下面的set_trace()注釋嘗試一下,

from IPython.core.debugger import set_trace

lr = 0.5 # learning rate
epochs = 2 # how many epochs to train for

for epoch in range(epochs):
    for i in range((n - 1) // bs + 1)):
        # set_trace()
        start_i = i * bs
        end_i = start_i + bs
        xb = x_train[start_i:end_i]
        yb = y_train[start_i:end_i]
        pred = model(xb)
        loss = loss_func(pred, yb)

        loss.backward()
        with torch.no_grad():
            weights -= weights.grad * lr
            bias -= bias.grad * lr
            weights.grad.zero_()
            bias.grad.zero_()

以上,我們從0構建和訓練了一個小型的神經網路(此例中,一個logistic回歸,因為沒有隱藏層),

檢查loss和準確率相較于之前如何,loss降低,準確率上升,事實如此,

print(loss_func(model(xb), yb), accuracy(model(xb), yb))

輸出:

tensor(0.0803, grad_fn=<NegBackward0>) tensor(1.)

使用torch.nn.functional

我們將利用PyTorch的nn類重構網路,使其和之前做的事情一致,但是更加簡潔和靈活,從這開始的每一步,我們可能會讓代碼更加簡短、易于理解、靈活,

首先最簡單的一步就是讓代碼更簡短,利用torch.nn.functional(通常習慣匯入時命名為F)代替手寫的激活和損失函式,該模塊包含torch.nn庫的所有函式(其它部分是類),除了大量的損失、激活函式外,你還可以在這里找到一些用于創建神經網路的函式,如池化函式,(也有一些卷積、線性層等的函式,但我們將看到,利用該庫的其它部分解決這些事情通常更好)

如果你使用負對數似然損失函式和log softmax激活函式,那么Pytorch提供一個單一函式F.cross_entropy聯合了這兩個,所以我們可以甚至將激活函式從我們的模型移除,

import torch.nn.functional as F

loss_func = F.cross_entropy

def model(xb):
    return xb @ weights + bias

注意,我們不再在model函式中呼叫log_softmax,確認loss和accuracy是否跟之前一致,

print(loss_func(model(xb), yb), accuracy(model(xb), yb))

輸出:

tensor(0.0803, grad_fn=<NllLossBackward0>) tensor(1.)

使用 nn.Module 重構

下一步,為了更加清晰和簡潔的訓練回圈,我們將使用nn.Modulenn.Parameter,我們繼承nn.Module(它本身是一個類并能追蹤狀態),在該例中,我們想創建一個類保存我們的權重、偏置,以及前向傳遞的方法,nn.Module有大量屬性和方法(例如.parameters().zero_grad()),

注意:nn.Module(大寫M)是PyTorch一個特定的概念,它是一個我們要大量使用的類,不要將nn.Module與Python中小寫m的module的概念混淆,后者是可以被匯入的Python檔案,

from torch import nn

class Mnist_Logistic(nn.Module):
    def __init__(self):
        super().__init__()
        self.weights = nn.Parameter(torch.randn(784, 10) / math.sqrt(784))
        self.bias = nn.Parameter(torch.zerors(10))

    def forward(self, xb):
        return xb @ self.weights + self.bias

因為我們是使用了一個物件而不是函式,我們首先需要實體化模型,

model = Mnist_Logistic()

現在就可以像上面那樣計算loss,注意nn.Module物件被用作函式(即它們是可呼叫的),但在底層,Pytorch將自動呼叫forward方法,

print(loss_func(model(xb), yb))

輸出:

tensor(2.2899, grad_fn=<NllLossBackward0>)

對于訓練回圈,我們需要根據名字更新每一個引數值,并手動分別將每個引數的梯度置0:

with torch.no_grad():
    weights -= weights.grad * lr
    bias -= bias.grad * lr
    weights.grad.zero_()
    bias.grad.zero_()

現在,我們可以利用model.parameters()model.zero_grad()(均是由Pytorch為nn.Module定義的)使這些步驟更加簡單,并且不太容易發生忘記某些引數的錯誤,特別是一些跟家復雜的模型:

with torch.no_grad():
    for p in model.parameters(): p -= p.grad * lr
    model.zero_grad()

將訓練回圈包圍在fit函式中,以便在后面再次運行

def fit():
    for epoch in range(epochs):
        for i in range((n - 1) // bs + 1):
            start_i = i * bs
            end_i = start_i + bs
            xb = x_train[start_i:end_i]
            yb = y_train[start_i:end_i]
            pred = model(xb)
            loss = loss_func(pred, yb)
            
            loss.backward()
            with torch.no_grad():
                for p in model.parameters():
                    p -= p.grad * lr
                model.zero_grad()

fit()

仔細檢查loss是否下降了:

print(loss_func(model(xb), yb))

輸出:

tensor(0.0835, grad_fn=<NllLossBackward0>)

使用 nn.Linear 重構

讓我們繼續重構代碼,替代手動定義和初始化self.weightsself.bias,以及計算xb @ self.weights + self.bias,對于一個線性層,我們將使用Pytorch類nn.Linear,可以實作以上所有功能,Pytorch由很多預先定義的layers,可以大大簡化和加速我們的代碼,

class Mnist_Logistic(nn.Module):
      def __init__(self):
          super().__init__()
          self.lin = nn.Linear(784, 10)
      def forward():
          return self.lin(xb)

實體化模型并計算loss

model = Mnist_Logistc()
print(loss_func(model(xb), yb))

輸出:

tensor(2.3694, grad_fn=<NllLossBackward0>)

使用fit方法訓練:

fit()

print(loss_func(model(xb), yb))

輸出:

tensor(0.0820, grad_fn=<NllLossBackward0>)

使用 optim 重構

Pytorch還有包含各種優化演算法的庫:torch.optim,我們可以使用step方法替代手動更新引數,

這樣就可以替代目前手動的優化步驟:

with torch.no_grad():
    for p in model.parameters(): p -= p.grad * lr
    model.zero_grad()

而僅用:

opt.step()
opt.zero_grad()

optim.zero_grad()重置梯度為0,需要在計算下一個minibatch的梯度前呼叫)

for torch import optim

定義一個小函式創建模型和優化器,以便在之后使用:

def get_model():
    model = Mnist_Logistic()
    return model, optim.SGD(model.parameters(), lr=lr)

model, opt = get_modle()
print(loss_func(model(xb), yb))

for epoch in range(epochs):
    for i in range((n - 1) // bs + 1):
        start_i = i * bs
        end_i = start_i + bs
        xb = x_train[start_i:end_i]
        yb = y_train[start_i:end_i]
        pred = model(xb)
        loss = loss_func(pred, yb)

        loss.backward()
        opt.step()
        opt.zero_grad()

print(loss_func(model(xb), yb))

輸出:

tensor(2.3185, grad_fn=<NllLossBackward0>)
tensor(0.0827, grad_fn=<NllLossBackward0>)

使用 Dataset 重構

PyTorch有一個抽象的Dataset類,一個Dataset可以是任意一個擁有__len__函式(可以被Python的標準len函式呼叫),和一個__getitem__()函式,用于索引,This tutorial完整描述了創建自定義Dataset的例子,將FacialLandmarkDataset類作為Dataset的子類,

Pytorch的TensorDataset是一個包裝tensor的Dataset,通過定義length和索引方式,它還提供了迭代、索引和沿著tensor第一維度進行切片的方式,這會使得我們在訓練時更容易在同一行訪問自變數和因變數,

from torch.utils.data import TensorDataset

x_trainy_train可以一同放入單個TensorDataset,以便迭代和切片,

train_ds = TensorDataset(x_train, y_train)

之前,我們需要分別迭代x和y的minibatches:

xb = x_train[start_i:end_i]
yb = y_train[start_i:end_i]

現在,可以把這兩步合成一步:

xb, yb = train_ds[i*bs : i*bs+bs]
model, opt = get_model()
for epcoh in range(epochs):
    for i in range((n - 1) // bs + 1):
        xb, yb = train_ds[i * bs: i * bs + bs]
        pred = model(xb)
        loss = loss_func(pred, yb)
        
        loss.backward()
        opt.step()
        opt.zero_grad()

print(loss_func(model(xb), yb))

輸出:

tensor(0.0812, grad_fn=<NllLossBackward0>)

使用 DataLoader 重構

Pytorch的 DataLoader負責管理batches,你可以從任何Dataset創建DataLoaderDataLoader使得迭代batch更加方便,相比使用train_ds[i * bs: i * bs + bs],DataLoader自動提供每一個minibatch,

from torch.utils.data import DataLoader

train_ds = TensorDataset(x_train, y_train)
train_dl = DataLoader(train_ds, batch_size=bs)

先前,回圈迭代batches (xb, yb)是這樣的:

for i in range((n-1)//bs + 1):
    xb,yb = train_ds[i*bs : i*bs+bs]
    pred = model(xb)

現在,(xb, yb)自動從dataloader加載,回圈更加簡潔:

for xb, yb in train_dl:
    pred = model(xb)
model, opt = get_model()

for epoch in range(epochs):
    for xb, yb in train_dl:
        pred = model(xb)
        loss = loss_func(pred, yb)

        loss.backward()
        opt.step()
        opt.zero_grad()

print(loss_func(model(xb), yb))

輸出:

tensor(0.0824, grad_fn=<NllLossBackward0>)

得益于Pytorch的nn.Modulenn.ParameterDataset,和DataLoader,我們的訓練回圈現在大大的縮小,并更容易理解,現在嘗試添加實踐中有效的模型所必須的基本功能,

添加驗證

在第一節中,我們只是試圖建立一個合理的訓練回圈以用于訓練資料,實際上,你還需要一個validation set,以驗證是否過擬合,

打亂訓練資料對于防止batch之間的聯系和過擬合很重要,但是另一方面,無論是否shuffle驗證集,驗證集的loss都是確定的,因此shuffle驗證集是無意義的,

我們使用2倍于訓練集batch的資料作為驗證集batch,這是因為驗證集不需要反向傳播,無需保存梯度,僅占很少的記憶體,利用這一點,我們使用更大的batch size并更快地計算損失,

train_ds = TensorDataset(x_train, y_train)
train_dl = DataLoader(train_ds, batch_size=bs, shuffle=True)

valid_ds = TensorDataset(x_valid, y_valid)
valid_dl = DataLoader(valid_ds, batch_size=bs*2)

我們將在每個epoch結束計算并列印驗證集loss

(注意,在訓練之前呼叫model.train(),在推理之前呼叫model.eval(),這是因為layers使用了如nn.BatchNorm2dnn.Dropout,這些在驗證時是不需要的)

model, opt = get_model()

for epoch in range(epochs):
    model.train()
    for xb, yb in train_dl:
        pred = model(xb)
        loss = loss_func(pred, yb)

        loss.backward()
        opt.step()
        opt.zero_grad()
    
    model.eval()
    with torch.no_grad():
        valid_loss = sum(loss_func(model(xb), yb) for xb, yb in valid_dl)
    
    print(epoch, valid_loss / len(valid_dl))

輸出:

0 tensor(0.3260)
1 tensor(0.2793)

構建 fit() 和 get_data()

現在做一些自定義的重構,因為在訓練和驗證時經過了兩次計算損失的類似程序,我們現在將其放入function,loss_batch,它可以為每一個batch計算損失,

我們為訓練集傳入optimizer,并用以反向傳播,而對于驗證集,不需要optimizer,所以該函式就不會進行反向傳播,

def loss_batch(model, loss_func, xb, yb, opt=None):
    loss = loss_func(model(xb), yb)

    if opt is not None:
        loss.backward()
        opt.step()
        opt.zero_grad()

    return loss.item(), len(xb)

fit 運行必要的操作訓練我們的模型,并計算每一epoch的訓練和驗證loss

import numpy as np

def fit(epochs, model, loss_func, opt, train_dl, valid_dl):
    for epoch in range(epochs):
        model.train()
        for xb, yb in train_dl:
            loss_batch(model, loss_func, xb, yb, opt)

        model.eval()
        with torch.no_grad():
            losses, nums = zip(
                *[loss_batch(model, loss_func, xb, yb) for xb, yb in valid_dl]
            )
        val_loss = np.sum(np.multiply(losses, nums)) / np.sum(nums)

        print(epoch, val_loss)

get_data 回傳訓練集和驗證集的dataloaders

def get_data(train_ds, valid_ds, bs):
    return(
        DataLoader(train_ds, batch_size=bs, shuffle=True),
        DataLoader(valid_ds, batch_size=bs * 2),
)

現在,所有程序,包括資料加載、擬合模型可以用3行代碼運行

train_dl, valid_dl = get_data(train_ds, valid_ds, bs)
model, opt = get_model()
fit(epochs, model, loss_func, opt, train_dl, valid_dl)

輸出:

0 0.37930963896512987
1 0.28746109589338303

你可以利用這3行基礎代碼訓練各種各樣的模型,來看一下我們能否利用這三行代碼訓練CNN,

Switch to CNN

我們現在要構建具有3層卷積層的神經網路,因為上一節沒有假設關于模型形式的函式,所以可以利用上面3行代碼直接訓練CNN,無需任何修改,

我們將利用Pytorch的預定義的Conv2d類作為我們的卷積層,定義一個具有3層卷積層的CNN,每個卷積層跟一個ReLU,最后,使用一個均值池化層(注意,view時numpy中的reshape對應的pytorch版本)

class Mnist_CNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 16, kernel_size=3, stride=2, padding=1)
        self.conv2 = nn.Conv2d(16, 16, kernel_size=3, stride=2, padding=1)
        self.conv3 = nn.Conv2d(16, 10, kernel_size=3, stride=2, padding=1)

    def forward(self, xb):
        xb = xb.view(-1, 1, 28, 28)
        xb = F.relu(self.conv1(xb))
        xb = F.relu(self.conv2(xb))
        xb = F.relu(self.conv2(xb))
        xb = F.avg_pool2d(xb, 4)
        return xb.view(-1, xb.size(1))

lr = 0.1

Momentum是隨機梯度下降的一個變體,它考慮而落之前的更新,通常會使訓練更快,

model = Mnist_CNN()
opt = optim.SGD(model.parameters(), lr=lr, momentum=0.9)

fit(epochs, model, loss_func, opt, train_dl, valid_dl)

輸出:

0 0.36561058859825135
1 0.2279014788389206

nn.Sequential

torch.nn有另一個方便的類可以用來簡化我們的代碼:Sequential ,一個Sequential物件按照順序運行其中包含的每個模塊,這是撰寫神經網路一種更簡單的方法,

為了利用這一點,我們需要從給定函式定義一個custom layer,例如,PyTorch沒有view層,我們需要創建一個,Lambda將創建一個層,當利用Sequential定義神經網路時可以使用,

class Lambda(nn.Module):
    def __init__(self, func):
        super().__init__()
        self.func = func

    def forward(self, x):
        return self.func(x)

def preprocess(x):
    return x.view(-1, 1, 28, 28)

使用Sequential創建model更加簡單:

model = nn.Sequential(
    Lambda(preprocess),
    nn.Conv2d(1, 16, kernel_size=3, stride=2, padding=1),
    nn.ReLU(),
    nn.Conv2d(16, 16, kernel_size=3, stride=2, padding=1),
    nn.ReLU(),
    nn.Conv2d(16, 10, kernel_size=3, stride=2, padding=1),
    nn.ReLU(),
    nn.AvgPool2d(4),
    Lambda(lambda x: x.view(x.size(0), -1)),
)

opt = optim.SGD(model.parameters(), lr=lr, momentum=0.9)

fit(epochs, model, loss_func, opt, train_dl, valid_dl)

輸出:

0 0.3266831987142563
1 0.24143515722751618

Wrapping DataLoader

我們的CNN相當簡潔,但是它僅能在MNIST上使用,因為:

  • 它假設輸入是28*28的長向量
  • 它假設最后的CNN網格大小是4*4(這是我們使用的平均池化核的大小)

讓我們跳出上面兩個假設,使得我們的模型可以用于任何2維單通道圖片,首先,我們可以通過將資料預處理移到生成器中來移除初始Lambda層,

def preprocess(x, y):
    return x.view(-1, 1, 28, 28), y

class WrapperDataLoader:
    def __init__(self, dl, func):
        self.dl = dl
        self.func = func

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

    def __iter__(self):
        for b in batches:
            yield (self.func(*b))

train_dl, valid_dl = get_data(train_ds, valid_ds, bs)
train_dl = WrapperDataLoader(train_dl, preprocess)
valid_dl = WrapperDataLoader(valid_dl, preprocess)

接下來,使用nn.AdaptiveAvgPool2d代替nn.AvgPool2d,它能讓我們定義所需的output tensor大小,而而不是我們已有的input tensor,這樣,模型就可以適用任意輸入大小了,

model = nn.Sequential(
    nn.Conv2d(1, 16, kernel_size=3, stride=2, padding=1),
    nn.ReLU(),
    nn.Conv2d(16, 16, kernel_size=3, stride=2, padding=1),
    nn.ReLU(),
    nn.Conv2d(16, 10, kernel_size=3, stride=2, padding=1),
    nn.ReLU(),
    nn.AdaptiveAvgPool2d(1),
    Lambda(lambda x: x.view(x.size(0), -1)),
)

opt = optim.SGD(model.parameters(), lr=lr, momentum=0.9)

試一試:

fit(epochs, model, loss_func, opt, train_dl, valid_dl)

輸出:

0 0.3653434091329575
1 0.31836258018016816

使用 GPU

如果你可以使用支持CUDA的GPU(你可以從大多數云供應商以0.5美元/每小時的價錢租用一個)加速你的代碼,首先檢查你的GPU能否在Pytorch中運行:

print(torch.cuda.is_available())

輸出:

True

然后創建一個device物件

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

更新preprocess,將batches移到GPU上:

def preprocess(x, y):
    return x.view(-1, 1, 28, 28).to(dev), y.to(dev)

train_dl, valid_dl = get_data(train_ds, valid_ds, bs)
train_dl = WrappedDataLoader(train_dl, preprocess)
valid_dl = WrappedDataLoader(valid_dl, preprocess)

最后,將model移到GPU:

model.to(dev)
opt = optim.SGD(model.parameters(), lr=lr, momentum=0.9)

你會發現現在運行的更快:

fit(epochs, model, loss_func, opt, train_dl, valid_dl)

輸出:

0 0.22935870126485824
1 0.21556809792518616

Closing thougths

現在我們已經有了一個通用的資料pipeline和訓練回圈,利用Pytorch,你可以用來訓練許多型別的models,要了解現在訓練模型有多簡單,可以查看mnist_sample樣例notebook,

當然,還有很多你想要添加的,如資料增強、超引數調整、監視訓練、遷移學習等等,這些功能都在fastai庫中,它是使用本教程所示的相同設計方法開發的,為希望進一步開發模型的從業者提供了方便,

我們在開頭保證,會通過示例解釋torch.nn、'torch.optim'、'Dataset'、'DataLoader',所以讓我們對上述內容總結一下:

  • torch.nn

    • Module:創建一個類似于函式的可呼叫物件,但還可以包括一些狀態(如神經網路層的權重),它知道它包含哪些Parameter(s),并能將它們的梯度歸0,回圈遍歷它們以進行權重更新等,

    • Parameter:a wrapper for a tensor,它告訴Module在反向傳播時需要更新的權重,只有帶有requires_grad屬性的tensor才會被更新,

    • functional:一個包含激活函式、損失函式等的模塊(通常匯入為F),還包括non-stateful版本的層,例如卷積層和線性層,

  • torch.optim:包含優化器,例如SGD等,在反向傳播step中更新Paramter的權重,

  • Dataset:一個具有__len____getitem__的物件的抽象介面,包括Pytorch提供的類,如TensorDataset

  • DataLoader:接收任意Dataset,并創建一個迭代器,該迭代器回傳資料的batches,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/423829.html

標籤:其他

上一篇:聊聊程式員面試時,那些必須注意的事情

下一篇:在 K8s 中快速部署使用 GitLab 并構建 DevOps 專案

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more