转换知识基础
图像中使用的卷积一般为,正方形卷积核针对一个同等面积邻域的,进行相乘后邻域叠加到中心,相当于考虑中心像素的周围信息,做了一定的信息融合。
卷积相关参数
卷积前: input c1
卷积中: kernel 卷积核 stride 步长 padding 填充 group 分组卷积 w预训练权重
卷积后: BN 归一化 act 激活函数
SAME: 相同的PAD
VALD: 不做任何填充
SAME和VASLID的优劣对比
总结:stride=1
时使用 "SAME"
的优势
维度 | 说明 |
---|---|
输出尺寸稳定 | 保持输入与输出尺寸一致,避免网络深层特征图过度缩小。 |
对称填充保证 | 自动计算对称填充量,与 PyTorch 的默认行为对齐,便于模型迁移。 |
代码简洁性 | 无需手动计算和添加填充层,减少冗余代码。 |
计算效率 | 框架原生优化填充操作,通常比手动填充更高效。 |
附:不同参数下的填充行为对比表
参数 | stride=1 + "SAME" | stride=2 + 手动填充 + "VALID" |
---|---|---|
输出尺寸 | 与输入相同 | 按公式 ⌊H+2p−ks⌋+1⌊sH+2p−k⌋+1 计算 |
填充方式 | 自动对称或轻微不对称 | 手动对称填充 |
跨框架一致性 | 与 PyTorch 的 padding=k//2 对齐 | 强制对齐 PyTorch 的填充逻辑 |
典型应用场景 | 密集特征提取(如残差块) | 下采样(如网络前半部分) |
# 注释版本 2025 03 10
class TFConv(keras.layers.Layer):"""实现标准卷积层,可选批归一化与激活函数,适用于TensorFlow。"""def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True, w=None):"""参数说明:c1 (int): 输入通道数(代码中未直接使用,可能通过权重自动推断)c2 (int): 输出通道数(即卷积核数量)k (int/tuple): 卷积核尺寸,默认为1s (int/tuple): 卷积步长,默认为1p (int/tuple/None): 填充大小,None时自动计算为k//2g (int): 分组卷积组数,默认1(代码支持但原注释提示可能限制)act (bool/str): 是否使用激活函数,默认Truew (object): 预训练权重对象,包含卷积和BN参数"""super().__init__()# 当步长s=1时使用"SAME"填充,否则手动填充后使用"VALID"卷积以对齐PyTorch行为# 创建Conv2D层,配置参数conv = keras.layers.Conv2D(filters=c2,kernel_size=k,strides=s,padding="SAME" if s == 1 else "VALID", # s=1用自动填充,s>1需手动填充use_bias=not hasattr(w, "bn"), # 存在BN层时禁用偏置groups=g, # 分组卷积参数(需确认TF版本支持性)kernel_initializer=keras.initializers.Constant(w.conv.weight.permute(2, 3, 1, 0).numpy() # 调整PyTorch权重维度到TF格式 (kH, kW, in, out)),bias_initializer="zeros" if hasattr(w, "bn") else keras.initializers.Constant(w.conv.bias.numpy()),)# 组合层:当s>1时,先填充再卷积self.conv = conv if s == 1 else keras.Sequential([TFPad(autopad(k, p)), conv]) # 自定义填充层处理非1步长# 批归一化层(存在BN参数时)或恒等映射self.bn = TFBN(w.bn) if hasattr(w, "bn") else tf.identity# 激活函数(根据act参数选择)或恒等函数self.act = activations(w.act) if act else tf.identitydef call(self, inputs):"""执行卷积、批归一化与激活函数的前向传播"""return self.act(self.bn(self.conv(inputs))) # 顺序: Conv -> BN -> Act