资讯详情

1x1卷积核详解:从数学原理到工程落地避坑指南

📅 2026/10/17 9:06:24 | 华诺云谱 👁 阅读
1x1卷积核详解:从数学原理到工程落地避坑指南
“1x1卷积”在深度学习项目里是个存在感极高、但往往又说不清到底做了什么的小模块。你会在各种网络结构、开源代码和模型配置文件里反复看到它问别人它有什么用十有八九会得到一句“用来降维”。降维确实是最常见的用法但把它理解成“降维”往往会忽略了这东西的真正价值。这篇文章把1x1卷积核从数学原理、设计动机到工程落地时容易踩的坑一次性梳理透。刚接触卷积网络的读者可以把它当基础补课已经写过模型的朋友也能拿它做一次快速复盘。1. 先搞清楚1x1卷积核到底做了什么运算1.1 从一次具体的前向计算看起一张特征图在送入卷积层前形状通常是(C_in, H, W)也就是有C_in个通道每个通道是一张H×W的二维特征。普通的3×3卷积是拿一个3×3的窗口在图上滑动每个输出位置会聚合以自己为中心、周围一圈共 9 个位置的信息。而1×1卷积的卷积核尺寸是1×1意思是它只看当前位置完全不关心上下左右邻居。输出特征图某个通道在(h, w)位置的值数学上可以写成out[c, h, w] sum_{k0}^{C_in-1} W[c, k] * x[k, h, w] b[c]注意这里的下标输入x的h和w和输出out的h和w是同一个位置。也就是说1×1卷积做的是一件事把同一个空间位置上所有通道的值取出来分别乘以可学习权重后累加最后加偏置。它聚合的是“通道”这个维度上的信息而不是“空间”维度上的信息。举一个更具体的例子。假设输入是 3 个通道输出是 6 个通道。那么每个输出通道本质上就是对 3 个输入通道做一次加权求和6 个输出通道就是 6 组不同的权重。这跟“把三个数字变成六个数字”的线性变换没有任何区别只不过这个变换在每个(h, w)上同时执行。1.2 它本质上是一个逐像素共享权重的全连接层理解了上面的计算就会发现1×1卷积和全连接层之间存在很近的关系。你可以把特征图某个位置上的所有通道值看成是一个长度为C_in的向量。对这个向量做1×1卷积就是把它线性映射到一个长度为C_out的新向量。这个线性映射的权重矩阵是(C_out, C_in)而且最关键的是这个矩阵在所有空间位置上都是共享的。所以一句话总结1×1卷积是对特征图的每个像素位置施加同一个全连接变换。它在每个位置上都做了一次“通道间的信息混合”但不会把附近位置的信息拉进来。用一个生活化的类比辅助理解。想象你有一叠同一时刻拍摄的照片每张照片从不同角度记录了同一个场景这就是通道。3×3卷积会参考某张照片里一个像素周边的内容相当于把局部范围的细节一起考虑。而1×1卷积只对同一像素点上不同照片的“读数”做综合你拿到的仍然是一张逐像素的“汇总表”并没有看到像素点以外的信息。明白这一点后面很多问题都会豁然开朗。比如为什么1×1卷积能改变通道数因为输出向量的长度就是输出通道数。为什么它能融合特征因为它对多个输入通道做了加权组合。为什么它不能带来更大的感受野因为它根本不看周围像素。1.3 与全连接层的等价关系1×1卷积和全连接层的等价性在实际工程里很有利用价值。假设输入特征图形状是(H, W, C_in)如果把它拉平成(H*W, C_in)再送给一个输入维度C_in、输出维度C_out的全连接层那对每个位置而言线性变换矩阵是完全一致的区别只在于卷积实现会在所有位置上共享权重并且保持特征图的空间结构不被破坏。在某些框架里1×1卷积可以用reshape matmul reshape来代替推理引擎也经常会做这种等价替换。不过实际做模型导出或图优化的时候要注意1×1卷积虽然在数学上等价于全连接但很多推理库对这两种算子的底层实现和优化程度完全不同。GPU 上卷积算子通常被优化得很好直接用1×1卷积往往比手动接全连接层更高效。2. 1x1卷积在模型设计中的四大核心用途2.1 通道升维与降维控制计算量的阀门降维是1×1卷积最知名的用途但很多人只记住了“降维”这个结果没搞懂为什么需要降维。核心原因是高分辨率特征图上做大卷积核的计算量非常惊人。假设输入是256个通道输出也是256个通道直接用3×3卷积在一张56×56的特征图上做运算浮点计算量大约是2 * 256 * 256 * 3 * 3 * 56 * 56 ≈ 37.07 亿次这个数字已经不小了。如果网络层数深一点几个这样的卷积叠加训练时间和显存占用都会迅速飙升。但如果我们先用一个1×1卷积把256通道压到64通道再用3×3卷积在64通道上做空间特征提取最后用一个1×1卷积升回256通道三个卷积加起来的总计算量大约只有1×1 (256→64)2 * 256 * 64 * 1 * 1 * 56 * 56 ≈ 1.03 亿次 3×3 (64→64)2 * 64 * 64 * 3 * 3 * 56 * 56 ≈ 2.31 亿次 1×1 (64→256)2 * 64 * 256 * 1 * 1 * 56 * 56 ≈ 1.03 亿次 合计约 4.37 亿次对比之下从约 37 亿次降到了约 4.4 亿次计算量直接缩到原来的八分之一左右。这就是为什么很多深层网络在进入3×3卷积之前会先用1×1做一次降维。说到底1×1卷积像一个阀门在昂贵的空间卷积之前把通道数压小等空间卷积处理完再通过升维把信息恢复到需要的宽度。升维也很常见。有些模块设计里会先把通道数压得很低在低维空间做完非线性变换和特征提取再扩充到更高的通道数。这种先降后升的结构设计本质上是在控制整体计算预算的前提下给网络提供更强的容量。2.2 跨通道特征融合让网络自己决定组合规则卷积网络里每一层都会产生很多通道不同通道往往代表不同的语义信息。有的是边缘响应有的是纹理响应有的可能是某种局部模式。这些信息在后续层里需要被组合成更高层级的语义而组合方式不应该由人来硬设定最好让网络自己学习。1×1卷积正好承担这个角色。因为它每个输出通道都是所有输入通道的加权和权重矩阵完全可学习所以网络可以自由决定“哪些通道的信息要融合”“按什么比例融合”。这和简单的torch.cat拼接不一样。拼接只是把多个特征堆叠到一起信息仍然各自独立后续层再去处理它们而1×1卷积在融合这一步就完成了跨通道的线性交互为之后的非线性激活提供了更有表达力的输入。我在实际项目里感受最明显的一个场景是多尺度特征融合。比如做目标检测时经常把低层高分辨率特征和高层语义特征拼到一起拼完以后如果直接走3×3卷积计算量会很大。更常见的做法是先拼接再用一个1×1卷积把通道数压到一个合适的范围。这个1×1卷积不光是降维它在同一时间完成了两条来源的通道特征融合让模型自己学习低层细节和高层语义之间的权重关系。2.3 代价极低的非线性增强卷积网络需要非线性来逼近任意复杂函数这是常识。但很少有人注意到实际网络中大量非线性其实是在1×1卷积之后引入的。原因很简单1×1卷积参数量极小后面跟一个批归一化和一个 ReLU几乎不增加任何计算负担但能给整个网络带来额外的非线性表达能力。试想如果网络里连续两层都是3×3卷积中间没有任何非线性激活那么这两层在数学上可以合并成一个更大的卷积核。比如两个连续的3×3卷积感受野相当于一个5×5卷积。如果中间有 ReLU就不能这么合并了因为非线性把两个线性操作隔开了。这就是“堆叠 非线性”能够增加表达能力的核心逻辑。而1×1卷积在这个逻辑里的优势是极高的性价比。一个3×3卷积后面接 ReLU 也能增加非线性但它同时会大幅度改变空间信息一个1×1卷积后面接 ReLU几乎不改变空间结构只是在通道维度上做一次非线性映射。所以在很多轻量化模块里1×1 BN ReLU是固定组合用来在不增加太多计算量的情况下加深网络。2.4 代替全连接保留空间信息的分类头与回归头早期的分类网络比如 VGG 风格的结构会把特征图拉平成一长串向量再接几个全连接层输出类别分数。拉平的问题有两个一是参数量巨大二是一旦输入尺寸变化全连接层的输入维度就固定死了。后来的网络设计越来越倾向于用全局平均池化 1×1 卷积来替代这个尾巴。全局平均池化把每个通道压成一个数值特征图变成(C, 1, 1)这时用1×1卷积把通道数从C映射到类别数N再取 softmax。这样做的好处是参数极少而且无论输入尺寸多大输出维度始终只跟通道数相关天然支持不同分辨率的输入。实际在检测模型和分割模型里1×1卷积做 head 的情况更普遍。比如检测框的分类分支通常就是在某个特征图上用1×1卷积输出K * 类别数的结果。它保留了每个空间位置对应的预测让分类头不再依赖全局信息而是可以在多尺度特征图上独立预测。这种使用方式说到底就是让模型在空间位置上“各管各的”而不是把所有位置全部混到一起。尤其对小目标检测这类任务空间信息的保留非常关键1×1卷积作为分类/回归输出层比全连接层要灵活得多。3. 经典网络里1x1卷积的应用脉络3.1 Network in Network第一次明确以1x1为核心1×1卷积的普及绕不开一篇早期的重要工作。它提出了一种思路把微型网络嵌入到卷积层中每次在局部感受野内先对通道做一次非线性映射再去聚合空间信息。这个思路后来被简化为“先用1×1卷积做通道变换再接非线性”这就是我们熟悉的1×1卷积块的雏形。那篇工作还顺带提出了全局平均池化的思路替代了当时分类网络尾部笨重的全连接层。这个组合在后来几乎所有主流网络里都有影子全局平均池化负责把空间信息聚合起来1×1卷积负责做最后的通道映射。可以说今天很多现代网络的基本单元都能追溯到这一步。3.2 Inception系列降维融合一体化真正让1×1卷积名声大噪的是 Inception 系列结构。Inception 块的设计思路是在同一层里并行使用多种尺寸的卷积核分别提取不同感受野的特征最后把结果拼到一起。但问题也随之而来如果每个分支都直接用3×3、5×5卷积通道数一旦放大计算量会爆炸。解决办法就是1×1卷积。在每个分支进入大卷积核之前先做一次降维把通道数压缩到原来的几分之一计算量立刻降下来。同时多个分支输出的特征图要进行拼接拼接后的通道数可能超出了预期再用1×1卷积把维度统一回来。Inception 系列还有一个容易忽略的细节拼接之后接一个1×1卷积能把不同分支的特征在通道维度上做一次全局融合。不同分支感受野不同各自提取的信息类型也不同1×1卷积让网络自己学习如何把不同尺度的信息组合成新特征。这个融合步骤对整体表达能力提升很关键。3.3 ResNet瓶颈块先压缩再做空间卷积ResNet 的两种基本块设计是理解1×1卷积降维价值的最好教材。第一种 basic block 是3×3卷积直接堆叠参数量小适合较浅的网络第二种 bottleneck block 就是典型的“先降后升”结构输入 256 通道 → 1×1 卷积降到 64 通道 → 3×3 卷积64 通道 → 1×1 卷积升到 256 通道为什么这样设计而不直接用3×3卷积在 256 通道上做前面已经算过这笔账在 256 通道上做3×3卷积的计算量大约是在 64 通道上做的 4 倍。经过 bottleneck 压缩以后计算量大幅下降网络就可以在同样的预算下堆到更深。这个设计直接决定了深度残差网络能否在合理资源下训练。所以每当我看到一些朋友把 bottleneck 的1×1层删掉、直接用大卷积核替换时都会提醒他们这不只是“通道数变来变去”的设计冗余它是控制整体计算量的结构性设计。删掉后网络可能仍然能跑但计算量可能直接翻几倍显存占用和训练时间都会显著上升。3.4 轻量网络Depthwise Pointwise 的组合标配到了移动端场景1×1卷积的地位进一步升级。轻量网络的常见做法是把标准卷积分解成两步第一步是 depthwise convolution对每个输入通道分别做3×3空间卷积第二步是 pointwise convolution也就是1×1卷积把所有通道的结果线性组合起来。这种分解的核心逻辑是把“空间特征提取”和“跨通道组合”解耦。depthwise 负责在单通道内看空间局部关系pointwise 负责把多个通道的信息混合。这样做以后计算量只有标准卷积的八分之一左右而表达能力基本能维持。很多轻量网络都延续了这个思路1×1卷积在其中不是边角料而是与 depthwise 并立的半边天。在这个思路的启发下还衍生出了一些更激进的做法比如对1×1卷积也做分组然后通过 channel shuffle 来增强跨组信息流动。你会发现只要想压缩计算量最后基本都会回到1×1卷积这个点上它是通道混合成本最低的通用算子。4. 实操经验、参数计算与避坑清单4.1 参数量与FLOPs到底怎么算1×1卷积的参数计算方式很简单。输入通道数为C_in输出通道数为C_out不考虑分组和偏置时参数量就是C_out * C_in如果考虑偏置就是C_out * C_in C_out。在一张H×W的特征图上计算量大约是2 * C_out * C_in * H * W乘以 2 是因为一次乘法和一次加法分别算一次浮点运算。很多开源库里的 FLOPs 统计包含这个系数也有一些工具给出的是 MACs乘累加次数这时不乘 2。读数值的时候注意工具统计口径不然对比模型复杂度容易闹乌龙。举例来说一个256→64的1×1卷积在56×56特征图上做参数量只有256*64 16384计算量约2*256*64*56*56 ≈ 1.03 亿。而同样输入输出通道数的3×3卷积参数量是256*64*9 147456大约是前者的 9 倍计算量也相应变成 9 倍。这就是1×1卷积的性价比来源。4.2 什么场景适合用什么场景别硬凑1×1卷积是个好工具但也不是哪里都该放。我总结过几种场景帮你在设计网络时快速判断通道数已经很小的时候比如一层的输入输出都是 16 以下再插一个1×1降维收益很小。因为它已经没有多少冗余通道可以压缩了强行加一层只是增加深度但几乎不改变容量。如果你的瓶颈不在计算量而在内存访问或者并行度上1×1卷积带来的理论 FLOPs 下降可能并不等于实际耗时的大幅下降。很多推理引擎里小通道数的1×1卷积很难发挥出理论上的峰值算力因为它有点像“逐点矩阵乘”数据搬运的比重很大。做分类头或回归头时1×1卷积非常好用尤其是在检测分割任务里它天然支持任意输入尺寸同时保留空间位置信息。做通道注意力或类似先降后升的结构时1×1卷积几乎是标配但要注意降维比例。压缩太狠会丢失信息压缩太浅则起不到节省计算的作用。通常 4:1 到 8:1 的压缩比在多数任务里表现比较稳。要想判断自己的网络设计是否合理最直接的办法是画一张每个 stage 的通道数和计算量表看一眼哪些层占用了最多的 FLOPs再决定是否在这些位置插入1×1降维。这不复杂但远比拍脑袋加模块有效。4.3 我在实际项目中踩过的几个坑第一个坑是批归一化与1×1卷积的配合。常见顺序是Conv1x1 - BN - ReLU这个顺序本身没问题。但有些框架在模型转换后对1×1卷积和 BN 的折叠处理不一样。训练好的模型在推理时如果不做 BN 折叠额外消耗的算子可能让推理速度下滑。所以我一般会在导出模型前做一次 preprocessing把 BN 参数折进前面的卷积里。第二个坑是把多个连续的1×1卷积当成深度来堆。如果没有非线性激活两个相邻的1×1卷积完全可以合并成一个它们本质上只是两个线性矩阵相乘。如果在网络里看到1×1 - 1×1中间没有非线性要么这是刻意设计的维度切换要么就是冗余结构。我在模型压缩时会把这种连续线性层合并掉参数量和计算量立刻降一截。第三个坑跟分组卷积有关。1×1卷积同样可以设置groups参数很多人会忽略这一点。分组数大于 1 时每个输出通道只和对应的那组输入通道有关跨组信息被切断。某些轻量网络就是靠分组 channel shuffle 来补偿信息交流的。但如果只是想在几层里加分组1×1降维一定要意识到组间信息会被隔离可能影响精度。第四个坑出现在模型量化环节。1×1卷积本质是矩阵乘量化误差对通道数比较敏感。通道数太少时量化标定不充分精度掉得比3×3层更明显。我遇到过类似问题最后是靠细化校准集、对1×1层单独设置量化参数才把掉点控制在可接受范围。如果你做端侧模型部署这块一定要额外留意。4.4 用一个小实验验证1x1卷积的边界说了这么多不如自己动手验证一次。这里给一个非常简单的小实验用纯1×1卷积堆一个网络来跑 MNIST。下面用 PyTorch 写一个最小版本import torch import torch.nn as nn import torch.nn.functional as F class PureConv1x1(nn.Module): def __init__(self): super().__init__() self.net nn.Sequential( nn.Conv2d(1, 32, kernel_size1, stride1, padding0), nn.ReLU(inplaceTrue), nn.Conv2d(32, 32, kernel_size1, stride1, padding0), nn.ReLU(inplaceTrue), nn.Conv2d(32, 10, kernel_size1, stride1, padding0), nn.AdaptiveAvgPool2d(1), ) def forward(self, x): out self.net(x) return out.view(x.size(0), -1)这个网络里面完全没有3×3卷积每一层只看当前像素点的通道信息。理论上它可以做通道间的非线性组合但它没有任何空间感受野所以如果要直接输入原始图像它几乎无法提取任何空间特征效果会很差。但反过来如果把输入先经过一个普通的3×3卷积来提取局部特征再把后续的通道混合层全部换成1×1卷积效果可能和普通小网络相差不大。这就是1×1卷积的定位它能高效地做跨通道建模但不能替代空间卷积。想明白这一点你就不会再把它当成神秘的“万能降维层”了。我在实际调模型时最深刻的感受是这个模块虽然不起眼却是网络结构里性价比最高的设计之一。很多项目里模型参数和计算量怎么都压不下来往往就是在几个大卷积层前面少了关键的1×1压缩。设计网络或者做模型压缩时我会习惯先把每个 stage 的通道数和 FLOPs 列成一张表再逐一判断哪些位置值得插入或保留1×1卷积。这个习惯帮我解决了不少训练资源紧张、部署性能不达标的问题。如果你也在设计自己的 backbone 或者改动现成网络不妨也试试这个方法。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑