成人性生交大片免费看视频r_亚洲综合极品香蕉久久网_在线视频免费观看一区_亚洲精品亚洲人成人网在线播放_国产精品毛片av_久久久久国产精品www_亚洲国产一区二区三区在线播_日韩一区二区三区四区区区_亚洲精品国产无套在线观_国产免费www

主頁 > 知識(shí)庫 > pytorch 搭建神經(jīng)網(wǎng)路的實(shí)現(xiàn)

pytorch 搭建神經(jīng)網(wǎng)路的實(shí)現(xiàn)

熱門標(biāo)簽:ai電話機(jī)器人哪里好 西藏房產(chǎn)智能外呼系統(tǒng)要多少錢 ai電銷機(jī)器人源碼 湛江智能外呼系統(tǒng)廠家 宿遷星美防封電銷卡 地圖標(biāo)注審核表 長(zhǎng)沙高頻外呼系統(tǒng)原理是什么 百度地圖標(biāo)注沒有了 外呼并發(fā)線路

1 數(shù)據(jù)

 (1)導(dǎo)入數(shù)據(jù)

我們以Fashion-MNIST數(shù)據(jù)集為例,介紹一下關(guān)于pytorch的數(shù)據(jù)集導(dǎo)入。

PyTorch域庫提供許多預(yù)加載的數(shù)據(jù)集(如FashionMNIST),這些數(shù)據(jù)集是torch.utils.data.Dataset的子類,并實(shí)現(xiàn)了特定于指定數(shù)據(jù)的功能。

Fashion-MNIST是Zalando文章中的圖像數(shù)據(jù)集,包含60,000個(gè)訓(xùn)練示例和10,000個(gè)測(cè)試示例。每個(gè)示例包括28×28灰度圖像和來自10個(gè)類中的一個(gè)的關(guān)聯(lián)標(biāo)簽。

import torch
from torchvision import datasets
from torchvision.transforms import ToTensor
import matplotlib.pyplot as plt
import os
os.environ['KMP_DUPLICATE_LIB_OK'] = 'TRUE'	# 沒有這句會(huì)報(bào)錯(cuò),具體原因我也不知道

training_data = datasets.FashionMNIST(
    root="../data",
    train=True,
    download=True,
    transform=ToTensor()
)

test_data = datasets.FashionMNIST(
    root="../data",
    train=False,
    download=True,
    transform=ToTensor()
)

輸出(下面的截圖不完整)

我們使用以下參數(shù)加載FashionMNIST數(shù)據(jù)集:
root是存儲(chǔ)訓(xùn)練/測(cè)試數(shù)據(jù)的路徑,
train指定訓(xùn)練或測(cè)試數(shù)據(jù)集,
download=True 如果數(shù)據(jù)集不存在于指定存儲(chǔ)路徑,那么就從網(wǎng)上下載。
transform和target_transform用于指定屬性和標(biāo)簽轉(zhuǎn)換操作,這里所說的“轉(zhuǎn)換操作”,通常封裝在torchvision.transforms中,因此通常需要導(dǎo)入torchvision.transforms,或者導(dǎo)入這個(gè)包中的操作

(2)數(shù)據(jù)集可視化

我們可以像列表一樣手動(dòng)索引數(shù)據(jù)集:training_data[index]。我們使用matplotlib來可視化訓(xùn)練數(shù)據(jù)中的一些示例。

labels_map = {
    0: "T-Shirt",
    1: "Trouser",
    2: "Pullover",
    3: "Dress",
    4: "Coat",
    5: "Sandal",
    6: "Shirt",
    7: "Sneaker",
    8: "Bag",
    9: "Ankle Boot",
}
figure = plt.figure(figsize=(8, 8))
cols, rows = 3, 3
for i in range(1, cols * rows + 1):
    # 從0-len(training_data)中隨機(jī)生成一個(gè)數(shù)字(不包括右邊界)
    sample_idx = torch.randint(len(training_data), size=(1,)).item() 
    img, label = training_data[sample_idx] # 獲得圖片和標(biāo)簽
    figure.add_subplot(rows, cols, i)
    plt.title(labels_map[label])
    plt.axis("off")                        # 坐標(biāo)軸不可見
    plt.imshow(img.squeeze(), cmap="gray") # 顯示灰度圖
plt.show()

輸出


上面的程序中,有兩個(gè)地方指的注意,一個(gè)是可以求training_data的長(zhǎng)度,另一個(gè)可以通過索引獲得單個(gè)樣本,當(dāng)然這里的樣本已經(jīng)被轉(zhuǎn)換成了張量,如下圖所示

(3)為自己制作的數(shù)據(jù)集創(chuàng)建類

如果要導(dǎo)入自己制作的數(shù)據(jù)集,需要編寫一個(gè)類,這個(gè)類用于繼承torch.utils.data中的Dataset類。自制的數(shù)據(jù)集類必須實(shí)現(xiàn)三個(gè)函數(shù):initlen__和__getitem,分別是初始化類,求長(zhǎng)度len(obj),通過索引獲得單個(gè)樣本(像列表一樣)。

import os
import pandas as pd
from torch.utils.data import Dataset
from torchvision.io import read_image

class CustomImageDataset(Dataset):
    def __init__(self, annotations_file, img_dir, transform=None, target_transform=None):
        self.img_labels = pd.read_csv(annotations_file)
        self.img_dir = img_dir
        self.transform = transform
        self.target_transform = target_transform

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

    def __getitem__(self, idx):
        img_path = os.path.join(self.img_dir, self.img_labels.iloc[idx, 0])
        image = read_image(img_path)
        label = self.img_labels.iloc[idx, 1]
        if self.transform:
            image = self.transform(image)
        if self.target_transform:
            label = self.target_transform(label)
        return image, label

具體細(xì)節(jié)可以在pytorch的官網(wǎng)教程:https://pytorch.org/tutorials/beginner/basics/data_tutorial.html
Creating a Custom Dataset for your files

(4)數(shù)據(jù)集批處理

上面的程序中,雖然可以使用索引獲得樣本,但一次只能獲得單個(gè)樣本,無法像列表、張量、numpy切片一樣一次切出多個(gè)

而在訓(xùn)練模型的時(shí)候,我們希望能夠批處理,即一次處理若干個(gè)樣本,同時(shí),我們希望數(shù)據(jù)在每次遍歷完之后打亂一次,以減少過擬合,并使用Python的多處理來加快數(shù)據(jù)提取。
pytorch中,專門有一個(gè)類可以實(shí)現(xiàn)上述功能,即torch.utils.data.DataLoader

下面的程序是將數(shù)據(jù)集導(dǎo)入到DataLoader中

from torch.utils.data import DataLoader

train_dataloader = DataLoader(training_data, batch_size=64, shuffle=True) 
# train_dataloader是一個(gè)DataLoader類的對(duì)象
test_dataloader = DataLoader(test_data, batch_size=64, shuffle=True)

training_data和test_data就是前面導(dǎo)入的數(shù)據(jù)集,由于我們指定了batch的大小是64,因?yàn)槲覀冎付藄huffle=True,所以在遍歷所有batch之后,數(shù)據(jù)將被打亂。

此時(shí)training_data和test_data仍然不是可迭代對(duì)象,還需要將其變成可迭代對(duì)象,可以使用iter函數(shù)將每一個(gè)batch轉(zhuǎn)化成可迭代對(duì)象,或者enumerate函數(shù)將其的每個(gè)batch帶上序號(hào)變成元組

用iter函數(shù)

for batch_index, (features, label) in enumerate(train_dataloader):
    print(batch_index)
    print(f"Feature batch shape: {features.size()}")
    print(f"Labels batch shape: {label.size()}")
    img = features[0].squeeze()
    label = label[0]
    plt.imshow(img, cmap="gray")
    plt.show()
    print(f"Label: {label}")
    break

輸出


上面的程序中,train_features, train_labels都是包含64個(gè)樣本的張量

用enumerate函數(shù)

for batch_index, (features, label) in enumerate(train_dataloader):
    print(batch_index)
    print(f"Feature batch shape: {features.size()}")
    print(f"Labels batch shape: {label.size()}")
    img = features[0].squeeze()
    label = label[0]
    plt.imshow(img, cmap="gray")
    plt.show()
    print(f"Label: {label}")
    break

(5)數(shù)據(jù)預(yù)處理

數(shù)據(jù)并不總是以訓(xùn)練機(jī)器學(xué)習(xí)算法所需的最終處理形式出現(xiàn),因此我們需要對(duì)數(shù)據(jù)進(jìn)行一些變換操作,使其適合于訓(xùn)練。
所有的TorchVision數(shù)據(jù)集都有兩個(gè)參數(shù),它們接受包含轉(zhuǎn)換邏輯的可調(diào)用對(duì)象:(1)transform用于修改特性,(2)target_transform用于修改標(biāo)簽

torchvision.transforms模塊提供了多種常用的轉(zhuǎn)換,這里我們介紹一下ToTensor和Lambda。

為了進(jìn)行訓(xùn)練,我們需要將FashionMNIST中的特征轉(zhuǎn)化為normalized tensors,將標(biāo)簽轉(zhuǎn)化為One-hot編碼的張量。為了完成這些變換,我們使用ToTensor和Lambda。

import torch
from torchvision import datasets
from torchvision.transforms import ToTensor, Lambda

ds = datasets.FashionMNIST(
    root="data",
    train=True,
    download=True,
    transform=ToTensor(),
    target_transform=Lambda(lambda y: torch.zeros(10, dtype=torch.float).scatter_(dim=0, index=torch.tensor(y), value=1))
)

ToTensor將PIL圖像或NumPy ndarray轉(zhuǎn)換為FloatTensor,并將圖像的像素值(或者灰度值)縮放到[0, 1]區(qū)間

Lambda可以用于任何用戶定義的lambda函數(shù),在這里,我們定義一個(gè)函數(shù)來將整數(shù)轉(zhuǎn)換為一個(gè)one-hot編碼張量,首先建立一個(gè)長(zhǎng)度為10的0張量(之所以為10,是因?yàn)橛?0個(gè)類別),然后調(diào)用scatter_函數(shù),把對(duì)應(yīng)的位置換成1。scatter_函數(shù)的用法如下:


更多torchvision.transforms的API詳見:https://pytorch.org/vision/stable/transforms.html

2 神經(jīng)網(wǎng)絡(luò)

神經(jīng)網(wǎng)絡(luò)由對(duì)數(shù)據(jù)進(jìn)行操作的層/模塊組成,torch.nn提供了構(gòu)建的神經(jīng)網(wǎng)絡(luò)所需的所有構(gòu)建塊。PyTorch中的每個(gè)模塊都繼承了nn.Module,神經(jīng)網(wǎng)絡(luò)本身就是一個(gè)模塊,它由其他模塊(層)組成,這種嵌套結(jié)構(gòu)允許輕松構(gòu)建和管理復(fù)雜的體系結(jié)構(gòu)。

在下面的小節(jié)中,我們將構(gòu)建一個(gè)神經(jīng)網(wǎng)絡(luò)來對(duì)FashionMNIST數(shù)據(jù)集中的圖像進(jìn)行分類。

(1)定義神經(jīng)網(wǎng)絡(luò)類

我們通過繼承nn.Module來定義我們的神經(jīng)網(wǎng)絡(luò)類,并在__init__中初始化神經(jīng)網(wǎng)絡(luò)層,每一個(gè)nn.Module的子類在forward方法中繼承了對(duì)輸入數(shù)據(jù)的操作。

在初始化方法中搭建網(wǎng)絡(luò)結(jié)構(gòu)

class NeuralNetwork(nn.Module):
    def __init__(self):
        super(NeuralNetwork, self).__init__()
        self.flatten = nn.Flatten()				# 打平
        self.linear_relu_stack = nn.Sequential(
            nn.Linear(28*28, 512),		# 線性層
            nn.ReLU(),					# 激活層
            nn.Linear(512, 512),
            nn.ReLU(),
            nn.Linear(512, 10),
            nn.ReLU()
        )

    def forward(self, x):
        x = self.flatten(x)					# 打平層
        logits = self.linear_relu_stack(x)	# 線性激活層
        return logits

We create an instance of NeuralNetwork, and print its structure.
我們可以建立一個(gè)NeuralNetwork(即剛剛定義的類)的實(shí)例,并打印它的結(jié)構(gòu)

model = NeuralNetwork()
print(model)

輸出

NeuralNetwork(
  (flatten): Flatten(start_dim=1, end_dim=-1)
  (linear_relu_stack): Sequential(
    (0): Linear(in_features=784, out_features=512, bias=True)
    (1): ReLU()
    (2): Linear(in_features=512, out_features=512, bias=True)
    (3): ReLU()
    (4): Linear(in_features=512, out_features=10, bias=True)
    (5): ReLU()
  )
)

使用模型時(shí),我們將輸入數(shù)據(jù)傳遞給它,這將執(zhí)行模型的forward方法,以及一些背后的操作。注意:不要直接調(diào)用model.forward() !

定義好我們自己的神經(jīng)網(wǎng)絡(luò)類之后,我們可以隨機(jī)生成一個(gè)張量,來測(cè)試一下輸出的size是否符合要求
每個(gè)樣本傳入模型后會(huì)得到一個(gè)10維的張量,將這個(gè)張量傳入nn.Softmax的實(shí)例中,可以得到每個(gè)類別的概率

X = torch.rand(1, 28, 28)	# 生成一個(gè)樣本
logits = model(X)							# 將樣本輸入到模型中,自動(dòng)調(diào)用forward方法
print(logits.size())						
pred_probab = nn.Softmax(dim=1)(logits)		# 實(shí)例化一個(gè)Softmax對(duì)象,并通過對(duì)象調(diào)用
y_pred = pred_probab.argmax(1)				# 獲得概率最大索引
print(f"Predicted class: {y_pred}")

輸出

torch.Size([1, 10])
Predicted class: tensor([8])

(2)神經(jīng)網(wǎng)絡(luò)組件

上面搭建神經(jīng)網(wǎng)絡(luò)時(shí),我們使用了打平函數(shù)、線性函數(shù)、激活函數(shù),我們來看看這些函數(shù)的功能

打平層

input_image = torch.rand(3,28,28)
print(input_image.size())

輸出

torch.Size([3, 28, 28])

線性層

layer1 = nn.Linear(in_features=28*28, out_features=20)
hidden1 = layer1(flat_image)
print(hidden1.size())

輸出

torch.Size([3, 20])

線性層其實(shí)就是實(shí)現(xiàn)了 y=w*x + b,其實(shí)是和下面的程序是等效的,但下面的程序不適合放在nn.Sequential中(但可以放在forward方法里)

w = torch.rand(784, 20)
b = torch.rand((1, 20))
hidden2 = flat_image @ w + b
print(hidden2.size())

輸出

torch.Size([3, 20])

nn.Sequential是一個(gè)模塊容器類,在初始化時(shí),將各個(gè)模塊按順序放入容器中,調(diào)用模型時(shí),數(shù)據(jù)按照初始化時(shí)的順序傳遞。
例如:

seq_modules = nn.Sequential(
    flatten,		# 在nn.Sequential中可以調(diào)用其他模塊
    layer1,
    nn.ReLU(),
    nn.Linear(20, 10)
)
input_image = torch.rand(3,28,28)
logits = seq_modules(input_image)

在nn.Sequential中可以調(diào)用其他模塊,nn.Sequential定義的模塊也可以被其他模塊調(diào)用

(3)模型參數(shù)

神經(jīng)網(wǎng)絡(luò)中的許多層都是參數(shù)化的,也就是說,在訓(xùn)練過程中會(huì)優(yōu)化相關(guān)的權(quán)值和偏差,我們可以使用模型的parameters()或named_parameters()方法訪問所有參數(shù)。

model.parameters()返回的是一個(gè)參數(shù)生成器,可以用list()將其轉(zhuǎn)化為列表,例如

para_list = list(model.parameters())

# 將參數(shù)生成器轉(zhuǎn)換成列表之后,列表的第一個(gè)元素是w,第二個(gè)元素是b
print(type(para_list[0]))
print(f'number of linear_layers :{len(para_list)/2}')
print('weights:')
print(para_list[0][:2])  # 只切出兩個(gè)樣本來顯示
print('bias:')
print(para_list[1][:2]) 
print('\nthe shape of first linear layer:', para_list[0].shape)

輸出

class 'torch.nn.parameter.Parameter'>
number of linear_layers :3.0
weights:
tensor([[ 0.0135,  0.0206,  0.0051,  ..., -0.0184, -0.0131, -0.0246],
        [ 0.0127,  0.0337,  0.0177,  ...,  0.0304, -0.0177,  0.0316]],
       grad_fn=SliceBackward>)
bias:
tensor([0.0333, 0.0108], grad_fn=SliceBackward>)

the shape of first linear layer: torch.Size([512, 784])

named_parameters()方法返回參數(shù)的名稱和參數(shù)張量,例如:

print("Model structure: ", model, "\n\n")

for name, param in model.named_parameters():
    print(f"Layer: {name} | Size: {param.size()} | Values : \n{param[:2]} \n")
    # 只切出前兩行顯示

輸出

Model structure:  NeuralNetwork(
  (flatten): Flatten(start_dim=1, end_dim=-1)
  (linear_relu_stack): Sequential(
    (0): Linear(in_features=784, out_features=512, bias=True)
    (1): ReLU()
    (2): Linear(in_features=512, out_features=512, bias=True)
    (3): ReLU()
    (4): Linear(in_features=512, out_features=10, bias=True)
    (5): ReLU()
  )
)
Layer: linear_relu_stack.0.weight | Size: torch.Size([512, 784]) | Values :
tensor([[ 0.0135,  0.0206,  0.0051,  ..., -0.0184, -0.0131, -0.0246],
        [ 0.0127,  0.0337,  0.0177,  ...,  0.0304, -0.0177,  0.0316]],
       grad_fn=SliceBackward>)

Layer: linear_relu_stack.0.bias | Size: torch.Size([512]) | Values :
tensor([0.0333, 0.0108], grad_fn=SliceBackward>)

Layer: linear_relu_stack.2.weight | Size: torch.Size([512, 512]) | Values :
tensor([[ 0.0338,  0.0266, -0.0030,  ..., -0.0163, -0.0096, -0.0246],
        [-0.0292,  0.0302, -0.0308,  ...,  0.0279, -0.0291, -0.0105]],
       grad_fn=SliceBackward>)

Layer: linear_relu_stack.2.bias | Size: torch.Size([512]) | Values :
tensor([ 0.0137, -0.0036], grad_fn=SliceBackward>)

Layer: linear_relu_stack.4.weight | Size: torch.Size([10, 512]) | Values :
tensor([[ 0.0029, -0.0025,  0.0105,  ..., -0.0054,  0.0090,  0.0288],
        [-0.0391, -0.0088,  0.0405,  ...,  0.0376, -0.0331, -0.0342]],
       grad_fn=SliceBackward>)

Layer: linear_relu_stack.4.bias | Size: torch.Size([10]) | Values :
tensor([0.0406, 0.0369], grad_fn=SliceBackward>)

更多關(guān)于torch.nn的API請(qǐng)看:https://pytorch.org/docs/stable/nn.html

3 最優(yōu)化模型參數(shù)

(1)超參數(shù)

在繪制計(jì)算圖之前,需要給出超參數(shù),這里說的超參數(shù),指的是學(xué)習(xí)率、批大小、迭代次數(shù)等

learning_rate = 1e-3
batch_size = 64
epochs = 5

(2)損失函數(shù)

回歸問題一般用nn.MSELoss,二分類問題一般用nn.BCELoss,多分類問題一般用nn.CrossEntropyLoss,這里FashionMNIST中,標(biāo)簽有十個(gè)類別,因此這里我們用nn.CrossEntropyLoss

# Initialize the loss function
loss_fn = nn.CrossEntropyLoss()

(3)優(yōu)化方法

這里我們用隨機(jī)梯度下降,即每傳入一個(gè)樣本,更新一次參數(shù)

optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)

更多優(yōu)化方法的API,可以看:https://pytorch.org/docs/stable/optim.html
常用的優(yōu)化算法原理,可以看:https://zhuanlan.zhihu.com/p/78622301

4 模型的訓(xùn)練與測(cè)試

(1)訓(xùn)練循環(huán)與測(cè)試循環(huán)

每個(gè)epoch包括兩個(gè)主要部分:
訓(xùn)練循環(huán)(train_loop)——遍歷訓(xùn)練數(shù)據(jù)集并嘗試收斂到最優(yōu)參數(shù)。
驗(yàn)證/測(cè)試循環(huán)(test_loop)——遍歷測(cè)試數(shù)據(jù)集以檢查模型性能是否正在改善。

我們先把上述兩個(gè)過程封裝成函數(shù)

def train_loop(dataloader, model, loss_fn, optimizer):
    size = len(dataloader.dataset)
    for batch, (X, y) in enumerate(dataloader):
        # Compute prediction and loss,下面兩步相當(dāng)于繪制計(jì)算圖
        pred = model(X)
        loss = loss_fn(pred, y)

        # Backpropagation
        optimizer.zero_grad()	# 梯度信息清零
        loss.backward()			# 反向傳播
        optimizer.step()		# 一旦有了梯度,就可以更新參數(shù)

        if batch % 100 == 0:
            loss, current = loss.item(), batch * len(X)
            print(f"loss: {loss:>7f}  [{current:>5d}/{size:>5d}]")


def test_loop(dataloader, model, loss_fn):
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    test_loss, correct = 0, 0

    with torch.no_grad():		# 禁用梯度跟蹤,后面會(huì)講
        for X, y in dataloader:
            pred = model(X)
            test_loss += loss_fn(pred, y).item()
            correct += (pred.argmax(1) == y).type(torch.float).sum().item()

    test_loss /= num_batches
    correct /= size
    print(f"Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")

現(xiàn)在可以進(jìn)行訓(xùn)練了

for t in range(epochs):
    print(f"Epoch {t+1}\n-------------------------------")
    train_loop(train_dataloader, model, loss_fn, optimizer)
    test_loop(test_dataloader, model, loss_fn)
print("Done!")

輸出

我們可以寫一段代碼,看看預(yù)測(cè)的圖片對(duì)不對(duì)

test_features, test_labels = next(iter(test_dataloader))
logits = model(test_features[0])
pred_probab = nn.Softmax(dim=1)(logits)
pred = pred_probab.argmax(1)

img = test_features[0].squeeze()    # 將長(zhǎng)度為1的維度去掉
true_label = test_labels[0]
plt.imshow(img, cmap="gray")
plt.show()
print(f"True label: {true_label}")
print(f"Predict: {pred.item()}")

輸出

(2)禁用梯度跟蹤

在上面的測(cè)試循環(huán)中,使用了torch.no_grad()方法,在表示所在的with塊不對(duì)梯度進(jìn)行記錄。
默認(rèn)情況下,所有requires_grad=True的張量(在創(chuàng)建優(yōu)化器的時(shí)候,內(nèi)部就把里面的參數(shù)全部設(shè)置為了requires_grad=True)都跟蹤它們的計(jì)算歷史并支持梯度計(jì)算。但是,在某些情況下,我們并不需要這樣做,例如,測(cè)試的時(shí)候,我們只是想通過網(wǎng)絡(luò)進(jìn)行正向計(jì)算。我們可以通過使用torch.no_grad()塊包圍計(jì)算代碼來停止跟蹤計(jì)算:

z = torch.matmul(x, w)+b
print(z.requires_grad)

with torch.no_grad():
    z = torch.matmul(x, w)+b
	print(z.requires_grad)

輸出

True
False

禁用梯度跟蹤主要用于下面兩種情況:
(1)將神經(jīng)網(wǎng)絡(luò)中的一些參數(shù)標(biāo)記為凍結(jié)參數(shù),這是對(duì)預(yù)先訓(xùn)練過的網(wǎng)絡(luò)進(jìn)行微調(diào)的一個(gè)常見的場(chǎng)景
(2)當(dāng)你只做正向傳遞時(shí),為了加快計(jì)算速度,因?yàn)椴桓櫶荻鹊膹埩康挠?jì)算會(huì)更有效率。

5 模型的保存、導(dǎo)入與GPU加速

(1)模型的保存與導(dǎo)入

PyTorch模型將學(xué)習(xí)到的參數(shù)存儲(chǔ)在一個(gè)內(nèi)部狀態(tài)字典中,稱為state_dict,我們可以通過torch.save()將模型的參數(shù)保存到指定路徑。
保存了模型的參數(shù),還需要保存模型的形狀(即模型的結(jié)構(gòu))

# 保存模型參數(shù)
torch.save(model.state_dict(), './model_weights.pth')
# 保存模型結(jié)構(gòu)
torch.save(model, './model.pth')

導(dǎo)入模型時(shí),需要先導(dǎo)入模型的結(jié)構(gòu),再導(dǎo)入模型的參數(shù),代碼如下:

# 導(dǎo)入模型結(jié)構(gòu)
model_loaded = torch.load('./model.pth') 
# 如果原來的model在cuda:0上,那么導(dǎo)入之后,model_loaded也在cuda:0上

# 導(dǎo)入模型參數(shù)
model_loaded.load_state_dict(torch.load('model_weights.pth'))

因?yàn)閙odel是NeuralNetwork類的一個(gè)對(duì)象,所以在導(dǎo)入狀態(tài)前,必須先有一個(gè)NeuralNetwork對(duì)象,要么實(shí)例化一個(gè),要么通過導(dǎo)入結(jié)構(gòu)torch.load('./model.pth')導(dǎo)入一個(gè).

torch.load直接導(dǎo)入模型,不是特別推薦,原因有以下兩點(diǎn):

(1)如果A.py文件中的程序保存了model.pth,如果文件B.py想讀取這個(gè)模型,則不能直接用torch.load導(dǎo)入模型結(jié)構(gòu),必須先實(shí)例化一個(gè)NeuralNetwork對(duì)象,要么從A.py或者從其他文件中把NeuralNetwork類給導(dǎo)進(jìn)來,要么這里重寫一個(gè)與A.py中一模一樣的NeuralNetwork類,類名也要一樣,否則報(bào)錯(cuò)。

# 實(shí)例化一個(gè)NeuralNetwork對(duì)象
model_loaded = NeuralNetwork() # model_loaded默認(rèn)是CPU中
# 導(dǎo)入模型參數(shù)
model_loaded.load_state_dict(torch.load('./gdrive/MyDrive/model_weights.pth'))

(2)如果用torch.load導(dǎo)入模型,當(dāng)我們?cè)赾uda:0上訓(xùn)練好一個(gè)模型并保存時(shí),讀取出來的模型也是默認(rèn)在cuda:0上的,如果訓(xùn)練過程的其他數(shù)據(jù)被放到了如cuda:1上,則會(huì)報(bào)錯(cuò)。而實(shí)例化創(chuàng)建模型,由于.load_state_dict可以跨設(shè)備,則無論原來的模型在什么設(shè)備上,都不妨礙把參數(shù)導(dǎo)入到新創(chuàng)建的模型對(duì)象當(dāng)中。

綜合上面兩點(diǎn),torch.load慎用,最好是先實(shí)例化后再導(dǎo)入模型狀態(tài)。

我們可以用導(dǎo)入的模型做預(yù)測(cè)

test_features, test_labels = next(iter(test_dataloader))
logits = model_loaded(test_features[0])   # 使用導(dǎo)入的模型
pred_probab = nn.Softmax(dim=1)(logits)
pred = pred_probab.argmax(1)

img = test_features[0].squeeze()    # 將長(zhǎng)度為1的維度去掉
true_label = test_labels[0]
plt.imshow(img, cmap="gray")
plt.show()
print(f"True label: {true_label}")
print(f"Predict: {pred.item()}")

輸出

(2)GPU加速

默認(rèn)情況下,張量和模型是在CPU上創(chuàng)建的。如果想讓其在GPU中操作,我們必須使用.to方法(確定GPU可用后)顯式地移動(dòng)到GPU。需要注意的是,跨設(shè)備復(fù)制大張量在時(shí)間和內(nèi)存上開銷都是很大的!

# We can move our tensor to the GPU if available
device = 'cuda' if torch.cuda.is_available() else 'cpu'
print('Using {} device'.format(device))

輸出

Using cuda device

在初始化模型時(shí),可以將模型放入GPU中

model = NeuralNetwork().to(device)

對(duì)于張量,可以在創(chuàng)建的時(shí)候指定為在GPU上創(chuàng)建,也可以在創(chuàng)建后轉(zhuǎn)移到GPU當(dāng)中

X = torch.rand(1, 28, 28, device=device)	# 創(chuàng)建時(shí)指定設(shè)備
Y = torch.rand(10).to(device)				# 創(chuàng)建后轉(zhuǎn)移

當(dāng)然,張量和模型也能從GPU轉(zhuǎn)移到CPU當(dāng)中,我們可以用.device()來查看張量所在設(shè)備

另外,需要注意的是,如果需要將模型送到GPU當(dāng)中,必須在構(gòu)建優(yōu)化器之前。因?yàn)镃PU和GPU中的模型,是兩個(gè)不同的對(duì)象,構(gòu)建完優(yōu)化器再將模型放入GPU,將導(dǎo)致優(yōu)化器只優(yōu)化CPU中的模型參數(shù)。

有些電腦有多張顯卡,那么.to(‘cuda')默認(rèn)是將張量或者模型轉(zhuǎn)移到第一張顯卡(編號(hào)為0)上,如果想轉(zhuǎn)移到其他顯卡上,則用下面的程序

device = torch.device(‘cuda:2')
# 2是設(shè)備號(hào),假如有八張顯卡,那么編號(hào)就是0—7

torch.save
至此,所有程序已經(jīng)完成

總結(jié)

上面的程序有點(diǎn)亂,我這里綜合一下:

# coding=utf-8
import torch
import torch.nn as nn
from torchvision import datasets
from torch.utils.data import DataLoader
from torchvision.transforms import ToTensor
import matplotlib.pyplot as plt
import os
os.environ['KMP_DUPLICATE_LIB_OK'] = 'TRUE'	# 沒有這句會(huì)報(bào)錯(cuò),具體原因我也不知道

# 導(dǎo)入數(shù)據(jù)
training_data = datasets.FashionMNIST(
    root="../data",
    train=True,
    download=True,
    transform=ToTensor()
)
test_data = datasets.FashionMNIST(
    root="../data",
    train=False,
    download=True,
    transform=ToTensor()
)

# 定義超參數(shù)
# 之所以在這個(gè)地方定義,是因?yàn)樵诔跏蓟疍ataLoader時(shí)需要用到batch_size
learning_rate = 1e-3
batch_size = 64
epochs = 5
train_dataloader = DataLoader(training_data, batch_size=batch_size, shuffle=True)
# train_dataloader是一個(gè)DataLoader類的對(duì)象
test_dataloader = DataLoader(test_data, batch_size=batch_size, shuffle=True)


# 搭建神經(jīng)網(wǎng)絡(luò)
class NeuralNetwork(nn.Module):
    def __init__(self):
        super(NeuralNetwork, self).__init__()
        self.flatten = nn.Flatten()				# 打平
        self.linear_relu_stack = nn.Sequential(
            nn.Linear(28*28, 512),		# 線性層
            nn.ReLU(),					# 激活層
            nn.Linear(512, 512),
            nn.ReLU(),
            nn.Linear(512, 10),
            nn.ReLU()
        )

    def forward(self, x):
        x = self.flatten(x)					# 打平層
        logits = self.linear_relu_stack(x)	# 線性激活層
        return logits

# 確定使用設(shè)備
device = 'cuda' if torch.cuda.is_available() else 'cpu'

# 實(shí)例化一個(gè)神經(jīng)網(wǎng)絡(luò)類
model = NeuralNetwork().to(device)

# 確定損失函數(shù)
loss_fn = nn.CrossEntropyLoss()

# 確定優(yōu)化器
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)


# 封裝訓(xùn)練過程
def train_loop(dataloader, model, loss_fn, optimizer):
    size = len(dataloader.dataset)
    for batch, (X, y) in enumerate(dataloader):
        X, y = X.to(device), y.to(device) # 將樣本和標(biāo)簽轉(zhuǎn)移到device中
        # Compute prediction and loss,下面兩步相當(dāng)于繪制計(jì)算圖
        pred = model(X)
        loss = loss_fn(pred, y)

        # Backpropagation
        optimizer.zero_grad()	# 梯度信息清零
        loss.backward()			# 反向傳播
        optimizer.step()		# 一旦有了梯度,就可以更新參數(shù)

        if batch % 100 == 0:
            loss, current = loss.item(), batch * len(X)
            print(f"loss: {loss:>7f}  [{current:>5d}/{size:>5d}]")
            

# 封裝測(cè)試過程
def test_loop(dataloader, model, loss_fn):
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    test_loss, correct = 0, 0

    with torch.no_grad():
        for X, y in dataloader:
            X, y = X.to(device), y.to(device)  # 將樣本和標(biāo)簽轉(zhuǎn)移到device中
            pred = model(X)
            test_loss += loss_fn(pred, y).item()
            correct += (pred.argmax(1) == y).type(torch.float).sum().item()

    test_loss /= num_batches
    correct /= size
    print(f"Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")

# 訓(xùn)練
for t in range(epochs):
    print(f"Epoch {t+1}\n-------------------------------")
    train_loop(train_dataloader, model, loss_fn, optimizer)
    test_loop(test_dataloader, model, loss_fn)
print("Done!")

# 保存模型參數(shù)
torch.save(model.state_dict(), './model_weights.pth')
# 保存模型結(jié)構(gòu)
torch.save(model, './model.pth')

# 導(dǎo)入模型結(jié)構(gòu)
model_loaded = torch.load('./model.pth')    # 模型自動(dòng)導(dǎo)入到GPU當(dāng)中
# 導(dǎo)入模型參數(shù)
model_loaded.load_state_dict(torch.load('model_weights.pth'))

# 用導(dǎo)入的模型測(cè)試
test_features, test_labels = next(iter(test_dataloader))
test_features = test_features.to(device)
logits = model_loaded(test_features[0])   # 使用導(dǎo)入的模型
pred_probab = nn.Softmax(dim=1)(logits)
pred = pred_probab.argmax(1)

# 可視化
img = test_features[0].squeeze()    # 將長(zhǎng)度為1的維度去掉
img = img.to('cpu')              # 繪圖時(shí),需要將張量轉(zhuǎn)回到CPU當(dāng)中
true_label = test_labels[0]   # 標(biāo)簽是否轉(zhuǎn)移到CPU無所謂,因?yàn)闆]有用于plt的方法中
plt.imshow(img, cmap="gray")
plt.show()
print(f"True label: {true_label}")
print(f"Predict: {pred.item()}")

到此這篇關(guān)于pytorch 搭建神經(jīng)網(wǎng)路的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)pytorch 神經(jīng)網(wǎng)路內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:
  • pytorch之深度神經(jīng)網(wǎng)絡(luò)概念全面整理
  • pytorch動(dòng)態(tài)神經(jīng)網(wǎng)絡(luò)(擬合)實(shí)現(xiàn)
  • Pytorch實(shí)現(xiàn)神經(jīng)網(wǎng)絡(luò)的分類方式
  • 對(duì)Pytorch神經(jīng)網(wǎng)絡(luò)初始化kaiming分布詳解
  • PyTorch一小時(shí)掌握之神經(jīng)網(wǎng)絡(luò)氣溫預(yù)測(cè)篇

標(biāo)簽:寧夏 南平 海南 大同 林芝 漯河 盤錦 普洱

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《pytorch 搭建神經(jīng)網(wǎng)路的實(shí)現(xiàn)》,本文關(guān)鍵詞  pytorch,搭建,神經(jīng),網(wǎng)路,的,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《pytorch 搭建神經(jīng)網(wǎng)路的實(shí)現(xiàn)》相關(guān)的同類信息!
  • 本頁收集關(guān)于pytorch 搭建神經(jīng)網(wǎng)路的實(shí)現(xiàn)的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    国内成人自拍视频| 国产网红女主播精品视频| 国产精品99久久久久久动医院| 天天影视色香欲综合| 国产成人高清激情视频在线观看| 国产精品三区www17con| jizz欧美性11| 日韩av中文字幕在线播放| 最新日本在线观看| 免费不卡av在线| 首页国产欧美久久| 99久久精品情趣| 精品日本一区二区三区| 性欧美大胆高清视频| 国产伦精品一区二区三区在线| 在线免费观看成人网| 99综合视频| 欧美一区二区三区在线观看| 精品欧美国产一区二区三区| 性折磨bdsm欧美激情另类| 一级黄色片在线观看| 亚洲色图第一页| 免费看91的网站| 国产精品稀缺呦系列在线| 婷婷综合激情网| 欧美亚洲在线| 人妻视频一区二区| 粉嫩一区二区三区四区公司1| 午夜精品毛片| 中文字幕中文字幕一区二区| 亚洲线精品一区二区三区八戒| 人人妻人人澡人人爽欧美一区| 欧美蜜桃一区二区三区| 美女啪啪无遮挡| 一区二区三区免费看视频| 一级性生活大片| 欧美亚洲免费在线一区| 中韩乱幕日产无线码一区| 狠久久av成人天堂| 日韩欧美电影在线观看| 香蕉视频网站在线播放| 亚洲一区二区三区成人在线视频精品| 午夜精品福利一区二区三区av| 亚洲精品自产拍在线观看| 精品成人av一区| 日韩欧美成人午夜| 欧美日韩日本国产| 日本欧美电影在线观看| 亚洲黄色网址在线观看| 182在线观看视频| 小早川怜子久久精品中文字幕| 思思久久99热只有频精品66| 精品国内亚洲在观看18黄| 日本一道高清一区二区三区| 视频一区国产| 国产91精品露脸国语对白| 亚洲精品欧美激情| 99自拍偷拍视频| 国产一区免费| 国产一区二区视频免费观看| 欧美日韩国产在线| 裸体丰满少妇做受久久99精品| 黄色片免费在线观看视频| 日韩精品不卡一区二区| 1024精品一区二区三区| 先锋影音亚洲资源| 蜜桃av在线免费观看| 新欧美整片sss第一页| 日韩hd视频在线观看| 午夜大片在线观看| 精品成人私密视频| 国内外成人激情视频| 亚洲欧美日韩国产成人| 91欧美激情一区二区三区成人| 欧美午夜精品一区| 久久久成人网| 蜜桃视频一区| 亚洲伊人网站| 久久国产情侣| 亚洲精品wwww| 天堂中文资源在线| sdde在线播放一区二区| 久久这里有精品视频| av在线免费观看网址| 在线观看国产日韩| 日韩在线观看一区二区三区| 97人人在线| 色综合影院在线观看| 国产永久av在线| 99热这里只有精品1| 久久久蜜桃精品| 永久免费看黄网站| 五月婷婷激情综合网| 国产免费一区二区三区| 久久亚洲国产成人精品无码区| 欧美亚韩一区| 麻豆精品久久精品色综合| 毛片不卡一区二区| 国产精品一区2区| 在线亚洲国产精品网站| 国产精品羞羞答答在线观看| 天天干视频在线| 欧美熟妇精品黑人巨大一二三区| 国产精品探花视频| 日韩中文字幕免费看| 影院在线观看全集免费观看| 国产大片在线免费观看| 亚洲精品97久久久babes| av一级久久| 日韩精品成人一区二区在线观看| 一区二区三区视频在线观看视频| 久久精品国产一区二区电影| 牛牛影视久久网| 欧美亚洲色图视频| 精品视频二区| 久草国产在线观看| 日韩av一区二区在线观看| 久久久成人精品视频| 老司机在线视频二区| 国产精品激情偷乱一区二区∴| 亚洲精品电影| 紧缚捆绑精品一区二区| 亚洲激情在线看| 奇米色在线视频| 97激碰免费视频| sdde在线播放一区二区| 日韩成人三级视频| 亚洲国产日韩在线人成电影| 亚洲a中文字幕| 一区二区三区在线观看免费视频| 国产激情久久久久| 久久久久久久久电影| 九九精品免费视频| 嗯用力啊快一点好舒服小柔久久| 91免费国产视频| 冲田杏梨av在线| 国产99久久久国产精品成人免费| 婷婷激情四射网| 欧美一区二区视频17c| 亚洲人成网站在线在线观看| 人妻无码中文字幕| 欧美日韩在线精品一区二区三区| 少妇大叫太大太粗太爽了a片小说| 精品日本美女福利在线观看| 国产精品欧美一区二区| 成人91免费视频| 一本久道久久综合中文字幕| 亚洲美女网站| 成人动漫在线视频| 国产一区久久精品| 亚洲第一精品电影| 国产综合在线观看| 欧美日韩在线视频免费播放| 国产午夜在线播放| 亚洲一区二区自拍| 无码少妇精品一区二区免费动态| mm131美女视频| 里番精品3d一二三区| 自拍偷自拍亚洲精品被多人伦好爽| 亚洲欧美影院| 91九色蝌蚪嫩草| 一区二区三区日本久久久| 黄色资源网久久资源365| 中文字幕无码毛片免费看| 99久久99久久久精品棕色圆| 亚洲精品男同| 26uuu久久噜噜噜噜| 午夜一区二区三区不卡视频| 国产探花视频在线观看| 国产精品第5页| 国产黄色小视频| jizz一区二区| 少妇高潮一区二区三区| 99视频精品免费观看| 青青在线免费观看视频| 欧美在线免费一级片| 久久精品亚洲a| 国产成人在线免费观看| 久久er99热精品一区二区三区| 9999精品成人免费毛片在线看| 川上优av一区二区线观看| 在线观看网站黄不卡| 国产三级日本三级在线播放| 亚洲欧美中文日韩在线| 欧美高清激情brazzers| 亚洲日产av中文字幕| 亚欧激情乱码久久久久久久久| 色愁久久久久久| 中文字幕国内精品| 波多野结衣在线一区二区| 国产一区二区三区精品在线观看| 欧洲成人在线视频| 精品国偷自产一区二区三区| 99久久久无码国产精品性色戒| 亚洲精品一区二区18漫画| 99久久99久久精品国产片果冰| 激情五月综合网| 亚洲欧美色婷婷| 亚洲男人第一天堂| 美女被爆操网站| 国产在线日韩精品| 国产午夜福利在线播放| 免费不卡av在线| 免费观看成人av| 无码人妻精品一区二区三区99v| 懂色一区二区三区av片| 97视频在线观看网址| 亚洲精品一区二区三区中文字幕| 日韩另类视频| 青青热久免费精品视频在线18| 精品久久久91| 免费女人毛片视频| 午夜影院福利社| 实拍女处破www免费看| 免费看又黄又无码的网站| 蜜乳av一区二区三区| 日本国产精品视频| 中文字幕视频一区二区| 一广人看www在线观看免费视频| 夜色福利资源站www国产在线视频| 国产视频精品视频| 亚洲网中文字幕| 青青国产视频| 欧亚一区二区三区| 欧美女子与性| 精品国产91亚洲一区二区三区婷婷| 熟女少妇a性色生活片毛片| 国产精品中文在线| √…a在线天堂一区| 国产免费av电影| 精品国产av无码一区二区三区| 在线日韩精品视频| ts人妖另类在线| 国产视频www| 国产农村妇女精品| www.97av| 亚洲自拍另类欧美丝袜| 男女爱爱视频免费| 奇米影视四色在观看线| 性欧美性free| 视频一区在线观看| 免费av一区| 日本成人在线视频网站| 欧美韩日国产| 精品国产1区二区| 精品在线观看入口| 国产一区二区三区色淫影院| 男女啪啪免费观看| 中文字幕超清在线免费观看| 一二三四区在线| 精品久久久av| 久久亚洲一区二区三区明星换脸| 欧美日韩性视频在线| 91日韩在线视频| 国产精品入口麻豆免费| 精品一区久久| 国产91精品不卡视频| 国产成人久久精品77777综合| 97精品伊人久久久大香线蕉| 亚洲色图另类小说| 2020中文字字幕在线不卡| 亚洲天堂日韩av| 日韩欧美成人免费视频| 日韩日韩日韩日韩日韩| 亚洲成人中文在线| 久久久久国产精品| 久久中文字幕二区| 欧美xxxx做受欧美.88| 不卡在线一区| 色婷婷精品久久二区二区密| 久久久国产免费| 女人被爽到呻吟gif动态图下载| av不卡一区| 人妻 日韩精品 中文字幕| 久久人91精品久久久久久不卡| 久久久久久天堂| 国产成人亚洲综合a∨猫咪| 国产精品自产拍在线观看中文| 久久精品人妻一区二区三区| 丁香花在线高清完整版视频| 国产情侣久久久久aⅴ免费| 精品噜噜噜噜久久久久久久久试看| 在线中文一区| 一本色道久久综合亚洲精品不| 91精品国产91久久久久久不卡| 男生草女生视频| 性生活免费观看视频| 国产xxx69麻豆国语对白| 一区二区三区成人在线视频| 久久97超碰色| 在线观看男女av免费网址| 亚洲36d大奶网| 国产性xxxx18免费观看视频| 蜜臀aⅴ国产精品久久久国产老师| 亚洲精品一区二区三区蜜桃下载| 777色狠狠一区二区三区| 亚洲综合首页| 精品高清久久| 国产一区二区色噜噜| 欧美怡红院视频一区二区三区| 91成人午夜| 99九九99九九九视频精品| 夜夜骑夜夜操| 国偷自产av一区二区三区麻豆| 国产美女高潮视频| 国产精品91在线观看| 欧美一区二区三| 久久久久久一区| 中文字幕在线资源| 久久在线观看| 色哟哟免费网站| 精品美女视频在线观看免费软件| 亚州av乱码久久精品蜜桃| 欧美性xxxx图片| 亚洲黄色在线免费观看| www.久久热| 蜜桃久久久久久久| 久久久国产视频| 日本亚洲一区二区三区| 国产精品综合不卡av| 欧美国产激情二区三区| 伦一区二区三区中文字幕v亚洲| 欧美国产日韩精品免费观看| 日本中文字幕在线播放| 亚洲成人蜜桃| 中文在线播放| 欧美顶级少妇做爰| 国产精品久久久久无码av色戒|