Partage de technologie

Pytorch (note 8 réseau neuronal nn)

2024-07-12

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

1.nn.Module

torch.nn est un module spécialement conçu pour le deep learning. La structure de données de base de torch.nn est Module, qui est un concept abstrait qui peut représenter soit une certaine couche dans un réseau neuronal, soit un réseau neuronal contenant plusieurs couches. En utilisation réelle, l'approche la plus courante consiste à hériter de nn.Module et à écrire votre propre réseau/couche. Voyons d'abord comment utiliser nn.Module pour implémenter votre propre couche entièrement connectée.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
  • Le réseau de couches personnalisé doit hériter de nn.Module et le constructeur de nn.Module doit être appelé dans son constructeur, c'est-à-dire super().initialisationialisation() ou nn.Module.initialisationialisation(auto), la première utilisation est recommandée ;
  • Dans le constructeur __init__, vous devez définir vous-même les paramètres apprenables et les encapsuler dans Paramètres. Par exemple, dans cet exemple, nous encapsulons w et b dans Paramètres. Le paramètre est un Tensor spécial, mais il nécessite des dérivées par défaut (requires_grad
    = Vrai)
  • La fonction forward implémente le processus de propagation vers l'avant et son entrée peut être un ou plusieurs Tensors ;
  • Il n'est pas nécessaire d'écrire une fonction de rétropropagation. nn.Module peut utiliser autograd pour implémenter automatiquement la rétropropagation, ce qui est beaucoup plus simple que Function ;
  • Les paramètres apprenables dans Module peuvent renvoyer un itérateur via approved_parameters() ou settings(). Le premier attachera un nom à chaque paramètre pour le rendre plus identifiable.

2. Couches de réseau neuronal couramment utilisées

2.1 Couche liée à l'image

Les couches liées à l'image comprennent principalement les couches de convolution (Conv), les couches de pooling (Pool), etc. En utilisation réelle, ces couches peuvent être divisées en couches unidimensionnelles (1D), bidimensionnelles (2D) et tridimensionnelles (3D). .La méthode de pooling est également divisée en pooling moyen (AvgPool), pooling maximum (MaxPool), pooling adaptatif (AdaptiveAvgPool), etc. En plus de la convolution directe couramment utilisée, la couche de convolution a également une convolution inverse (TransposeConv), etc. Un exemple sera donné ci-dessous.

  • Extraction de caractéristiques
  • Maintenir la structure de l'espace de données
  • Introduction d'une transformation non linéaire Après l'opération de convolution, une fonction d'activation (telle que ReLU, Sigmoid ou Tanh) est généralement appliquée pour introduire une transformation non linéaire. Ces fonctions d'activation peuvent augmenter le pouvoir expressif de CNN et lui permettre d'apprendre des relations non linéaires plus complexes.
  • Améliorer l'efficacité de calcul Grâce à l'utilisation combinée d'opérations de convolution et de couches de pooling, la couche de convolution peut réduire la dimension spatiale de la carte de caractéristiques, réduisant ainsi la quantité de calcul et améliorant l'efficacité de calcul du modèle. Dans le même temps, la couche de pooling peut également améliorer l'invariance de traduction des caractéristiques, rendant le modèle plus robuste aux petits changements dans les données d'entrée.

couche de convolution

En apprentissage profond, la structure de réseau la plus importante liée au traitement d'images est la couche convolutive (Conv). L'essence d'un réseau neuronal convolutif est la superposition de couches convolutives, de couches de pooling, de couches d'activation et d'autres couches. Par conséquent, il est extrêmement important de comprendre le principe de fonctionnement de la couche convolutive. opération de convolution.
Insérer la description de l'image ici

# 导入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

Couche de mise en commun

La couche de pooling peut être considérée comme une couche de convolution spéciale, principalement utilisée pour le sous-échantillonnage. L'ajout d'une couche de pooling peut réduire le nombre de paramètres tout en conservant les caractéristiques principales, empêchant ainsi le surajustement dans une certaine mesure. La couche de pooling n'a aucun paramètre apprenable et son poids est fixe. Diverses couches de pooling sont regroupées dans la boîte à outils torch.nn. Les plus courantes incluent le pooling maximum (MaxPool) et le pooling moyen (AvgPool). La couche de pooling joue un rôle très important dans le réseau neuronal convolutif (CNN). Ses principales utilisations peuvent être résumées comme suit :

  • Réduction de la dimensionnalité (réduction de la quantité de calcul) : la couche de regroupement réduit la quantité de calcul et le nombre de paramètres des couches suivantes en réduisant la taille spatiale des données (c'est-à-dire la hauteur et la largeur). Ceci est très bénéfique pour éviter le surajustement et accélérer les calculs.
  • Invariance des fonctionnalités : la couche de pooling peut permettre au modèle d'apprendre une représentation des fonctionnalités plus robuste, c'est-à-dire invariante aux petits changements dans les données d'entrée (telles que la translation, la rotation, etc.). En effet, les opérations de regroupement (telles que le regroupement maximum, le regroupement moyen, etc.) sélectionnent des entités représentatives dans la zone plutôt que de s'appuyer sur des informations de localisation spécifiques.
  • Extraire les caractéristiques principales : grâce à l'opération de regroupement, les caractéristiques les plus importantes de l'image peuvent être extraites tout en ignorant certains détails sans importance. Ceci est utile pour les couches convolutionnelles suivantes afin d’extraire davantage les fonctionnalités de haut niveau.
  • Extension du champ récepteur : à mesure que le nombre de couches du réseau augmente, la couche de regroupement peut progressivement étendre la zone d'entrée (c'est-à-dire le champ récepteur) correspondant à chaque neurone dans les couches suivantes. Cela aide le réseau à obtenir davantage d’informations sur les fonctionnalités globales.
  • Réduire le surajustement : étant donné que la couche de pooling réduit le nombre de paramètres en réduisant la dimension spatiale des données, cela peut réduire la complexité du modèle dans une certaine mesure, contribuant ainsi à éviter le surajustement.

Les opérations de mutualisation courantes comprennent :

  • Max Pooling : sélectionnez la valeur maximale dans la fenêtre de pooling comme sortie. Cette approche permet de préserver les informations de bord et de texture de l'image.
  • Pooling moyen : calculez la moyenne de toutes les valeurs dans la fenêtre de pooling comme sortie. Cette approche permet de préserver les informations d’arrière-plan de l’image.
  • Pooling stochastique : en fonction de la valeur de chaque élément dans la fenêtre de pooling, les éléments sont sélectionnés au hasard comme sortie en fonction de leur probabilité. Cette méthode combine les avantages du pooling maximum et du pooling moyen, mais présente une complexité de calcul plus élevée.

En bref, la couche de pooling est un élément indispensable du réseau neuronal convolutif. Elle fournit la capacité d'apprentissage et les performances de l'ensemble du réseau en réduisant la dimension spatiale des données, en extrayant les principales caractéristiques, en élargissant le champ de réception et en empêchant le surajustement. soutien.

# 导入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

autres couches

En plus des couches convolutives et des couches de pooling, les couches suivantes sont également couramment utilisées dans l'apprentissage profond :

  • Linéaire : couche entièrement connectée ;
  • BatchNorm : couche de normalisation par lots, divisée en 1D, 2D et 3D. En plus du BatchNorm standard, il existe également la couche InstanceNorm qui est couramment utilisée dans la migration de style ;
  • Abandon : la couche d'abandon, utilisée pour éviter le surajustement, est également divisée en 1D, 2D et 3D.

3. Stratégie d'initialisation

L'initialisation des paramètres est très importante dans l'apprentissage en profondeur. Une bonne initialisation peut faire converger le modèle plus rapidement et atteindre un niveau plus élevé, tandis qu'une mauvaise initialisation peut entraîner l'effondrement rapide du modèle. Les paramètres du module de nn.Module dans PyTorch adoptent une stratégie d'initialisation plus raisonnable, nous n'avons donc généralement pas besoin d'en tenir compte. Bien entendu, nous pouvons également utiliser une initialisation personnalisée pour remplacer l'initialisation par défaut du système. Lorsque nous utilisons Parameter, l'initialisation personnalisée est particulièrement importante. En effet, torch.Tensor() renvoie un nombre aléatoire en mémoire, qui est susceptible d'avoir une valeur maximale, ce qui provoquera un débordement ou un débordement dans le réseau d'entraînement réel. . Le module nn.init de PyTorch est un module spécialement conçu pour l'initialisation, qui implémente des stratégies d'initialisation couramment utilisées. Si une certaine stratégie d'initialisation nn.init ne fournit pas, les utilisateurs peuvent également l'initialiser directement eux-mêmes.

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