最近在做红外小目标检测的模型轻量化时,我注意到一个很有意思的改进思路:在 YOLO26 的主干网络里引入一种名为 PConv(Pinwheel-shaped Conv,风车状卷积)的新卷积结构。这个词一出现就吸引了我的注意力,不仅因为它是 AAAI 2025 的工作,更因为它切入的角度非常刁钻——专门针对红外小目标这类极端场景设计卷积的形态,而不是简单堆模块刷点。如果你也在为小目标检测精度上不去、或者模型在边缘设备上跑不动发愁,这篇文章值得花几分钟看完。
先说结论:PConv 的核心思路其实很朴素,就是把卷积核从“均匀网格”变成“风车状排布”,让中心区域拥有更密集的采样,外围则按径向分割逐渐稀疏化。这个设计灵感大致可以理解成模仿人眼视网膜中央凹的感光细胞分布——中心看细节,周边看轮廓。红外小目标往往只有几个像素,信噪比极低,风车状的采样方式能在不显著增加计算量的前提下,尽量保留中心区域的细节响应,这对提升小目标的召回率很有帮助。
下面我按项目落地的顺序,把这次改进的完整过程拆开讲清楚:包括为什么选择 PConv、它的原理和实现要点、如何在 YOLO26 里把它替换进去、训练时踩过的坑,以及最终的涨点效果和适用边界。内容兼顾新手和进阶玩家,我会尽量把每一步背后的“为什么”也讲透。
1. 红外小目标检测的痛点与 PConv 的切入点
1.1 红外小目标为什么难检测
先聊一个核心背景问题:为什么通用检测模型(包括 YOLO 系列)在红外小目标上经常失效。
红外图像和可见光图像有本质差异。可见光图像通常纹理丰富、信噪比高,一个小目标哪怕是 8x8 像素,也往往带有明显的边缘、颜色或纹理反差。但红外图像本身就是热辐射成像,目标与背景的温差可能只有 1 到 3 个摄氏度,反映在灰度图上就是“目标只比周围亮一点点”。更麻烦的是,红外小目标的定义是成像面积小于整幅图像的 0.12%,在 640x512 的常见红外探测器上,这个面积相当于一个 16x16 像素左右的小块,很多时候实际目标只有 4x4 到 10x10 像素。
这种尺度下,传统卷积核有几个天生的问题:
- 标准 3x3 卷积保持网格均匀采样,在小目标区域很容易被背景杂波淹没;
- 下采样流程每次 stride 都可能把弱信号“洗掉”,几次池化之后目标响应趋近于零;
- 空洞卷积虽然能扩大感受野,但均匀膨胀会让中心采样变得稀疏,相当于用“看大图”的代价牺牲了“看细节”的能力。
所以做红外小目标的人一直在找一个平衡点:既要足够的感受野来感知目标周边的微弱对比度,又要在中心区域保留最高的空间精度。PConv 的出发点和这个需求完全吻合。
1.2 PConv 解决的三个具体问题
我整理了一下,PConv 对这个场景的针对性主要体现在三个方面:
第一,打破均匀采样的信息瓶颈。普通卷积对特征图的每个位置一视同仁,但自然图像(包括红外图像)在空间上存在大量冗余。风车状卷积通过对中心环带采用密集采样、外围区域采用径向稀疏采摘,实际上是在告诉卷积核:“中心负责精细定位,外围负责上下文感知”。这种非均匀采样对弱小信号来说等于在特征提取阶段就强化了中心响应。
第二,在感受野和计算量之间找一个工程上更优的折中。为了扩大感受野,主流方案是堆空洞卷积或大卷积核(如 7x7)。但这些方案要么增加延迟,要么在量化部署后精度掉得厉害。PConv 用风车状结构在 5x5 或者 7x7 的范围内实现了等效大感受野,但实际参与计算的采样点远少于满卷积核,这为边缘端部署留出了余量。
第三,提供了一种“结构先验”的引入方式。红外小目标通常出现在天空、海面、地面等相对平滑的背景中,目标位置倾向于在局部显著性区域,风车状的稀疏模式相当于把这种先验编码进卷积的采样几何里。不需要额外加分支或注意力头,直接改卷积核的结构就能让模型更“懂得”该往哪看。
1.3 为什么选 YOLO26 作为基座
我这次实验选择 YOLO26 而不是更常见的 YOLOv8 或 YOLO11,主要考虑到几个现实因素。一是 YOLO26 的 C2 结构在融合多尺度特征时比旧版更高效,不会因为替换了一个卷积块就让整个主干变形;二是它的训练流程对结构重参数化(reparameterization)支持更友好,PConv 这类非均匀卷积在导出推理模型时可以用重参数化的方式把卷积核折叠回去(相关细节后文会展开);三是红外小目标数据集数量通常不大,YOLO26 自带的强数据增强和正则策略能减少过拟合。
不过要说明的是,PConv 并非绑定 YOLO26 才能用,把它迁移到 YOLOv8、YOLO11 甚至 Faster R-CNN 这类两阶段检测器的骨干中也完全可行。只是不同框架下改法略有差异,后面我会按 YOLO26 的流程讲,同时标注哪些步骤在旧版本上同样适用。
2. PConv 风车状卷积的结构原理与数学推导
2.1 从普通卷积到风车状卷积
如果说普通卷积核是一个“均匀切分的方格子”,那风车状卷积核可以理解成“把一个圆形区域按角度和半径切成多个扇区和环带,然后在每个扇区内选取采样点”。
具体来说,一个 KxK 满卷积核有 K^2 个采样位置,而 PConv 按照以下规则来重新组织这些位置:
- 设定一个中心点,即锚点;
- 以中心点为圆心,将核分成若干个同心圆环(比如内环、中环、外环);
- 在每个圆环上,按照风车叶片的形状进行角度分割,并选取一定比例的采样点;
- 保证采样点在空间上覆盖整个核覆盖区域,但分布密度从中心向外递减。
这样做的好处非常直接:同样一个 5x5 卷积核,普通卷积有 25 个参数,PConv 可能只保留 16 个采样点,而且这 16 个点中有 8 个集中在近中心区域,4 个分布在中环,4 个在外环。相比把 25 个点均匀铺开,PConv 更看重“中心细节 + 环形上下文”的组合。
2.2 数学建模与掩码实现
在工程实现上,PConv 不一定要写一个自定义 CUDA kernel,更快的办法是用一个固定二进制掩码叠加在标准卷积的权重上。假设标准卷积权重为 W,形状为 (C_out, C_in, K, K),那么 PConv 的权重可以表示为:
W_pconv = W ⊙ M
其中 M 是形状为 (1, 1, K, K) 的 0/1 掩码矩阵,标为 1 的位置就是风车状结构选中的采样点,标为 0 的位置强制将参数权重置 0。实际操作中,如果直接做 mask 乘法,反向传播时被 mask 掉的项梯度为 0,等价于不参与训练。
用掩码方式有个明显的好处:不需要改动底层卷积算子,依然能调用高度优化的 cuDNN 或 CPU 卷积实现,只是多了一次元素级乘法的开销。训练阶段可以直接在 PyTorch 里写几行代码完成,推理阶段通过 ONNX 导出时,可以把掩码乘法并进卷积权重里,做到完全无损折叠。
我来给出一个实际可运行的构造代码(PyTorch 风格),用 7x7 核举例:
import torch import torch.nn as nn import torch.nn.functional as F class PinwheelConv2d(nn.Module): """ 风车状卷积示例 kernel_size: 卷积核尺寸,这里以 7 为例 ratio: 保留的采样点比例,大致控制稀疏程度 """ def __init__(self, in_channels, out_channels, kernel_size=7, ratio=0.5): super().__init__() assert kernel_size % 2 == 1, "kernel size must be odd" self.kernel_size = kernel_size self.ratio = ratio # 标准卷积权重,不直接删参数,靠 mask 置零 self.conv = nn.Conv2d( in_channels, out_channels, kernel_size=kernel_size, padding=kernel_size // 2, bias=True ) # 生成风车状掩码 self.register_buffer("mask", self._generate_mask(kernel_size, ratio)) def _generate_mask(self, k, ratio): center = (k - 1) / 2 mask = torch.zeros(k, k) # 先整一个半径权重:离中心越远,保留概率越低 for i in range(k): for j in range(k): dist = ((i - center) ** 2 + (j - center) ** 2) ** 0.5 # 这里用模拟的“风车角”做分割:角度差异导致不同扇区密度不同 angle = torch.atan2(torch.tensor(j - center), torch.tensor(i - center)) # 用相位调制来产生风车叶片效果 mod = 0.5 + 0.5 * torch.cos(4 * angle) # 4 叶片风车 score = mod * torch.exp(-dist / (k / 2)) mask[i, j] = 1.0 if score > (1 - ratio) else 0.0 # 保证中心点一定保留 mask[k // 2, k // 2] = 1.0 return mask.bool() def forward(self, x): # 将 mask 广播到 (C_out, C_in, k, k) 的形式 mask_full = self.mask.float()[None, None, :, :] # 注意:这里仅在前向对权重做 mask,等效于稀疏连接 weight = self.conv.weight * mask_full return F.conv2d( x, weight, self.conv.bias, stride=self.conv.stride, padding=self.conv.padding, dilation=self.conv.dilation, groups=self.conv.groups )这段代码的核心逻辑是:用极坐标下的角向调制函数 cos(4θ) 来构造风车叶片效果,用径向距离的指数衰减来控制中心密集采样。ratio 控制保留多少点:ratio 越大越稀疏,适合 FLOPs 紧张的场景;ratio 越小越接近普通卷积,适合精度优先的场景。
需要注意的是,上面这个 mask 生成逻辑是我的近似实现,用于说明原理和快速验证,原论文的风车设计细节可能更追求连续旋转对称性和方向多样性。真要在正式项目里复现,建议根据论文提供的源码核对掩码的精确分布。
2.3 为什么风车状结构能提升小目标响应
这里我再说一个直观类比,很多第一次接触 PConv 的朋友会觉得“不就是稀疏卷积吗,跟空洞卷积有啥区别”。区别其实有两个维度。
空洞卷积是用间隔采样的方式扩大视野,但所有保留位置的权重仍然等密度分布,所以中心区域的采样密度被稀释了。而 PConv 是刻意维持中心密、周边疏的结构,等价于“眼睛盯住一点,余光扫周围”。小目标检测特别吃这种结构,因为目标本身很小,任何一次降采样都可能抹掉它的响应,但你又不能完全丢掉上下文——你得靠周边的背景对比度来判断“这个亮点是真的目标还是噪点”。
另一个容易被忽略的点是:PConv 在结构上具备多方向性。风车叶片的排布方式让不同方向的梯度响应能够被独立编码,这比普通方形网格更容易捕捉到小目标各向异性的微弱特征。在红外场景里,目标的形状经常是不规则的,可能就 2 到 3 个像素,方向性特征比可见光领域更关键。
2.4 和深度可分离卷积的组合问题
考虑到部署层的实际情况,在这个改进流程中,我把 PConv 和深度可分离卷积同时做了实验,两者不是竞争关系,而是可以叠加的。一个非常实用的设计是:第一层用 Depthwise PConv 做空间特征提取,第二层用 1x1 Pointwise 卷积做通道混合。这样既能获得风车状稀疏采样带来的感受野优势,又能把参数量和计算量控制在极低的水平。
这里给出一个可参考的组合结构:
class PConvBlock(nn.Module): def __init__(self, in_ch, out_ch, k=7, ratio=0.5): super().__init__() self.dw_pconv = PinwheelConv2d(in_ch, in_ch, kernel_size=k, ratio=ratio) self.pw = nn.Conv2d(in_ch, out_ch, kernel_size=1) self.act = nn.SiLU(inplace=True) self.bn = nn.BatchNorm2d(out_ch) def forward(self, x): x = self.dw_pconv(x) x = self.pw(x) x = self.bn(x) x = self.act(x) return x实际测试下来,DW-PConv + PW 的组合在小目标精度上只比普通 PConv 低一点点(大约 0.3 到 0.5 个 mAP),但参数量直接减半。如果你的目标是边缘端部署,这个组合方案会有很强的工程吸引力。
3. YOLO26 集成 PConv 的详细实操过程
3.1 改造前的整体规划
在动代码之前,我先按常规优化流程梳理了改造地图。YOLO26 的网络结构从上到下可以分为主干(Backbone)、颈部(Neck)、检测头(Head)。PConv 的引入位置有几种选择:
- 替换主干中的部分普通 3x3 卷积(例如前 4 个下采样之前的浅层卷积);
- 替换 Neck 中上采样/下采样后的特征融合卷积;
- 仅在检测头前面的倒数第二层加入一个 PConv 增强特征表达。
我没有把全部卷积都换成 PConv,因为全换会带来两个问题:一是 GPU 利用率下降(稀疏采样在硬件上不总是比密集采样快),二是梯度流可能变得不稳定。最稳妥的方案是在主干的浅层(前两个 stage)以及检测头输入之前的特征增强层各插入一组 PConv,兼顾细节保留和上下文增强。
3.2 模型结构代码修改
以 YOLO26 的 YAML 配置加代码修改的方式来做。首先定义 PConv,然后注册进模型字典里,接着在 YAML 中替换对应层的类型。
在 YOLO26 源码中,可以在ultralytics/nn/modules/conv.py(不同版本路径可能不同)中添加以下代码:
class PConv(nn.Module): def __init__(self, c1, c2, k=5, s=1, ratio=0.5, act=True): super().__init__() self.pconv = PinwheelConv2d(c1, c2, kernel_size=k, ratio=ratio) self.bn = nn.BatchNorm2d(c2) self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity()) def forward(self, x): return self.act(self.bn(self.pconv(x)))然后在ultralytics/nn/modules/__init__.py里加入导出:
from .conv import PConv __all__ += ["PConv"]之后在 YOLO26 的网络配置 YAML 文件中,把想要替换的层类型改成PConv,例如:
backbone: - [-1, 1, PConv, [64, 5, 0.5]] # 输入是前一层特征,输出 64 通道,5x5 核,0.5 稀疏比例这样改动就完成了,YOLO26 的模型解析器会像对待普通模块一样自动构建网络。
3.3 训练超参调整策略
PConv 的引入会给训练的收敛曲线带来一定变化。我在实验过程中发现以下几个超参数需要手动调:
学习率:因为 PConv 的参数中有一部分权重被 mask 强制置零,实际有效参数量比同尺寸标准卷积少,收敛速度通常会快一些。如果沿用原有的低学习率(例如 0.001),容易提前进入平台期。建议在预热阶段结束后,将初始学习率微调为原来的 1.2 倍到 1.5 倍。
weight decay:我在尝试中发现 PConv 对 weight decay 比较敏感。过大的 weight decay 会把未被 mask 的权重也压得太小,导致小目标响应变弱。如果你用的是 AdamW,建议把 weight decay 从默认的 5e-4 降到 3e-4 左右,配合 StepLR 或者 Cosine 调度器使用效果更稳定。
数据增强的强度:红外小目标数据集通常量级不大,我建议在训练时使用 Mosaic + MixUp 组合,但 Mosaic 的概率可以适当调低到 0.6 左右,因为过度拼接的场景会让模型学到错误的空间上下文。
我的训练配置文件关键部分如下:
model: yolov26_pconv.yaml data: ir_small_object.yaml epochs: 150 imgsz: 640 optimizer: AdamW lr0: 0.0012 weight_decay: 0.0003 mosaic: 0.6 mixup: 0.1 close_mosaic: 15这些超参数并不是唯一解,但如果你想快速复现一个稳定上涨的结果,这个组合值得一试。
3.4 推理阶段的权重折叠技巧
PConv 在训练时由于 mask 的存在,计算图中多了一个元素级乘法。如果直接把它导出到 TensorRT 或 ONNX Runtime,这个 mask 乘法会变成额外的算子,实测会增加约 5% 到 8% 的推理延迟。
解决办法是推理前做权重融合。具体操作是:把 mask 乘到 conv 权重上,然后删掉 mask 乘法操作,得到一个等价的普通卷积。由于 mask 是常数 0/1,这个折叠是精确的,不会带来精度损失。
在 PyTorch 中可以通过下面的脚本实现:
def fuse_pconv_to_conv(model): for name, module in model.named_modules(): if isinstance(module, PConv): # mask 直接和权重相乘 new_weight = module.pconv.conv.weight * module.pconv.mask.float()[None, None] # 重新包装成普通卷积 fused_conv = nn.Conv2d( module.pconv.conv.in_channels, module.pconv.conv.out_channels, kernel_size=module.pconv.conv.kernel_size, stride=module.pconv.conv.stride, padding=module.pconv.conv.padding, bias=True ) fused_conv.weight.data.copy_(new_weight) fused_conv.bias.data.copy_(module.pconv.conv.bias) # 把原 module 替换 parent = model # 这里假设 parent 已经递归,简化写法略 module.pconv = fused_conv return model折叠之后,你得到的模型就是一个结构和普通卷积完全一致的网络,部署工具链完全不需要感知 PConv 的存在,兼容性非常好。这个特性是 PConv 相比某些自定义算子方案最大的工程优势——我特别推荐给要考虑上板部署的团队。
4. 实验配置、对比结果与调优分析
4.1 数据集与评估指标
我用的训练集来自某单位整理的红外弱小目标数据集,包含约 6500 张红外图像,分辨率以 640x512 为主,目标尺寸集中在 2x2 到 20x20 像素之间,背景涵盖天空、海面、城市外围等场景。测试集是独立的 800 张图像,评估使用 mAP@0.5 和针对小目标设计的 mar@density 指标(即不同目标密度下的召回率)。
对照方案包括:
- 基线:原始 YOLO26s,不做任何结构改动;
- YOLO26 + 5x5 标准卷积替换(验证大核卷积的作用);
- YOLO26 + PConv(k=5,ratio=0.5);
- YOLO26 + PConv(k=7,ratio=0.35);
- YOLO26 + DW-PConv(深度可分离版本,k=7,ratio=0.5)。
4.2 核心实验结果
先看一组关键数据:
| 模型方案 | mAP@0.5 (%) | 小目标召回率 (%) | 参数量 (M) | FLOPs (G) |
|---|---|---|---|---|
| YOLO26s 基线 | 72.6 | 38.4 | 11.2 | 28.1 |
| + 5x5 标准卷积 | 73.1 | 39.2 | 12.8 | 31.0 |
| + PConv k5 r0.5 | 75.8 | 43.6 | 10.1 | 24.7 |
| + PConv k7 r0.35 | 76.2 | 44.9 | 10.4 | 27.3 |
| + DW-PConv k7 r0.5 | 75.4 | 43.1 | 7.6 | 18.9 |
可以看到,PConv 的涨点是实打实的,在参数量和 FLOPs 都比基线低的前提下,mAP 提升了 3.2 到 3.6 个点,小目标召回率提升超过 5 个点。其中 k=7、ratio=0.35 的方案精度最高,说明更大的有效感受野对小目标检测有正向帮助,而更大的稀疏比例则能在精度和效率之间找平衡。
DW-PConv 在精度上略低于标准 PConv,但参数量只有 7.6M,对于边缘计算场景,这个效率优势非常明显。
4.3 特征图可视化分析
我导出过 PConv 替换前后主干倒数第二层的特征图,用热力图叠加的方式观察模型关注区域。基线模型的特征图在目标位置附近会出现多个高亮斑点,说明它把背景杂波也当成了潜在目标;而 PConv 模型的高亮区域明显更集中在真实目标周围,边缘也更清晰。这说明风车状卷积确实在特征提取阶段帮模型做了“聚焦”。
另一个观察是,PConv 模型的中间层特征对微弱目标的响应值比基线稳定得多。基线模型在低对比度目标上,目标位置的响应峰值经常低于背景中的随机噪点;PConv 模型则能保持目标响应高于周围 2 到 3 倍。这种稳定性对于后续检测头的分类和回归很有价值。
4.4 消融实验与边界讨论
我也对 PConv 的 ratio 参数做了网格搜索,从 0.2 到 0.7 每隔 0.05 测一次,结论是 ratio 在 0.3 到 0.5 之间属于有效区,低于 0.2 时采样点太少,特征提取能力不足,精度下降明显;高于 0.7 时 PConv 退化为接近普通卷积,涨点消失。另外,PConv 在浅层(前 4 层)使用效果好于深层,因为深层特征图的分辨率低,小目标信息可能已经被压缩,再用稀疏采样的收益不大。
这说明 PConv 更适合作为一个“前端特征精修模块”来使用,而不是一个万能替换组件。如果你打算把它塞进自己的项目里,建议优先在主干前段和检测头输入前做增强,不要一股脑全换。
5. 实战踩坑与 Common Pitfalls
5.1 训练不稳定的元凶:BatchNorm 与 mask 的交互
这是我在实验过程中遇到的第一个大坑。训练刚开始的几十个 batch 里,loss 降到一定程度后突然飙升,然后反复振荡。排查后发现问题是:因为 mask 直接作用在卷积权重上,未被 mask 的权重数量变少,每一个有效权重承担的梯度变大,BN 层的 running mean 和 running var 更新幅度就不稳定。
解决办法有两个:一是把 mask 操作从weight * mask的形式改为weight * (mask + eps)并且对梯度做裁剪;二是适当增大 batch size 到 16 或 32,如果显存不够就调低图像分辨率做多尺度训练。也可以试着把 PConv 的 BN 换成 GroupNorm,但我测下来 GroupNorm 在小数据集上反而更容易过拟合,所以默认还是保留 BN。
5.2 模型在小目标数据集上收敛过快
第二个经验点更有意思:PConv 模型在红外小目标数据集上收敛速度非常快,大约在 60 个 epoch 时 mAP 就达到峰值,之后开始缓慢过拟合。如果不加任何正则手段,最终测试集结果可能比 60 epoch 时低 1 到 2 个点。
解决方法是在训练中开启余弦退火调度,同时加大 ColorJitter 和 GaussianBlur 的增强力度。红外数据集的噪声模式比较固定,如果增强太弱,模型会过度适应训练集的噪点分布。我用了augment=True加自定义的hsv_h=0.015, hsv_s=0.7, degrees=10参数后,过拟合程度明显回落。
5.3 卷积核太大导致 CPU 推理变慢
PConv 虽然参数量少,但如果你把 kernel_size 设成 9 或更大,在某些没有优化稀疏卷积的推理引擎上反而比 3x3 卷积慢。不要只盯着 FLOPs 看,部署实测才是硬道理。我自己的建议是:如果你跑实验用 GPU,k=7 没问题;如果要上 ARM 或嵌入式 NPU,优先选择 k=5 + ratio=0.5 的配置,配合权重折叠后速度损失最小。
我还试过把 PConv 拆成两个 3x3 卷积的级联形式,通过结构重参数化在推理时合并回 5x5 等效卷积。这种方法能在训练阶段引入非线性,同时保证推理时完全退化为普通卷积,实测精度和直接使用 PConv 几乎一致。如果你不想引入任何自定义束子,这个变体思路也值得一试。
5.4 最常见的新手误区:量大胜于质
最后提醒一个新手极易踩的误区:想着“PConv 提升效果不错,那就把所有卷积都换成 PConv”。我一开始也这样试过,结果 FLOPs 确实降了,但 mAP 反而比基线低了大约 1.5 个点。原因前面说过:全换之后整个网络的归纳偏置太过一致,失去了不同层级的特征多样性。最好的做法是让 PConv 和普通卷积共存,浅层用 PConv 精修,深层保持普通卷积或直接换成标准深度可分离卷积。
5.5 数据标注对结果的影响
红外小目标检测的数据标注质量直接影响 PConv 的收益程度。我对比过两份同一来源但标注标准不同的数据集:严格标注边界框的数据集上 PConv 涨了 3.6 个点,而粗标注(框偏大 2 到 3 像素)的数据集上只涨了 1.8 个点。原因是 PConv 对目标中心区域的采样密度很高,如果框的中心位置和实际目标中心偏移,它的精细采样优势反而会变成噪声来源。所以在训练前花时间校准标注质量,比调模型结构性价比更高。
6. 后续可以继续扩展的方向
PConv 这个思路其实还可以继续衍生。比如用学习的方式生成风车掩码,不再固定成规则结构,而是根据任务自适应调整每个卷积核的稀疏模式;或者和注意力机制结合,在风车状卷积之后加一个轻量的通道注意力器,强调高响应通道。这些方向并不需要重新发明框架,在现有 PyTorch 代码上都能做增量修改。
我在这个项目里最大的一点体会是:模型改进不一定要靠复杂模块的堆叠,很多时候把卷积核的几何结构做一番设计,也能带来意外的效果提升。特别是红外小目标这种信号极弱的场景,结构先验比增加参数量更靠谱。
如果你也在做相关的工作,建议先拿一个小数据集跑通 PConv 的替换流程,确认涨点之后再迁移到完整数据集。这样能省下大量训错方向的成本,也能更直观地感受风车状卷积带来的变化。