GTWR插件 error: matrix multiplication: inverse of singular matrix

本文探讨了在数据处理中遇到奇异矩阵问题的原因,包括解释变量过多或样本量不足等情况,以及如何通过调整样本量或减少变量数量来解决这一问题。

error: matrix multiplication: inverse of singular matrix; suggest to use solve() instead
在这里插入图片描述
singular matrix为奇异矩阵

【设A为n阶方阵,若存在另一n阶方阵B,使得AB=BA=I,则称A为非奇异矩阵,若不存在,则为奇异矩阵。
当exogenous variable 中虚拟变量过多,可能产生singular matrix或near singular matrix,表示这些变量间存在较大相关性。
在数据处理时,控制变量个数太多而样本量太小(损耗过多自由度,尤其是在时间序列中,若时间窗口较窄),都有可能出现奇异矩阵的问题。
要改变的话只有增加样本量或减少解释变量的个数】

#include "CMatrix.h" #include <algorithm> #include <cmath> #include <iomanip> const double EPSILON = 1e-10; // 浮点数精度阈值 // 构造函数 CMatrix::CMatrix() : rows(0), cols(0) {} CMatrix::CMatrix(size_t r, size_t c, double initVal) : rows(r), cols(c), data(r, std::vector<double>(c, initVal)) {} CMatrix::CMatrix(const std::vector<std::vector<double>>& d) { if (d.empty() || d[0].empty()) throw std::invalid_argument("Invalid matrix dimensions"); rows = d.size(); cols = d[0].size(); data = d; } // 拷贝构造函数 CMatrix::CMatrix(const CMatrix& other) : rows(other.rows), cols(other.cols), data(other.data) {} // 赋值运算符 CMatrix& CMatrix::operator=(const CMatrix& other) { if (this != &other) { rows = other.rows; cols = other.cols; data = other.data; } return *this; } // 调整矩阵大小 void CMatrix::resize(size_t newRows, size_t newCols, double initVal) { data.resize(newRows); for (auto& row : data) { row.resize(newCols, initVal); } rows = newRows; cols = newCols; } // 矩阵加法 CMatrix CMatrix::operator+(const CMatrix& rhs) const { if (rows != rhs.rows || cols != rhs.cols) { throw std::invalid_argument("Matrix dimensions do not match for addition"); } CMatrix result(rows, cols); for (size_t i = 0; i < rows; ++i) { for (size_t j = 0; j < cols; ++j) { result.data[i][j] = data[i][j] + rhs.data[i][j]; } } return result; } // 矩阵减法 CMatrix CMatrix::operator-(const CMatrix& rhs) const { if (rows != rhs.rows || cols != rhs.cols) { throw std::invalid_argument("Matrix dimensions do not match for subtraction"); } CMatrix result(rows, cols); for (size_t i = 0; i < rows; ++i) { for (size_t j = 0; j < cols; ++j) { result.data[i][j] = data[i][j] - rhs.data[i][j]; } } return result; } // 矩阵乘法 CMatrix CMatrix::operator*(const CMatrix& rhs) const { if (cols != rhs.rows) { throw std::invalid_argument("Matrix dimensions do not match for multiplication"); } CMatrix result(rows, rhs.cols); for (size_t i = 0; i < rows; ++i) { for (size_t k = 0; k < cols; ++k) { for (size_t j = 0; j < rhs.cols; ++j) { result.data[i][j] += data[i][k] * rhs.data[k][j]; } } } return result; } // 标量乘法(右乘) CMatrix CMatrix::operator*(double scalar) const { CMatrix result(*this); for (auto& row : result.data) { for (double& elem : row) { elem *= scalar; } } return result; } // 标量除法 CMatrix CMatrix::operator/(double scalar) const { if (std::abs(scalar) < EPSILON) throw std::invalid_argument("Division by zero"); return *this * (1.0 / scalar); } // 矩阵除法(乘以逆矩阵) CMatrix CMatrix::operator/(const CMatrix& rhs) const { return *this * rhs.inverse(); } // 转置 CMatrix CMatrix::transpose() const { CMatrix result(cols, rows); for (size_t i = 0; i < rows; ++i) { for (size_t j = 0; j < cols; ++j) { result.data[j][i] = data[i][j]; } } return result; } // 高斯消元法(全选主元) void CMatrix::gaussianElimination(std::vector<std::vector<double>>& mat, bool fullPivot) const { size_t n = mat.size(); for (size_t i = 0; i < n; ++i) { // 寻找主元 size_t maxRow = i, maxCol = i; double maxVal = std::abs(mat[i][i]); if (fullPivot) { for (size_t r = i; r < n; ++r) { for (size_t c = i; c < n; ++c) { if (std::abs(mat[r][c]) > maxVal) { maxVal = std::abs(mat[r][c]); maxRow = r; maxCol = c; } } } // 交换行和列 if (maxRow != i) std::swap(mat[i], mat[maxRow]); if (maxCol != i) { for (size_t r = 0; r < n; ++r) { std::swap(mat[r][i], mat[r][maxCol]); } } } // 消元 for (size_t j = i + 1; j < n; ++j) { double factor = mat[j][i] / mat[i][i]; for (size_t k = i; k < mat[j].size(); ++k) { mat[j][k] -= factor * mat[i][k]; } } } } // 求逆 CMatrix CMatrix::inverse() const { if (rows != cols) throw std::invalid_argument("Only square matrices can be inverted"); size_t n = rows; std::vector<std::vector<double>> augMat(n, std::vector<double>(2 * n, 0.0)); // 构造增广矩阵 [A | I] for (size_t i = 0; i < n; ++i) { for (size_t j = 0; j < n; ++j) { augMat[i][j] = data[i][j]; } augMat[i][n + i] = 1.0; } // 高斯-约当消元 gaussianElimination(augMat, true); // 回代 for (int i = n - 1; i >= 0; --i) { double diag = augMat[i][i]; if (std::abs(diag) < EPSILON) throw std::runtime_error("Matrix is singular"); for (size_t j = 0; j < 2 * n; ++j) { augMat[i][j] /= diag; } for (int k = i - 1; k >= 0; --k) { double factor = augMat[k][i]; for (size_t j = 0; j < 2 * n; ++j) { augMat[k][j] -= factor * augMat[i][j]; } } } // 提取逆矩阵 CMatrix inv(n, n); for (size_t i = 0; i < n; ++i) { for (size_t j = 0; j < n; ++j) { inv.data[i][j] = augMat[i][j + n]; } } return inv; } // 求秩 size_t CMatrix::rank() const { std::vector<std::vector<double>> temp = data; gaussianElimination(temp); size_t rk = 0; for (size_t i = 0; i < rows; ++i) { bool nonZeroRow = false; for (size_t j = 0; j < cols; ++j) { if (std::abs(temp[i][j]) > EPSILON) { nonZeroRow = true; break; } } if (nonZeroRow) ++rk; } return rk; } // 标量乘法(左乘) CMatrix operator*(double scalar, const CMatrix& matrix) { return matrix * scalar; } // 输出运算符 std::ostream& operator<<(std::ostream& os, const CMatrix& matrix) { for (size_t i = 0; i < matrix.rows; ++i) { for (size_t j = 0; j < matrix.cols; ++j) { os << std::setw(10) << matrix.data[i][j] << " "; } os << std::endl; } return os; } // 输入运算符 std::istream& operator>>(std::istream& is, CMatrix& matrix) { size_t r, c; is >> r >> c; matrix.resize(r, c); for (size_t i = 0; i < r; ++i) { for (size_t j = 0; j < c; ++j) { is >> matrix.data[i][j]; } } return is; } 简介缩短一点
最新发布
12-31
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Prophet.Z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值