
把全书知识串起来的第一个实战项目用 Eigen 做最小二乘直线拟合。这是数据科学、机器学习的入门基础也是 Eigen 的典型应用。36.1 问题拟合一条直线假设你有一批实验数据点 (x, y)(0, 1.1), (1, 3.0), (2, 5.2), (3, 6.9), (4, 9.1), (5, 11.0)它们大致落在一条直线上但有点噪声。你想找一条直线y ax b最好地拟合这些点。最小二乘的思想找 a、b使得所有点到直线的误差平方和最小。36.2 数学原理正规方程把问题写成矩阵形式。对每个点 (xᵢ, yᵢ)有a·xᵢ b yᵢn 个点就是 n 个方程写成矩阵[ x₁ 1 ] [ y₁ ] [ x₂ 1 ] [ a ] [ y₂ ] [ ... ] [ b ] [ ...] [ xₙ 1 ] [ yₙ ]即A·c y其中A 是 n×2 矩阵第一列是 x第二列全 1c [a; b] 是待求参数y 是观测值这是方程比未知数多的超定方程一般没有精确解但有最小二乘解c (AᵀA)⁻¹ Aᵀ y ← 正规方程或者直接用 QR 分解求解更稳定。36.3 用 Eigen 实现#includeEigen/Dense#includeiostream#includevectorintmain(){// 原始数据std::vectordoublexs{0,1,2,3,4,5};std::vectordoubleys{1.1,3.0,5.2,6.9,9.1,11.0};intnxs.size();Eigen::MatrixXdA(n,2);// 设计矩阵Eigen::VectorXdy(n);for(inti0;in;i){A(i,0)xs[i];// 第一列是 xA(i,1)1.0;// 第二列是 1对应截距 by(i)ys[i];// 观测值}// 最小二乘求解QR 分解稳健通用Eigen::VectorXd cA.colPivHouseholderQr().solve(y);doubleac(0);// 斜率doublebc(1);// 截距std::cout拟合直线y a * x bstd::endl;return0;}运行结果接近y 1.98571 * x 1.08571真实关系是 y 2x 1 加噪声拟合非常准。编译运行把上面代码存成ch36.cpp然后路径写法见附录 C.3g-stdc17-O2-I你的Eigen目录ch36.cpp-och36.exe ./ch36.exe实际输出拟合直线y 1.98571 * x 1.0857136.4 评估拟合质量用残差真实值与预测值的差评估。在ch36.cpp的std::cout 拟合直线...后面加两行doubleerror(A*c-y).norm();// 残差范数std::cout残差 errorstd::endl;重新编译运行输出变成拟合直线y 1.98571 * x 1.08571 残差 0.226779残差越小拟合越好。这里 6 个点的总偏差约 0.23相对 y 本身 1~11 的量级来说很小说明直线确实贴住了这批数据。36.5 拓展多项式拟合直线拟合是线性拟合。想拟合曲线如二次 y ax² bx c只需扩展设计矩阵——加一列 x²。下面是独立的一份完整程序存成ch36_poly.cpp注意变量名和 36.3 的c无关#includeEigen/Dense#includeiostream#includevectorintmain(){std::vectordoublexs{0,1,2,3,4,5};std::vectordoubleys{1.1,3.0,5.2,6.9,9.1,11.0};Eigen::Index nxs.size();Eigen::MatrixXdA(n,3);// 三列x²、x、1Eigen::VectorXdy(n);for(Eigen::Index i0;in;i){A(i,0)xs[i]*xs[i];// x²A(i,1)xs[i];// xA(i,2)1.0;// 常数项y(i)ys[i];}Eigen::Vector3d cA.colPivHouseholderQr().solve(y);// c [a, b, c]std::cout二次拟合y c(0) * x^2 c(1) * x c(2)std::endl;std::cout残差 (A*c-y).norm()std::endl;return0;}实际输出二次拟合y 0 * x^2 1.98571 * x 1.08571 残差 0.226779这个结果很有意思二次项系数是0残差和直线拟合一模一样0.226779。原因是这批数据本来就是直线你给它更高次的模型它也只会把多余的那项压成 0。把ys改成{0, 1, 4, 9, 16, 25}正好是 y x²再跑一次实测输出二次拟合y 1 * x^2 -5.21706e-15 * x 7.14981e-15 残差 1.39037e-14二次项变成 1一次项和常数项是 1e-15 量级也就是 0残差 1e-14也就是 0——模型正确识别出了真实关系。思路完全一样把特征塞进设计矩阵的列就能拟合任意线性模型。这正是机器学习的核心思路——特征 最小二乘。36.6 为什么这是机器学习基础最小二乘拟合 机器学习里线性回归的 C 实现设计矩阵 A 特征矩阵 X待求参数 c 模型权重 w观测值 y 标签学会这个你就理解了线性回归、岭回归、甚至神经网络最后一层的数学本质。36.7 小结最小二乘让误差平方和最小的拟合。写成矩阵 Ax y用 QR 分解求解。残差范数评估拟合质量。扩展设计矩阵就能做多项式拟合 线性回归。下一章第二个实战项目3D 点云与刚体变换。练习题用上面的代码拟合给定数据打印斜率和截距。自己造一批数据y 3x 2 加随机噪声拟合看能不能还原。把拟合从直线改成二次曲线扩展设计矩阵。计算并打印拟合的残差。说说最小二乘和机器学习线性回归的关系。