最大池化(Max Pooling)是卷积神经网络中常用的一种池化技术。其操作是:在输入特征图的一个局部窗口内选取最大的值作为该窗口的输出。
数学表达式如下:
考虑一个输入特征图 A A A,并定义一个大小为 f × f f \times f f×f 的池化窗口和步长 s s s。对于输出特征图 M M M 中的元素 M ( i , j ) M(i,j) M(i,j),其值由以下公式确定:
M ( i , j ) = max u = 0 f − 1 max v = 0 f − 1 A ( i × s + u , j × s + v ) M(i,j) = \max_{u=0}^{f-1} \max_{v=0}^{f-1} A(i \times s + u, j \times s + v) M(i,j)=maxu=0f−1maxv=0f−1A(i×s+u,j×s+v)
其中:
这个公式简单地描述了最大池化的操作:对于每个输出元素 M ( i , j ) M(i,j) M(i,j),都在输入特征图 A A A 的相应局部窗口中找到最大的值。
//最大池化
Eigen::MatrixXf Pooling::maxPoolingForward(const Eigen::MatrixXf& input,int m_poolSize,int m_stride)
{
int outputHeight = (input.rows() - m_poolSize) / m_stride + 1;
int outputWidth = (input.cols() - m_poolSize) / m_stride + 1;
Eigen::MatrixXf output(outputHeight, outputWidth);
for (int i = 0; i < outputHeight; ++i)
{
for (int j = 0; j < outputWidth; ++j)
{
output(i, j) = input.block(i * m_stride, j * m_stride, m_poolSize, m_poolSize).maxCoeff();
}
}
return output;
}
//最大池化 反向
Eigen::MatrixXf Pooling::maxPoolingBackward(const Eigen::MatrixXf& input, const Eigen::MatrixXf& gradient,int m_poolSize,int m_stride)
{
Eigen::MatrixXf output = Eigen::MatrixXf::Zero(input.rows(), input.cols());
int outputHeight = gradient.rows();
int outputWidth = gradient.cols();
for (int i = 0; i < outputHeight; ++i)
{
for (int j = 0; j < outputWidth; ++j)
{
int row,col;
input.block(i * m_stride, j * m_stride, m_poolSize, m_poolSize).maxCoeff(&row,&col);
output(i * m_stride + row, j * m_stride + col) += gradient(i, j);
}
}
return output;
}
平均池化(Average Pooling)是卷积神经网络中另一种常用的池化技术。其操作是在输入特征图的一个局部窗口内计算所有值的平均值,然后将此平均值作为该窗口的输出。
数学表达式如下:
考虑一个输入特征图 A A A,并定义一个大小为 f × f f \times f f×f 的池化窗口和步长 s s s。对于输出特征图 M M M 中的元素 M ( i , j ) M(i,j) M(i,j),其值由以下公式确定:
M ( i , j ) = 1 f × f ∑ u = 0 f − 1 ∑ v = 0 f − 1 A ( i × s + u , j × s + v ) M(i,j) = \frac{1}{f \times f} \sum_{u=0}^{f-1} \sum_{v=0}^{f-1} A(i \times s + u, j \times s + v) M(i,j)=f×f1∑u=0f−1∑v=0f−1A(i×s+u,j×s+v)
其中:
这个公式描述了平均池化的操作:对于每个输出元素 M ( i , j ) M(i,j) M(i,j),都在输入特征图 A A A 的相应局部窗口中计算所有值的平均值。
//平均池化
Eigen::MatrixXf Pooling::averagePoolingForward(const Eigen::MatrixXf& input,int m_poolSize,int m_stride)
{
int outputHeight = (input.rows() - m_poolSize) / m_stride + 1;
int outputWidth = (input.cols() - m_poolSize) / m_stride + 1;
Eigen::MatrixXf output(outputHeight, outputWidth);
for (int i = 0; i < outputHeight; ++i)
{
for (int j = 0; j < outputWidth; ++j)
{
output(i, j) = input.block(i * m_stride, j * m_stride, m_poolSize, m_poolSize).mean();
}
}
return output;
}
// 反向传播对于平均池化比较简单,因为只需要分摊输入梯度到相应的位置。
Eigen::MatrixXf Pooling::averagePoolingBackward(const Eigen::MatrixXf& input,const Eigen::MatrixXf& gradient,int m_poolSize,int m_stride)
{
Eigen::MatrixXf output = Eigen::MatrixXf::Zero(input.rows(), input.cols());
int inputHeight = gradient.rows();
int inputWidth = gradient.cols();
for (int i = 0; i < inputHeight; ++i)
{
for (int j = 0; j < inputWidth; ++j)
{
output.block(i * m_stride, j * m_stride, m_poolSize, m_poolSize).array() += gradient(i, j) / (m_poolSize * m_poolSize);
}
}
return output;
}
更多【机器学习-神经网络系列---池化】相关视频教程:www.yxfzedu.com