一维卷积通过滑动窗口实现,输出长度为(N+2×P−F)÷S+1(向下取整);以input=[1,2,3,4,5]、kernel=[1,0,−1]为例,padding=0、stride=1时输出为[−2,−2,−2]。

用数组实现卷积运算,核心是把卷积核(filter)在输入数组上逐位置滑动,每滑一次就做一次对应元素的乘加运算。关键不在“写多复杂”,而在理清滑动窗口的起止边界、索引映射关系和输出尺寸推导逻辑。
明确输入、卷积核与输出的尺寸关系
设输入数组长度为 N,卷积核长度为 F,步长(stride)为 S,填充(padding)为 P(两端各补 P 个零),则输出长度为:
(N + 2×P − F) ÷ S + 1(结果向下取整,要求分子 ≥ 0)
常见情况举例:
- 无填充、步长为1:输出长度 = N − F + 1
- 输入 [1,2,3,4,5],核 [1,0,−1],则输出长度 = 5 − 3 + 1 = 3
- 若核越界(如当前位置 i=0 时想取 input[-1]),必须靠 padding 或直接跳过——实际编码中应先确保索引合法
手动模拟滑动窗口的索引提取过程
以输入 input = [1,2,3,4,5]、核 kernel = [1,0,−1]、stride=1, padding=0 为例:
- 窗口 0:覆盖 input[0:3] → [1,2,3],计算 1×1 + 2×0 + 3×(−1) = −2
- 窗口 1:覆盖 input[1:4] → [2,3,4],计算 2×1 + 3×0 + 4×(−1) = −2
- 窗口 2:覆盖 input[2:5] → [3,4,5],计算 3×1 + 4×0 + 5×(−1) = −2
注意:Python 切片 input[i:i+F] 天然对应第 i 个窗口;其他语言需用循环或指针偏移模拟该区间。
用纯数组代码实现一维卷积(无框架依赖)
以下为可直接运行的 Python 示例(思路通用,其他语言只需改语法):
def conv1d(input_arr, kernel, stride=1, padding=0):
# 补零
padded = [0]*padding + input_arr + [0]*padding
N, F = len(padded), len(kernel)
out_len = (N - F) // stride + 1
if out_len result = []
for i in range(0, out_len * stride, stride):
window = padded[i:i+F]
s = sum(window[j] * kernel[j] for j in range(F))
result.append(s)
return result
测试
print(conv1d([1,2,3,4,5], [1,0,-1])) # 输出: [-2, -2, -2]
要点说明:
- padding 后统一处理索引,避免边界判断分散逻辑
- 外层循环用 range(0, out_len × stride, stride) 确保每次移动 stride 步
- 内层用 zip(window, kernel) 或索引对齐均可,重点是位置一一对应
二维卷积只需扩展索引维度
图像卷积本质是二维滑动窗口。输入为 H×W 矩阵,核为 F×F,则:
- 每个输出点 (i,j) 对应输入区域:input[i:i+F, j:j+F]
- 双层循环控制 i 和 j(步长仍可设为 >1)
- 窗口内做 F×F 次乘加,等价于两个二维数组的逐元素相乘再求和
例如 OpenCV 中 cv2.filter2D() 底层就是这类遍历;深度学习框架如 PyTorch 的 nn.Conv2d 在训练时会将这种滑动展开为矩阵乘法(im2col),但原理起点仍是窗口提取。










