UNet改进模型全解析:四大流派、PyTorch实现与避坑指南

发布时间:2026/10/29 7:18:42
UNet改进模型全解析:四大流派、PyTorch实现与避坑指南 简介一套面向图像分割与深度学习实践者的UNet改进模型合集系统汇集37种主流变体从原始UNet到融合ASPP、CBAM、ECANet、GAM、坐标注意力、Non-local、Transformer、FPN、可变形卷积、Ghost模块等方案可作为对比实验、模块替换与论文复现的直接参考。资源压缩包共370个文件包含148个Python训练与验证脚本、111个pyc缓存、37份md与37份docx项目说明书及37个txt说明文档总大小仅43KB携带方便、目录按模型名称逐项拆分便于快速定位再到对应改进结构。当前已有292人学习下载适合具备一定分割基础、希望系统梳理UNet改进路径的研究者或工程师。每种改进均有独立文件夹脚本内可查看模块接入位置与完整训练验证流程项目说明书则分别介绍设计思路与用途帮助读者结合自家数据快速评估不同注意力机制与多尺度模块的实际效果节省逐篇翻论文、自行搭建对比基线的时间。同时保留原始UNet作为基线便于逐一对照各改动的增益尤其适合毕业设计、课程项目或科研入门阶段的模型选型与效果验证。1. 37种unet改进模型先别急着全试这套“模型大全”的正确打开方式手里有一个分割任务baseline UNet 的 DSC 卡在 0.73怎么看都上不去 0.8。这时候有人甩过来一份“UNet改进模型大全37种unet改进包含训练验证脚本”。翻完目录很兴奋挨个模型试了一周结果不但没涨点有的还比 baseline 差。这不是改法没用而是用错了方式。这份资料的本质不是“37 个模型排排坐”而是一张改进方向目录加一组可运行的最小实现。37 种 unet 改进绝大多数不是并行的独立模型而是结构、注意力、算子、损失四个方向上的模块组合。正确打开方式是先定位 baseline 的短板是感受野不够、边界不精细还是类别不平衡再按第 2 章的选型逻辑挑两三个模块插进去用第 4 章的脚本做消融。适合谁看做医疗影像分割、遥感地物提取、工业表面缺陷检测手里已有能跑的 UNet但对“改进从哪下手”没把握。新手能顺着这里把模块复现出来熟手能直接拿走参数边界和踩坑清单。全文只讲一件事怎么让这 37 种 unet 改进模型真正变成你模型涨点的确认键而不是收藏夹里的装饰。2. UNet改进究竟改在哪结构、注意力、算子与损失四大流派与选型逻辑拿到模型库先别急着跑目录看不懂等于白拿。我看下来绝大多数 unet 改进都没有跳出四个流派动结构、加注意力、换算子、改损失。下面按“改进什么、代价多少、适合什么数据”拆开讲。2.1 结构派换Encoder、改跳跃连接、加深监督收益最大但工程最重结构派的核心动作是换骨干网络。把原版 UNet 的编码器从“两层卷积池化”替换成 ResNet34、ResNet50 这样自带预训练权重的分类网络。好处是浅层特征更丰富训练收敛明显变快。代价是显存上升、加载预训练权重的代码多出一截而且输出 stride 从 16 变 32需要手动补一个空洞卷积或者上采样才能对齐解码器的尺寸。另一个常见结构改造是跳跃连接增强。原版 UNet 的 skip connection 只是把编码器特征直接 concat 给解码器改进版会在拼接之前加一个 ASPP 或 SPP 做多尺度融合让解码器同时看到局部细节和全局上下文。第三种是深度监督在解码器的每一级都接一个辅助分割头每个头都参与 loss 计算。这个做法收敛快但推理时必须只保留主输出否则预测图会变成多张掩膜叠加的“重影”。结构派是精度上限的提升但也是改动量最大的一类。我的建议是如果你的项目允许加载预训练权重优先换编码器收益非常直接如果没有预训练可用别硬上从注意力改起更划算。2.2 注意力派通道、空间、混合三种写法性价比最高注意力是 37 种 unet 改进里出现频率最高的一类因为它几乎不改变网络拓扑只对特征图做重标定。按作用维度分三小类通道注意力、空间注意力、混合注意力。通道注意力的代表是 SE 模块。它把每个特征图压缩成一个全局描述符再学出一组通道权重把有信息的通道放大、没信息的通道压低。空间注意力的代表是 CBAM 里的空间注意力分支它对每个像素位置学一个权重定位“该看哪里”。混合注意力就是把两者串行或并行接在一起CBAM、BAM、NAM 都是这条路子。注意力的插入位置很有讲究。你把它插在编码器每层之后提升的是特征表达质量插在解码器每级上采样之后提升的是边界恢复能力。我在第 3 章会给出 SE 的完整实现。这一类改进参数增量小通常在几万到几十万之间涨点却稳定是“先优化网络哪里”的首选答案。2.3 算子派空洞卷积、可变形卷积、深度可分离不动结构的微调算子派不改网络结构只替换卷基本身。最常见的是空洞卷积通过 dilation rate 在卷积核里填洞不增加参数却扩大了感受野。UNet 原版编码器下采样四次后感受野有限遇到大尺度的目标比如整片道路、大块病灶经常顾此失彼。在中间层串一个 ASPP 或直接把最后一层卷积换成 dilation2 的版本大目标召回率会有明显提升。可变形卷积处理的是形态不规则的目标它给每个采样点学一个偏移量让卷积核贴着目标形状走。代价是计算量大、显存占用高而且当前主流框架对可变形卷积的优化还没普通卷积成熟推理速度可能要打折。深度可分离卷积属于轻量化改进把标准卷积拆成逐通道卷积和逐点卷积模型体积直接缩水一半以上。用在边缘部署场景合适精度通常会小幅下降。算子派的核心判断依据是感受野不够选空洞形状复杂选可变形算力不够选深度可分离。2.4 损失派Dice、Tversky、Focal与边界损失类别不平衡时的关键模型结构没动涨点却可能最明显的一派是改损失函数。UNet 原版常用交叉熵在类别不平衡严重的数据集上前景只占几个百分点交叉熵会让模型偏向预测背景于是精度高但召回极低。Dice 损失直接优化分割重叠度是这一类任务的主流选择。Tversky 损失是 Dice 的变体多了两个超参 alpha 和 beta分别调节假阳性和假阴性的惩罚权重。小目标漏检多就加大 alpha误检多就加大 beta。Focal 损失关注难分样本让模型在背景占比极高的场景下不再“无脑”预测背景。边界损失则通过计算预测掩膜和真实掩膜的距离把注意力拉向边界区域医学影像里腺体、血管这类细长结构很吃这一套。我见过一个实际项目模型结构从 UNet 换到 UNet 都没涨点最后只把 Dice 系数改成 Tverskyalpha0.7、beta0.3DSC 直接涨了 3 个多点。所以模型库里的 37 种改进多数是上面四个方向的两两组合。说明书里最值钱的就是那张选型表按“先看场景再选方向”的方式对应大致如下。改进方向预期收益主要代价适合场景换 Backbone精度上限提升明显改动大、显存上升有预训练权重可用的自然图像轻量卷积算子显存与推理下降精度略降边缘部署、实时分割注意力SE/CBAM涨点稳定、幅度中等FLOPs 小幅增加大多数任务都值得先加ASPP/空洞卷积大目标召回提升小目标可能漏检遥感大场景、道路提取Transformer 分支全局上下文建模强显存与训练时间暴涨小目标多、背景复杂的医学图损失函数调整不增加模型规模超参需要调类别极不平衡前景小于5%3. 三个高频改进模块的PyTorch实现SE-Gate、ASPP与混合损失模型库真正能当工具用的是里面那几个高频模块。我挑了三个最有代表性的SE-Gate、ASPP、DiceCE 混合损失。把它们串起来就等于在 UNet 上同时做了注意力、多尺度结构和损失优化也就是 37 种 unet 改进里最常见的组合套路。3.1 SE-Gate在编码器每层之后插入的通道注意力SE 模块的两个关键操作squeeze 把每张特征图压缩成一个数值excite 用两个全连接层学出通道权重。这里注意一个细节原版用全连接层但放在 UNet 里通常换成 1x1 卷积只减少参数量效果几乎不变。import torch import torch.nn as nn class SEConv(nn.Module): def __init__(self, in_channels, reduction16): super().__init__() self.squeeze nn.AdaptiveAvgPool2d(1) # 用两个1x1卷积替代全连接输入输出尺寸【B, C, 1, 1】 self.excite nn.Sequential( nn.Conv2d(in_channels, in_channels // reduction, 1, biasFalse), nn.ReLU(inplaceTrue), nn.Conv2d(in_channels // reduction, in_channels, 1, biasFalse), nn.Sigmoid() ) def forward(self, x): # x: [B, C, H, W] w self.squeeze(x) # 全局平均池化得到 [B, C, 1, 1] w self.excite(w) # 学习每个通道的重要性 return x * w # 通道加权不改变特征图尺寸逻辑说明forward 里的两个变量写得很直白squeeze 输出的是全局描述符excite 输出的是 0 到 1 之间的通道权重最后乘回原图。这个模块不改变特征图尺寸所以可以随意插入 UNet 的任意层之后不需要调整后续结构。参数说明reduction 是通道压缩比例常见取 16 或 32。取值太大会让瓶颈层丢失信息太小则参数膨胀明显。插入位置建议优先放在编码器最后一层之后或解码器每级上采样之后。我在实际项目中第一个涨点改动就是在编码器每层后面各插一个 SEDSC 普遍提升 0.5 到 1 个点。3.2 ASPP一组不同rate的空洞卷积并行扩大感受野ASPP 的核心思路是把同一个特征图分别用不同 dilation rate 的 3x3 卷积并行处理再拼接起来。rate 小的分支负责精细的局部结构rate 大的分支负责远距离上下文。拼接后通道数会变成 rate 数量乘以单分支输出通道数所以后面通常要再接一个 1x1 卷积做通道压缩。class ASPP(nn.Module): def __init__(self, in_channels, out_channels256, rates(1, 6, 12, 18)): super().__init__() self.branch nn.ModuleList() for r in rates: if r 1: # rate1 等价于普通1x1卷积保留局部细节 conv nn.Conv2d(in_channels, out_channels, 1, padding0, biasFalse) else: # padding 必须等于 rate才能保证输出尺寸不缩水 conv nn.Conv2d(in_channels, out_channels, 3, paddingr, dilationr, biasFalse) self.branch.append(nn.Sequential( conv, nn.BatchNorm2d(out_channels), nn.ReLU(inplaceTrue) )) def forward(self, x): # 每个分支的输出尺寸相同可以直接在通道维拼接 outs [branch(x) for branch in self.branch] return torch.cat(outs, dim1) # [B, len(rates) * out_channels, H, W]逻辑说明这段代码里最容易翻车的是 padding 和 dilation 的关系。普通卷积 padding 是为了保证输出形状等于输入形状而空洞卷积里 padding 必须等于 dilation否则输出尺寸会随着 rate 增大而缩小后续拼接直接炸掉。另外一个细节是 rate1 的分支用 1x1 卷积而不是 3x3 卷积作用相当于一个残差捷径保留原始局部信息这是防止“只看到全局、丢掉细节”的关键。参数说明rates 常用四元组 (1, 6, 12, 18)对应输入尺寸在 256 到 512 之间的场景。如果输入尺寸只有 128rate18 的空洞几乎采样不到有效信息建议压缩成 (1, 3, 6, 9)。out_channels 单分支取 256 是平衡计算和效果的经验值显存紧可以降到 128。使用位置替换 UNet 最底层瓶颈处的普通卷积或者在编码器最后一层的输出后接一组 ASPP再接解码器。3.3 混合损失DiceCE 系数配比与 DSC 指标口径模型库里的训练脚本绝大多数都会配混合损失最常见是 Dice 系数加交叉熵。只套 Dice 损失训练容易收敛到“局部最优”预测掩膜整体形状没问题但边界和背景区域模糊因为 Dice 对每类像素一视同仁缺乏逐像素约束。交叉熵恰好补这个短板。配比一般是一比一类别极不平衡时把 Dice 权重调到 0.7 或 0.8。import torch.nn.functional as F class DiceCELoss(nn.Module): def __init__(self, dice_weight0.5, ce_weight0.5, num_classes2): super().__init__() self.dice_weight dice_weight self.ce_weight ce_weight self.num_classes num_classes def forward(self, pred, target): # pred: [B, C, H, W] 未经过 softmax 的 logits # target: [B, 1, H, W] 或 [B, H, W]值为类别索引 target target.squeeze(1).long() ce F.cross_entropy(pred, target, ignore_index255) p torch.softmax(pred, dim1) # [B, C, H, W] t F.one_hot(target, self.num_classes) # [B, H, W, C] t t.permute(0, 3, 1, 2).float() # 对齐为 [B, C, H, W] inter (p * t).sum(dim(2, 3)) # 每个类别的交集 union p.sum(dim(2, 3)) t.sum(dim(2, 3)) 1e-6 dice (2 * inter / union).mean() # 多类别取平均 return self.dice_weight * (1 - dice) self.ce_weight * ce逻辑说明这个 loss 函数建议直接抄进自己的训练脚本。forward 里第一行 squeeze 是为了兼容“标签通道是 1”的常见做法不会改变实际值。交叉熵用 ignore_index255 可以过滤标注里的无效区域。Dice 部分先把 logits 做 softmax 得到概率再把标签转成 one-hot维度对齐到和预测相同最后按空间维度求和。参数说明dice_weight 和 ce_weight 的和不要求等于 1但建议都保存在中间区间方便调参。我常用的三组配置类别平衡用 0.5/0.5前景占比低于 10% 用 0.7/0.3前景占比低于 3% 用 0.8/0.2 并配合 Focal 损失替代交叉熵。1e-6是平滑项防止某个类别在预测和标签中都不存在时除零。4. 训练验证脚本的用法配置、超参与指标怎么写才不翻车模型库自带训练验证脚本但脚本的默认参数通常是作者在自己的数据集上调出来的直接跑你的数据大概率翻车。这一章讲怎么读懂脚本里的关键参数按你自己的显存、数据量、任务目标做调整。4.1 文件布局与一份最小 YAML 配置大多数 UNet 改进模型库的文件布局是同一套思路模型定义放在 models 目录下base_unet.py 放原始结构improved_blocks.py 放注意力、ASPP 等可插拔模块model_zoo.py 通过一个函数把模块按名称组装起来。训练入口是 train.py推理导出是 predict.py配置文件全部集中在 configs 目录。data: train_img: ./data/train/images train_mask: ./data/train/masks val_img: ./data/val/images val_mask: ./data/val/masks input_size: [512, 512] batch_size: 8 model: name: unet_se_aspp # model_zoo 里注册的组合名 in_channels: 3 num_classes: 2 encoder: resnet34 # 可选项unet / resnet34 / resnet50 attention: se # 可选项none / se / cbam / eca use_aspp: true loss: dice_weight: 0.5 ce_weight: 0.5 train: lr: 0.001 epochs: 120 scheduler: poly warmup: 5 ema: true amp: true seed: 42参数说明input_size 必须是 32 的倍数。UNet 编码器通常下采样 4 次每次乘 2如果输入尺寸不能被 2 的 4 次方整除最后一层特征图尺寸会取整漂移训练不报错但指标会波动。batch_size 以显存为上限建议先用 batch_size8 跑通一个 epoch再往下调。注意 batch_size 是影响 BN 稳定性的关键参数后面避坑章会专门讲。model.name 是组合名常见命名规则是 base 注意力名 多尺度名比如 unet_se_aspp、unet_cbam_transformer。不要自己瞎编组合名先看 model_zoo.py 里注册了哪些名字没有的就要手动组装。loss 参数直接对应第 3.3 节的权重。train.lr 用 0.001 起步encoder 换成 resnet 系列时可以给骨干部分单独设更小的学习率一般是全局学习率的 0.1 倍。4.2 train.py 里的三个关键逻辑poly 衰减、EMA 与早停看一眼 train.py 里学习率调度的实现如果是普通的 StepLR 每隔几十个 epoch 降一次建议改成 poly 策略。poly 是图像分割训练里最稳的衰减方式学习率按剩余 epoch 比例逐步减小没有阶梯跳变长尾收敛更好。# 每个 epoch 开始时调用计算当前学习率 base_lr 0.001 total_epochs 120 current_epoch 10 lr base_lr * (1 - current_epoch / total_epochs) ** 0.9逻辑说明** 0.9是衰减指数控制学习率下降的快慢。指数为 1.0 是线性衰减0.9 让前期稍微多学一会后期收敛更平滑。这是一个纯经验值不需要绑定在特定模型上。EMA 是第二个值得开的选项。它的做法是训练过程中维护一组模型权重的指数移动平均验证和推理时用平均权重而不是最后一个 step 的权重。分割模型训练后期权重在局部最优附近抖动EMA 等效于把抖动平滑掉通常能带来 0.3 到 0.5 个点的 DSC 提升。# 每个 step 更新一次模型参数后同步更新 EMA 权重 ema_alpha 0.999 for name, p in model.named_parameters(): ema_state ema_weights.get(name, p.data.clone()) ema_state.copy_(ema_alpha * ema_state (1 - ema_alpha) * p.data) ema_weights[name] ema_state参数说明ema_alpha 取 0.999 代表当前权重只贡献千分之一历史信息主导适合长训练。如果 epoch 数很少少于 30或者数据量小建议降到 0.99否则 EMA 更新太慢权重还停留在几十个 epoch 之前的平均水平。早停条件建议写成“验证 DSC 在连续 15 个 epoch 内没有刷新最佳记录就停”。不要只看最近几次验证的波动DSC 在小验证集上经常上下跳动 1 个点。停的时候要把最优权重复制一份别让 Emily 停逻辑覆盖掉。4.3 指标记录、最优权重导出与 predict 输出的后处理验证环节每个 epoch 都跑一次太慢常见做法是每 5 个 epoch 验证一次。验证指标至少要记录三类DSC、IoU、HD95。DSC 和 IoU 直接反映掩膜重叠度HD95 反映边界误差医学影像任务特别看重 HD95。# 验证脚本里计算指标的方法 import numpy as np def compute_metrics(pred_mask, true_mask): inter (pred_mask true_mask).sum() union (pred_mask | true_mask).sum() dsc 2 * inter / (pred_mask.sum() true_mask.sum() 1e-6) iou inter / (union 1e-6) # HD95 需要计算两个边界点集的距离可调用 scipy 的 distance_transform_edt return dsc, iou逻辑说明pred_mask 和 true_mask 都是二值化的 0/1 数组。DSC 在数值口径上跟训练损失里的 dice 保持一致注意一个是“越小越好”的损失一个是“越大越好”的指标不要混用。IoU 和 DSC 的差异在于对假阳性、假阴性的权重灵敏度不同一个涨另一个跌的情况很常见记录时两个都要看。predict.py 输出的预测图不要直接保存模型原始 logits。正确做法是先做 argmax 得到类别索引再按数据集类别映射成掩膜颜色最后用 OpenCV 做一次基于连通域的噪声过滤把面积小于某个阈值的零散预测块删掉。这一步能把验证集里看着还行、实际预测满屏小碎点的模型拦下来具体细节在第 5 章讲。5. 避坑unet改进里最容易翻车的5个位置改进模型库踩坑踩得多了会发现八成问题不在模型设计而在工程细节。这里的每条都是真实翻车记录按“现象、原因、解决”写清楚。5.1 换了Encoder之后loss直接不降先查输入归一化现象把 UNet 编码器换成 resnet34 后loss 明显比 baseline 高出一截前几个 epoch 几乎不下降。排查了几轮模型代码都没有问题。原因resnet 系列是拿 ImageNet 预训练的ImageNet 输入归一化要求用固定的 mean 和 std原版 UNet 的数据管道通常只做 0-1 归一化。两者冲突导致预训练权重面向的特征分布和实际输入对不上。解决在数据增强管道里加一行归一化固定用 mean(0.485, 0.456, 0.406)std(0.229, 0.224, 0.225)。这是把预训练权重用起来的默认输入格式换任何一种新 encoder 都先查这里。5.2 验证DSC高实际预测图却碎成一片现象验证集 DSC 到 0.85但把模型接到新测试图上预测掩膜全是小碎块不少是孤立的噪声点。原因DSC 指标本身对零散小区域不敏感只要整体重叠度高就打分高同时训练时后处理只做了阈值二值化没有做连通域过滤。解决predict 阶段先做二值化再用cv2.connectedComponentsWithStats找出每个连通域面积小于图片总面积 0.5% 的块直接删除。这一步通常能过滤掉八成以上噪声。若仍碎把 Dice 损失里的平滑项从 1e-6 调到 1e-4模型不一定能多涨点但预测图会更干净。5.3 batch_size减半就崩BN统计量带崩整条loss曲线现象显存不够把 batch_size 从 8 降到 2loss 曲线开始剧烈震荡验证指标掉得厉害。原因UNet 里的 BN 层统计的是当前 batch 的均值和方差batch_size2 时统计量噪声太大训练和验证时的分布不一致。解决有三种显存允许的话保持 batch 不小于 4不行则做梯度累积用两批 2 张图的梯度累积成等效 4最彻底的做法是把关键 BN 层替换成 GroupNormGroupNorm 对 batch 大小不敏感改一行就能跑。5.4 ASPP中间层rate设到24小目标反而消失现象加了 ASPP 后大目标召回率上去但小目标、细长结构反而丢得厉害对比 feature map 发现小目标的位置被大感受野分支淹没了。原因rate 越大卷积核采样点越稀疏rate24 配合 input_size512单分支的采样点间距已经超过小目标直径只读得到背景读不到目标。解决把 rates 从 (1, 6, 12, 18) 降回 (1, 3, 6, 9)或者在小 rate 分支后面追加一个注意力模块强化局部细节的通道权重。总体上 input_size 小于 256 时rate 最大值不要超过 12。5.5 AMP混合精度下训练loss抖动个别层被float16吃掉现象开了 AMP 自动混合精度后loss 曲线出现周期性尖峰训练几个 epoch 后验证不涨反跌。原因不是所有算子都能在 float16 下稳定计算比如某些归一化和上采样操作在半精度下数值溢出而 loss scaler 又来不及动态调整。解决遇到抖动先关掉 AMP跑 20 个 epoch 确认 baseline 正常要开的话在模型 forward 里对不稳定层单独指定 float32常见做法是在上采样层前加一行x x.float()让该层输入保持单精度。6. 自制第38种改进消融实验、Grad-CAM与基线先行的验证套路6.1 消融实验只认三种写法拿到某个改进模块后判断它对你数据集有没有用只做三组对比加一个、减一个、换一个。加一个是在 baseline 上单独插入模块记录 DSC、IoU、HD95 的变化减一个是从已经涨点的组合里拆掉某个模块验证它是不是不可替代换一个是在同一位置更换同类模块比如把 SE 换成 ECA或者把 ASPP 换成 SPP成本几乎为零但能看出选择是否最优。我习惯记录一张三行四列的表格baseline、加模块 A、加模块 B、AB 组合。每行写 DSC 和显存峰值一眼就能看出模块间是互补还是互斥。37 种改进模型里至少有三分之一在真实数据集上作用重叠消融实验的价值就是帮你把重叠项删掉留下最少的改动实现最大的涨幅。6.2 用Grad-CAM快速检查模块是否真的在“看”目标区域指标之外还要看热力图。Grad-CAM 可以对着最后一层卷积做梯度加权生成一类可视化的注意力热力图。做法是注册一个 forward hook 取最后一层特征图再通过 backward 取梯度把梯度按通道平均后乘回特征图得到粗略的注意力位置。跑通后你很快能发现某些改进模块热力图集中在背景上说明它学到的是背景特征去掉反而更好。我现在拿到新的分割任务第一动作永远是先复现两个强基线原版 UNet 和 UNetSE。两个跑完才对照模型库选方向。这不是保守而是血泪经验。37 种 unet 改进是给你做增量确认的武器库不是让你从零练级的教程。先把基线的指标、显存、收敛速度摸清楚后面所有改进才有参照物。盲目叠模块只会让你连“哪个改动涨的点”都说不清最后停在黑匣子前干瞪眼。希望这套选型、实现和验证的路径能帮你少走这一段弯路。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询