欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報邀請碼778899分享:人工智能 Pytorch的學習

柚子快報邀請碼778899分享:人工智能 Pytorch的學習

http://yzkb.51969.com/

1.基本數(shù)據(jù):Tensor

Tensor,即張量,是PyTorch中的基本操作對象,可以看做是包含單一數(shù)據(jù)類型元素的多維矩陣。從使用角度來看,Tensor與NumPy的ndarrays非常類似,相互之間也可以自由轉(zhuǎn)換,只不過Tensor還支持GPU的加速【重點】。

1.1 Tensor的創(chuàng)建

1.2 tensor的操作:

第一部分: 分為FloatTensor,IntTensor,randn,range,zeros,ones,empty

import torch

a = torch.FloatTensor(2,3) # 1.生成兩行三列的向量,3代表維度

b = torch.FloatTensor([2,3,4,5]) # 2.生成float類型的四個維度向量

a,b

(tensor([[1.0561e-38, 1.0102e-38, 9.6429e-39],

[8.4490e-39, 9.6429e-39, 9.1837e-39]]),

tensor([2., 3., 4., 5.]))

torch.IntTensor: 用于生成數(shù)據(jù)類型為整型的Tensor,傳遞給傳遞給torch.IntTensor的參數(shù)可以是列表,也可以是一個維度值。

import torch

a = torch.IntTensor(2,3)

b = torch.IntTensor([2,3,4,5])

a,b

torch.randn: 用于生成數(shù)據(jù)類型為浮點數(shù)且維度指定的隨機Tensor,隨機生成的浮點數(shù)的取值滿足均值為0,方差為1的正態(tài)分布。

import torch

a = torch.randn(2,3)

a

tensor([[-0.0067, -0.0707, -0.6682],

[ 0.8141, 1.1436, 0.5963]])

torch.zeros: torch.zeros用于生成數(shù)據(jù)類型為浮點型且維度指定的Tensor

import torch

a = torch.zeros(2,3)

a

tensor([[0., 0., 0.],

[0., 0., 0.]])

torch.abs 、torch.add、torch.clamp、torch.mm()計算: torch.clamp()的作用:對tensor中的數(shù)據(jù)進行裁剪。 torch.mm()的作用:將參數(shù)傳遞到torch.mm后返回輸入?yún)?shù)的求積結(jié)果作為輸出,不過這個求積的方式和之前的torch.mul運算方式不太一樣,torch.mm 運用矩陣之間的乘法規(guī)則進行計算 ,所以被傳入的參數(shù)會被當作矩陣進行處理,參數(shù)的維度自然也要滿足矩陣乘法的前提條件,即前一個矩陣的行數(shù)必須和后一個矩陣列數(shù)相等

# 這段代碼的目的是展示不同類型的張量的使用方法。下面是加上中文注釋后的代碼:

import torch

# 1.demo1

a = torch.FloatTensor(2, 3) # 創(chuàng)建一個大小為2x3的浮點型張量

b = torch.FloatTensor([2, 3, 4, 5]) # 創(chuàng)建一個大小為4的浮點型向量

c = torch.Tensor(2, 3) # 創(chuàng)建一個大小為2x3的任意類型張量

# print(a, b) # 輸出a和b

# print(c)

# 2.demo2

a = torch.IntTensor(2, 3)

b = torch.IntTensor([2, 3, 4, 5])

# print(a, b)

# 3.demo3:生成數(shù)據(jù)類型為浮點數(shù)且維度指定的隨機Tensor,取值滿足均值為0,方差為1的正態(tài)分布

a = torch.randn(2, 3)

b = torch.range(1, 20, 2) # torch.range用于生成數(shù)據(jù)類型為浮點型且起始范圍和結(jié)束范圍的Tensor

# print(a)

# print(b)

# 4.demo4: Tensor的計算

a = torch.randn(2, 3)

b = torch.abs(a) # 絕對值的輸出

# print(a)

# print(b)

a = torch.randn(2, 3)

b = torch.randn(2, 3)

c = torch.add(a, b)

# print(c)

d = torch.randn(2, 3)

e = torch.add(d, 10) # 增加標量

# print(e)

a = torch.randn(2, 3)

# print(a)

b = torch.clamp(a, -0.1, 0.1) # 卡位操作:限制張量里面每個值都在-0.1到0.1之間,如果<-0.1則設置未-0.1,如果>0.1,則設置未0.1

# print(b)

# 4.demo4:矩陣計算-torch.mm() (2x3)*(3x2)=2x2,如果是矩陣和向量之間的計算,舊用torch.mv()

a = torch.randn(2, 3)

print(a)

b = torch.rand(2, 3)

print(b)

c = torch.mm(a, b.T)

print(c)

torch.mv(): 將參數(shù)傳遞到torch.mv后返回輸入?yún)?shù)的求積結(jié)果作為輸出,torch.mv運用矩陣與向量之間的乘法規(guī)則進行計算,被傳入的第1個參數(shù)代表矩陣,第2個參數(shù)代表向量,循序不能顛倒。

a = torch.randn(2,3)

a

#我們得到a為:

#tensor([[ 1.0909, -1.1679, 0.3161],

# [-0.8952, -2.1351, -0.9667]])

b = torch.randn(3)

b

#我們得到b為:

#tensor([-1.4689, 1.6197, 0.7209])

#用產(chǎn)生的a,b進行矩陣乘法操作:

c = torch.mv(a,b)

c

#tensor([-3.2663, -2.8402])

2.神經(jīng)網(wǎng)絡工具箱torch.nn

torch.autograd 庫雖然實現(xiàn)了自動求導與梯度反向傳播。 torch.nn: 該接口構(gòu)建于 Autograd 之上,提供了網(wǎng)絡模組、優(yōu)化器和初始化策略等一系列功能 nn.Module類: nn.Module是PyTorch提供的神經(jīng)網(wǎng)絡類,并在類中實現(xiàn)了網(wǎng)絡各層的定義及前向計算與反向傳播機制。在實際使用時,如果想要實現(xiàn)某個神經(jīng)網(wǎng)絡,只需繼承nn.Module,在初始化中定義模型結(jié)構(gòu)與參數(shù),在函數(shù)**forward()**中編寫網(wǎng)絡前向過程即可。

1.nn.Parameter函數(shù)

2.forward()函數(shù)與反向傳播

3.多個Module的嵌套

4.nn.Module與nn.functional庫

5.nn.Sequential()模塊

import torch.nn as nn

import torch

class MLP(nn.Module):

"""

實現(xiàn)一個具有三層隱藏層的MLP模型。

參數(shù):

- in_dim (int): 輸入維度

- hid_dim1 (int): 第一層隱藏層的維度

- hid_dim2 (int): 第二層隱藏層的維度

- out_dim (int): 輸出維度

返回:

- 無

"""

def __init__(self, in_dim, hid_dim1, hid_dim2, out_dim):

super(MLP, self).__init__() # 1.調(diào)用父類 nn.Module 的初始化方法

# 2.定義一個包含三層線性變換和三層ReLU激活函數(shù)的序列模型

self.layers = nn.Sequential(

nn.Linear(in_dim, hid_dim1), # 3.第一層線性變換

nn.ReLU(), # 第一層激活函數(shù)

nn.Linear(hid_dim1, hid_dim2), # 第二層線性變換

nn.ReLU(), # 第二層激活函數(shù)

nn.Linear(hid_dim2, out_dim) # 第三層線性變換

# 通常在最后一層線性變換后不會再加 ReLU,因為這會影響輸出的范圍

)

def forward(self, x):

"""

定義網(wǎng)絡的前向傳播過程。

參數(shù):

- x (Tensor): 輸入的特征張量

返回:

- x (Tensor): 經(jīng)過模型處理后的輸出張量

"""

x = self.layers(x) # 輸入x依次經(jīng)過self.layers中定義的各層

return x

# 定義MLP模型輸入輸出的維度

in_dim = 10

hid_dim1 = 20

hid_dim2 = 15

out_dim = 5

# 實例化MLP模型

model = MLP(in_dim, hid_dim1, hid_dim2, out_dim)

# 得到輸入張量x,維度應該和模型model定義的輸入張量維度一樣的

x = torch.randn(32, in_dim)

# 將輸入張量 x 傳入模型得到輸出的維度,本質(zhì)就是傳遞給模型的 forward 方法(或者直接傳遞給模型實例,因為 forward 方法會被自動調(diào)用)

output = model(x)

print(output.shape)

3.搭建簡易的神經(jīng)網(wǎng)絡:

3.1下面我們用torch搭一個簡易神經(jīng)網(wǎng)絡: 1、【torch.autograd】包的主要功能就是完成神經(jīng)網(wǎng)絡后向傳播中的鏈式求導,手動去寫這些求導程序會導致重復造輪子的現(xiàn)象。 2、【自動梯度的功能過程大致為】:先通過輸入的Tensor數(shù)據(jù)類型的變量在神經(jīng)網(wǎng)絡的前向傳播過程中生成一張計算圖,然后根據(jù)這個計算圖和輸出結(jié)果精確計算出每一個參數(shù)需要更新的梯度,并通過完成后向傳播完成對參數(shù)的梯度更新。

import torch

from torch.autograd import Variable

batch_n = 100 # 一個批次輸入數(shù)據(jù)的數(shù)量

hidden_layer = 100

input_data = 1000 # 每個數(shù)據(jù)的特征為1000

output_data = 10

x = Variable(torch.randn(batch_n, input_data), requires_grad=False)

y = Variable(torch.randn(batch_n, output_data), requires_grad=False)

# 用Variable對Tensor數(shù)據(jù)類型變量進行封裝的操作。requires_grad如果是False,表示該變量在進行自動梯度計算的過程中不會保留梯度值。

w1 = Variable(torch.randn(input_data, hidden_layer), requires_grad=True)

w2 = Variable(torch.randn(hidden_layer, output_data), requires_grad=True)

# 學習率和迭代次數(shù)

epoch_n = 50

lr = 1e-6

for epoch in range(epoch_n):

h1 = x.mm(w1) # (100,1000)*(1000,100)-->100*100

print(h1.shape)

h1 = h1.clamp(min=0)

y_pred = h1.mm(w2)

# y_pred = x.mm(w1).clamp(min=0).mm(w2)

loss = (y_pred - y).pow(2).sum()

print("epoch:{},loss:{:.4f}".format(epoch, loss.data))

# grad_y_pred = 2*(y_pred-y)

# grad_w2 = h1.t().mm(grad_y_pred)

loss.backward() # 后向傳播

# grad_h = grad_y_pred.clone()

# grad_h = grad_h.mm(w2.t())

# grad_h.clamp_(min=0)#將小于0的值全部賦值為0,相當于sigmoid

# grad_w1 = x.t().mm(grad_h)

w1.data -= lr * w1.grad.data

w2.data -= lr * w2.grad.data

w1.grad.data.zero_()

w2.grad.data.zero_()

# w1 = w1 -lr*grad_w1

# w2 = w2 -lr*grad_w2

3.2重寫前向傳播函數(shù): 該代碼并沒有繼承父類的model,初始化直接利用父類的model,關鍵點在于重寫了前向傳播算法

import torch

from torch.autograd import Variable

batch_n = 64#一個批次輸入數(shù)據(jù)的數(shù)量

hidden_layer = 100

input_data = 1000#每個數(shù)據(jù)的特征為1000

output_data = 10

class Model(torch.nn.Module):#完成類繼承的操作

def __init__(self):

super(Model,self).__init__()#類的初始化

def forward(self,input,w1,w2):

x = torch.mm(input,w1)

x = torch.clamp(x,min = 0)

x = torch.mm(x,w2)

return x

def backward(self):

pass

model = Model()

x = Variable(torch.randn(batch_n,input_data),requires_grad=False)

y = Variable(torch.randn(batch_n,output_data),requires_grad=False)

#用Variable對Tensor數(shù)據(jù)類型變量進行封裝的操作。requires_grad如果是F,表示該變量在進行自動梯度計算的過程中不會保留梯度值。

w1 = Variable(torch.randn(input_data,hidden_layer),requires_grad=True)

w2 = Variable(torch.randn(hidden_layer,output_data),requires_grad=True)

epoch_n=30

for epoch in range(epoch_n):

y_pred = model(x,w1,w2)

loss = (y_pred-y).pow(2).sum()

print("epoch:{},loss:{:.4f}".format(epoch,loss.data))

loss.backward()

w1.data -= lr*w1.grad.data

w2.data -= lr*w2.grad.data

w1.grad.data.zero_()

w2.grad.data.zero_()

3.3 利用torch.nn.Sequential類(一種序列容器)進行神經(jīng)網(wǎng)絡的搭建: Sequential 類是torch.nn中的一種序列容器,通過在容器中嵌套各種實現(xiàn)神經(jīng)網(wǎng)絡模型的搭建,最主要的是,參數(shù)會按照我們定義好的序列自動傳遞下去。 Linear(input,hidden)的作用就是對輸入的數(shù)據(jù)進行線性變換,以下的權重和偏置會在訓練過程中通過反向傳播算法進行更新。 相關鏈接: 線性回歸 分類的基礎學習 線性和非線性

import torch

from torch.autograd import Variable

batch_n = 100 #一個批次輸入數(shù)據(jù)的數(shù)量

hidden_layer = 100

input_data = 1000 #每個數(shù)據(jù)的特征為1000

output_data = 10

x = Variable(torch.randn(batch_n,input_data),requires_grad=False)

y = Variable(torch.randn(batch_n,output_data),requires_grad=False)

#用Variable對Tensor數(shù)據(jù)類型變量進行封裝的操作。requires_grad如果是F,表示該變量在進行自動梯度計算的過程中不會保留梯度值。

models = torch.nn.Sequential(

torch.nn.Linear(input_data,hidden_layer),

torch.nn.ReLU(),

torch.nn.Linear(hidden_layer,output_data)

)

#torch.nn.Sequential括號內(nèi)就是我們搭建的神經(jīng)網(wǎng)絡模型的具體結(jié)構(gòu),Linear完成從隱藏層到輸出層的線性變換,再用ReLU激活函數(shù)激活

#torch.nn.Sequential類是torch.nn中的一種序列容器,通過在容器中嵌套各種實現(xiàn)神經(jīng)網(wǎng)絡模型的搭建,

#最主要的是,參數(shù)會按照我們定義好的序列自動傳遞下去。

4.一些計算損失函數(shù)的方法

4.1 MSE均方差

torch.nn.MSELoss類使用均方誤差函數(shù)對損失值進行計算,定義類的對象時不用傳入任何參數(shù),但在使用實例時需要輸入兩個維度一樣的參數(shù)方可進行計算。

用于場景: MSE 是預測值和實際值之間差值的平方的平均值。它主要用于回歸問題。

import torch

from torch.autograd import Variable

loss_f = torch.nn.MSELoss()

x = Variable(torch.randn(100,100)) # 100行100列的向量

y = Variable(torch.randn(100,100))

loss = loss_f(x,y)

loss.data

#tensor(1.9529)

4.2 L1平均絕對誤差

torch.nn.L1Loss類使用平均絕對誤差函數(shù)對損失值進行計算,定義類的對象時不用傳入任何參數(shù),但在使用實例時需要輸入兩個維度一樣的參數(shù)方可進行計算。 應用場景: L1 損失是預測值與實際值之間差的絕對值的平均值。它對異常值具有較好的魯棒性。

import torch

from torch.autograd import Variable

loss_f = torch.nn.L1Loss()

x = Variable(torch.randn(100,100))

y = Variable(torch.randn(100,100))

loss = loss_f(x,y)

loss.data

#tensor(1.1356)

4.3 交叉熵的計算

交叉熵+線性非線性 交叉熵一般就用于多分類的情況,(3,5)表示為3個樣本,每個樣本為5維的數(shù)據(jù),所以我們要給每個樣本附上一個標簽。

'''

交叉熵:用于多分類任務的損失函數(shù),它需要兩個輸入:模型的預測輸出和目標標簽

'''

loss_f = torch.nn.CrossEntropyLoss()

x = Variable(torch.randn(3, 5)) # 創(chuàng)建一個形狀為 (3, 5) 的隨機張量 x,表示 3 個樣本,每個樣本有 5 個特征。

y = Variable(torch.LongTensor(3).random_(5)) # 3個0-4的隨機數(shù)字(表特征),生成了一個包含 3 個隨機整數(shù)的張量,每個整數(shù)的范圍在 0 到 4 之間

print(y)

loss = loss_f(x, y)

print(loss.data)

5.使用pytorch搭建神經(jīng)網(wǎng)絡(識別數(shù)字)

首先介紹幾個常見的包:

5.1 torchvision

torchvision 是PyTorch中專門用來處理圖像的庫。這個包中有四個大類:

torchvision.datasetstorchvision.modelstorchvision.transformstorchvision.utils

1.torchvision.datasets torchvision.datasets可以實現(xiàn)對一些數(shù)據(jù)集的下載和加載如MNIST可以用torchvision.datasets.MNIST COCO、ImageNet、CIFCAR等都可用這個方法下載和載入。

這里用torchvision.datasets加載MNIST數(shù)據(jù)集:

data_train = datasets.MNIST(root="./data/",

transform=transform,

train = True,

download = True)

data_test = datasets.MNIST(root="./data/",

transform = transform,

train = False)

2.torchvision.models torchvision.models 中為我們提供了已經(jīng)訓練好的模型. torchvision.models模塊的 子模塊中包含以下模型結(jié)構(gòu)。如:

AlexNet VGG ResNet SqueezeNet DenseNet等

import torchvision.models as models

resnet18 = models.resnet18()

alexnet = models.alexnet()

squeezenet = models.squeezenet1_0()

densenet = models.densenet_161()

5.1.1 如何修改這些模型的參數(shù)?

比如修改模型的輸入層或輸出層。

示例: 修改ResNet18模型以適應具有100個輸出類別的任務:

import torchvision.models as models

import torch.nn as nn

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

num_ftrs = resnet18.fc.in_features # 獲取最后一個全連接層的輸入特征數(shù)量

resnet18.fc = nn.Linear(num_ftrs, 100) # 修改為100個輸出類別

凍結(jié)參數(shù),并更新全連接層(遷移學習)。

在遷移學習中,你可能希望凍結(jié)模型的一部分,只訓練模型的特定層。這通常通過設置參數(shù)的requires_grad屬性來實現(xiàn)。

示例: 凍結(jié)DenseNet161模型的所有參數(shù),只訓練最后的分類層: 目的: 1. 利用預訓練模型的特征提取能力:一個已經(jīng)在數(shù)據(jù)集上訓練過的模型(如DenseNet161)通過訓練已經(jīng)學會了如何從圖像中提取有用的特征,比如邊緣、紋理、形狀等。這些特征對于圖像識別任務是非常有用的。所以我們可以利用它已經(jīng)學習到的特征提取能力,利用模型已經(jīng)理解的復雜和通用的視覺特征,這些特征通常對于大多數(shù)視覺識別任務都是有效的。 2.只更新模型的最后部分:盡管預訓練模型在特征提取方面表現(xiàn)優(yōu)秀,但它最初是為處理其他類型的任務(如識別ImageNet數(shù)據(jù)庫中的1000個類別)而訓練的。如果我們要處理一個新的任務(例如分類100個不同的類別),我們通常需要調(diào)整模型的最后一層,使其輸出與新任務的類別數(shù)量相匹配。這樣的原因:模型的前面幾層通常負責提取圖像的通用特征,而最后幾層則更專注于將這些特征轉(zhuǎn)換成特定的預測輸出(比如分類)。 3.訓練速度和效果:顯著減少需要訓練的參數(shù)數(shù)量,因為只有最后一層是新的或被重新訓練的。

densenet = models.densenet161(pretrained=True) # 加載了一個預訓練的 DenseNet161 模型。這個模型已經(jīng)在大型的圖像數(shù)據(jù)集(通常是ImageNet)上進行了訓練,學習了很多圖像特征。

for param in densenet.parameters():

param.requires_grad = False # 遍歷 DenseNet161 模型中的所有參數(shù),這些參數(shù)在接下來的訓練過程中不會被更新(即它們被“凍結(jié)”了)

# 僅修改最后的分類層,重新啟用梯度

num_ftrs = densenet.classifier.in_features # 獲取 DenseNet161 模型中的最后一層全連接層(即為分類層)的輸入特征數(shù)量

densenet.classifier = nn.Linear(num_ftrs, 100) # 假設有100個類別

densenet.classifier.weight.requires_grad = True # 重新啟用了新分類器層權重的梯度計算。

還需要考慮一個點(遷移學習),即為任務的相似性: 如果新任務與原始任務在視覺上有一定的相似性,比如從識別一般物體到識別特定物體(例如從識別動物到識別特定的動物種類),那么原始模型的特征提取層可能仍然非常有效。然而,如果任務從識別日常物品變?yōu)樽R別細粒度的人臉特征,那么可能需要對這些層進行更細致的調(diào)整或重新訓練,因為這些任務在視覺特征上的需求可能有較大差異。

修改架構(gòu)。

對于一些模型,例如SqueezeNet,你可能需要修改其內(nèi)部架構(gòu),例如改變某些層的激活函數(shù)或調(diào)整層之間的連接方式。

squeezenet = models.squeezenet1_0(pretrained=True)

# 假設你想修改特定層的屬性

squeezenet.features[3].expand3x3.activation = nn.ReLU(inplace=False)

5.1.2 torch.transforms

torch.transforms中有大量數(shù)據(jù)變換類,如:

5.1.3.1 torchvision.transforms.Resize 用于對載入的圖片數(shù)據(jù)按照我們需求的大小進行縮放。傳遞的參數(shù)可以是一個整型數(shù)據(jù),也可以是一個類似于(h,w)的序列。h代表高度,w代表寬度,如果輸入的是整型數(shù)據(jù)那么h和w都等于這個數(shù)。

5.1.3.2 torchvision.transforms.Scale 用于對載入的圖片數(shù)據(jù)按照我們需求的大小進行縮放。和Resize類似。

5.1.3.3 torchvision.transforms.CenterCrop 用于對載入的圖片以圖片中心為參考點,按照我們需要的大小進行裁剪。傳遞給這個類的參數(shù)可以是一個整型數(shù)據(jù),也可以是一個類似于(h,w)的序列。

5.1.3.4 torchvision.transforms.RandomCrop 用于對載入的圖片按照我們需要的大小進行隨機裁剪。傳遞給這個類的參數(shù)可以是一個整型數(shù)據(jù),也可以是一個類似于(h,w)的序列。

5.1.3.5 torchvision.transforms.RandomHorizontalFlip 用于對載入的圖片按隨機概率進行水平翻轉(zhuǎn)。我們通過傳遞給這個類的自定義隨機概率,如果沒有定義,則使用默認的概率為0.5

5.1.3.6 torchvision.transforms.RandomVerticalFlip 用于對載入的圖片按隨機概率進行垂直翻轉(zhuǎn)。我們通過傳遞給這個類的自定義隨機概率,如果沒有定義,則使用默認的概率為0.5

5.1.3.7 torchvision.transforms.ToTensor 用于對載入的圖片數(shù)據(jù)進行類型轉(zhuǎn)換,將之前構(gòu)成PIL圖片數(shù)據(jù)轉(zhuǎn)換為Tensor數(shù)據(jù)類型的變量,讓PyTorch能夠?qū)ζ溥M行計算和處理。

5.1.3.8 torchvision.transforms.ToPILImage: 用于對Tensor變量的數(shù)據(jù)轉(zhuǎn)換成PIL圖片數(shù)據(jù),主要為方便圖片顯示

#torchvision.transforms: 常用的圖片變換,例如裁剪、旋轉(zhuǎn)等;

transform=transforms.Compose(

[transforms.ToTensor(),#將PILImage轉(zhuǎn)換為張量

transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))#將[0, 1]歸一化到[-1, 1]

#前面的(0.5,0.5,0.5) 是 R G B 三個通道上的均值, 后面(0.5, 0.5, 0.5)是三個通道的標準差

])

#上述代碼我們可以將transforms.Compose()看作一種容器,它能夠同時對多種數(shù)據(jù)變換進行組合。

#傳入的參數(shù)是一個列表,列表中的元素就是對載入數(shù)據(jù)進行的變換操作。

5.1.4 torch.utils

關于torchvision.utils我們介紹一種用來對數(shù)據(jù)進行裝載的類:torch.utils.data.DataLoader和

dataset 參數(shù)指定我們載入的數(shù)據(jù)集的名稱; batch_size 參數(shù)設置每個包中圖片的數(shù)量; (每個批次的樣本數(shù)量) shuffle 設置為True代表在裝載的過程會將數(shù)據(jù)隨機打亂順序并進行打包(True為打亂增強泛化性)。

data_loader_train=torch.utils.data.DataLoader(dataset=data_train,

batch_size=64,#每個batch載入的圖片數(shù)量,默認為1,這里設置為64

shuffle=True,

#num_workers=2#載入訓練數(shù)據(jù)所需的子任務數(shù)

)

data_loader_test=torch.utils.data.DataLoader(dataset=data_test,

batch_size=64,

shuffle=True)

#num_workers=2)

5.1.5 torchvision.utils.make_grid將一個批次的圖片構(gòu)造成網(wǎng)格模式的圖片

1、iter和next:獲取一個批次的圖片數(shù)據(jù)和其對應的圖片標簽——>2、再使用torchvision.utils.make_grid:將一個批次的圖片構(gòu)造成網(wǎng)格模式 經(jīng)過torchvision.utils.make_grid后圖片維度變?yōu)閏hannel,h,w三維【 因為要用matplotlib將圖片顯示,我們要使用的數(shù)據(jù)要是數(shù)組且維度為(height,weight,channel)即色彩通道在最后】——> 3、因此我們需要用numpy和transpose完成原始數(shù)據(jù)類型的轉(zhuǎn)換和數(shù)據(jù)維度的交換。

#預覽

#在嘗試過多次之后,發(fā)現(xiàn)錯誤并不是這一句引發(fā)的,而是因為圖片格式是灰度圖只有一個channel,需要變成RGB圖才可以,所以將其中一行做了修改:

images,labels = next(iter(data_loader_train))

# dataiter = iter(data_loader_train) #隨機從訓練數(shù)據(jù)中取一些數(shù)據(jù)

# images, labels = dataiter.next()

img = torchvision.utils.make_grid(images)

img = img.numpy().transpose(1,2,0)

std = [0.5,0.5,0.5]

mean = [0.5,0.5,0.5]

img = img*std+mean

print([labels[i] for i in range(64)])

plt.imshow(img)

5.2 CNN網(wǎng)絡卷積層搭建

CNN的學習 ResNet的學習

import math

import torch

import torch.nn as nn

class Model(nn.Module):

def __init__(self):

super(Model, self).__init__()

#構(gòu)建卷積層之后的全連接層以及分類器

self.conv1 = nn.Sequential(

# 輸入通道數(shù)、輸出通道數(shù)、卷積核大小[3x3]、卷積核移動步長和paddingde值(用于對邊界像素的填充)

nn.Conv2d(3,64,kernel_size=3,stride=1,padding=1),

nn.ReLU(),

nn.Conv2d(64,128,kernel_size=3,stride=1,padding=1),

nn.ReLU(),

nn.MaxPool2d(stride=2,kernel_size=2)

)

self.dense = torch.nn.Sequential(

nn.Linear(14*14*128,1024),

nn.ReLU(),

nn.Dropout(p=0.5), # 防止卷積神經(jīng)網(wǎng)絡在訓練過程中發(fā)生過擬合,原理是以一定的隨機概率將卷積神經(jīng)網(wǎng)絡模型的部分參數(shù)歸零,以達到減少相鄰兩層神經(jīng)連接的目的[本質(zhì)就是減少參數(shù)]

nn.Linear(1024,10)

)

def forward(self,x):

x=self.conv1(x)

x=x.view(-1,14*14*128)

x=self.dense(x)

return x

6.完整代碼

import torch # 用于深度學習和張量計算

import torch.nn as nn

from torchvision import datasets, transforms, utils # 從Torchvision導入數(shù)據(jù)集、數(shù)據(jù)變換工具和utils

import torch.optim as optim

import torchvision # 導入Torchvision庫,用于計算機視覺學習任務。

from torchvision import datasets, transforms # 從Torchvision庫中導入數(shù)據(jù)集合數(shù)據(jù)變換工具

from torch.autograd import Variable # autograd包下自動計算梯度的工具

import numpy as np # 導入NumPy庫,用于數(shù)值計算

import matplotlib.pyplot as plt # 導入Matplotlib庫,用于繪圖片

'''

1.檢查是否可以使用GPU

'''

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

print('設備狀態(tài):', device)

'''

2.定義數(shù)據(jù)變換操作:將圖像轉(zhuǎn)換為tensor進行標準化

2.1 x 是一個圖像張量,可能是一個單通道(灰度圖像)的張量

2.2 第一個維度是通道(channels):從 1 重復到 3,這意味著將單通道圖像轉(zhuǎn)換為 RGB 三通道圖像。

如果你有一個灰度圖像,這樣做會創(chuàng)建三個相同副本的通道,形成一個彩色圖像,每個通道都有相同的灰度值。

2.3 第二個維度是高度(height):1 表示不改變圖像的高度,即不重復。

2.4 第三個維度是寬度(width):同樣為 1,表示也不改變圖像的寬度,不進行重復。

'''

transform = transforms.Compose([

transforms.ToTensor(), # 將圖像轉(zhuǎn)換為tensor

transforms.Lambda(lambda x: x.repeat(3, 1, 1)), # 將單道系統(tǒng)重復成3條道,符合預期輸入格式

transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5)) # 標準化操作,將圖像像素值范圍調(diào)整到[-1, 1]之間

])

'''

3.下載并加載MNIST數(shù)據(jù)集。

3.1 定義數(shù)據(jù)集位置、數(shù)據(jù)變換操作、是否訓練。

'''

data_train = datasets.MNIST(root='./data/',

transform=transform,

train=True,

download=True)

data_test = datasets.MNIST(root='./data/',

transform=transform,

train=False,

download=False)

'''

4.定義數(shù)據(jù)加載器。

'''

data_loader_train = torch.utils.data.DataLoader(dataset=data_train, # 定義訓練集位置

batch_size=64, # 每個批次加載64張圖片

shuffle=True) # shuffle=True,即打亂數(shù)據(jù)順序,增強泛化能力

data_loader_test = torch.utils.data.DataLoader(dataset=data_test,

batch_size=64,

shuffle=True)

'''

5.預覽數(shù)據(jù)

5.1:.transpose(1, 2, 0)操作的意義在于:(而matplotlib在展示圖像時,它期望的數(shù)據(jù)格式遵循(height, width, channels)的規(guī)則)

把原始張量的第二維度(高度,height)移動到新張量的第一維度。

把原始張量的第三維度(寬度,width)移動到新張量的第二維度。

把原始張量的第一維度(通道,channels)移動到新張量的第三維度。

5.2:反標準化操作的數(shù)學表達式:

假設原始圖像數(shù)據(jù)經(jīng)過了這樣的標準化處理:x_normalized = (x - mean) / std,其中x是原始像素值,x_normalized是標準化后的像素值,mean是平均值,std是標準差。

要從標準化后的數(shù)據(jù)恢復到原始數(shù)據(jù),就需要執(zhí)行反向操作:x = x_normalized * std + mean。

'''

images, labels = next(iter(data_loader_train)) # 獲取一個批次的圖像和標簽

img = utils.make_grid(images) # 將多個圖像images合并為一張大圖像,便于可視化

img = img.numpy().transpose(1, 2, 0) # 轉(zhuǎn)換圖片維度將其tensor轉(zhuǎn)為numpy形式,以符合matplotlib的要求

std = [0.5, 0.5, 0.5]

mean = [0.5, 0.5, 0.5]

img = img * std + mean # 根據(jù)歸一化公式反標準化圖片,以恢復原始圖像的像素值范圍,方便展示圖像。

print([labels[i] for i in range(64)]) # 打印圖片的標簽,用于檢查數(shù)據(jù)加載是否正確

plt.imshow(img) # 顯示圖片

plt.show() # 確保圖片顯示

'''

6.定義卷積神經(jīng)網(wǎng)絡

'''

class Model(nn.Module):

def __init__(self):

super(Model, self).__init__() # 繼承父類nn.Module的初始化方法

'''

6.1定義卷積層。

6.1.1:因為之前數(shù)據(jù)預覽的時候(一批次),圖層是8x8=64的,我們的這里卷積核是3x3的,并且步長stride=1,所以要充分讀取圖層信息,故需要將padding填充設置為1

6.1.2:nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1): 這是第二層卷積層,與第一層類似,但輸出通道數(shù)增加到128,進一步提取更復雜的特征。

64個濾波器,每個濾波器都會生成一個不同的特征圖(feature map),kernel_size=3,這表示每個濾波器的尺寸是3x3

6.1.3:用激活函數(shù)Rule:第一是緩解了梯度消失的影響,第二是保證正值不變,負值替換為0,幫助網(wǎng)絡更好的學習圖像特征(關鍵信息)。

6.1.4:nn.MaxPool2d(stride=2, kernel_size=2): 這是最大池化層,通常用于降低特征圖的空間維度,減少計算量,同時保持重要特征。

'''

self.conv1 = nn.Sequential(

nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1), # 第一層卷積,輸入3通道,輸出64通道,步長為1,填充為1

nn.ReLU(), # ReLU激活函數(shù),增加模型的非線性

nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1), # 第二層卷積,輸入64通道,輸出128通道

nn.ReLU(), # ReLU激活函數(shù)

nn.MaxPool2d(stride=2, kernel_size=2) # 最大化池化層,減少特征圖尺寸,保持重要特征

)

'''

6.2 定義全連接層

6.2.1:14*14*128:是經(jīng)過池化層后變?yōu)?4*14的特征圖,然后每個特征有128個通道得到

1024:是全連接層中隱藏單元數(shù)

6.2.2:nn.Linear(1024, 10): 這是第二個全連接層,也是模型的輸出層。輸入維度為1024,

與前一層的輸出維度相對應。輸出維度為10,對應MNIST數(shù)據(jù)集的10個類別(0-9的數(shù)字)

'''

self.dense = nn.Sequential(

nn.Linear(14 * 14 * 128, 1024), # 全連接層,輸入14*14*128,輸出1024

nn.ReLU(), # ReLU激活函數(shù)

nn.Dropout(p=0.5), # Dropout層,防止過擬合

nn.Linear(1024, 10) # 輸出層,10個類別對應MNIST數(shù)據(jù)集的10個數(shù)字

)

'''

6.3 定義前向傳播

'''

def forward(self, x):

x = self.conv1(x) # 前向傳播:卷積層

x = x.view(-1, 14 * 14 * 128) # 將特征圖轉(zhuǎn)為一維張量

x = self.dense(x) # 前向傳播:全連接層

return x # 返回輸出

model = Model().to(device) # 實例化模型并轉(zhuǎn)移到GPU上。

cost = nn.CrossEntropyLoss() # 定義交叉熵損失函數(shù),用于多分類任務

optimizer = optim.Adam(model.parameters()) # 定義Adam優(yōu)化器,用于更新模型參數(shù)

print(model) # 打印模型結(jié)構(gòu)

'''

7.訓練模型

'''

n_epochs = 3

for epoch in range(n_epochs):

running_loss = 0.0

running_correct = 0

print("Epoch {}/{}".format(epoch, n_epochs)) # 打印輪數(shù)

print("-" * 10)

for data in data_loader_train:

X_train, y_train = data

print("訓練數(shù)據(jù)X_train,y_train:")

print(X_train, y_train)

X_train, y_train = Variable(X_train).to(device), Variable(y_train).to(device) # 將數(shù)據(jù)轉(zhuǎn)移到GPU

print("轉(zhuǎn)為GPU后:")

print(X_train, y_train)

outputs = model(X_train) # 前向傳播,計算模型輸出

_, pred = torch.max(outputs.data, 1) # 獲取預測結(jié)果

optimizer.zero_grad() # 梯度清零,防止累積

loss = cost(outputs, y_train) # 計算損失

loss.backward() # 反向傳播,計算梯度

optimizer.step() # 更新參數(shù)

running_loss += loss.data # 累加損失

running_correct += torch.sum(pred == y_train.data) # 計算訓練準確率

testing_correct = 0

for data in data_loader_test: # 使用測試集來監(jiān)控訓練進程,有助于及時調(diào)整訓練策略或提前停止訓練,從而節(jié)省資源并避免過擬合。

X_test, y_test = data

X_test, y_test = Variable(X_test).to(device), Variable(y_test).to(device) # 將數(shù)據(jù)轉(zhuǎn)移到GPU

outputs = model(X_test) # 前向傳播,計算測試集上的模型輸出

_, pred = torch.max(outputs.data, 1) # 獲取預測結(jié)果

testing_correct += torch.sum(pred == y_test.data) # 計算測試準確率

print("Loss is:{:4f}, Train Accuracy is:{:.4f}%, Test Accuracy is:{:.4f}".format(running_loss / len(data_train),

100 * running_correct / len(

data_train),

100 * testing_correct / len(

data_test))) # 輸出訓練損失和準確率

'''

8.測試模型:

8.1: torch.max(pred, 1)會返回一個包含這些索引的張量[2, 4],其中_會捕獲每行的最大值,

但由于前面使用了下劃線(_)作為變量名,這意味著我們【忽略了這些最大值】,【只關心索引】

8.2:batch_size=4說明每次處理4個樣本,每個樣本10維向量【4x10】,如果有1000個樣本,則每個epoch需要處理250批次

8.3:X_test 的維度通常是 (batch_size, channels, height, width):batch_size 是每個批次的樣本數(shù)。channels 表示圖像的通道數(shù)(對于灰度圖像是1,對于彩色圖像是3)。height 和 width 表示圖像的高度和寬度。

8.4:y_test 的維度通常是 (batch_size,),包含每個圖像對應的類別標簽

8.5:pred為預測標簽

'''

data_loader_test = torch.utils.data.DataLoader(dataset=data_test,

batch_size=4,

shuffle=True) # 重新定義測試數(shù)據(jù)加載器,用于測試

X_test, y_test = next(iter(data_loader_test)) # 獲取一個批次的測試數(shù)據(jù)進行預測,X_test是4個樣本的張量

inputs = Variable(X_test).to(device) # 將數(shù)據(jù)轉(zhuǎn)移到GPU

pred = model(inputs) # 前向傳播,計算預測結(jié)果

_, pred = torch.max(pred, 1) # 獲取預測標簽

print("預測標簽:")

print(pred)

print("Predict Label is:", [i for i in pred.data.cpu()]) # 打印預測標簽

print("Real Label is:", [i for i in y_test]) # 打印真實標簽

img = torchvision.utils.make_grid(X_test.cpu()) # 將4個測試樣本的圖像拼接成了一張2x2的網(wǎng)格圖,所以你會看到4個數(shù)字

img = img.numpy().transpose(1, 2, 0) # 轉(zhuǎn)換圖片維度順序

std = [0.5, 0.5, 0.5]

mean = [0.5, 0.5, 0.5]

img = img * std + mean # 反標準化圖片

plt.imshow(img) # 顯示測試圖片及其標簽

plt.show() # 確保圖片顯示

柚子快報邀請碼778899分享:人工智能 Pytorch的學習

http://yzkb.51969.com/

推薦閱讀

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權,聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19375238.html

發(fā)布評論

您暫未設置收款碼

請在主題配置——文章設置里上傳

掃描二維碼手機訪問

文章目錄