Condivisione della tecnologia

Pytorch (note 8 rete neurale nn)

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

1、nn.Modulo

torch.nn è un modulo appositamente progettato per il deep learning. La struttura dati principale di torch.nn è Modulo, che è un concetto astratto che può rappresentare un determinato livello in una rete neurale o una rete neurale contenente molti livelli. Nell'uso reale, l'approccio più comune è ereditare nn.Module e scrivere la propria rete/livello. Diamo prima un'occhiata a come utilizzare nn.Module per implementare il proprio livello completamente connesso.Y=AX+B

import torch as t
import torch.nn as nn

class network(nn.Module):
    def __init__(self, input, output):
        super().__init__()
        # 定义权重矩阵a,它是一个可训练的参数,形状为(input, output)
        self.a = nn.Parameter(t.randn(input, output))
        # 定义偏置向量b,它也是一个可训练的参数,形状为(output,)
        # 注意:偏置向量的长度应与输出特征的维度相匹配
        self.b = nn.Parameter(t.randn(output))

    def forward(self, x):
        """
        定义前向传播过程

        参数:
            x (torch.Tensor): 输入数据,形状应为(batch_size, input)

        返回:
            torch.Tensor: 输出数据,形状为(batch_size, output)
        """
        # 首先,使用权重矩阵a对输入x进行线性变换
        # [email protected]执行矩阵乘法,x的每一行与a相乘,结果形状为(batch_size, output)
        x = x @ self.a
        # 然后,将偏置向量b扩展(通过broadcasting)到与x相同的形状,并加到x上
        # self.b.expand_as(x)将b的形状从(output,)扩展到(batch_size, output)
        # x + self.b.expand_as(x)将偏置加到每个样本的输出上
        x = x + self.b.expand_as(x)
        # 返回变换后的输出
        return x


a = network(4, 3)
# 创建输入数据,形状为(6, 4),表示有6个样本,每个样本有4个特征
input = t.rand(6, 4)
# 通过网络前向传播得到输出
output = a(input)
# 打印输出,形状应为(6, 3),表示有6个样本,每个样本的输出特征维度为3
print(output)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • La rete del livello personalizzato deve ereditare nn.Module e il costruttore di nn.Module deve essere chiamato nel suo costruttore, ovvero super().dentro() o nn.Modulo.dentro(auto), si consiglia il primo utilizzo;
  • Nel costruttore __init__, è necessario definire personalmente i parametri apprendibili e incapsularli in Parametri. Ad esempio, in questo esempio, incapsuliamo w e b in Parametri. Il parametro è un tensore speciale, ma richiede derivati ​​per impostazione predefinita (requires_grad
    = Vero)
  • La funzione forward implementa il processo di propagazione in avanti e il suo input può essere uno o più tensori;
  • Non è necessario scrivere una funzione di backpropagation. nn.Module può utilizzare autograd per implementare automaticamente la backpropagation, che è molto più semplice di Function;
  • I parametri apprendibili nel modulo possono restituire un iteratore tramitenamed_parameters() o parametri() Il primo attribuirà un nome a ciascun parametro per renderlo più identificabile.

2. Livelli di rete neurale comunemente utilizzati

2.1 Livello relativo all'immagine

I livelli relativi alle immagini includono principalmente livelli di convoluzione (Conv), livelli di pooling (Pool), ecc. Nell'uso reale, questi livelli possono essere divisi in monodimensionali (1D), bidimensionali (2D) e tridimensionali (3D) Anche il metodo di pooling è suddiviso in pooling medio (AvgPool), pooling massimo (MaxPool), pooling adattivo (AdaptiveAvgPool), ecc. Oltre alla convoluzione diretta comunemente usata, il livello di convoluzione ha anche una convoluzione inversa (TransposeConv) e così via. Di seguito verrà fornito un esempio.

  • Estrazione di caratteristiche
  • Mantenere la struttura dello spazio dati
  • Introduzione della trasformazione non lineare Dopo l'operazione di convoluzione, viene solitamente applicata una funzione di attivazione (come ReLU, Sigmoid o Tanh) per introdurre la trasformazione non lineare. Queste funzioni di attivazione possono aumentare il potere espressivo della CNN e consentirle di apprendere relazioni non lineari più complesse.
  • Migliorare l'efficienza computazionale Attraverso l'uso combinato di operazioni di convoluzione e livelli di pooling, il livello di convoluzione può ridurre la dimensione spaziale della mappa delle caratteristiche, riducendo così la quantità di calcoli e migliorando l'efficienza computazionale del modello. Allo stesso tempo, il livello di pooling può anche migliorare l’invarianza di traduzione delle caratteristiche, rendendo il modello più robusto rispetto a piccoli cambiamenti nei dati di input.

strato di convoluzione

Nel deep learning, la struttura di rete più importante relativa all’elaborazione delle immagini è lo strato convoluzionale (Conv). L'essenza di una rete neurale convoluzionale è la sovrapposizione di strati convoluzionali, strati di pooling, strati di attivazione e altri strati. Pertanto, è estremamente importante comprendere il principio di funzionamento dello strato convoluzionale operazione di convoluzione.
Inserisci qui la descrizione dell'immagine

# 导入PyTorch库  
import torch  
import torch.nn as nn  
  
# 从torchvision.transforms导入ToTensor和ToPILImage,用于图像张量和PIL图像之间的转换  
from torchvision.transforms import ToTensor, ToPILImage  
  
# 从PIL(Python Imaging Library,Pillow是其一个分支)导入Image模块,用于处理图像文件  
from PIL import Image  
  
# 使用PIL的Image.open函数打开指定路径的图片文件,并通过.convert("L")将其转换为灰度图像(单通道)  
img = Image.open("H:\PYTHON_Proj\handlearnpytorch\OIP-C.jpg").convert("L")  
  
# 实例化ToTensor转换对象,用于将PIL图像转换为PyTorch张量  
to_tensor = ToTensor()  
  
# 实例化ToPILImage转换对象,用于将PyTorch张量转换回PIL图像  
to_PIL = ToPILImage()  
  
# 使用to_tensor将PIL图像转换为PyTorch张量,并通过.unsqueeze(0)在批次大小维度上增加一个维度,使其形状变为(1, 1, H, W)  
img = to_tensor(img).unsqueeze(0)  
  
# 创建一个3x3的卷积核(滤波器),初始时所有元素都被设置为-1/9,然后将中心元素设置为1  
kernel = torch.ones(3, 3) / (-9.0)  
kernel[1][1] = 1  
  
# 创建一个Conv2d层,指定输入通道数为1(因为是灰度图像),输出通道数也为1,卷积核大小为3x3,步长为1,填充为1(保持输出尺寸与输入相同),且不使用偏置项  
conv = nn.Conv2d(1, 1, 3, 1, 1, bias=False)  
  
# 将之前定义的卷积核赋值给Conv2d层的权重,注意要调整形状以匹配Conv2d层的期望(out_channels, in_channels, kernel_size[0], kernel_size[1])  
conv.weight.data = kernel.reshape(1, 1, 3, 3)  
  
# 对图像应用卷积操作,此时img是一个四维张量,Conv2d层会处理它并返回一个新的四维张量  
img = conv(img)  
  
# 使用to_PIL将卷积后的PyTorch张量转换回PIL图像,并通过.squeeze(0)移除批次大小维度  
img = to_PIL(img.squeeze(0))  
  
# 使用PIL的.show()方法显示图像  
img.show()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

Strato di raggruppamento

Lo strato di pooling può essere considerato come uno speciale strato di convoluzione, utilizzato principalmente per il downsampling. L'aggiunta di uno strato di pooling può ridurre il numero di parametri mantenendo le caratteristiche principali, impedendo così in una certa misura l'overfitting. Il livello di pooling non ha parametri apprendibili e il suo peso è fisso. Vari livelli di pooling sono inclusi nel toolbox torch.nn. Quelli comuni includono Max Pooling (MaxPool) e Average Pooling (AvgPool). Il livello di pooling svolge un ruolo molto importante nella rete neurale convoluzionale. I suoi principali utilizzi possono essere così riassunti:

  • Riduzione della dimensionalità (riduzione della quantità di calcolo): il livello di pooling riduce la quantità di calcolo e il numero di parametri dei livelli successivi riducendo la dimensione spaziale dei dati (ovvero altezza e larghezza). Ciò è molto utile per prevenire il sovradattamento e accelerare i calcoli.
  • Invarianza delle caratteristiche: il livello di pooling può consentire al modello di apprendere una rappresentazione delle caratteristiche più solida, ovvero invariante rispetto a piccole modifiche nei dati di input (come traslazione, rotazione, ecc.). Questo perché le operazioni di pooling (come pooling massimo, pooling medio, ecc.) selezionano caratteristiche rappresentative all'interno dell'area anziché fare affidamento su informazioni sulla posizione specifica.
  • Estrai caratteristiche principali: attraverso l'operazione di pooling, è possibile estrarre le caratteristiche più importanti dell'immagine ignorando alcuni dettagli non importanti. Ciò è utile per i successivi strati convoluzionali per estrarre ulteriormente funzionalità di alto livello.
  • Espansione del campo recettivo: all'aumentare del numero di strati della rete, lo strato di pooling può espandere gradualmente l'area di input (cioè il campo recettivo) corrispondente a ciascun neurone negli strati successivi. Ciò aiuta la rete a ottenere più informazioni sulle funzionalità globali.
  • Ridurre l'overfitting: poiché il livello di pooling riduce il numero di parametri riducendo la dimensione spaziale dei dati, ciò può ridurre in una certa misura la complessità del modello, contribuendo così a prevenire l'overfitting.

Le operazioni di pooling comuni includono:

  • Max Pooling: selezionare il valore massimo all'interno della finestra di pooling come output. Questo approccio aiuta a preservare le informazioni sui bordi e sulla trama dell'immagine.
  • Pooling medio: calcola la media di tutti i valori all'interno della finestra di pooling come output. Questo approccio aiuta a preservare le informazioni di sfondo dell'immagine.
  • Pooling stocastico: in base al valore di ciascun elemento nella finestra di pooling, gli elementi vengono selezionati casualmente come output in base alla probabilità. Questo metodo combina i vantaggi del pooling massimo e del pooling medio, ma presenta una maggiore complessità computazionale.

In breve, il livello di pooling è una parte indispensabile della rete neurale convoluzionale. Fornisce la capacità di apprendimento e le prestazioni dell'intera rete riducendo la dimensione spaziale dei dati, estraendo le caratteristiche principali, espandendo il campo ricettivo e prevenendo l'overfitting supporto.

# 导入PyTorch库  
import torch  
  
# 导入PyTorch的神经网络模块,用于构建和训练神经网络  
import torch.nn as nn  
  
# 从torchvision.transforms模块导入ToTensor和ToPILImage,这两个转换工具用于图像数据的预处理和后处理  
from torchvision.transforms import ToTensor, ToPILImage  
  
# 从PIL库导入Image模块,用于图像的打开、显示等操作  
from PIL import Image  
  
# 创建一个ToTensor的实例,用于将PIL图像或numpy.ndarray转换为FloatTensor,并归一化到[0.0, 1.0]  
to_tensor = ToTensor()  
  
# 创建一个ToPILImage的实例,用于将Tensor或ndarray转换为PIL图像  
to_pil = ToPILImage()  
  
# 使用PIL的Image.open方法打开指定路径的图像文件,并将其转换为灰度图像('L'模式)  
img = Image.open("H:\PYTHON_Proj\handlearnpytorch\OIP-C.jpg").convert('L')  
  
# 使用PIL的show方法显示图像  
img.show()  
  
# 使用ToTensor转换将PIL图像转换为Tensor,并增加一个维度使其成为[1, H, W]形状,即增加一个批次维度  
img = to_tensor(img).unsqueeze(0)  
  
# 创建一个平均池化层实例,使用2x2的窗口大小和步长为2进行池化  
pool = nn.AvgPool2d(2, 2)  
  
# 对图像Tensor应用平均池化层,然后移除批次维度(squeeze(0)),使其变回[H', W']形状  
img = pool(img).squeeze(0)  
  
# 将Tensor转换回PIL图像以便显示  
img = to_pil(img)  
  
# 再次使用PIL的show方法显示经过池化处理的图像  
img.show()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

altri strati

Oltre ai livelli convoluzionali e ai livelli di pooling, nel deep learning vengono comunemente utilizzati anche i seguenti livelli:

  • Lineare: strato completamente connesso;
  • BatchNorm: livello di normalizzazione batch, suddiviso in 1D, 2D e 3D. Oltre al BatchNorm standard, esiste anche il livello InstanceNorm comunemente utilizzato nella migrazione degli stili;
  • Dropout: il livello di dropout, utilizzato per evitare l'overfitting, è anch'esso diviso in 1D, 2D e 3D.

3. Strategia di inizializzazione

L'inizializzazione dei parametri è molto importante nel deep learning. Una buona inizializzazione può far convergere il modello più velocemente e raggiungere un livello più alto, mentre una scarsa inizializzazione può causare il rapido collasso del modello. I parametri del modulo di nn.Module in PyTorch adottano una strategia di inizializzazione più ragionevole, quindi generalmente non è necessario prenderla in considerazione. Naturalmente, possiamo anche utilizzare l'inizializzazione personalizzata per sostituire l'inizializzazione predefinita del sistema. Quando utilizziamo il parametro, l'inizializzazione personalizzata è particolarmente importante perché torch.Tensor() restituisce un numero casuale in memoria, che probabilmente avrà un valore massimo, che causerà overflow o overflow nella rete di addestramento effettiva . Il modulo nn.init in PyTorch è un modulo appositamente progettato per l'inizializzazione, che implementa le strategie di inizializzazione comunemente utilizzate. Se nn.init non fornisce una determinata strategia di inizializzazione, gli utenti possono anche inizializzarla direttamente da soli.

import torch  
from torch.nn import init  
from torch import nn  
  
# 创建一个线性层,其权重和偏置会被随机初始化(与torch.manual_seed无关,因为这是在调用torch.manual_seed之前发生的)  
linear = nn.Linear(3, 4)  
  
# 打印层创建时默认初始化的权重  
print("默认初始化的权重:")  
print(linear.weight)  
  
# 设置随机数生成的种子,以确保接下来的随机数生成是可重复的  
torch.manual_seed(2021)  
  
# 使用Xavier正态分布重新初始化权重  
# 这个初始化是受torch.manual_seed(2021)影响的  
init.xavier_normal_(linear.weight)  
  
# 打印重新初始化后的权重  
print("Xavier正态分布初始化后的权重:")  
print(linear.weight)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21