深度学习基本单元结构与输入输出维度解析

embedded/2024/11/29 8:53:26/

深度学习基本单元结构与输入输出维度解析

深度学习领域,模型的设计和结构是理解其性能和应用的关键。本文将介绍深度学习中的基本单元结构,包括卷积神经网络(CNN)、反卷积(转置卷积)、循环神经网络(RNN)、门控循环单元(GRU)和长短期记忆网络(LSTM),并详细讨论每个单元的输入和输出维度。我们将以 MNIST 数据集为例,展示这些基本单元如何组合在一起构建复杂的模型。
之前的博客:
深入理解 RNN、LSTM 和 GRU:结构、参数与应用
理解 Conv2d 和 ConvTranspose2d 的输入输出特征形状计算

1. 模型结构概述

我们构建的模型包含以下主要部分:

  • 卷积神经网络(CNN)
  • 反卷积(转置卷积)
  • 循环神经网络(RNN)
  • 门控循环单元(GRU)
  • 长短期记忆网络(LSTM)
  • 全连接层

2. 模型代码

以下是实现综合模型的代码:

python">import torch
import torch.nn as nn
import torch.optim as optim
import torchvision.transforms as transforms
from torchvision import datasets
from torch.utils.data import DataLoader# 定义模型
class CombinedModel(nn.Module):def __init__(self):super(CombinedModel, self).__init__()# CNN 部分self.conv1 = nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1)  # 输入: (1, 28, 28) -> 输出: (32, 28, 28)self.pool = nn.MaxPool2d(kernel_size=2, stride=2)  # 最大池化层self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)  # 输入: (32, 28, 28) -> 输出: (64, 28, 28)# 反卷积部分self.deconv = nn.ConvTranspose2d(64, 32, kernel_size=2, stride=2)  # 输入: (64, 14, 14) -> 输出: (32, 28, 28)# RNN 部分self.rnn_input_size = 32 * 14 * 14  # 输入到 RNN 的特征数self.rnn = nn.RNN(input_size=self.rnn_input_size, hidden_size=128, num_layers=1,batch_first=True)  # 输入: (batch_size, seq_len, input_size)# GRU 部分self.gru = nn.GRU(input_size=128, hidden_size=64, num_layers=1,batch_first=True)  # 输入: (batch_size, seq_len, input_size)# LSTM 部分self.lstm = nn.LSTM(input_size=64, hidden_size=32, num_layers=1,batch_first=True)  # 输入: (batch_size, seq_len, input_size)# 全连接层self.fc = nn.Linear(32, 10)  # 输出: (batch_size, 10)def forward(self, x):# CNN 部分print(f'Input shape: {x.shape}')  # 输入形状: (batch_size, 1, 28, 28)x = self.pool(torch.relu(self.conv1(x)))  # 输出: (batch_size, 32, 28, 28)print(f'After conv1 and pool: {x.shape}')x = self.pool(torch.relu(self.conv2(x)))  # 输出: (batch_size, 64, 14, 14)print(f'After conv2 and pool: {x.shape}')# 反卷积部分x = self.deconv(x)  # 输出: (batch_size, 32, 14, 14)print(f'After deconv: {x.shape}')# 将数据展平并调整形状以输入到 RNNx = x.view(x.size(0), -1)  # 展平为 (batch_size, 32 * 14 * 14)print(f'After flattening: {x.shape}')x = x.unsqueeze(1)  # 添加序列长度维度,变为 (batch_size, 1, 32 * 14 * 14)print(f'After unsqueeze for RNN: {x.shape}')# RNN 部分x, _ = self.rnn(x)  # 输出: (batch_size, 1, 128)print(f'After RNN: {x.shape}')# GRU 部分x, _ = self.gru(x)  # 输出: (batch_size, 1, 64)print(f'After GRU: {x.shape}')# LSTM 部分x, _ = self.lstm(x)  # 输出: (batch_size, 1, 32)print(f'After LSTM: {x.shape}')# 取最后一个时间步的输出x = x[:, -1, :]  # 输出: (batch_size, 32)print(f'After selecting last time step: {x.shape}')# 全连接层x = self.fc(x)  # 输出: (batch_size, 10)print(f'Output shape: {x.shape}')return x# 3. 数据加载
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5,), (0.5,))  # MNIST 数据集的均值和标准差
])# 下载 MNIST 数据集
train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform)train_loader = DataLoader(dataset=train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(dataset=test_dataset, batch_size=64, shuffle=False)# 4. 训练模型
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = CombinedModel().to(device)
criterion = nn.CrossEntropyLoss()  # 损失函数
optimizer = optim.Adam(model.parameters(), lr=0.001)  # 优化器# 训练过程
num_epochs = 5
for epoch in range(num_epochs):model.train()running_loss = 0.0correct = 0total = 0for images, labels in train_loader:images, labels = images.to(device), labels.to(device)  # 将数据移动到设备optimizer.zero_grad()  # 清空梯度outputs = model(images)  # 前向传播loss = criterion(outputs, labels)  # 计算损失loss.backward()  # 反向传播optimizer.step()  # 更新参数running_loss += loss.item()_, predicted = torch.max(outputs.data, 1)  # 获取预测结果total += labels.size(0)correct += (predicted == labels).sum().item()avg_loss = running_loss / len(train_loader)accuracy = 100 * correct / totalprint(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {avg_loss:.4f}, Accuracy: {accuracy:.2f}%')# 5. 评估模型
model.eval()
correct = 0
total = 0
with torch.no_grad():for images, labels in test_loader:images, labels = images.to(device), labels.to(device)  # 将数据移动到设备outputs = model(images)_, predicted = torch.max(outputs.data, 1)  # 获取预测结果total += labels.size(0)correct += (predicted == labels).sum().item()print(f'Accuracy of the model on the test images: {100 * correct / total:.2f}%')

3. 每个基本单元的输入输出维度

3.1 CNN 部分

  1. 输入(batch_size, 1, 28, 28)

    • 这是 MNIST 数据集的输入形状,其中 1 表示单通道(灰度图像),28x28 是图像的高度和宽度。
  2. 卷积层 1

    • self.conv1 = nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1)
    • 输入形状(batch_size, 1, 28, 28)
    • 输出形状(batch_size, 32, 28, 28)
    • 32 个特征图,空间维度保持不变。
  3. 最大池化层 1

    • 输入形状(batch_size, 32, 28, 28)
    • 输出形状(batch_size, 32, 14, 14)
    • 高度和宽度减半。
  4. 卷积层 2

    • self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
    • 输入形状(batch_size, 32, 14, 14)
    • 输出形状(batch_size, 64, 14, 14)
    • 64 个特征图,空间维度保持不变。
  5. 最大池化层 2

    • 输入形状(batch_size, 64, 14, 14)
    • 输出形状(batch_size, 64, 7, 7)
    • 高度和宽度再次减半。

3.2 反卷积部分

  1. 反卷积层
    • self.deconv = nn.ConvTranspose2d(64, 32, kernel_size=2, stride=2)
    • 输入形状(batch_size, 64, 7, 7)
    • 输出形状(batch_size, 32, 14, 14)
    • 高度和宽度翻倍。

3.3 RNN 部分

  1. 展平

    • x = x.view(x.size(0), -1)
    • 输入形状(batch_size, 32, 14, 14)
    • 输出形状(batch_size, 6272) # 这里的 6272 是 32 * 14 * 14
    • 将特征图展平为一个向量。
  2. 添加序列长度维度

    • x = x.unsqueeze(1)
    • 输入形状(batch_size, 6272)
    • 输出形状(batch_size, 1, 6272)
    • 添加序列长度维度,表示只有一个时间步。
  3. RNN

    • 输入形状(batch_size, 1, 6272)
    • 输出形状(batch_size, 1, 128)
    • RNN 输出的隐藏状态,隐藏层大小为 128。

3.4 GRU 和 LSTM 部分

  1. GRU

    • 输入形状(batch_size, 1, 128)
    • 输出形状(batch_size, 1, 64)
    • GRU 输出的隐藏状态,隐藏层大小为 64。
  2. LSTM

    • 输入形状(batch_size, 1, 64)
    • 输出形状(batch_size, 1, 32)
    • LSTM 输出的隐藏状态,隐藏层大小为 32。

3.5 全连接层

  1. 全连接层
    • self.fc = nn.Linear(32, 10)
    • 输入形状(batch_size, 32)
    • 输出形状(batch_size, 10)
    • 最终输出的类别数(10 类,表示 MNIST 的数字 0-9)。

4. 可视化模型结构

python">from torchinfo import summary
model = CombinedModel()
summary(model, input_size=(64,1, 28, 28))

或者

python">import torch
import torch.nn as nn
from torchviz import make_dot
model = CombinedModel()
dummy_input = torch.randn(1, 1, 28, 28)  # (batch_size, channels, height, width)
output = model(dummy_input)
dot = make_dot(output, params=dict(model.named_parameters()))
dot.render("model_structure", format="png")  # 生成 model_structure.png

在这里插入图片描述


http://www.ppmy.cn/embedded/141415.html

相关文章

泷羽sec-linux进阶

基础之linux进阶 声明! 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽…

【YOLO系列复现】二、基于YOLOv6的目标检测:YOLOv6训练自己的数据集(史诗级详细教程)

官方模型:YOLOv6/README_cn.md at main meituan/YOLOv6 目录 1、模型和环境准备 1.1 模型下载 1.2 依赖环境安装 1.3 权重文件下载 1.4 环境测试 2、配置文件和数据集准备 2.1 准备数据集 2.2 配置文件准备 2.3 BUG修改 3、模型训练 3.1 模型训练 3.2 …

IDEA 2024 Maven 设置为全局本地仓库,避免新建项目重新配置maven

使用idea创建Java项目时每次都要重新配置Maven,非常麻烦。其实IDEA可以配置全局Maven。方法如下: 1.关闭所有项目进入初始页面 2.选择所有配置 3.设置为自己的路径

网络安全方面的专业词汇大全[荐]

Access Control List(ACL) 访问控制列表 access token 访问令牌 account lockout 帐号封锁 account policies 记帐策略 accounts 帐号 adapter 适配器 adaptive speed leveling 自适应速率等级调整 Address Resolution Protocol(ARP) 地址解析协议 Admin…

go-carbon v2.5.0 发布,轻量级、语义化、对开发者友好的 golang 时间处理库

carbon 是一个轻量级、语义化、对开发者友好的 Golang 时间处理库,提供了对时间穿越、时间差值、时间极值、时间判断、星座、星座、农历、儒略日 / 简化儒略日、波斯历 / 伊朗历的支持。 carbon 目前已捐赠给 dromara 开源组织,已被 awesome-go 收录&am…

分布式MQTT代理中使用布隆过滤器管理通配符主题

论文标题:Wildcard Topic Management using Bloom Filter in Distributed MQTT Brokers 中文标题:分布式MQTT代理中使用布隆过滤器管理通配符主题 作者信息: Ryohei Banno,Hitotsubashi University, Graduate School of Social…

将自定义 AWS S3 快照存储库连接到 Elastic Cloud

作者:来自 Elastic Annie Hansen, Stef Nestor 在本博客中,我们将介绍如何通过 Elasticsearch 的快照将我们已提交的集群数据备份到 AWS S3 存储桶中。在 Elastic Cloud(企业版)中,Elastic 在其 found-snapshots 存储…

C#面向对象,封装、继承、多态、委托与事件实例

一.面向对象封装性编程 创建一个控制台应用程序,要求: 1.定义一个服装类(Cloth),具体要求如下 (1)包含3个字段:服装品牌(mark),服装…