我正在使用 Eigen 进行线性代数运算,用 C++ 实现神经网络。在
DenseLayer::forward
函数中,我在尝试将偏差向量添加到层的输出矩阵时遇到了维度不匹配问题。
这是我的代码的结构:
预期行为:
乘以
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()
,并通过不同的重塑/转置直接添加偏差。问题: 如何在每行输出之间正确广播偏差以执行元素加法,而不会使 Eigen 引发维度不匹配错误?有没有更好的方法来处理 Eigen 中的这种广播,或者我是否遗漏了 Eigen 矩阵加法中的一些基本内容?
调试输出: 为了提供帮助,这里是错误发生之前打印的尺寸:
任何有关实现正确广播或解决方法的见解将不胜感激!
这是我修复它的方法
回顾一下问题:
出现断言错误是因为 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;
}
说明:
bias.transpose().replicate(output.rows(), 1);
创建一个bias_expanded 矩阵,其中每一行都是bias 的副本。这确保了bias_expanded具有与输出完全相同的尺寸,因此如果输出是64x128,bias_expanded也将是64x128。.rowwise() + bias.transpose()
:.rowwise()
。这种方法规避了 Eigen 的广播限制和类型检查问题,使代码更加健壮。