多项式回归和Lasso多项式回归都是用于建模数据关系的方法,但它们在实现方式和目标上有一些重要的区别。以下是它们的主要区别:
1. 基本概念
-
多项式回归:
-
多项式回归是一种线性回归的扩展,它通过引入多项式特征(如
,
,…)来捕捉数据中的非线性关系。
-
其目标是拟合一个多项式方程
,其中 n 是多项式的阶数。
-
多项式回归的核心是将非线性问题转化为线性问题,通过增加多项式特征来提高模型的拟合能力。
-
-
Lasso多项式回归:
-
Lasso(Least Absolute Shrinkage and Selection Operator)回归是一种正则化的线性回归方法,它在损失函数中引入了 L1 正则化项。
-
当应用于多项式回归时,Lasso多项式回归不仅考虑多项式特征,还会通过 L1 正则化来约束模型的复杂度,避免过拟合。
-
Lasso回归的损失函数为:
其中,
是正则化参数,
是模型系数,L1 正则化会惩罚系数的绝对值。
-
2. 模型复杂度和过拟合
-
多项式回归:
-
多项式回归的一个主要问题是容易过拟合,尤其是当多项式的阶数较高时。
-
高阶多项式会过度拟合训练数据中的噪声,导致模型在新数据上的泛化能力较差。
-
-
Lasso多项式回归:
-
Lasso回归通过 L1 正则化来约束模型的复杂度,能够自动选择重要的特征(即系数不为零的特征),并将不重要的特征系数压缩到零。
-
这种稀疏性有助于减少模型的复杂度,降低过拟合的风险,同时提高模型的可解释性。
-
3. 特征选择
-
多项式回归:
-
多项式回归本身不具有特征选择能力。它会使用所有生成的多项式特征来拟合模型,无论这些特征是否对目标变量有实际影响。
-
-
Lasso多项式回归:
-
Lasso回归具有特征选择的能力。由于 L1 正则化会将一些系数压缩到零,因此可以自动筛选出对目标变量影响较大的特征,同时忽略不重要的特征。
-
这种特性使得Lasso多项式回归在处理高维数据时更加高效,尤其是在特征数量较多的情况下。
-
4. 模型的可解释性
-
多项式回归:
-
多项式回归的可解释性较差,尤其是当多项式的阶数较高时。模型可能包含许多复杂的高阶项,难以直观理解每个特征对目标的影响。
-
-
Lasso多项式回归:
-
Lasso回归通过稀疏性提高了模型的可解释性。由于一些特征的系数被压缩到零,模型中只保留了重要的特征,使得模型更易于解释。
-
5. 应用场景
-
多项式回归:
-
适用于数据具有明显非线性关系的场景,且对模型的复杂度和过拟合风险不敏感。
-
例如,拟合某些物理或化学过程中的非线性关系。
-
-
Lasso多项式回归:
-
适用于特征数量较多且可能存在冗余的场景,尤其是在需要进行特征选择和提高模型泛化能力的情况下。
-
例如,在生物医学数据分析或金融数据分析中,数据可能包含大量特征,但只有少数特征对目标变量有显著影响。
-
总结
-
多项式回归和Lasso多项式回归的主要区别在于Lasso回归引入了 L1 正则化,从而具备了特征选择能力和对过拟合的抑制能力。
-
如果数据存在明显的非线性关系且特征数量较少,多项式回归可能是一个不错的选择;但如果数据特征较多且需要进行特征选择和提高模型泛化能力,Lasso多项式回归则更为合适。
一个具体的例子
输入一组数据,N行10列,其中前3列为自变量,后7列为因变量。通过多项式Lasso函数拟合,实现任意给定3维自变量,输出7维向量。
#include <iostream>
#include <Eigen/Dense>
//#include <unsupported/Eigen/NonLinearOptimization>
#include <cmath>// 软阈值函数
double softThreshold(double x, double lambda) {if (x > lambda) {return x - lambda;}else if (x < -lambda) {return x + lambda;}return 0.0;
}// 多项式特征扩展函数
Eigen::MatrixXd polynomialFeatures(const Eigen::MatrixXd& X, int degree) {int n_samples = X.rows();int n_features = X.cols();Eigen::MatrixXd polyFeatures(n_samples, (degree + 1) * n_features);for (int i = 0; i < n_samples; ++i) {for (int j = 0; j < n_features; ++j) {for (int d = 0; d <= degree; ++d) {polyFeatures(i, j * (degree + 1) + d) = std::pow(X(i, j), d);}}}return polyFeatures;
}// Lasso回归函数
Eigen::VectorXd lassoRegression(const Eigen::MatrixXd& X, const Eigen::VectorXd& y, double alpha, int max_iter = 2000, double tol = 1e-6) {int n_samples = X.rows();int n_features = X.cols();Eigen::VectorXd w = Eigen::VectorXd::Zero(n_features);Eigen::VectorXd w_old = Eigen::VectorXd::Zero(n_features);for (int iter = 0; iter < max_iter; ++iter) {for (int j = 0; j < n_features; ++j) {Eigen::VectorXd r = y - X * w + X.col(j) * w(j);double rho = X.col(j).dot(r);w(j) = (rho < -alpha / 2) ? (rho + alpha / 2) / X.col(j).squaredNorm() :(rho > alpha / 2) ? (rho - alpha / 2) / X.col(j).squaredNorm() : 0;}if ((w - w_old).norm() < tol) {break;}w_old = w;}return w;
}int main() {int numSamples = 17;int numFeatures = 3;int degree = 6;double lambda = 0.1;Eigen::MatrixXd data(numSamples, 10);data << 10, 50, 3, 29, 28, 30, 22, 21, 3.9, 3.39,10, 50, 5, 35, 34, 34, 26, 25, 4.54, 4.05,10, 60, 3, 34, 34, 31, 23, 23, 4.11, 4.15,15, 50, 3, 24, 27, 35, 19, 20, 1.51, 3.25,15, 50, 5, 31, 33, 38, 23, 24, 2.9, 3.34,15, 50, 8, 38, 38, 40, 26, 26, 3.49, 3.58,15, 50, 10, 41, 41, 42, 29, 29, 3.99, 3.76,15, 60, 3, 30, 33, 36, 20, 22, 1.77, 3.31,15, 60, 5, 37, 38, 40, 26, 26, 3.32, 3.79,15, 60, 8, 40, 41, 41, 27, 27, 3.64, 3.78,20, 50, 3, 17, 27, 40, 13, 20, -2, 2.81,20, 50, 5, 26, 32, 43, 19, 23, -0.35, 2.96,20, 50, 8, 33, 38, 45, 22, 25, 0.71, 3.42,20, 50, 10, 36, 40, 47, 25, 27, 1.63, 3.43,20, 60, 3, 22, 31, 41, 15, 21, -1.7, 2.95,20, 60, 5, 31, 37, 45, 22, 26, 0.78, 3.24,20, 60, 8, 35, 40, 46, 24, 27, 0.98, 3.1;// 生成示例数据Eigen::MatrixXd X = Eigen::MatrixXd::Zero(numSamples, numFeatures);Eigen::VectorXd y = Eigen::VectorXd::Zero(numSamples);for (int colId = 3; colId <= 9; colId++){for (int i = 0; i < numSamples; i++){X(i, 0) = data(i, 0);X(i, 1) = data(i, 1);X(i, 2) = data(i, 2);y(i, 0) = data(i, colId);}// 构造多项式特征Eigen::MatrixXd polyX = polynomialFeatures(X, degree);//cout << "polyX = " << polyX << endl;// 进行Lasso回归Eigen::VectorXd coefficients = lassoRegression(polyX, y, lambda);//std::cout << "Fitted coefficients: " << coefficients.transpose() << std::endl;// 计算预测值Eigen::VectorXd y_pred = polyX * coefficients;Eigen::VectorXd residuals = y - y_pred;// 输出残差std::cout << "Residuals: " << residuals.transpose() << std::endl;}return 0;
}