Compartilhamento de tecnologia

Pytorch (notas 8 rede neural nn)

2024-07-12

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

1、nn.Módulo

torch.nn é um módulo especialmente desenvolvido para aprendizado profundo. A estrutura de dados central do torch.nn é Módulo, que é um conceito abstrato que pode representar uma determinada camada em uma rede neural ou uma rede neural contendo muitas camadas. No uso real, a abordagem mais comum é herdar nn.Module e escrever sua própria rede/camada. Vamos primeiro dar uma olhada em como usar nn.Module para implementar sua própria camada totalmente conectada.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
  • A rede da camada customizada deve herdar nn.Module, e o construtor de nn.Module precisa ser chamado em seu construtor, ou seja, super().iniciar() ou nn.Module.iniciar(auto), recomenda-se o primeiro uso;
  • No construtor __init__, você mesmo deve definir os parâmetros que podem ser aprendidos e encapsulá-los em Parâmetros. Por exemplo, neste exemplo, encapsulamos w e b em Parâmetros. O parâmetro é um Tensor especial, mas requer derivadas por padrão (requires_grad
    = Verdadeiro)
  • A função forward implementa o processo de propagação forward e sua entrada pode ser um ou mais tensores;
  • Não há necessidade de escrever uma função de retropropagação. nn.Module pode usar autograd para implementar automaticamente a retropropagação, que é muito mais simples que Function;
  • Os parâmetros que podem ser aprendidos no Módulo podem retornar um iterador por meio de Named_Parameters() ou Parâmetros().

2. Camadas de rede neural comumente usadas

2.1 Camada relacionada à imagem

As camadas relacionadas à imagem incluem principalmente camadas de convolução (Conv), camadas de pooling (Pool), etc. No uso real, essas camadas podem ser divididas em unidimensionais (1D), bidimensionais (2D) e tridimensionais (3D) O método de pool também é dividido em pool médio (AvgPool), pool máximo (MaxPool), pool adaptativo (AdaptiveAvgPool), etc. Além da convolução direta comumente usada, a camada de convolução também possui convolução inversa (TransposeConv) e assim por diante. Um exemplo será dado abaixo.

  • Extração de recursos
  • Manter a estrutura do espaço de dados
  • Introdução de transformação não linear Após a operação de convolução, uma função de ativação (como ReLU, Sigmoid ou Tanh) é geralmente aplicada para introduzir transformação não linear. Essas funções de ativação podem aumentar o poder expressivo da CNN e permitir-lhe aprender relações não lineares mais complexas.
  • Melhorar a eficiência computacional Através do uso combinado de operações de convolução e camadas de pooling, a camada de convolução pode reduzir a dimensão espacial do mapa de características, reduzindo assim a quantidade de cálculo e melhorando a eficiência computacional do modelo. Ao mesmo tempo, a camada de pooling também pode melhorar a invariância de tradução dos recursos, tornando o modelo mais robusto a pequenas mudanças nos dados de entrada.

camada de convolução

No aprendizado profundo, a estrutura de rede mais importante relacionada ao processamento de imagens é a camada convolucional (Conv). A essência de uma rede neural convolucional é a superposição de camadas convolucionais, camadas de pooling, camadas de ativação e outras camadas. Portanto, é extremamente importante compreender o princípio de funcionamento da camada convolucional. operação de convolução.
Insira a descrição da imagem aqui

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

Camada de pooling

A camada de pooling pode ser considerada uma camada de convolução especial, usada principalmente para redução da resolução. Adicionar uma camada de pooling pode reduzir o número de parâmetros, mantendo os recursos principais, evitando assim o sobreajuste até certo ponto. A camada de pooling não possui parâmetros que podem ser aprendidos e seu peso é fixo. Várias camadas de pooling são empacotadas na caixa de ferramentas torch.nn. As mais comuns incluem Max Pooling (MaxPool) e Average Pooling (AvgPool). A camada de pooling desempenha um papel muito importante na Rede Neural Convolucional. Seus principais usos podem ser resumidos da seguinte forma:

  • Redução da dimensionalidade (reduzindo a quantidade de cálculo): A camada de pooling reduz a quantidade de cálculo e o número de parâmetros das camadas subsequentes, reduzindo o tamanho espacial dos dados (ou seja, altura e largura). Isso é muito benéfico para evitar overfitting e acelerar os cálculos.
  • Invariância de recursos: a camada de pooling pode permitir que o modelo aprenda uma representação de recursos mais robusta, ou seja, invariante a pequenas alterações nos dados de entrada (como translação, rotação, etc.). Isso ocorre porque as operações de agrupamento (como agrupamento máximo, agrupamento médio, etc.) selecionam características representativas dentro da área em vez de depender de informações de localização específicas.
  • Extrair características principais: Através da operação de pooling, as características mais importantes da imagem podem ser extraídas, ignorando alguns detalhes sem importância. Isso é útil para camadas convolucionais subsequentes para extrair ainda mais recursos de alto nível.
  • Expandindo o campo receptivo: À medida que o número de camadas da rede aumenta, a camada de pooling pode expandir gradualmente a área de entrada (ou seja, campo receptivo) correspondente a cada neurônio nas camadas subsequentes. Isso ajuda a rede a aprender mais informações sobre recursos globais.
  • Reduzir o sobreajuste: Como a camada de pooling reduz o número de parâmetros ao reduzir a dimensão espacial dos dados, isso pode reduzir até certo ponto a complexidade do modelo, ajudando assim a evitar o sobreajuste.

As operações comuns de pooling incluem:

  • Max Pooling: Selecione o valor máximo na janela de pooling como saída. Essa abordagem ajuda a preservar as informações de borda e textura da imagem.
  • Agrupamento Médio: Calcule a média de todos os valores dentro da janela de agrupamento como saída. Essa abordagem ajuda a preservar as informações de fundo da imagem.
  • Pooling Estocástico: Com base no valor de cada elemento na janela de pooling, os elementos são selecionados aleatoriamente como saída de acordo com a probabilidade. Este método combina as vantagens do pool máximo e do pool médio, mas possui maior complexidade computacional.

Em suma, a camada de pooling é uma parte indispensável da rede neural convolucional. Ela fornece a capacidade de aprendizagem e o desempenho de toda a rede, reduzindo a dimensão espacial dos dados, extraindo características principais, expandindo o campo receptivo e evitando o overfitting. apoiar.

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

outras camadas

Além das camadas convolucionais e das camadas de pooling, as seguintes camadas também são comumente usadas no aprendizado profundo:

  • Linear: camada totalmente conectada;
  • BatchNorm: Camada de normalização de lote, dividida em 1D, 2D e 3D. Além do BatchNorm padrão, há também a camada InstanceNorm que é comumente usada na migração de estilo;
  • Dropout: A camada dropout, usada para evitar overfitting, também é dividida em 1D, 2D e 3D.

3. Estratégia de inicialização

A inicialização dos parâmetros é muito importante no aprendizado profundo. Uma boa inicialização pode fazer o modelo convergir mais rapidamente e atingir um nível mais alto, enquanto uma inicialização ruim pode fazer com que o modelo entre em colapso rapidamente. Os parâmetros do módulo nn.Module no PyTorch adotam uma estratégia de inicialização mais razoável, portanto geralmente não precisamos considerá-la. Claro, também podemos usar a inicialização personalizada para substituir a inicialização padrão do sistema. Quando usamos Parâmetro, a inicialização personalizada é particularmente importante. Isso ocorre porque torch.Tensor() retorna um número aleatório na memória, que provavelmente terá um valor máximo, o que causará estouro ou estouro na rede de treinamento real. . O módulo nn.init no PyTorch é um módulo especialmente projetado para inicialização, que implementa estratégias de inicialização comumente usadas. Se uma determinada estratégia de inicialização nn.init não for fornecida, os próprios usuários também poderão inicializá-la diretamente.

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