pytorch

往日か發表於2024-04-22

pytorch

pytorch基礎

Tensor(張量)

pytorch中最基本的操作物件,表示的是一個多維的矩陣

pytorch可以在GPU上執行,numpy的ndarry只能在CPU上執行

Tensor資料型別:

32位浮點型: torch.FloatTensor

64位浮點型:torch.DoubleTensor

16位整形:torch.ShoutTensor

32位整形:torch.IntTensor

64位整形:torch.LongTensor

定義一個三行兩列矩陣:

a = torch.Tensor([2,3][4,5][6,7])

torch.Tensor預設為torch.FloatTensor

Variable(變數)

Variable Tensor 本質上沒有區別,不過 Variable 會被放入個計算圖中,然後進行前向傳播,反向傳播,自動求導

Variable 是在 torch.autograd.Variable 中

Variable有三個較重要的組成屬性:
data 取出Variable中的tensor數值

grad 這個Variable傳播梯度

grad_fn 表示得到這個Variable的操作,比如透過加減還是乘除來得到的

dataset(資料集)

定義資料類

from torch.utils.data import Dataset
import os
from PIL import Image
class my_dateset(Dataset):
    def __init__(self,root_dir,label_dir):
        self.root_dir = root_dir
        self.label_dir = label_dir
        self.path = os.path.join(self.root_dir,self.label_dir)
        self.img_path = os.listdir(self.path)
    def __getitem__(self, idx):
        img_name = self.img_path[idx]
        img_item_path = os.path.join(self.root_dir,self.label_dir,img_name)
        img = Image.open(img_item_path)
        label = self.label_dir
        return img,label
    def __len__(self):
        return len(self.img_path)

pytorch提供torch.utils.data.DataLoader 來定義一個新的迭代器

dataiter = DataLoader(my_dataset, batch_size=32, shuffle=True, collate_fn=default_collate)

collate_fn 是表示如何取樣本的

torchvision中有一個關於計算機視覺的資料讀取類ImageFolder主要功能是處理圖片,且要求圖片是下面這種存放形式

root/dog/xxx.png

root/dog/xxy.png

root/dog/xxz.png

root/cat/123.png

root/cat/asd.png

root/cat/zxc.png

之後這樣來呼叫這個類:

dset = ImageFolder(root='root_path', transform=None, loader=default_loader) 

nn.Module (模組)

PyTorch 裡面編寫神經網路,所有的層結構和損失函式都來自於 torch.nn

class net_name(nn.Module):
	def __init__(self, other_argi ments):
		super(net_name, self) .__init__
		self.convl = nn .Conv2d(in channels, out channels, kernel size) 
		# other network layer 
	def forward(self, x) : 
		x = self. convl (x) 
		return x

相當於建立了一個計算圖,並且這個結構可以複用多次,每次呼叫就相當於用該計算圖定義的相同引數做一次前向傳播

torch.optim (最佳化)

一階最佳化演算法

![](C:\Users\wyx\Pictures\Screenshots\螢幕截圖 2024-04-18 155241.png)

最常用的一階最佳化演算法是梯度下降

二階最佳化演算法

二階最佳化演算法使用了二階導數( 也叫做 Hessian 方法)來最小化或最大化損失函式

模型的儲存與載入

PyTorch 裡面使用 torch.save 來儲存模型的結構和引數,有兩種儲存方式:

(1)儲存整個模型的結構資訊和引數資訊,儲存的物件是模型 model;

(2)儲存模型的引數,儲存的物件是模型的狀態 model.state diet ()

可以這樣儲存, save 的第一個引數是儲存物件,第二個引數是儲存路徑及名稱:

torch.save(model ,’./model.pth ’) 

torch.save(model.state_dict(), './model_state . pth ’) 

載入模型有兩種方式對應於儲存模型的方式:

(1)載入完整的模型結構和引數資訊,使用

load model = torch.load (’ model. pth ')

在網路較大的時候載入的時間比較長,同時儲存空間也比較大;

(2)載入模型引數資訊,需要先導人模型的結構,然後透過

model.load_state_die (torch.load( 'model_state pth '))來導人

pytorch核心模組

Tensor

張量表示的是一個多維陣列,它是標量、向量、矩陣的擴充.標量是零維張量,向量是一維張量,矩陣是二維張量,一個RGB影像陣列就是一個三維張量,第一維是影像高,第二維是影像的寬,第三維是影像顏色通道

張量相關函式

張量的建立

直接建立

torch.tensor(data, dtype=None, device=None, requires_grad=False, pin_memory=False)
  • data(array_like) - tensor的初始資料,可以是list, tuple, numpy array, scalar或其他型別。
  • dtype(torch.dtype, optional) - tensor的資料型別,如torch.uint8, torch.float, torch.long等
  • device (torch.device, optional) – 決定tensor位於cpu還是gpu。如果為None,將會採用預設值,預設值在torch.set_default_tensor_type()中設定,預設為 cpu。
  • requires_grad (bool, optional) – 決定是否需要計算梯度。
  • pin_memory (bool, optional) – 是否將tensor存於鎖頁記憶體。這與記憶體的存在方式有關,通常為False。
torch.from_numpy()

透過numpy建立tensor,改變array中的值,tensor的值也會改變

依據數值建立

torch.zeros(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)

依給定的size建立一個全0的tensor,預設資料型別為torch.float32(也稱為torch.float)

layout(torch.layout, optional) - 參數列明張量在記憶體中採用何種佈局方式。常用的有torch.strided, torch.sparse_coo等。

out(tensor, optional) - 輸出的tensor,即該函式返回的tensor可以透過out進行賦值

torch.zeros_like(input, dtype=None, layout=None, device=None, requires_grad=False)

依input的size建立全0的tensor。

input(Tensor) - 建立的tensor與intput具有相同的形狀。

依據機率分佈建立

torch.normal(mean, std, out=None)

為每一個元素以給定的mean和std用高斯分佈生成隨機數

mean (Tensor or Float) - 高斯分佈的均值,

std (Tensor or Float) - 高斯分佈的標準差

torch.rand(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)

在區間[0, 1)上,生成均勻分佈

size (int...) - 建立的張量的形狀

張量的操作
cat 將多個張量拼接在一起,例如多個特徵圖的融合可用。
concat 同cat, 是cat()的別名。
conj 返回共軛複數。
chunk 將tensor在某個維度上分成n份。
dsplit 類似numpy.dsplit()., 將張量按索引或指定的份數進行切分。
column_stack 水平堆疊張量。即第二個維度上增加,等同於torch.hstack。
dstack 沿第三個軸進行逐畫素(depthwise)拼接。
gather 高階索引方法,目標檢測中常用於索引bbox。在指定的軸上,根據給定的index進行索引。強烈推薦看example。
hsplit 類似numpy.hsplit(),將張量按列進行切分。若傳入整數,則按等分劃分。若傳入list,則按list中元素進行索引。例如:[2, 3] and dim=0 would result in the tensors input[:2], input[2:3], and input[3:].
hstack 水平堆疊張量。即第二個維度上增加,等同於torch.column_stack。
index_select 在指定的維度上,按索引進行選擇資料,然後拼接成新張量。可知道,新張量的指定維度上長度是index的長度。
masked_select 根據mask(0/1, False/True 形式的mask)索引資料,返回1-D張量。
movedim 移動軸。如0,1軸交換:torch.movedim(t, 1, 0) .
moveaxis 同movedim。Alias for torch.movedim().(這裡發現pytorch很多地方會將dim和axis混用,概念都是一樣的。)
narrow 變窄的張量?從功能看還是索引。在指定軸上,設定起始和長度進行索引。例如:torch.narrow(x, 0, 0, 2), 從第0個軸上的第0元素開始,索引2個元素。x[0:0+2, ...]
nonzero 返回非零元素的index。torch.nonzero(torch.tensor([1, 1, 1, 0, 1])) 返回tensor([[ 0], [ 1], [ 2], [ 4]])。建議看example,一看就明白,尤其是對角線矩陣的那個例子,太清晰了。
permute 交換軸。
reshape 變換形狀。
row_stack 按行堆疊張量。即第一個維度上增加,等同於torch.vstack。Alias of torch.vstack().
scatter scatter_(dim, index, src, reduce=None) → Tensor。將src中資料根據index中的索引按照dim的方向填進input中。這是一個十分難理解的函式,其中index是告訴你哪些位置需要變,src是告訴你要變的值是什麼。這個就必須配合例子講解,請跳轉到本節底部進行學習。
scatter_add 同scatter一樣,對input進行元素修改,這裡是 +=, 而scatter是直接替換。
split 按給定的大小切分出多個張量。例如:torch.split(a, [1,4]); torch.split(a, 2)
squeeze 移除張量為1的軸。如t.shape=[1, 3, 224, 224]. t.squeeze().shape -> [3, 224, 224]
stack 在新的軸上拼接張量。與hstack\vstack不同,它是新增一個軸。預設從第0個軸插入新軸。
swapaxes Alias for torch.transpose().交換軸。
swapdims Alias for torch.transpose().交換軸。
t 轉置。
take 取張量中的某些元素,返回的是1D張量。torch.take(src, torch.tensor([0, 2, 5]))表示取第0,2,5個元素。
take_along_dim 取張量中的某些元素,返回的張量與index維度保持一致。可搭配torch.argmax(t)和torch.argsort使用,用於對最大機率所在位置取值,或進行排序,詳見官方文件的example。
tensor_split 切分張量,核心看indices_or_sections變數如何設定。
tile 將張量重複X遍,X遍表示可按多個維度進行重複。例如:torch.tile(y, (2, 2))
transpose 交換軸。
unbind 移除張量的某個軸,並返回一串張量。如[[1], [2], [3]] --> [1], [2], [3] 。把行這個軸拆了。
unsqueeze 增加一個軸,常用於匹配資料維度。
vsplit 垂直切分。
vstack 垂直堆疊。
where 根據一個是非條件,選擇x的元素還是y的元素,拼接成新張量。看案例可瞬間明白。
張量的隨機種子
seed 獲取一個隨機的隨機種子。Returns a 64 bit number used to seed the RNG.
manual_seed 手動設定隨機種子
initial_seed 返回初始種子。
get_rng_state 獲取隨機數生成器狀態。Returns the random number generator state as a torch.ByteTensor.
set_rng_state 設定隨機數生成器狀態。這兩怎麼用暫時未知。Sets the random number generator state.

隨機種子主要用於對實驗的復現

張量的數學操作
  • Pointwise Ops: 逐元素的操作,如abs, cos, sin, floor, floor_divide, pow等
  • Reduction Ops: 減少元素的操作,如argmax, argmin, all, any, mean, norm, var等
  • Comparison Ops:對比操作, 如ge, gt, le, lt, eq, argsort, isnan, topk,
  • Spectral Ops: 譜操作,如短時傅立葉變換等各類訊號處理的函式。
  • Other Operations:其它, clone, diag,flip等
  • BLAS and LAPACK Operations:BLAS(Basic Linear Algebra Subprograms)基礎線性代數)操作。如, addmm, dot, inner, svd等。

計算圖--自動求導核心

計算圖由節點和邊構成

節點表示資料,如標量,向量,矩陣,張量等;

表示運算,如加、減、乘、除、卷積、relu等;

![](C:\Users\wyx\Desktop\pytorch\螢幕截圖 2024-04-19 161906.png)

葉子節點

葉子結點是最基礎的結點,其資料不是由運算生成的,因此是整個計算圖的基石,是不可輕易”修改“的

張量有一個屬性是is_leaf, 就是用來指示一個張量是否為葉子結點的屬性

import torch

w = torch.tensor([1.], requires_grad=True)
x = torch.tensor([2.], requires_grad=True)

a = torch.add(w, x)
b = torch.add(w, 1)     # retain_grad()
y = torch.mul(a, b)

y.backward()
print(w.grad)

# 檢視葉子結點
print("is_leaf:\n", w.is_leaf, x.is_leaf, a.is_leaf, b.is_leaf, y.is_leaf)
# 檢視梯度
print("gradient:\n", w.grad, x.grad, a.grad, b.grad, y.grad)
# 檢視 grad_fn
print("grad_fn:\n", w.grad_fn, x.grad_fn, a.grad_fn, b.grad_fn, y.grad_fn)
#

只有葉子節點的梯度得到保留,中間變數的梯度預設不保留;在pytorch中,非葉子結點的梯度在反向傳播結束之後就會被釋放掉,如果需要保留的話可以對該結點設定retain_grad()

grad_fn是用來記錄建立張量時所用到的運算,在鏈式求導法則中會使用到。

自動微分--Autograd

  • 自動求導機制透過有向無環圖(directed acyclic graph ,DAG)實現
  • 在DAG中,記錄資料(對應tensor.data)以及操作(對應tensor.grad_fn
  • 操作在pytorch中統稱為Function,如加法、減法、乘法、ReLU、conv、Pooling等,統統是Function

autograd的使用

torch.autograd.backward

使用頻率最高的自動求導函式

torch.autograd.backward(tensors,grad_tensors=None,retain_graph=None,create_graph=False, 						grad_variables=None, inputs=None)
  • tensors (Sequence[Tensor] or Tensor) – 用於求導的張量。如上例的loss。
  • grad_tensors (Sequence[Tensor or None] or Tensor, optional) – 雅克比向量積中使用
  • retain_graph (bool, optional) – 是否需要保留計算圖。pytorch的機制是在方向傳播結束時,計算圖釋放以節省記憶體。連續使用loss.backward(),就會報錯。如果需要多次求導,則在執行backward()時,retain_graph=True。
  • create_graph (bool, optional) – 是否建立計算圖,用於高階求導

使用時可直接呼叫.backward()函式

torch.autograd.grad
torch.autograd.grad(outputs, inputs, grad_outputs=None, retain_graph=None, create_graph=False, only_inputs=True, allow_unused=False)

功能:計算outputs對inputs的導數

主要引數:

  • outputs (sequence of Tensor) – 用於求導的張量,如loss
  • inputs (sequence of Tensor) – 所要計算導數的張量
  • grad_outputs (sequence of Tensor) – 雅克比向量積中使用。
  • retain_graph (bool, optional) – 是否需要保留計算圖。
  • create_graph (bool, optional) – 是否建立計算圖,用於高階求導。
  • allow_unused (bool, optional) – 是否需要指示,計算梯度時未使用的張量是錯誤的。

例:

import torch
x = torch.tensor([3.], requires_grad=True)
y = torch.pow(x, 2)     # y = x**2

# 一階導數
grad_1 = torch.autograd.grad(y, x, create_graph=True)   # grad_1 = dy/dx = 2x = 2 * 3 = 6
print(grad_1)
# 二階導數
grad_2 = torch.autograd.grad(grad_1[0], x)              # grad_2 = d(dy/dx)/dx = d(2x)/dx = 2
print(grad_2)
torch.autograd.Function

想要實現自己的一些操作時,如特殊的數學函式、pytorch的module中沒有的網路層,那就需要自己寫一個Function

pytorch資料模組

Dataset

torch.utils.data.Dataset,供使用者繼承編寫dataset

例:

from torch.utils.data import Dataset
import os
from PIL import Image
class my_dateset(Dataset):
    def __init__(self,root_dir,label_dir):
        self.root_dir = root_dir
        self.label_dir = label_dir
        self.path = os.path.join(self.root_dir,self.label_dir)
        self.img_path = os.listdir(self.path)
    def __getitem__(self, idx):
        img_name = self.img_path[idx]
        img_item_path = os.path.join(self.root_dir,self.label_dir,img_name)
        img = Image.open(img_item_path)
        label = self.label_dir
        return img,label
    def __len__(self):
        return len(self.img_path)
  • getitem:需要實現讀取一個樣本的功能。通常是傳入索引(index,可以是序號或key),然後實現從磁碟中讀取資料,並進行預處理(包括online的資料增強),然後返回一個樣本的資料。資料可以是包括模型需要的輸入、標籤,也可以是其他元資訊,例如圖片的路徑。getitem返回的資料會在dataloader中組裝成一個batch。即,通常情況下是在dataloader中呼叫Dataset的getitem函式獲取一個樣本。
  • len:返回資料集的大小。如果這個函式返回的是0,dataloader會報錯:"ValueError: num_samples should be a positive integer value, but got num_samples=0"

DataLoader

torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=False, sampler=None, batch_sampler=None, num_workers=0, collate_fn=None, pin_memory=False, drop_last=False, timeout=0, worker_init_fn=None, multiprocessing_context=None, generator=None, *, prefetch_factor=2, persistent_workers=False)
  • dataset:一個Dataset例項,要能實現從索引(indices/keys)到樣本的對映。(即getitem函式)
  • batch_size:每個batch的樣本量
  • shuffle:是否對打亂樣本順序。訓練集通常要打亂它!驗證集和測試集無所謂。
  • sampler:設定取樣策略。
  • batch_sampler:設定取樣策略, batch_sampler與sampler二選一
  • num_workers: 設定多少個子程序進行資料載入(data loading)
  • collate_fn:組裝資料的規則, 決定如何將一批資料組裝起來。
  • pin_memory:是否使用鎖頁記憶體,具體行為是“the data loader will copy Tensors into CUDA pinned memory before returning them”
  • drop_last:每個epoch是否放棄最後一批不足batchsize大小的資料,即無法被batchsize整除時,最後會有一小批資料,是否進行訓練,如果資料量足夠多,通常設定為True。

Dataset及常用API

concat

在實際專案中,資料的來源往往是多源的,很難統一到一個資料格式.一種靈活的方式是每批資料編寫一個Dataset,然後使用torch.utils.data.ConcatDataset類將他們拼接起來,這種方法可以靈活的處理多源資料,也可以很好的使用別人的資料及Dataset

Subset

subset可根據指定的索引獲取子資料集,Subset也是Dataset類

    def __init__(self, dataset: Dataset[T_co], indices: Sequence[int]) -> None:
        self.dataset = dataset
        self.indices = indices

    def __getitem__(self, idx):
        if isinstance(idx, list):
            return self.dataset[[self.indices[i] for i in idx]]
        return self.dataset[self.indices[idx]]

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

random_aplit

該函式的功能是隨機的將dataset劃分為多個不重疊的子集,適合用來劃分訓練、驗證集

torch.utils.data.random_split(dataset, lengths, generator=None)

只需要設定每個子集的資料量,傳給lengths即可

sampler

sampler是在dataloader中起到挑選資料的功能,主要是設定挑選策略,如按順序挑選、隨機挑選、按類別分機率挑選等

sampler 與 batch_sampler

本質上兩者都是取樣器,當採用auto_collation時,採用batch_sampler

batch_sampler是一次返回一個batch的索引。通常我們用的都是batch_sampler,其對應的是BatchSampler類

BatchSampler
torch.utils.data.BatchSampler(sampler, batch_size, drop_last)

第一個引數傳入的是一個sampler取樣器,在這裡會有兩種情況,如果需要shuffle,則傳入RandomSampler,不需要打亂,則傳入SequentialSampler

BatchSampler是在其它兩者之上封裝了一個批抽取的功能,一次yield一個batch的index,而樣本取樣的順序取決於RandomSampler和SequentialSample。

SequentialSampler

順序迭代器,按順序的迭代器

RandomSamoler

預設情況下會使用這行程式碼實現:yield from torch.randperm(n, generator=generator).tolist(), 利用torch的隨機方法生成一個隨機整數序列,對於generator預設採用的是隨機一個隨機種子進行設定

SubsetRandomSampler

透過索引定義一個自己的隨機取樣器

這個取樣器返回的樣本總數是傳入的索引的長度

def __iter__(self) -> Iterator[int]:
	for i in torch.randperm(len(self.indices), generator=self.generator):
		yield self.indices[i]
WeightedRandomSampler
torch.utils.data.WeightedRandomSampler(weights, num_samples, replacement=True, generator=None)
  • weights (sequence) – 每個樣本的取樣權重,權重之和不必為1,只需要關心各樣本之間的比例即可。
  • num_samples (int) – 取樣數量,一般設為樣本總量。
  • replacement (bool) –是否有放回取樣。 True,表示有放回。
  • generator (Generator) – 自定義生成器,通常用預設的

transforms

pytorch的影像資料增強函式庫

變換方法

Compose

用於包裝一系列transforms方法

例:

dataset_transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor()])
Resize

支援對PIL或Tensor物件的縮放

Resize(size, interpolation=, max_size=None, antialias=None)
Totensor

將PIL物件或nd.array物件轉換成tensor,並且對數值縮放到[0, 1]之間,並且對通道進行右移

Normalize

對tensor物件進行逐通道的標準化,具體操作為減均值再除以標準差

Normalize(mean, std, inplace=False)
transforms.Pad

對影像進行填充

torchvision.transforms.Pad(padding, fill=0, padding_mode='constant')
transforms.Grayscale

將圖片轉為灰度圖

torchvision.transforms.Grayscale(num_output_channels=1)
PILImage:transforms.ToPILImage
torchvision.transforms.ToPILImage(mode=None)

將 tensor 或者 ndarray 的資料轉換為 PIL Image 型別資料

mode- 為None時為 1 通道, mode=3 通道預設轉換為 RGB,4 通道預設轉換為 RGBA

裁剪方法

隨機裁剪:transforms.RandomCrop

依據給定的 size 隨機裁剪

torchvision.transforms.RandomCrop(size, padding=None, pad_if_needed=False, fill=0,
padding_mode='constant')

中心裁剪:transforms.CenterCrop

torchvision.transforms.CenterCrop(size)

依據給定的 size 從中心裁剪

隨機長寬比裁剪:transforms.RandomResizedCrop

torchvision.transforms.RandomResizedCrop(size, scale=(0.08, 1.0), ratio=(0.75, 1.33333
33333333333), interpolation=2)

機大小,隨機長寬比裁剪原始圖片,最後將圖片 resize 到設定好的 size

size- 輸出的解析度

scale- 隨機 crop 的大小區間,如 scale=(0.08, 1.0),表示隨機 crop 出來的圖片會在的 0.08

倍至 1 倍之間。

ratio- 隨機長寬比設定

interpolation- 插值的方法,預設為雙線性插值(PIL.Image.BILINEAR)

上下左右中心裁剪transforms.FiveCrop

torchvision.transforms.FiveCrop(size)

功能:對圖片進行上下左右以及中心裁剪,獲得 5 張圖片,返回一個 4D-tensor

上下左右中心裁剪後翻轉: transforms.TenCrop

torchvision.transforms.TenCrop(size,vertical_flip=False)

功能:對圖片進行上下左右以及中心裁剪,然後全部翻轉(水平或者垂直),獲得 10 張圖

片,返回一個 4D-tensor。

vertical_flip (bool) - 是否垂直翻轉,預設為 flase,即預設為水平翻轉

翻轉和旋轉

依機率 p 水平翻轉 transforms.RandomHorizontalFlip

torchvision.transforms.RandomHorizontalFlip(p=0.5)

功能:依據機率 p 對 PIL 圖片進行水平翻轉

p- 機率,預設值為 0.5

垂直翻轉 transforms.RandomVerticalFlip

torchvision.transforms.RandomVerticalFlip(p=0.5)

功能:依據機率 p 對 PIL 圖片進行垂直翻轉

p- 機率,預設值為 0.5

隨機旋轉transforms.RandomRotation

torchvision.transforms.RandomRotation(degrees,resample=False,expand=False,center=None)

功能:依 degrees 隨機旋轉一定角度

degress- (sequence or float or int) ,若為單個數,如 30,則表示在(-30,+30)之間隨機旋

resample- 重取樣方法選擇,可選PIL.Image.NEAREST, PIL.Image.BILINEAR, PIL.Image.BICUBIC,預設為False

expand-用於指定是否擴充套件影像以適應旋轉後的影像。如果設定為 True,則會擴充套件影像的邊界以容納整個旋轉後的影像;如果設定為 False,則會保留旋轉後影像的原始尺寸,預設為 False

center- 可選為中心旋轉還是左上角旋轉

自動資料增強

AutoAugment
torchvision.transforms.AutoAugment(policy: torchvision.transforms.autoaugment.AutoAugmentPolicy = , interpolation: torchvision.transforms.functional.InterpolationMode = , fill: Optional[List[float]] = None)

功能:自動資料增強方法的封裝,支援三種資料增強策略,分別是IMAGENET、CIFAR10 和SVHN

引數:

policy :需要是AutoAugmentPolicy類

interpolation:設定插值方法

fill :設定填充畫素的畫素值,預設為0,黑色。

RandAugment

RandAugment是進行N次(num_ops )變換,變換方法從策略池中隨機挑選

num_ops :執行多少次變換

magnitude :每個變換的強度,

num_magnitude_bins:與變化強度的取樣分佈有關

pytorch模型模組

module

Module是所有神經網路的基類,所有的模型都必須繼承於Module類,並且它可以巢狀

構建自己的網路只需要三步:

  1. 寫一個類繼承於Module
  2. init函式中把需要的網路層建立好
  3. forward函式中把模型如何搭建的規則寫好

parameter--引數

parameter繼承於Tensor,主要作用是用來區分可訓練的引數與常規的tensor

Parameter指模型的引數,如卷積層的卷積核權重和偏置,Linear層的權重和偏置,BN層的α和β等等

  optimizer = optim.SGD(model.parameters(), lr=0.1, momentum=0.9, weight_decay=5e-4)

module的容器

Sequential

將一系列網路層按固定的先後順序串起來,當成一個整體,呼叫時資料從第一個層按順序執行到最後一個層

例:

model = nn.Sequential(
          nn.Conv2d(1,20,5),
          nn.ReLU(),
          nn.Conv2d(20,64,5),
          nn.ReLU()
        )
def forward(self, input):
    for module in self:
    	input = module(input)
    return input

ModuleList

將各個網路層放到一個“列表”中,便於迭代的形式呼叫

class MyModule(nn.Module):
	def __init__(self):
		super(MyModule, self).__init__()
		self.linears = nn.ModuleList([nn.Linear(10, 10) for i in range(10)])

def forward(self, x):
	for sub_layer in self.linears:
		x = sub_layer(x)
	return x

ModuleDict

ModuleDict就是可以像python的Dict一樣為每個層賦予名字,可以根據網路層的名字進行選擇性的呼叫網路層

class MyModule2(nn.Module):
    def __init__(self):
        super(MyModule2, self).__init__()
        self.choices = nn.ModuleDict({
            'conv': nn.Conv2d(3, 16, 5),
            'pool': nn.MaxPool2d(3)
        })
        self.activations = nn.ModuleDict({
            'lrelu': nn.LeakyReLU(),
            'prelu': nn.PReLU()
        })
     def forward(self, x, choice, act):
        x = self.choices[choice](x)
        x = self.activations[act](x)
        return x

常用網路層

Convolutional Layers

卷積層

torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros')

對多個二維平面組成的訊號進行二維卷積

  • in_channels (int) – 輸入這個網路層的影像的通道數是多少。
  • out_channels (int) – 此網路層輸出的特徵圖的通道數是多少,等價於卷積核數量是多少。
  • kernel_size (int or tuple) – 卷積核大小。
  • stride (int or tuple, optional) – 卷積核卷積過程的步長。
  • padding (int, tuple or str, optional) –對於輸入影像的四周進行填充的數量進行控制,可指定填充畫素數量,也可以指定填充模式,
  • padding_mode (string, optional) – 填充的畫素值如何確定。預設填充0。
  • dilation (int or tuple, optional) – 孔洞卷積的孔洞大小。
  • groups (int, optional) – 分組卷積的分組。
  • bias (bool, optional) – 是否採用偏置。

![](C:\Users\wyx\Desktop\pytorch\螢幕截圖 2024-04-20 161320.png)

![](C:\Users\wyx\Desktop\pytorch\螢幕截圖 2024-04-20 161332.png)

Pooling Layers

池化層

將特徵圖解析度變小,通常減小一半(提取特徵量)

可對池化層進行劃分為最大值池化、平均值池化、分數階池化、基於範數的池化。分別對應torch.nn中的Maxpool, Avgpool, FractionalMaxPool, LPPool

Maxpool:

torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)

2D最大池化

  • kernel_size – 池化視窗大小

  • stride – 滑窗步長

  • padding – 原圖填充大小

  • dilation – 孔洞大小

  • return_indices – 是否返回最大值所在位置,主要在 torch.nn.MaxUnpool2d 中使用,是上取樣的一種策略

  • ceil_mode – 當無法整除時,是向下取整還是向上取整,預設為向下。

    ![](C:\Users\wyx\Desktop\pytorch\螢幕截圖 2024-04-20 161320-1713600998558-3.png)

    Padding Layers

    給特徵圖周圍填充一定的畫素,調整特徵圖解析度的一種方法

    可將padding layer劃分為三類,映象填充、邊界重複填充,指定值填充、零值填充,分別對應nn的三大類,nn.ReflectionPad2d, nn.ReplicationPad2d, nn.ZeroPad2d, nn.ConstantPad2d

Linear Layers

線性層

Linear Layers包含4個層分別是nn.Identity,nn.Linear, nn.Bilinear, nn.LazyLinear

nn.Identity 是恆等對映,不對輸入做任何變換,它通常用於佔位。

nn.Linear 全連線層(Fully Connection Layer),可實現 y= Wx + b

nn.Bilinear 是雙線性層,它有兩個輸入,實現公式 y = x1Wx2 +b

nn.LazyLinear 是nn.Linear的lazy版本,也就是懶惰的Linear層,它在第一次推理時自動根據輸入特徵圖的尺寸來設定in_features,免去了手動計算in_features的麻煩。

Dropout Layers

隨機失活--防止模型過擬合

Dropout使用注意事項:

  • Dropout通常用於nn.Linear層之前;
  • Dropout執行後,神經元個數會減少,導致資料尺度發生變化.

Non - linear Layers

非線性啟用函式函式

Module常用函式

  • 設定模型訓練、評估模式

    eval:設定模型為評估模式,與BN,Dropout息息相關,即評估模式下模型的某些層執行的操作與訓練狀態下是不同的。

    train:設定模型為訓練模式,如BN層需要統計runing_var這些統計資料,Dropout層需要執行隨機失活等

  • 設定模型存放在cpu/gpu/xpu

    1. cpu,將Module放到cpu上
    2. cuda,把需要運算的資料放到gpu即可。方法就是 xxx.cuda()
    3. to,可將物件放到指定的裝置中去,如to.("cpu") 、 to.("cuda)、to("cuda:0") 等
  • 獲取模型引數、載入權重引數

    1. load_state_dict,將引數字典中的引數複製到當前模型中。要求key要一一對應
    2. state_dict,返回引數字典。key是告訴你這個權重引數是放到哪個網路層
  • 管理模型的modules, parameters, sub_module

    parameters:返回一個迭代器,迭代器可丟擲Module的所有parameter物件

    named_parameters:作用同上,不僅可得到parameter物件,還會給出它的名稱

    modules:返回一個迭代器,迭代器可以丟擲Module的所有Module物件,注意:模型本身也是module,所以也會獲得自己。

    named_modules:作用同上,不僅可得到Module物件,還會給出它的名稱

    children:作用同modules,但不會返回Module自己。

    named_children:作用同named_modules,但不會返回Module自己

  • 設定模型的引數精度,可選半精度、單精度、雙精度等

    1. bfloat16
    2. half
    3. float
    4. double
  • 對子模組執行特定功能

    1. apply
    2. zero_grad

pytorch最佳化模組

損失函式--Loss Function

損失函式(loss function)是用來衡量模型輸出與真實標籤之間的差異,當模型輸出越接近標籤,認為模型越好,反之亦然

在pytorch中提供了二十一個損失函式,如下所示

nn.L1Loss
nn.MSELoss
nn.CrossEntropyLoss
nn.CTCLoss
nn.NLLLoss
nn.PoissonNLLLoss
nn.GaussianNLLLoss
nn.KLDivLoss
nn.BCELoss
nn.BCEWithLogitsLoss
nn.MarginRankingLoss
nn.HingeEmbeddingLoss
nn.MultiLabelMarginLoss
nn.HuberLoss
nn.SmoothL1Loss
nn.SoftMarginLoss
nn.MultiLabelSoftMarginLoss
nn.CosineEmbeddingLoss
nn.MultiMarginLoss
nn.TripletMarginLoss
nn.TripletMarginWithDistanceLoss

L1loss

torch.nn.L1Loss(size_average=None, reduce=None, reduction='mean')

計算output和target之差的絕對值,可選返回同維度的tensor(reduction=none)或一個標量(reduction=mean/sum)

CrossEntropyLoss -- 交叉熵損失函式

torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=- 100, reduce=None, reduction='mean', label_smoothing=0.0)

將輸入經過softmax啟用函式之後,計算交叉熵損失

eight (Tensor, optional) – 類別權重,用於調整各類別的損失重要程度,常用於類別不均衡的情況
ignore_index (int, optional) – 忽略某些類別不進行loss計算。
size_average (bool, optional) – 已捨棄使用的變數,功能已經由reduction代替實現,仍舊保留是為了舊版本程式碼可以正常執行。
reduce (bool, optional) – 已捨棄使用的變數,功能已經由reduction代替實現,仍舊保留是為了舊版本程式碼可以正常執行。
reduction (string, optional) – 是否需要對loss進行“降維”,這裡的reduction指是否將loss值進行取平均(mean)、求和(sum)或是保持原尺寸(none)

最佳化器--Optimizer

對模型進行最佳化使loss不斷降低

最佳化器的實現在torch.optim中

最佳化器基類

引數組(param_groups):引數組是用於管理需要進行最佳化的那些引數,例如權值weight,偏置bias,BN的alpha/beta等

這裡是引數組不是引數,表明可以將所有引數進行分組,例如在finetune過程中,通常讓前面層的網路採用較小的學習率,後面幾層全連線層採用較大的學習率,這時我們就要把網路的引數劃分為兩組,每一組有它對應的學習率

引數組是一個list,其元素是一個dict,dict中包含,所管理的引數,對應的超參,例如學習率,momentum,weight_decay等等。

state:用於儲存最佳化策略中需要儲存的一些快取值,例如在用momentum時,需要儲存之前的梯度,這些資料儲存在state中。

defaults:最佳化方法預設的超引數

方法:

zero_grad()

功能:清零所管理引數的梯度。由於pytorch不會自動清零梯度,因此需要再optimizer中手動清零,然後再執行反向傳播,得出當前iteration的loss對權值的梯度。

step()

功能:執行一步更新,依據當前的梯度進行更新引數

add_param_group(param_group)

功能:給optimizer管理的引數組中增加一組引數,可為該組引數定製lr,momentum,weight_decay等,在finetune中常用。

例如:

optimizer_1.add_param_group({'params': w3, 'lr': 0.001, 'momentum': 0.8})

state_dict()

功能:獲取當前state屬性。

通常在儲存模型時同時儲存最佳化器狀態,用於斷點儲存,下次繼續從當前狀態訓練;

load_state_dict(state_dict)

功能:載入所儲存的state屬性,恢復訓練狀態。

SGD--隨機梯度下降

深度學習中最基礎的一個

SGD核心理論知識是梯度下降( gradient descent),即沿著梯度的負方向,是變化最快的方向。

SGD的使用
optimizer = optim.SGD(model.parameters(), lr=0.1, momentum=0.9, weight_decay=5e-4)#例項化
optimizer.zero_grad()#loss.backward()之前進行梯度清零
loss.backward()
optimizer.step()#loss.backward()之後執行一步更新

pytorch 視覺化

TensorBoard

from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter("logs")
writer.add_image("test",img_array,2,dataformats="HWC")
writer.close()

終端輸入

tensorboard --logdir=your path dir

add_scalar

add_scalar(tag, scalar_value, global_step=None, walltime=None, new_style=False, double_precision=False)

新增標量;tag的設定可以有個技巧是在同一欄下繪製多個圖,如'Loss/train', 'Loss/Valid', 這就類似於matplotlib的subplot(121), subplot(122)

  • tag (string) – Data identifier
  • scalar_value (float or string/blobname) – Value to save
  • global_step (int) – Global step value to record

add_scalars

add_scalars`(main_tag, tag_scalar_dict, global_step=None,walltime=None)

功能:在一個座標軸中繪製多條曲線。常用於曲線對比。

  • main_tag (string) – The parent name for the tags
  • tag_scalar_dict (dict) – Key-value pair storing the tag and corresponding values
  • global_step (int) – Global step value to record

add_image

add_image(tag, img_tensor, global_step=None, walltime=None, dataformats='CHW')

功能:繪製影像。

  • tag (string) – Data identifier
  • img_tensor (torch.Tensor, numpy.array, or string/blobname) – Image data
  • global_step (int) – Global step value to record dataformats- 資料通道順序物理意義。預設為 CHW

相關文章