特征矩阵广播中的断言失败:神经网络前向传递中的维度不匹配

问题描述 投票:0回答:1

我正在使用 Eigen 进行线性代数运算,用 C++ 实现神经网络。在

DenseLayer::forward
函数中,我在尝试将偏差向量添加到层的输出矩阵时遇到了维度不匹配问题。

这是我的代码的结构:

  • 输入矩阵的尺寸为 64x74(批量大小 64)。
  • 权重初始化为尺寸 128x784。
  • bias 是维度为 128x1 的列向量。

预期行为:

乘以

input * weights.transpose()
后,我得到一个大小为64x128的输出矩阵。我需要为每一行输出添加偏差,以便最终结果保持 64x128。

目前的做法:

这是转发功能:

Eigen::MatrixXd DenseLayer::forward(const Eigen::MatrixXd& input) {
input_cache = input;
Eigen::MatrixXd output = input * weights.transpose();

// Attempt to replicate bias across rows to match output dimensions
Eigen::MatrixXd bias_replicated = bias.replicate(output.rows(), 1);

output += bias_replicated;
return output;
}

错误信息:

当我运行代码时,遇到以下断言失败:

Assertion failed: (dst.rows() == src.rows() && dst.cols() == src.cols()), function resize_if_allowed, file AssignEvaluator.h, line 754.

我尝试过的:

  • 使用
    .colwise() + bias.col(0)
    .rowwise() + bias.transpose()
    ,并通过不同的重塑/转置直接添加偏差。
  • 我通过调试语句检查了尺寸,并确认输出为 64x128,偏差为 128x1。

问题: 如何在每行输出之间正确广播偏差以执行元素加法,而不会使 Eigen 引发维度不匹配错误?有没有更好的方法来处理 Eigen 中的这种广播,或者我是否遗漏了 Eigen 矩阵加法中的一些基本内容?

调试输出: 为了提供帮助,这里是错误发生之前打印的尺寸:

  • 偏置添加前的输出尺寸:64x128
  • 添加偏差尺寸:128x1
  • 复制偏差大小:64x128

任何有关实现正确广播或解决方法的见解将不胜感激!

c++ matrix neural-network eigen
1个回答
0
投票

这是我修复它的方法

回顾一下问题:

出现断言错误是因为 Eigen 的

.rowwise()
方法要求将偏差视为沿行广播的向量。然而,如果向量不完全符合预期,Eigen 的内部检查通常会标记不匹配,尤其是在
.rowwise()
加法等操作中转置向量。

解决方案:在添加之前将偏差扩展为完整矩阵

为了解决此限制,我在添加偏差之前手动复制了偏差以匹配输出维度,这确保了输出矩阵的每一行都收到偏差向量的副本,使 Eigen 的类型系统满意并避免断言错误。

我更新了forward功能实现:

Eigen::MatrixXd DenseLayer::forward(const Eigen::MatrixXd& input) {
     std::cout << "[DenseLayer Forward] Input size: " << input.rows() << "x" << input.cols() << std::endl;
     std::cout << "[DenseLayer Forward] Weights size: " << weights.rows() << "x" << weights.cols() << std::endl;
     std::cout << "[DenseLayer Forward] Bias size: " << bias.rows() << "x" << bias.cols() << std::endl;

     input_cache = input;
     Eigen::MatrixXd output = input * weights.transpose();

     // Create a matrix of the same size as output, where each row is a copy of the bias vector
     Eigen::MatrixXd bias_expanded = bias.transpose().replicate(output.rows(), 1);

     std::cout << "[DenseLayer Forward] Output before bias addition size: " << output.rows() << "x" << output.cols() << std::endl;
     std::cout << "[DenseLayer Forward] Expanded bias size: " << bias_expanded.rows() << "x" << bias_expanded.cols() << std::endl;

     output += bias_expanded;

     std::cout << "[DenseLayer Forward] Output after bias addition size: " << output.rows() << "x" << output.cols() << std::endl;
     return output;
}

说明:

  1. 偏见的显式复制:
  • bias.transpose().replicate(output.rows(), 1);
    创建一个bias_expanded 矩阵,其中每一行都是bias 的副本。这确保了bias_expanded具有与输出完全相同的尺寸,因此如果输出是64x128,bias_expanded也将是64x128。
  1. 避免
    .rowwise() + bias.transpose()
  • 通过使用这种显式复制,我完全绕过了
    .rowwise()
    。这种方法规避了 Eigen 的广播限制和类型检查问题,使代码更加健壮。
© www.soinside.com 2019 - 2024. All rights reserved.