PyTorch深度学习实战 |常见层 layer结构的实现和代码实战

简介: 本文介绍了PyTorch中常见的7种神经网络层结构及其输入输出逻辑。通过代码示例演示了全连接层(nn.Linear)、卷积层(nn.Conv2d)、LSTM层、GCN图卷积层和Transformer层的使用方法,重点讲解了各层的输入输出维度变换规则。文章以一张海绵宝宝图片为例,详细展示了图像数据的预处理流程,包括使用PIL和OpenCV两种方法读取图片并转换为PyTorch张量的过程。通过"代码+实战"的方式帮助读者理解神经网络层如何对特征进行维度变换,最终实现从原始输入到目标输出的映射

引言

     深度学习模型的搭建就像搭积木。在 PyTorch 中,torch.nn模块为我们提供了各种形状和功能

的“积木”(层)。很多初学者能跑通复杂的 GitHub 代码,却在自己手写nn.Linear或nn.Conv2d

时因为维度对不上而报错。本文将带你通过“代码+实战”的方式,彻底搞懂 PyTorch 中最常见的 7

种层结构及其输入输出逻辑。

image.gif


核心容器:一切的容器

在 PyTorch 中,所有的层都继承自 nn.Module。但在实际组装时,我们最常用的是

nn.Sequential,它像一个传送带,让数据按顺序流过。

image.gif

🚀举个例子

一个样本有10个特征,深度学习中层的作用就是不断的把特征在各个空间中进行维度变化。

比如经过第一个线性层的作用,特征会变成20,然后经过一个激活函数进行非线性变化,再经过一

个线性层,变成1个特征。【本质就是对特征进行变换,直到变换到样本对应的标签】

import torch
import torch.nn as nn
# 实战:像搭积木一样串联层
# 输入 -> [全连接] -> [激活] -> [全连接] -> 输出
net = nn.Sequential(
    nn.Linear(10, 20),
    nn.ReLU(),
    nn.Linear(20, 1)
)
# 模拟 Batch=4, 特征=10 的输入
x = torch.randn(4, 10)
print(f"输入形状: {x.shape}")        # torch.Size([4, 10])
print(f"输出形状: {net(x).shape}")   # torch.Size([4, 1])

image.gif


本文所用到的数据

     下面我们就以一张海绵宝宝的照片为例'haimian.png'。这张图片的原始大小是图片形状 (高×宽

×通道): (533, 533, 3),神经网络输入需batch维度,格式为[batch, C, H, W],标注化之后的大小是

[1, 3, 224, 224]。这里进行一个简单的说明,因为你看到的彩色,是由红绿蓝三个通道合成出来

的。而你所看到的单个通道的黑白并不是色彩,而是红绿蓝颜色数值的形象化表示。黑代表0,白

色代表255,各种灰代表0-255之间的所有数灰。

具体的变换过程如下图所示:

image.gif

image.gif

import cv2
import torch
import numpy as np
from PIL import Image
import torchvision.transforms as transforms
# ===================== 1. 基础配置 =====================
# 图片路径(当前目录下的haimian.png)
img_path = "haimian.png"
# 设备配置(优先使用GPU)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# ===================== 2. 方法1:用PIL+TorchVision读取(推荐,适配PyTorch) =====================
print("="*50)
print("方法1:PIL + TorchVision 读取(适配PyTorch)")
print("="*50)
# 步骤1:读取原始图片并查看基础信息
img_pil = Image.open(img_path).convert("RGB")  # 强制转为RGB(避免灰度图/透明通道问题)
print(f"【原始图片信息】")
print(f"图片格式: {img_pil.mode}")  # 色彩模式(RGB/灰度等)
print(f"图片尺寸 (宽×高): {img_pil.size}")  # (width, height)
# 步骤2:定义转换流程(转为张量+归一化,适配神经网络输入)
# 注:归一化均值/方差可根据任务调整(如ImageNet的均值[0.485, 0.456, 0.406],方差[0.229, 0.224, 0.225])
transform = transforms.Compose([
    transforms.Resize((224, 224)),  # 缩放到神经网络常用的224×224(可选,根据模型调整)
    transforms.ToTensor(),  # 转为张量:(H,W,C)→(C,H,W),数值归一化到[0,1]
    transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])  # 归一化到[-1,1](可选)
])
# 步骤3:转换为神经网络可用的张量
img_tensor = transform(img_pil).to(device)  # 移至指定设备(CPU/GPU)
# 步骤4:添加batch维度(神经网络输入需batch维度,格式为[batch, C, H, W])
img_tensor_batch = img_tensor.unsqueeze(0)  # 从[3,224,224]→[1,3,224,224]
# 输出张量关键信息
print(f"\n【张量核心信息】")
print(f"张量形状 (无batch维度): {img_tensor.shape}")  # (C, H, W)
print(f"张量形状 (含batch维度): {img_tensor_batch.shape}")  # (batch, C, H, W)
print(f"张量数据类型: {img_tensor.dtype}")  # 通常为torch.float32
print(f"张量设备: {img_tensor.device}")  # cpu/cuda:0
print(f"张量数值范围: [{img_tensor.min().item():.4f}, {img_tensor.max().item():.4f}]")
# ===================== 3. 方法2:用OpenCV读取(备用,兼容CV任务) =====================
print("\n" + "="*50)
print("方法2:OpenCV 读取(兼容CV任务)")
print("="*50)
# 步骤1:读取图片(OpenCV默认BGR格式)
img_cv = cv2.imread(img_path)
# 转换为RGB(与PIL统一)
img_cv_rgb = cv2.cvtColor(img_cv, cv2.COLOR_BGR2RGB)
# 步骤2:查看原始信息
print(f"【原始图片信息】")
print(f"图片形状 (高×宽×通道): {img_cv.shape}")  # (H, W, C)
print(f"图片数据类型: {img_cv.dtype}")  # uint8(0-255)
print(f"像素值范围: [{img_cv.min()}, {img_cv.max()}]")
# 步骤3:转换为PyTorch张量
# 调整维度:(H,W,C)→(C,H,W),并归一化到[0,1]
img_cv_tensor = torch.from_numpy(img_cv_rgb).permute(2, 0, 1).float() / 255.0
img_cv_tensor = img_cv_tensor.to(device)
# 添加batch维度
img_cv_tensor_batch = img_cv_tensor.unsqueeze(0)
# 输出张量信息
print(f"\n【张量核心信息】")
print(f"张量形状 (无batch维度): {img_cv_tensor.shape}")
print(f"张量形状 (含batch维度): {img_cv_tensor_batch.shape}")
print(f"张量数据类型: {img_cv_tensor.dtype}")
print(f"张量设备: {img_cv_tensor.device}")

image.gif

==================================================

方法1:PIL + TorchVision 读取(适配PyTorch)

==================================================

【原始图片信息】

图片格式: RGB

图片尺寸 (宽×高): (533, 533)

【张量核心信息】

张量形状 (无batch维度): torch.Size([3, 224, 224])

张量形状 (含batch维度): torch.Size([1, 3, 224, 224])

张量数据类型: torch.float32

张量设备: cpu

张量数值范围: [-1.0000, 1.0000]

==================================================

方法2:OpenCV 读取(兼容CV任务)

==================================================

【原始图片信息】

图片形状 (高×宽×通道): (533, 533, 3)

图片数据类型: uint8

像素值范围: [0, 255]

【张量核心信息】

张量形状 (无batch维度): torch.Size([3, 533, 533])

张量形状 (含batch维度): torch.Size([1, 3, 533, 533])

张量数据类型: torch.float32

张量设备: cpu


神经网络层

💾本质就是:   对一维的数据进行特征维度的变化

  线性层(nn.Linear)输入是[batch_size, in_features](2 维,批量一维特征向量),输出是

[batch_size, out_features](2 维,批量映射后的特征向量)。

🚀举个例子

# 定义:将 784 维特征压缩到 256 维
fc = nn.Linear(in_features=784, out_features=256)
# 实战:模拟处理一批 MNIST 数据 (64张)
# 注意:输入必须是 2D 张量 [Batch_Size, Features]
x = torch.randn(64, 784)
out = fc(x)
print(f"全连接层变换: {x.shape} -> {out.shape}")
# 输出: [64, 784] -> [64, 256]

image.gif

比如这里我们原始图片经过标准化之后的的大小是(3,224,224)这里我们需要把他变成一维度

的表示(1,150528)。(batch_size, in_features),经过线性层之后就变成了(1, 100),

(batch_size, in_features)。

image.gif


卷积神经网络层

💾本质是:CNN 提取空间特征

二维卷积层(nn.Conv2d)输入是[batch_size, in_channels, height, width](4 维,CHW 格

式),输出是[batch_size, out_channels, out_h, out_w](4 维,通道数由卷积核数量决定,尺

寸由卷积参数计算)。

关键参数:

in_channels: 输入通道数 (RGB=3, 灰度=1)。

out_channels: 输出通道数 (即卷积核的数量)。

kernel_size: 卷积核大小 (如 3x3)。

stride (步长) 和 padding (填充)。

🚀举个例子

# 定义:输入3通道(RGB),输出16通道,3x3卷积,保持尺寸不变(padding=1)
conv = nn.Conv2d(in_channels=3, out_channels=5, kernel_size=3, padding=1)
# 实战:模拟一张 224x224 的彩色图片 (Batch=1)
img = torch.randn(1, 3, 224, 224)
out = conv(img)
print(f"卷积层变换: {img.shape} -> {out.shape}")
# 输出: [1, 3, 224, 224] -> [1, 5, 224, 224]

image.gif

image.gif


循环神经网络数据层

💾LSTM 捕捉序列特征

LSTM 层(batch_first=True)输入是[batch_size, seq_len, input_size](3 维,批量 - 序列长度

- 输入特征维度),输出包含输出序列[batch_size, seq_len, hidden_size] 和 最终隐状态 / 细胞

状态(各为[num_layers, batch_size, hidden_size])。

一般用于处理时间序列(如股票、文本、语音)。

关键参数:input_size (特征维), hidden_size (隐藏层维)。

避坑指南:默认输入格式是 (Seq_Len, Batch, Feature)。强烈建议开启 batch_first=True,让输入

变成符合直觉的 (Batch, Seq_Len, Feature)

🚀举个例子

# 定义:输入特征10,隐藏层20,双层LSTM
lstm = nn.LSTM(input_size=10, hidden_size=20, num_layers=2, batch_first=True)
# 模拟: Batch=3, 时间步=5, 特征=10
x_seq = torch.randn(1, 750, 10)
out, (h_n, c_n) = lstm(x_seq)
print(f"序列输出: {out.shape}") # [1, 5, 20] (包含所有时间步)
print(f"最后状态: {h_n.shape}") # [2, 3, 20] (层数, Batch, 隐藏层)

image.gif

图片→LSTM 输入的关键转换

LSTM 只能处理[batch, seq_len, input_size]的序列数据,而图片是[C, H, W]的空间数据,因此

需要:空间转序列:将图片按行展开(每行作为一个 “时间步”),比如:50x50x3 的图片 → 50

行 × (3×50)=150 维 / 行;特征维度匹配:将 150 维 / 行拆分为 10 维 ×15 组 → 序列长度变为

750,满足input_size=10;添加 batch 维度:单张图片→batch_size=1,最终输入形状[1, 750,

10]。

image.gif

image.gif


图神经网络层

💾提取图结构的关联特征

张量名称 形状 (Shape) 含义 备注
Input: x [N, F_in] 节点特征 N=节点数, F_in=输入特征数
Input: edge_index [2, E] 边连接关系 E=边数, 0行=起点, 1行=终点
Output: out [N, F_out] 新的节点特征 N不变, F_out=输出特征数
(可选) Input: edge_attr [E, F_edge] 边的特征 有些层(如GAT)支持边的权重或属性

🚀举个例子

import torch
from torch_geometric.nn import GCNConv
# ================= 输入 =================
# 1. 节点特征 x: [N=3, F_in=2]
x = torch.tensor([
    [1.75, 65.0], # Node 0
    [1.80, 75.0], # Node 1
    [1.65, 55.0]  # Node 2
], dtype=torch.float)
# 2. 边索引 edge_index: [2, E=4]
# 意思: 0连1, 1连0, 1连2, 2连1
edge_index = torch.tensor([
    [0, 1, 1, 2], # Source 节点索引
    [1, 0, 2, 1]  # Target 节点索引
], dtype=torch.long)
# ================= 定义层 =================
# 定义层: 输入特征2 -> 输出特征8
conv = GCNConv(in_channels=2, out_channels=8)
# ================= 输出 =================
out = conv(x, edge_index)
print(f"输入 x 形状: {x.shape}")            # torch.Size([3, 2])
print(f"输入 edge_index 形状: {edge_index.shape}") # torch.Size([2, 4])
print(f"输出 out 形状: {out.shape}")        # torch.Size([3, 8])

image.gif

image.gif

image.gif


Transformer层

💾提取全局上下文关联特征

张量 形状 (batch_first=True) 含义
Input [Batch, Seq_Len, d_model]

Batch: 批次大小

Seq_Len: 序列长度(如单词数、像素块数)

d_model: 特征维度

Output [Batch, Seq_Len, d_model] 形状不变。现在的每个向量都融合了上下文信息。

🚀举个例子

d_model: 输入特征的维度(例如词向量的长度,如 512)。

nhead: 多头注意力的头数(必须能被 d_model 整除)。

batch_first: 非常重要! 默认为 False。如果设置为 True,输入格式为 (Batch, Seq, Feat),更符合人类直觉。

import torch
import torch.nn as nn
# ================= 配置参数 =================
batch_size = 2      # 比如有 2 句话
seq_len = 5         # 每句话有 5 个单词
d_model = 512       # 每个单词用 512 维向量表示
nhead = 8           # 8 个注意力头
# ================= 定义 Transformer 层 =================
# 这是一个单独的层(Block)
transformer_layer = nn.TransformerEncoderLayer(
    d_model=d_model, 
    nhead=nhead, 
    batch_first=True  # 强烈建议设为 True,否则输入维度需要换位置
)
# ================= 输入数据 =================
# 形状: [Batch_Size, Sequence_Length, Embedding_Dimension]
# 模拟: 2句话,每句5个词,每个词512维
src = torch.randn(batch_size, seq_len, d_model)
# ================= 前向传播 =================
out = transformer_layer(src)
# ================= 输出 =================
print(f"输入形状: {src.shape}") # torch.Size([2, 5, 512])
print(f"输出形状: {out.shape}") # torch.Size([2, 5, 512])

image.gif

image.gif

目录
相关文章
|
4月前
|
机器学习/深度学习 数据挖掘 PyTorch
PyTorch深度学习实战 |手算​​FCN全卷积神经网络
本文介绍了FCN-8s语义分割网络的实现细节。首先解释了语义分割的概念及其与图像分类的区别,重点分析了FCN网络结构中的全卷积化、上采样和跳跃连接三个关键技术。全卷积化将传统CNN的全连接层改为卷积层,实现像素级分类;上采样通过双线性插值恢复特征图尺寸;跳跃连接则融合高低层特征以提升细节表现。文章详细推导了损失函数的计算过程,并提供了完整的PyTorch实现代码,包括双线性插值权重初始化、VGG16骨干网络和FCN-8s主体结构。最后通过测试验证了模型能正确输出与输入尺寸匹配的预测结果。
409 3
|
4月前
|
机器学习/深度学习 存储 人工智能
图解人工智能的数学基础(线性代数)
本文系统讲解线性代数核心概念,涵盖向量(定义、几何/坐标表示、内积)、矩阵(含义、运算、秩、逆、相似、分解)、行列式(几何意义与变换关系)、线性方程组、特征值与特征向量、二次型、向量空间及范数等,强调其在AI与神经网络中的实际应用。
526 7
|
4月前
|
机器学习/深度学习 数据可视化 PyTorch
PyTorch深度学习实战 | 基于LSTM的时间序列预测任务
本文介绍了使用LSTM模型预测印度德里市平均温度的两个项目。项目1对温度数据进行归一化处理,采用滑动窗口法构建监督学习样本,设计5层LSTM网络结构,并详细说明了模型训练过程及评估方法。项目2在数据处理上增加了标准化和周期性特征,改进了网络架构,引入了学习率调整和早停机制优化训练过程。两个项目均通过可视化对比预测值和真实值,验证了LSTM模型在时间序列预测中的有效性。文章从数据处理、模型构建到训练优化,完整呈现了温度预测的实现流程,为时序预测任务提供了实用参考。
290 0
|
4月前
|
机器学习/深度学习 编解码 算法
PyTorch深度学习实战 |手算​​U-net
本文详细解析了U-Net网络架构及其在医学图像分割中的应用。重点对比了U-Net与FCN的核心区别:U-Net采用特征拼接(Concat)保留所有层级信息,而FCN使用特征相加(Add)进行融合。文章深入剖析了U-Net的编码器-瓶颈-解码器结构,解释了其独特的裁剪拼接机制和Overlap-tile策略,并提供了完整的PyTorch实现代码。现代U-Net通过SamePadding实现了输入输出尺寸一致,显著提升了分割精度。文章还探讨了弹性形变数据增强和带空间权重的损失函数设计,为医学图像分析提供了实用解决
340 2
|
4月前
|
机器学习/深度学习 自然语言处理 PyTorch
PyTorch深度学习实战 |手算ViT(Vision Transformer)模型
ViT将图像分块为Patch,经卷积嵌入成Token序列,加入CLS Token和位置编码后输入Transformer Encoder。其核心是让简单分类头依赖Encoder提炼的强特征,凸显Transformer的全局特征提取能力,奠定多模态大模型基础。(239字)
538 0
|
8月前
|
存储 弹性计算 网络协议
阿里云服务器ECS购买流程:按照图片一步步,2026配置省钱指南
阿里云ECS购买全流程指南(2026新版):图文详解自定义配置步骤——选付费类型(包年包月/按量/抢占式)、地域与可用区、实例规格族、操作系统镜像、系统盘/数据盘、公网带宽(固定or流量)、安全组、弹性网卡及IPv6等,助您高效省钱下单。
|
4月前
|
人工智能 缓存 API
阿里云百炼api调用Qwen3.7-Max模型限时5折活动(免费领取100Tokens)
阿里云百炼推出Qwen3.7-Max模型API调用5折优惠,新用户免费领100万Tokens!该旗舰模型支持1M上下文、64K输出、256K思考预算,强化Agent能力,全面支持Function Calling、内置工具及批量调用,专为复杂工程与中文生产力场景优化。开通阿里云百炼:https://t.aliyun.com/U/fPVHqY
|
4月前
|
机器学习/深度学习 PyTorch 测试技术
PyTorch深度学习实战 |多头注意力机制
摘要:本文详细介绍了Transformer中的多头自注意力机制,从整体结构到实现细节,包括四部分内容:(1)多头自注意力的基本架构;(2)内部计算流程解析;(3)注意力计算公式详解;(4)代码实现。重点阐述了多头并行的计算方式、缩放点积注意力的计算步骤(QK转置、缩放、softmax和加权求和),以及残差连接和层归一化的作用。通过"Are you OK?"示例展示了输入张量如何经过8个64维注意力头处理后拼接成512维输出。文章最后提供了完整的PyTorch实现代码,并附测试用例验证模型
314 0
|
4月前
|
机器学习/深度学习 人工智能 PyTorch
PyTorch深度学习实战 | 人工智能项目从训练到部署
本项目基于LSTM模型对污水处理厂总曝气量(旧区+新区)进行时序预测。通过数据清洗、Min-Max归一化、滑动窗口构造(12小时输入→预测未来1小时),构建并训练轻量级LSTM模型,支持API部署与实时调用,已实现端到端预测流程及模型保存。
345 6
|
4月前
|
机器学习/深度学习 算法 机器人
图解强化学习 |手算SAC算法
SAC(Soft Actor-Critic)是最稳定、强大的连续动作强化学习算法,广泛应用于机器人控制与决策任务。其核心是最大熵强化学习:通过双Q网络抑制过估计,柔性策略网络增强探索,自适应温度系数α动态平衡利用与探索,兼顾最优性与鲁棒性。(239字)
649 1