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

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

引言

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

的“积木”(层)。很多初学者能跑通复杂的 GitHub 代码,却在自己手写nn.Linearnn.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

目录
相关文章
|
17天前
|
机器学习/深度学习 存储 人工智能
图解人工智能的数学基础(线性代数)
本文系统讲解线性代数核心概念,涵盖向量(定义、几何/坐标表示、内积)、矩阵(含义、运算、秩、逆、相似、分解)、行列式(几何意义与变换关系)、线性方程组、特征值与特征向量、二次型、向量空间及范数等,强调其在AI与神经网络中的实际应用。
237 7
|
17天前
|
人工智能 缓存 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
|
17天前
|
人工智能 自然语言处理 计算机视觉
人工智能|大白话Meshed-Memory Transformer
M2Transformer是一种图像描述生成模型,由三部分构成:骨干编码器(Faster R-CNN)提取区域特征;记忆增强编码器(Transformer)对特征进行语义细化;网格解码器(Transformer)将增强特征转化为自然语言描述。结构清晰、层次分明,兼顾准确性与可解释性。(239字)
171 4
|
17天前
|
人工智能 自然语言处理 API
阿里云海外重磅发布 Qwen Cloud
Qwen Cloud,正是为AI Agent 而生的全新服务方式。
1678 53
|
17天前
|
机器学习/深度学习 数据挖掘 PyTorch
PyTorch深度学习实战 |手算​​FCN全卷积神经网络
本文介绍了FCN-8s语义分割网络的实现细节。首先解释了语义分割的概念及其与图像分类的区别,重点分析了FCN网络结构中的全卷积化、上采样和跳跃连接三个关键技术。全卷积化将传统CNN的全连接层改为卷积层,实现像素级分类;上采样通过双线性插值恢复特征图尺寸;跳跃连接则融合高低层特征以提升细节表现。文章详细推导了损失函数的计算过程,并提供了完整的PyTorch实现代码,包括双线性插值权重初始化、VGG16骨干网络和FCN-8s主体结构。最后通过测试验证了模型能正确输出与输入尺寸匹配的预测结果。
207 3
|
17天前
|
机器学习/深度学习 编解码 算法
PyTorch深度学习实战 |手算​​U-net
本文详细解析了U-Net网络架构及其在医学图像分割中的应用。重点对比了U-Net与FCN的核心区别:U-Net采用特征拼接(Concat)保留所有层级信息,而FCN使用特征相加(Add)进行融合。文章深入剖析了U-Net的编码器-瓶颈-解码器结构,解释了其独特的裁剪拼接机制和Overlap-tile策略,并提供了完整的PyTorch实现代码。现代U-Net通过SamePadding实现了输入输出尺寸一致,显著提升了分割精度。文章还探讨了弹性形变数据增强和带空间权重的损失函数设计,为医学图像分析提供了实用解决
150 2
|
17天前
|
机器学习/深度学习 自动驾驶 PyTorch
PyTorch深度学习实战 |SegNet
CamVid_11是面向自动驾驶的语义分割数据集,含700+张精准标注图像,划分为训练/验证/测试集。涵盖道路、车辆、行人等11类场景目标(含背景共12类),支持SegNet等模型训练与评估。
164 3
|
17天前
|
机器学习/深度学习 存储 编解码
PyTorch深度学习实战 | 手算卷积网络(Resnet-18)
ResNet-18是解决深层网络梯度消失与退化问题的经典模型,核心在于残差连接(Shortcut):让输入X直接跳跃传递,与卷积学习的残差F(X)相加(F(X)+X),实现恒等映射。其含4个stage、18层可训练层,每个BasicBlock由两个3×3卷积+BN+ReLU构成,并通过1×1卷积适配尺寸/通道差异,显著提升深层网络训练稳定性与性能。(239字)
182 2
|
17天前
|
人工智能 自然语言处理 供应链
|
17天前
|
机器学习/深度学习 自然语言处理 PyTorch
PyTorch深度学习实战 |词嵌入和位置编码
本文介绍了PyTorch中词嵌入(Embedding)和位置编码(Positional Encoding)的实现与应用。词嵌入通过Word2Vec、GloVe等技术将单词转换为连续向量,其中使用nn.Embedding层加载预训练词向量,并展示如何可视化词向量间的语义关系(如"king-man≈queen-woman")。位置编码部分详细解释了如何通过正弦/余弦函数为词向量添加位置信息,包含公式推导和代码实现(PositionalEncoding类)。文章提供了完整的PyTorch代码示
126 0

热门文章

最新文章