全网最实用--神经网络各个组件以及效率指标 (含代码助理解,粘贴即用)

一、神经网络相关组件

0.前奏

在神经网络中,"宽度"和"深度"是描述模型结构的两个关键维度。

  1. 模型的宽度(Width)–隐藏层大小:

    • 模型的宽度通常指的是单个层中神经元或节点的数量。
    • 一个更宽的层意味着它有更多的神经元,能够捕捉更复杂的特征,但同时也可能增加计算成本和过拟合的风险。
    • 例如,在全连接层中,宽度就是该层神经元的数量。
  2. 模型的深度(Depth)–隐藏层数量➕2:

    • 模型的深度指的是网络中层的总数,包括输入层和输出层之间的所有隐藏层。
    • 一个更深的网络意味着它有更多的层,能够学习更复杂的函数和抽象特征,但同时也可能增加梯度消失或梯度爆炸的问题。
    • 例如,一个具有输入层、两个隐藏层和一个输出层的网络,其深度为4。

在设计神经网络时,宽度和深度都是需要仔细考虑的因素。增加宽度可以提高模型的表达能力,但可能会导致计算成本增加和过拟合;增加深度可以学习更复杂的特征,但也可能带来训练困难和性能下降的问题。通常,通过实验和经验来平衡宽度和深度,以达到最佳的模型性能。

1.全连接层(Fully Connected Layer, FC)/密集层(Dense Layer):

每个神经元与前一层的所有神经元相连,主要用于特征的线性组合。

import torch
import torch.nn as nn

# 定义一个简单的全连接层
class SimpleDenseLayer(nn.Module):
    def __init__(self, input_size, output_size):
        super(SimpleDenseLayer, self).__init__()
        self.fc = nn.Linear(input_size, output_size)

    def forward(self, x):
        x = torch.relu(self.fc(x))
        return x

# 创建一个实例
input_size = 20  # 输入特征的数量
output_size = 10  # 神经元的数量
dense_layer = SimpleDenseLayer(input_size, output_size)

# 创建一个虚拟输入数据来测试层
dummy_input = torch.randn(1, input_size)  # 批量大小为1
output = dense_layer(dummy_input)

print(output)

2.卷积层(Convolutional Layer, Conv):

主要用于处理图像数据,通过卷积操作提取空间特征。

a.一维卷积

import torch
import torch.nn as nn

# 定义一维卷积层
conv1d = nn.Conv1d(in_channels=1, out_channels=16, kernel_size=3, stride=1, padding=1)

# 创建一个虚拟输入数据
input_data = torch.randn(1, 1, 20)  # 批量大小为1,通道数为1,长度为20

# 前向传播
output = conv1d(input_data)
print(output.shape)  # 输出形状torch.Size([1, 16, 20])

  • padding参数决定了在输入特征图的边缘周围添加多少层零值像素。这样做有两个主要目的:
    保持特征图尺寸: 通过适当的padding,可以使得卷积操作后的输出特征图尺寸与输入特征图尺寸保持一致。这对于构建深层网络时保持特征图的尺寸非常有用。
    边缘信息: 如果不使用padding,边缘的像素点在卷积操作中被使用的次数会比中心像素点少,这可能导致边缘信息的丢失。通过padding,可以确保边缘像素点也被充分使用。

  • stride参数决定了卷积核在输入特征图上移动的步长。默认情况下,stride=1意味着卷积核每次移动一个像素。增加stride值会减少输出特征图的尺寸,因为卷积核移动的步长增加了。
    例如,如果stride=2,卷积核每次移动2个像素,这样输出特征图的尺寸会减半。

  • kernel_size=n:卷积核的尺寸为nxn。

b.二维卷积

import torch
import torch.nn as nn

# 定义二维卷积层
conv2d = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=3, stride=1, padding=1)

# 创建一个虚拟输入数据
input_data = torch.randn(1, 3, 32, 32)  # 批量大小为1,通道数为3,图像大小为32x32

# 前向传播
output = conv2d(input_data)

print(output.shape)  # 输出形状torch.Size([1, 16, 32, 32])

  • 输出尺寸的计算
    输出特征图的尺寸可以通过以下公式计算:
    对于二维卷积:
    在这里插入图片描述
    其中,input_size是输入特征图的尺寸,padding是边缘填充的层数,kernel_size是卷积核的尺寸,stride是卷积核移动的步长。

c.分组卷积

分组卷积(Grouped Convolution)将输入通道和输出通道分成多个组,每个组独立进行卷积操作。

import torch
import torch.nn as nn

# 定义一个分组卷积层
conv2d_grouped = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=3, stride=1, padding=1, groups=4)

# 创建一个虚拟输入数据
input_data = torch.randn(1, 16, 32, 32)  # 批量大小为1,通道数为16,图像大小为32x32

# 前向传播
output = conv2d_grouped(input_data)
print(output.shape)  # 输出形状torch.Size([1, 32, 32, 32])

3.池化层(Pooling Layer):

通常跟在卷积层后面,用于降低特征维度和参数数量,提高计算效率,包括最大池化(Max Pooling)和平均池化(Average Pooling)等。

a.最大池化

import torch
import torch.nn as nn

# 定义一个最大池化层
maxpool = nn.MaxPool2d(kernel_size=2, stride=2)

# 创建一个虚拟输入数据
input_data = torch.randn(1, 16, 32, 32)  # 批量大小为1,通道数为16,图像大小为32x32

# 前向传播
output = maxpool(input_data)
print(output.shape)  # 输出形状torch.Size([1, 16, 16, 16])

b.平均池化

import torch
import torch.nn as nn

# 定义一个平均池化层
avgpool = nn.AvgPool2d(kernel_size=2, stride=2)

# 创建一个虚拟输入数据
input_data = torch.randn(1, 16, 32, 32)  # 批量大小为1,通道数为16,图像大小为32x32

# 前向传播
output = avgpool(input_data)
print(output.shape)  # 输出形状torch.Size([1, 16, 16, 16])

c.池化层较卷积层没有引入参数的原因

池化层之所以没有参数引入,是因为池化操作本身是一个固定的操作,不涉及可学习的参数。池化层的主要作用是减少特征图的尺寸,提取特征图中的主要信息(如最大值或平均值),而不需要学习权重。
卷积层有参数引入的原因
卷积层引入参数的原因是卷积操作涉及可学习的权重(即卷积核)。每个卷积核都是一个可学习的参数矩阵,用于从输入特征图中提取特征。卷积层的参数包括:
卷积核权重: 每个卷积核的权重矩阵。
偏置项: 每个输出通道可以有一个偏置项,用于调整输出特征图的值。
当你初始化一个卷积层的模型时,权重矩阵会被赋予初始值,而不是空值或零。这些参数在训练过程中通过反向传播算法进行优化,以提取输入数据中的有用特征。

4.循环层(Recurrent Layer, RNN):

适用于处理序列数据,如语音、文本等,单元间具有循环连接,可以捕获时间序列信息。

a.基础RNN(Vanilla RNN):

最简单的循环网络结构,但容易出现梯度消失和梯度爆炸的问题。

序列长度 表示每个样本的时间步数。在处理序列数据(如文本、时间序列等)时,每个样本通常由多个时间步组成。RNN通过在每个时间步接收输入并更新内部状态,能够捕捉序列中的时间依赖关系。因此,序列长度是RNN处理序列数据时的一个重要参数。

循环 体现在nn.RNN模块内部的计算过程中。具体来说,nn.RNN在每个时间步都会接收一个输入向量,并产生一个输出向量,同时更新其内部隐藏状态。这个隐藏状态在下一个时间步会被用作输入的一部分,从而形成了一个循环的结构。

import torch
import torch.nn as nn

# 定义输入数据
batch_size = 5  # 批次大小
sequence_length = 10  # 序列长度
input_size = 10  # 输入特征的大小
hidden_size = 20  # 隐藏层的大小
num_layers = 2  # RNN层的层数

# 随机生成输入数据
x = torch.randn(batch_size, sequence_length, input_size)


# 基础RNN
class VanillaRNN(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers):
        super(VanillaRNN, self).__init__()
        self.rnn = nn.RNN(input_size, hidden_size, num_layers, batch_first=True)

    def forward(self, x):
        output, h_n = self.rnn(x)
        return output, h_n


model_rnn = VanillaRNN(input_size, hidden_size, num_layers)
output_rnn, h_n_rnn = model_rnn(x)

print("Output Shape:", output_rnn.shape)  # 输出形状: [batch_size, sequence_length, hidden_size][5, 10, 20]
print("Hidden State Shape:", h_n_rnn.shape)  # 隐藏状态形状: [num_layers, batch_size, hidden_size][2, 5, 20]

b.长短期记忆网络(LSTM):

引入了三个门(输入门、输出门、遗忘门)来控制信息的流动,有效解决了梯度消失问题,适合处理长序列数据。

import torch
import torch.nn as nn

# 定义输入数据
batch_size = 5  # 批次大小
sequence_length = 10  # 序列长度
input_size = 10  # 输入特征的大小
hidden_size = 20  # 隐藏层的大小
num_layers = 2  # RNN层的层数

# 随机生成输入数据
x = torch.randn(batch_size, sequence_length, input_size)
class LSTM(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers):
        super(LSTM, self).__init__()
        self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)

    def forward(self, x):
        output, (h_n, c_n) = self.lstm(x)
        return output, (h_n, c_n)


model_lstm = LSTM(input_size, hidden_size, num_layers)
output_lstm, (h_n_lstm, c_n_lstm) = model_lstm(x)

print("Output Shape:", output_lstm.shape)  # 输出形状: [batch_size, sequence_length, hidden_size][5, 10, 20]
print("Hidden State Shape:", h_n_lstm.shape)  # 隐藏状态形状: [num_layers, batch_size, hidden_size][2, 5, 20]
print("Cell State Shape:", c_n_lstm.shape)  # 单元状态形状: [num_layers, batch_size, hidden_size][2, 5, 20]

c.门控循环单元(GRU):

简化版的LSTM,只有两个门(更新门和重置门),计算复杂度低,但效果与LSTM相似。

import torch
import torch.nn as nn

# 定义输入数据
batch_size = 5  # 批次大小
sequence_length = 10  # 序列长度
input_size = 10  # 输入特征的大小
hidden_size = 20  # 隐藏层的大小
num_layers = 2  # RNN层的层数

# 随机生成输入数据
x = torch.randn(batch_size, sequence_length, input_size)# GRU层
class GRU(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers):
        super(GRU, self).__init__()
        self.gru = nn.GRU(input_size, hidden_size, num_layers, batch_first=True)

    def forward(self, x):
        output, h_n = self.gru(x)
        return output, h_n

model_gru = GRU(input_size, hidden_size, num_layers)
output_gru, h_n_gru = model_gru(x)

print("Output Shape:", output_gru.shape)  # 输出形状: [batch_size, sequence_length, hidden_size][5, 10, 20]
print("Hidden State Shape:", h_n_gru.shape)  # 隐藏状态形状: [num_layers, batch_size, hidden_size][2, 5, 20]

5.归一化层(Normalization Layer):

归一化层(Normalization Layer)在深度学习中用于提高模型的训练稳定性和加速收敛。

a. 批量归一化(Batch Normalization)

批量归一化是在每个小批量数据上进行归一化处理,使得网络的输入在训练过程中保持稳定的分布。

import torch
import torch.nn as nn

# 定义一个简单的卷积神经网络
class SimpleCNN(nn.Module):
    def __init__(self):
        super(SimpleCNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 16, kernel_size=3, stride=1, padding=1)
        self.bn1 = nn.BatchNorm2d(16)
        self.relu = nn.ReLU()
        self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
        self.conv2 = nn.Conv2d(16, 32, kernel_size=3, stride=1, padding=1)
        self.bn2 = nn.BatchNorm2d(32)
        self.fc = nn.Linear(32 * 7 * 7, 10)

    def forward(self, x):
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.relu(x)
        x = self.pool(x)
        x = self.conv2(x)
        x = self.bn2(x)
        x = self.relu(x)
        x = self.pool(x)
        x = x.view(x.size(0), -1)
        x = self.fc(x)
        return x

# 创建模型实例
model = SimpleCNN()
print(model)

当你在定义模型时只写了一句 self.bn2 = nn.BatchNorm2d(32),实际上你只是创建了一个批量归一化层(Batch Normalization Layer),并指定了输入通道数为32。然而,当你打印模型时,PyTorch会显示这个层的详细配置信息,包括默认参数和一些额外的信息。

(bn2): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  • (bn2):这是你在模型中给这个层的命名。 BatchNorm2d:表示这是一个二维的批量归一化层。 32:表示输入通道数。
  • eps=1e-05:这是批量归一化层的一个默认参数,用于防止除以零的情况。
  • momentum=0.1:这是批量归一化层的一个默认参数,用于控制运行时均值和方差的更新速度。
  • affine=True:表示这个层会学习两个参数(gamma和beta),用于在归一化之后对数据进行缩放和偏移。
  • track_running_stats=True:表示这个层会跟踪运行时的均值和方差,并在推理阶段使用这些统计量。

b. 层归一化(Layer Normalization)

层归一化是对每个样本的所有特征进行归一化处理,不依赖于小批量数据的大小。

class SimpleLSTM(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers):
        super(SimpleLSTM, self).__init__()
        self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
        self.ln = nn.LayerNorm(hidden_size)
        self.fc = nn.Linear(hidden_size, 1)

    def forward(self, x):
        x, _ = self.lstm(x)
        x = self.ln(x)
        x = self.fc(x)
        return x

# 创建模型实例
model = SimpleLSTM(input_size=10, hidden_size=20, num_layers=2)
print(model)

c. 实例归一化(Instance Normalization)

实例归一化是对每个样本的每个通道进行归一化处理,常用于风格迁移等任务。

class SimpleConvNet(nn.Module):
    def __init__(self):
        super(SimpleConvNet, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, kernel_size=3, stride=1, padding=1)
        self.in1 = nn.InstanceNorm2d(16)
        self.relu = nn.ReLU()
        self.conv2 = nn.Conv2d(16, 32, kernel_size=3, stride=1, padding=1)
        self.in2 = nn.InstanceNorm2d(32)
        self.fc = nn.Linear(32 * 32 * 32, 10)

    def forward(self, x):
        x = self.conv1(x)
        x = self.in1(x)
        x = self.relu(x)
        x = self.conv2(x)
        x = self.in2(x)
        x = self.relu(x)
        x = x.view(x.size(0), -1)
        x = self.fc(x)
        return x

# 创建模型实例
model = SimpleConvNet()
print(model)

d. 组归一化(Group Normalization)

组归一化是将通道分成若干组,对每组内的通道进行归一化处理。

class SimpleConvNet(nn.Module):
    def __init__(self):
        super(SimpleConvNet, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, kernel_size=3, stride=1, padding=1)
        self.gn1 = nn.GroupNorm(4, 16)
        self.relu = nn.ReLU()
        self.conv2 = nn.Conv2d(16, 32, kernel_size=3, stride=1, padding=1)
        self.gn2 = nn.GroupNorm(8, 32)
        self.fc = nn.Linear(32 * 32 * 32, 10)

    def forward(self, x):
        x = self.conv1(x)
        x = self.gn1(x)
        x = self.relu(x)
        x = self.conv2(x)
        x = self.gn2(x)
        x = self.relu(x)
        x = x.view(x.size(0), -1)
        x = self.fc(x)
        return x

# 创建模型实例
model = SimpleConvNet()
print(model)

e.参数微调与归一化层

在某些情况下,只调整归一化层的参数(如批量归一化的gammabeta)可以有效地改善模型的性能。这是因为归一化层的参数直接影响了数据的分布,从而影响了模型的训练过程。通过微调这些参数,可以更好地适应数据的分布,提高模型的泛化能力。

例如,在迁移学习中,通常会冻结预训练模型的卷积层参数,只微调归一化层的参数,以适应新任务的数据分布。这是因为卷积层的参数已经在大规模数据集上训练过,而归一化层的参数需要根据新数据进行调整。

# 假设我们有一个预训练的模型
model = torchvision.models.resnet18(pretrained=True)

# 冻结所有卷积层参数
for param in model.parameters():
    param.requires_grad = False

# 只微调归一化层的参数
for module in model.modules():
    if isinstance(module, nn.BatchNorm2d):
        for param in module.parameters():
            param.requires_grad = True

# 继续训练模型

6.激活层(Activation Layer):

引入非线性因素,使神经网络可以学习复杂模式,常见激活函数有ReLU、Sigmoid、Tanh等。
(对硬件不友好的激活函数慎用)

import torch
import torch.nn as nn

class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()
        self.fc1 = nn.Linear(784, 128)
        self.relu = nn.ReLU()
        self.sigmoid = nn.Sigmoid()
        self.tanh = nn.Tanh()
        self.leaky_relu = nn.LeakyReLU()
        self.elu = nn.ELU()
        self.fc2 = nn.Linear(128, 10)
    
    def forward(self, x):
        x = self.fc1(x)
        x = self.relu(x)  # ReLU activation
        # x = self.sigmoid(x)  # Sigmoid activation
        # x = self.tanh(x)  # Tanh activation
        # x = self.leaky_relu(x)  # Leaky ReLU activation
        # x = self.elu(x)  # ELU activation
        x = self.fc2(x)
        return x

model = SimpleNN()
print(model)

7.Dropout层:

一种正则化技术,随机丢弃网络中的一些神经元,防止模型过拟合。Dropout 层在训练过程中随机地将其输入单元的一部分设置为0,这有助于使模型变得不依赖于任何一个特征,因而能够提高模型的泛化能力。

import torch
import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.fc1 = nn.Linear(16, 32)  # 输入层到隐藏层
        self.dropout = nn.Dropout(0.5)  # Dropout层,丢弃率设置为0.5
        self.fc2 = nn.Linear(32, 2)  # 隐藏层到输出层

    def forward(self, x):
        x = F.relu(self.fc1(x))  # 应用ReLU激活函数
        x = self.dropout(x)  # 应用Dropout
        x = self.fc2(x)  # 最后一层不使用激活函数
        return x

# 实例化模型
model = Net()
print(model)

# 随机生成一些数据进行测试
x = torch.randn(1, 16)  # 假设输入有16个特征
output = model(x)
print(output)

8.嵌入层(Embedding Layer):

嵌入层(Embedding Layer)在自然语言处理(NLP)任务中非常常见,它用于将单词的索引(通常是整数)转换为密集的向量表示。这种向量通常是通过学习得到的,可以捕捉单词之间的语义关系。

import torch
import torch.nn as nn
import torch.nn.functional as F

class SimpleTextClassifier(nn.Module):
    def __init__(self, vocab_size, embedding_dim, num_classes):
        super(SimpleTextClassifier, self).__init__()
        self.embedding = nn.Embedding(vocab_size, embedding_dim)  # 嵌入层
        self.fc = nn.Linear(embedding_dim, num_classes)  # 全连接层

    def forward(self, x):
        x = self.embedding(x)  # 将输入的索引序列转换为嵌入向量
        x = torch.mean(x, dim=1)  # 对序列中的嵌入向量取平均
        x = self.fc(x)  # 通过全连接层输出分类结果
        return x

# 参数设置
vocab_size = 1000  # 词汇表大小
embedding_dim = 30  # 嵌入向量的维度
num_classes = 4  # 分类的类别数

# 实例化模型
model = SimpleTextClassifier(vocab_size, embedding_dim, num_classes)
print(model)

# 随机生成一些数据进行测试
x = torch.randint(0, vocab_size, (64, 10))  # 64个样本,每个样本有10个单词索引
output = model(x)
print(output.shape)  # 输出形状应为 (64, num_classes)

9.注意力层(Attention Layer):

通过学习输入序列的权重分布来提高模型的焦点,在序列到序列的模型、Transformer结构中特别有用。这个例子展示的是一个基本的加性注意力(Additive Attention),也被称为Bahdanau 注意力。

import torch
import torch.nn as nn
import torch.nn.functional as F

class AdditiveAttention(nn.Module):
    def __init__(self, key_dim, query_dim, hidden_dim):
        super(AdditiveAttention, self).__init__()
        self.key_layer = nn.Linear(key_dim, hidden_dim)
        self.query_layer = nn.Linear(query_dim, hidden_dim)
        self.v = nn.Parameter(torch.rand(hidden_dim))
    
    def forward(self, keys, query, mask=None):
        # keys: [batch_size, seq_len, key_dim]
        # query: [batch_size, query_dim]
        # mask: [batch_size, seq_len]
        
        # 对keys和query进行变换
        keys_transformed = self.key_layer(keys)  # [batch_size, seq_len, hidden_dim]
        query_transformed = self.query_layer(query)  # [batch_size, hidden_dim]
        
        # 扩展query的维度以便可以添加到keys上
        query_expanded = query_transformed.unsqueeze(1)  # [batch_size, 1, hidden_dim]
        
        # 计算加性注意力的分数
        scores = torch.tanh(keys_transformed + query_expanded)  # [batch_size, seq_len, hidden_dim]
        scores = torch.matmul(scores, self.v)  # [batch_size, seq_len]
        
        if mask is not None:
            scores = scores.masked_fill(mask == 0, -1e9)  # 应用mask
        
        # 应用softmax得到注意力权重
        attention_weights = F.softmax(scores, dim=1)
        
        # 应用注意力权重到keys上
        weighted_sum = torch.bmm(attention_weights.unsqueeze(1), keys).squeeze(1)
        return weighted_sum, attention_weights

# 假设的维度
key_dim = 64
query_dim = 64
hidden_dim = 32

# 示例
batch_size = 5
seq_len = 10

# 随机生成keys和query
keys = torch.randn(batch_size, seq_len, key_dim)
query = torch.randn(batch_size, query_dim)
mask = torch.ones(batch_size, seq_len)  # 假设没有需要mask的

attention_layer = AdditiveAttention(key_dim, query_dim, hidden_dim)
weighted_sum, attention_weights = attention_layer(keys, query, mask)

print("Weighted sum shape:", weighted_sum.shape)  # 应为 [batch_size, key_dim]
print("Attention weights shape:", attention_weights.shape)  # 应为 [batch_size, seq_len]

二、神经网络经典架构

1.前馈神经网络(Feedforward Neural Networks, FNN):

最简单的神经网络形式,数据从输入层流向输出层,没有循环或反馈,包括多层感知器(MLP)等。

import numpy as np

# 定义激活函数
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

# 定义前馈神经网络类
class FeedForwardNN:
    def __init__(self, input_size, hidden_size, output_size):
        # 初始化权重和偏置
        self.weights1 = np.random.randn(input_size, hidden_size)
        self.bias1 = np.random.randn(hidden_size)
        self.weights2 = np.random.randn(hidden_size, output_size)
        self.bias2 = np.random.randn(output_size)
    
    def forward(self, x):
        # 第一层
        self.hidden = sigmoid(np.dot(x, self.weights1) + self.bias1)
        # 第二层
        self.output = sigmoid(np.dot(self.hidden, self.weights2) + self.bias2)
        return self.output

# 超参数
input_size = 3
hidden_size = 4
output_size = 2

# 实例化模型
model = FeedForwardNN(input_size, hidden_size, output_size)

# 打印模型参数
print("Weights1:", model.weights1)
print("Bias1:", model.bias1)
print("Weights2:", model.weights2)
print("Bias2:", model.bias2)

2.卷积神经网络(Convolutional Neural Networks, CNN):

主要用于图像和视频处理。
通过卷积层、池化层和全连接层提取和学习图像特征。
(AlexNet:层维度的计算;
VGG-16: 3*3卷积;
ResNet-50:三重分支结构;
MobileNetV2:分组数等于通道数)

import torch
import torch.nn as nn

# 定义 AlexNet 模型
class AlexNet(nn.Module):
    def __init__(self, num_classes=1000):
        super(AlexNet, self).__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 64, kernel_size=11, stride=4, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
            nn.Conv2d(64, 192, kernel_size=5, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
            nn.Conv2d(192, 384, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(384, 256, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(256, 256, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
        )
        self.avgpool = nn.AdaptiveAvgPool2d((6, 6))
        self.classifier = nn.Sequential(
            nn.Dropout(),
            nn.Linear(256 * 6 * 6, 4096),
            nn.ReLU(inplace=True),
            nn.Dropout(),
            nn.Linear(4096, 4096),
            nn.ReLU(inplace=True),
            nn.Linear(4096, num_classes),
        )

    def forward(self, x):
        x = self.features(x)
        x = self.avgpool(x)
        x = torch.flatten(x, 1)
        x = self.classifier(x)
        return x

# 实例化模型
model = AlexNet()

# 打印模型结构
print(model)

3.循环神经网络(Recurrent Neural Networks, RNN):

适用于序列数据处理,如自然语言和时间序列,具有内部状态,可以处理变长序列。

import torch
import torch.nn as nn

# 定义一个简单的 RNN 模型
class SimpleRNN(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(SimpleRNN, self).__init__()
        self.hidden_size = hidden_size
        self.rnn = nn.RNN(input_size, hidden_size, batch_first=True)
        self.fc = nn.Linear(hidden_size, output_size)
    
    def forward(self, x):
        # 初始化隐藏状态
        h0 = torch.zeros(1, x.size(0), self.hidden_size)
        # 前向传播 RNN
        out, _ = self.rnn(x, h0)
        # 取最后一个时间步的输出
        out = self.fc(out[:, -1, :])
        return out

# 超参数
input_size = 10  # 输入特征的大小
hidden_size = 20  # 隐藏层的大小
output_size = 1  # 输出的大小

# 实例化模型
model = SimpleRNN(input_size, hidden_size, output_size)

# 打印模型结构
print(model)

4.自编码器(Autoencoders):

无监督学习模型,用于数据降维和特征学习,包括编码器和解码器两部分。

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader


# 定义自编码器模型
class Autoencoder(nn.Module):
    def __init__(self):
        super(Autoencoder, self).__init__()
        # 编码器部分
        self.encoder = nn.Sequential(
            nn.Linear(28 * 28, 128),
            nn.ReLU(True),
            nn.Linear(128, 64),
            nn.ReLU(True),
            nn.Linear(64, 12),
            nn.ReLU(True),
            nn.Linear(12, 3)  # 压缩到3维
        )
        # 解码器部分
        self.decoder = nn.Sequential(
            nn.Linear(3, 12),
            nn.ReLU(True),
            nn.Linear(12, 64),
            nn.ReLU(True),
            nn.Linear(64, 128),
            nn.ReLU(True),
            nn.Linear(128, 28 * 28),
            nn.Tanh()
        )

    def forward(self, x):
        x = self.encoder(x)
        x = self.decoder(x)
        return x


# 超参数
batch_size = 64
learning_rate = 0.001
num_epochs = 10

# 实例化模型、损失函数和优化器
model = Autoencoder()
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)

# 打印模型结构
print(model)

变分自编码器(Variational Autoencoders, VAE):

自编码器的扩展,用于生成模型和概率建模,可以生成新的数据样本。

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader

# 定义 VAE 模型
class VAE(nn.Module):
    def __init__(self):
        super(VAE, self).__init__()
        # 编码器
        self.fc1 = nn.Linear(784, 400)
        self.fc21 = nn.Linear(400, 20)  # 均值输出层
        self.fc22 = nn.Linear(400, 20)  # 对数方差输出层
        # 解码器
        self.fc3 = nn.Linear(20, 400)
        self.fc4 = nn.Linear(400, 784)

    def encode(self, x):
        h1 = F.relu(self.fc1(x))
        return self.fc21(h1), self.fc22(h1)

    def reparameterize(self, mu, logvar):
        std = torch.exp(0.5*logvar)
        eps = torch.randn_like(std)
        return mu + eps*std

    def decode(self, z):
        h3 = F.relu(self.fc3(z))
        return torch.sigmoid(self.fc4(h3))

    def forward(self, x):
        mu, logvar = self.encode(x.view(-1, 784))
        z = self.reparameterize(mu, logvar)
        return self.decode(z), mu, logvar

# 实例化 VAE 模型、损失函数和优化器
model = VAE()
optimizer = optim.Adam(model.parameters(), lr=1e-3)

# 定义损失函数
def loss_function(recon_x, x, mu, logvar):
    BCE = F.binary_cross_entropy(recon_x, x.view(-1, 784), reduction='sum')
    KLD = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp())
    return BCE + KLD

# 训练模型
def train(model, epoch, train_loader):
    model.train()
    train_loss = 0
    for batch_idx, (data, _) in enumerate(train_loader):
        optimizer.zero_grad()
        recon_batch, mu, logvar = model(data)
        loss = loss_function(recon_batch, data, mu, logvar)
        loss.backward()
        train_loss += loss.item()
        optimizer.step()
        
        if batch_idx % log_interval == 0:
            print(f'Train Epoch: {epoch} [{batch_idx * len(data)}/{len(train_loader.dataset)}'
                  f' ({100. * batch_idx / len(train_loader):.0f}%)]\tLoss: {loss.item() / len(data):.6f}')
    print(f'====> Epoch: {epoch} Average loss: {train_loss / len(train_loader.dataset):.4f}')

# 数据加载和变换
dataset = datasets.MNIST('./data', train=True, download=True, transform=transforms.ToTensor())
train_loader = DataLoader(dataset, batch_size=128, shuffle=True)

# 设置训练参数
epochs = 10
log_interval = 10  # 每隔多少批次打印一次信息

for epoch in range(1, epochs + 1):
    train(model, epoch, train_loader)

# 打印模型结构
print(model)

5.生成对抗网络(Generative Adversarial Networks, GAN):

由生成器和判别器组成,通过对抗训练生成新数据,广泛用于图像生成、风格迁移等。

import torch
import torch.nn as nn

# 定义生成器模型
class Generator(nn.Module):
    def __init__(self, input_dim, output_dim):
        super(Generator, self).__init__()
        self.model = nn.Sequential(
            nn.Linear(input_dim, 128),
            nn.ReLU(True),
            nn.Linear(128, 256),
            nn.ReLU(True),
            nn.Linear(256, 512),
            nn.ReLU(True),
            nn.Linear(512, output_dim),
            nn.Tanh()
        )

    def forward(self, x):
        return self.model(x)

# 定义判别器模型
class Discriminator(nn.Module):
    def __init__(self, input_dim):
        super(Discriminator, self).__init__()
        self.model = nn.Sequential(
            nn.Linear(input_dim, 512),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Linear(512, 256),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Linear(256, 128),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Linear(128, 1),
            nn.Sigmoid()
        )

    def forward(self, x):
        return self.model(x)

# 超参数
z_dim = 100  # 噪声向量的维度
image_dim = 28 * 28  # MNIST 图像的维度

# 实例化生成器和判别器
generator = Generator(input_dim=z_dim, output_dim=image_dim)
discriminator = Discriminator(input_dim=image_dim)

# 打印模型结构
print("Generator Model: \n", generator)
print("Discriminator Model: \n", discriminator)

6.Transformer:

基于自注意力机制的模型,适用于序列到序列的任务,在自然语言处理领域取得了巨大成功,如BERT、GPT等。(接触部分和生成部分;每个transformer包含一个多头注意力机制和两个全连接层;多查询注意力;组注意力)

import torch
import torch.nn as nn

# 定义 Transformer 模型
class TransformerModel(nn.Module):
    def __init__(self, input_dim, model_dim, num_heads, num_layers, output_dim, dropout=0.1):
        super(TransformerModel, self).__init__()
        self.model_dim = model_dim
        
        # 词嵌入层
        self.embedding = nn.Embedding(input_dim, model_dim)
        
        # 位置编码
        self.pos_encoder = PositionalEncoding(model_dim, dropout)
        
        # Transformer 编码器
        encoder_layer = nn.TransformerEncoderLayer(d_model=model_dim, nhead=num_heads, dropout=dropout)
        self.transformer_encoder = nn.TransformerEncoder(encoder_layer, num_layers=num_layers)
        
        # 输出层
        self.fc = nn.Linear(model_dim, output_dim)
        
    def forward(self, src, src_mask=None):
        # 词嵌入和位置编码
        src = self.embedding(src) * torch.sqrt(torch.tensor(self.model_dim, dtype=torch.float32))
        src = self.pos_encoder(src)
        
        # 通过 Transformer 编码器
        output = self.transformer_encoder(src, src_mask)
        
        # 输出层
        output = self.fc(output)
        return output

# 位置编码
class PositionalEncoding(nn.Module):
    def __init__(self, model_dim, dropout=0.1, max_len=5000):
        super(PositionalEncoding, self).__init__()
        self.dropout = nn.Dropout(p=dropout)
        
        pe = torch.zeros(max_len, model_dim)
        position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
        div_term = torch.exp(torch.arange(0, model_dim, 2).float() * (-torch.log(torch.tensor(10000.0)) / model_dim))
        pe[:, 0::2] = torch.sin(position * div_term)
        pe[:, 1::2] = torch.cos(position * div_term)
        pe = pe.unsqueeze(0).transpose(0, 1)
        self.register_buffer('pe', pe)
        
    def forward(self, x):
        x = x + self.pe[:x.size(0), :]
        return self.dropout(x)

# 超参数
input_dim = 10000  # 词汇表大小
model_dim = 512  # 模型维度
num_heads = 8  # 注意力头数
num_layers = 6  # 编码器层数
output_dim = 10000  # 输出维度
dropout = 0.1  # 丢弃率

# 实例化 Transformer 模型
transformer_model = TransformerModel(input_dim, model_dim, num_heads, num_layers, output_dim, dropout)

# 打印模型结构
print(transformer_model)

7.图神经网络(Graph Neural Networks, GNN):

用于处理图结构数据,如社交网络、分子结构等,可以学习节点、边和图级别的特征。

import torch
import torch.nn.functional as F
from torch_geometric.nn import GCNConv
from torch_geometric.data import Data

# 定义GCN模型
class GCN(torch.nn.Module):
    def __init__(self, num_node_features, num_classes):
        super(GCN, self).__init__()
        self.conv1 = GCNConv(num_node_features, 16)
        self.conv2 = GCNConv(16, num_classes)

    def forward(self, data):
        x, edge_index = data.x, data.edge_index

        # 应用第一个图卷积层
        x = self.conv1(x, edge_index)
        x = F.relu(x)
        x = F.dropout(x, training=self.training)

        # 应用第二个图卷积层
        x = self.conv2(x, edge_index)

        return F.log_softmax(x, dim=1)

# 假设有一个图数据实例
num_node_features = 3  # 节点特征的维度
num_classes = 4  # 类别数

# 实例化模型
model = GCN(num_node_features=num_node_features, num_classes=num_classes)

# 打印模型结构
print(model)

8.深度强化学习(Deep Reinforcement Learning, DRL):

结合深度学习和强化学习,用于决策和控制问题,如AlphaGo等。

import gym
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
import random
from collections import deque

# 超参数
BATCH_SIZE = 64
GAMMA = 0.99
EPS_START = 0.9
EPS_END = 0.05
EPS_DECAY = 200
TARGET_UPDATE = 10

# 创建环境
env = gym.make('CartPole-v1')
n_actions = env.action_space.n
n_states = env.observation_space.shape[0]

# 定义神经网络
class DQN(nn.Module):
    def __init__(self, n_states, n_actions):
        super(DQN, self).__init__()
        self.fc1 = nn.Linear(n_states, 128)
        self.fc2 = nn.Linear(128, 128)
        self.fc3 = nn.Linear(128, n_actions)

    def forward(self, x):
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        return self.fc3(x)

# 初始化网络和目标网络
policy_net = DQN(n_states, n_actions)
target_net = DQN(n_states, n_actions)
target_net.load_state_dict(policy_net.state_dict())
target_net.eval()

# 优化器
optimizer = optim.Adam(policy_net.parameters())

# 经验回放缓冲区
memory = deque(maxlen=10000)

# 选择动作
def select_action(state, steps_done):
    sample = random.random()
    eps_threshold = EPS_END + (EPS_START - EPS_END) * \
        math.exp(-1. * steps_done / EPS_DECAY)
    if sample > eps_threshold:
        with torch.no_grad():
            return policy_net(state).max(1)[1].view(1, 1)
    else:
        return torch.tensor([[random.randrange(n_actions)]], dtype=torch.long)

# 优化模型
def optimize_model():
    if len(memory) < BATCH_SIZE:
        return
    transitions = random.sample(memory, BATCH_SIZE)
    batch = zip(*transitions)
    state_batch = torch.cat(next(batch))
    action_batch = torch.cat(next(batch))
    reward_batch = torch.cat(next(batch))
    next_state_batch = torch.cat([s for s in next(batch) if s is not None])
    non_final_mask = torch.tensor(tuple(map(lambda s: s is not None, next(batch))), dtype=torch.bool)

    state_action_values = policy_net(state_batch).gather(1, action_batch)

    next_state_values = torch.zeros(BATCH_SIZE)
    next_state_values[non_final_mask] = target_net(next_state_batch).max(1)[0].detach()
    expected_state_action_values = (next_state_values * GAMMA) + reward_batch

    loss = F.smooth_l1_loss(state_action_values, expected_state_action_values.unsqueeze(1))

    optimizer.zero_grad()
    loss.backward()
    for param in policy_net.parameters():
        param.grad.data.clamp_(-1, 1)
    optimizer.step()

# 主循环
num_episodes = 50
for i_episode in range(num_episodes):
    state = env.reset()
    state = torch.tensor([state], dtype=torch.float32)
    for t in range(1000):
        action = select_action(state, i_episode)
        next_state, reward, done, _ = env.step(action.item())
        reward = torch.tensor([reward], dtype=torch.float32)

        if done:
            next_state = None
        else:
            next_state = torch.tensor([next_state], dtype=torch.float32)

        memory.append((state, action, next_state, reward))

        state = next_state

        optimize_model()

        if done:
            print(f"Episode {i_episode} finished after {t+1} timesteps")
            break

    if i_episode % TARGET_UPDATE == 0:
        target_net.load_state_dict(policy_net.state_dict())

env.close()

三、神经网络效率指标

1. 延迟(Latency)

延迟是指从输入数据到得到模型输出结果所需的时间。在神经网络中,这通常指的是单个输入(或一小批输入)通过整个网络所需的时间。延迟是评估模型实时性能的重要指标,尤其在对实时性要求高的应用中,如自动驾驶、在线视频处理等。

延迟的衡量指标包括:

  • 单次推理时间:一个数据点通过神经网络所需的时间。
  • 首次推理时间:模型从初始化到完成第一次推理的总时间,这通常包括模型加载、权重初始化等准备工作的时间。
  • 平均推理时间:多次推理操作的平均时间,可以更准确地反映模型的实际运行效率。

2. 吞吐量(Throughput)

吞吐量是指单位时间内网络能够处理的数据量。对于批处理任务或数据中心等场景,吞吐量是一个至关重要的性能指标。

吞吐量的衡量指标通常有:

  • 每秒处理的帧数(FPS,Frames Per Second):特别是在视频处理或游戏渲染中,FPS是一个常用的吞吐量衡量指标。
  • 每秒处理的事务数(TPS,Transactions Per Second):在数据库和服务器应用中更常见。
  • 批量处理速度:给定批量大小下,模型每秒可以处理多少批数据。

3. 能效

能效的提升通常涉及到减少内存访问、优化模型大小和计算复杂度等方面。以下是一些具体的能效优化策略和相关指标:

  • 减少内存引用:在神经网络中,内存访问通常是能耗的主要来源之一。通过减少内存访问次数,可以显著提高能效。例如,使用更高效的内存访问模式或通过量化减少数据存储所需的位数。

  • 模型大小:模型大小通常由模型参数的数量和每个参数的比特位数决定。较小的模型不仅占用更少的存储空间,而且通常在推理时消耗更少的能量。

  • 平衡总体激活和峰值激活:在神经网络中,每一层的输入和输出(激活)都需要存储在内存中。优化这些激活的存储和访问模式可以减少能耗。例如,通过使用稀疏表示或激活函数来减少非零元素的数量。

  • MAC乘加运算:MAC(Multiply-Accumulate)操作是神经网络中最基本的计算操作。分析每一层的MAC操作数量可以帮助我们理解模型的计算复杂度,并据此优化能效。

  • Flops(浮点运算次数):Flops是衡量模型计算量的一个指标,通常等于MAC操作次数的一半(因为每个MAC操作包含一次乘法和一次加法)。Flops可以帮助我们评估模型在硬件上的执行效率。

  • Ops(运算次数):Ops是一个更通用的术语,用来描述模型执行的所有类型的运算次数,包括但不限于浮点运算。Ops可以用来衡量模型的整体计算复杂度。

在实际应用中,能效的优化需要综合考虑上述各个因素,通过模型压缩、量化、剪枝、知识蒸馏等技术手段来减少模型的大小和计算复杂度,同时保持或提升模型的性能。此外,选择合适的硬件平台和优化算法实现也是提高能效的关键。

  • 9
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对不起,我之前的回答有误,`vue-markdown-editor`并不支持粘贴图片的功能。但是,您可以使用`mavon-editor`来实现Vue 3中的Markdown编辑器,并支持粘贴图片。 以下是使用`mavon-editor`实现Markdown编辑器并支持粘贴图片的步骤: 1. 首先,使用npm或yarn安装`mavon-editor`: ```bash npm install mavon-editor ``` 2. 在您的Vue组件中,导入并注册`mavon-editor`: ```javascript import Vue from 'vue'; import mavonEditor from 'mavon-editor'; import 'mavon-editor/dist/css/index.css'; Vue.use(mavonEditor); ``` 3. 在模板中使用`mavon-editor`: ```html <template> <div> <mavon-editor v-model="markdownText" @imgAdd="handleImageUpload"></mavon-editor> </div> </template> ``` 4. 在Vue组件的`data`中定义`markdownText`,用于存储Markdown文本: ```javascript export default { data() { return { markdownText: '', }; }, }; ``` 5. 在Vue组件中定义处理图像上传的方法`handleImageUpload`: ```javascript export default { methods: { handleImageUpload(file, callback) { // 在这里处理图像上传逻辑 // 可以使用第三方库或自己实现图像上传功能 // 并返回图像URL,然后通过回调函数将其插入到Markdown文本中 // 示例代码: const imgUrl = 'http://example.com/image.png'; callback(imgUrl); }, }, }; ``` 通过以上步骤,您可以在Vue 3中使用`mavon-editor`实现Markdown编辑器,并支持粘贴图片的功能。请注意,您可能需要根据您的项目需求进行进一步的配置和样式调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值