CNN计算池化组件
本文介绍了池化操作的基本概念和实现方法。池化是卷积神经网络中的重要操作,通过在输入矩阵上滑动窗口并提取最大值(max pooling)或平均值(average pooling)来降低特征图维度。文章提供了一个基于NumPy的手动池化实现代码,支持2×2池化核和步长2的设置。示例中分别对4×4输入矩阵进行了最大池化和平均池化操作,并展示了运算结果。该实现通过双重循环完成窗口滑动,并使用np.max和
1.引言
前序学习进程中,已经对卷积计算组件有了一定认识。
知晓卷积计算的核心组件要求有一个矩阵,有一个卷积核,卷积核按照步长滑动,在矩阵上选取和自己等大的小矩阵快开展元素相乘再求和的卷积计算。
如果换一种计算方法,不用元素相乘再求和,而是只取最大值或者平均值,这就是池化。
今天主要学习池化。
代码分析
这里直接给出完整代码,然后逐步分析。
# 引入模块
import numpy as np
# 定义池化功能函数
def manual_pooling(input_feature, kernel_size=2, stride=2, pool_type='max'):
"""
手动实现池化操作
参数:
input_feature: 输入特征图(2D数组)
kernel_size: 池化核大小(默认2×2)
stride: 滑动步长(默认2)
pool_type: 池化类型('max' 最大池化 / 'avg' 平均池化)
返回:
output: 池化后的输出特征图
"""
# 获取输入特征图尺寸
h, w = input_feature.shape
# 计算输出特征图尺寸(向下取整,不考虑填充)
out_h = (h - kernel_size) // stride + 1
out_w = (w - kernel_size) // stride + 1
# 初始化输出特征图
output = np.zeros((out_h, out_w))
# 滑动窗口计算池化
for i in range(out_h):
for j in range(out_w):
# 计算当前窗口在输入特征图中的起始位置
start_i = i * stride
start_j = j * stride
# 截取当前窗口的局部区域
window = input_feature[start_i:start_i + kernel_size,
start_j:start_j + kernel_size]
# 根据池化类型计算结果
if pool_type == 'max':
output[i, j] = np.max(window) # 最大池化:取窗口最大值
elif pool_type == 'avg':
output[i, j] = np.mean(window) # 平均池化:取窗口平均值
else:
raise ValueError("池化类型仅支持 'max' 或 'avg'")
return output
# 测试算例
if __name__ == "__main__":
# 输入特征图(4×4)
input_feature = np.array([
[1, 3, 2, 4],
[5, 2, 7, 1],
[3, 6, 8, 5],
[4, 1, 3, 2]
], dtype=np.float32)
# 手动计算最大池化和平均池化
max_pool_result = manual_pooling(input_feature, kernel_size=2, stride=2, pool_type='max')
avg_pool_result = manual_pooling(input_feature, kernel_size=2, stride=2, pool_type='avg')
# 打印结果
print("输入特征图:\n", input_feature, "\n")
print("手动最大池化结果 (2×2核,步长2):\n", max_pool_result, "\n")
print("手动平均池化结果 (2×2核,步长2):\n", avg_pool_result)
因为池化本身是矩阵运算,首先引入必要的numpy模块是基本需求。
然后是输入待池化的矩阵,也就是直接跳到代码的下端,看到这一区域:
测试算例
if name == “main”:
# 输入特征图(4×4)
input_feature = np.array([
[1, 3, 2, 4],
[5, 2, 7, 1],
[3, 6, 8, 5],
[4, 1, 3, 2]
], dtype=np.float32)
# 手动计算最大池化和平均池化
max_pool_result = manual_pooling(input_feature, kernel_size=2, stride=2, pool_type='max')
avg_pool_result = manual_pooling(input_feature, kernel_size=2, stride=2, pool_type='avg')
# 打印结果
print("输入特征图:\n", input_feature, "\n")
print("手动最大池化结果 (2×2核,步长2):\n", max_pool_result, "\n")
print("手动平均池化结果 (2×2核,步长2):\n", avg_pool_result)
这部分给出了待池化矩阵,调用manual_pooling()函数开展了最大值和平均值两种池化计算,最后输出了计算结果。
这样看代码会相对高效,通过main()函数知道代码运算的目标,再尝试找到完成目标需要使用的工具。manual_pooling()函数就是这个工具。
ranhoujiu定义一个manual_pooling()函数:
定义池化功能函数
def manual_pooling(input_feature, kernel_size=2, stride=2, pool_type=‘max’):
“”"
手动实现池化操作
参数:
input_feature: 输入特征图(2D数组)
kernel_size: 池化核大小(默认2×2)
stride: 滑动步长(默认2)
pool_type: 池化类型(‘max’ 最大池化 / ‘avg’ 平均池化)
返回:
output: 池化后的输出特征图
“”"
# 获取输入特征图尺寸
h, w = input_feature.shape
# 计算输出特征图尺寸(向下取整,不考虑填充)
out_h = (h - kernel_size) // stride + 1
out_w = (w - kernel_size) // stride + 1
# 初始化输出特征图
output = np.zeros((out_h, out_w))
# 滑动窗口计算池化
for i in range(out_h):
for j in range(out_w):
# 计算当前窗口在输入特征图中的起始位置
start_i = i * stride
start_j = j * stride
# 截取当前窗口的局部区域
window = input_feature[start_i:start_i + kernel_size,
start_j:start_j + kernel_size]
# 根据池化类型计算结果
if pool_type == 'max':
output[i, j] = np.max(window) # 最大池化:取窗口最大值
elif pool_type == 'avg':
output[i, j] = np.mean(window) # 平均池化:取窗口平均值
else:
raise ValueError("池化类型仅支持 'max' 或 'avg'")
return output
这里的窗口滑动使用for循环逐个选择:
滑动窗口计算池化
for i in range(out_h):
for j in range(out_w):
# 计算当前窗口在输入特征图中的起始位置
start_i = i * stride
start_j = j * stride
# 截取当前窗口的局部区域
window = input_feature[start_i:start_i + kernel_size,
start_j:start_j + kernel_size]
最大值和均值计算调用numpy模块就可以满足:
这里是引用 # 根据池化类型计算结果
if pool_type == ‘max’:
output[i, j] = np.max(window) # 最大池化:取窗口最大值
elif pool_type == ‘avg’:
output[i, j] = np.mean(window) # 平均池化:取窗口平均值
else:
raise ValueError(“池化类型仅支持 ‘max’ 或 ‘avg’”)
代码运行后的输出效果为:
总结
学习了池化操作的基本知识。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)