C++代码实现MATLAB中fitrgam函数功能
// fitrgam.cpp// 自包含 GAM 实现循环梯度提升 决策树桩// 逻辑对应 MATLAB fitrgam// - 每个预测变量独立提升cyclic boosting// - 基学习器为决策树桩 (max_depth 1)// - 默认迭代 300 次学习率 0.1// - 预测 截距 Σ 形状函数#includeiostream#includevector#includealgorithm#includecmath#includerandom#includenumeric#includelimits// // 决策树桩 (Decision Stump)// structStump{doublethreshold0.0;doubleleft_value0.0;doubleright_value0.0;// 预测x threshold 走左子树否则走右子树doublepredict(doublex)const{return(xthreshold)?left_value:right_value;}};// 用平方误差损失训练一棵树桩Stumptrain_stump(conststd::vectordoublex,conststd::vectordoubleresidual){constintnstatic_castint(x.size());Stump s;// 1) 按 x 排序std::vectorintidx(n);std::iota(idx.begin(),idx.end(),0);std::sort(idx.begin(),idx.end(),[](inta,intb){returnx[a]x[b];});std::vectordoublexs(n),rs(n);for(inti0;in;i){xs[i]x[idx[i]];rs[i]residual[idx[i]];}// 2) 前缀和用于 O(1) 计算任意切分的 SSEstd::vectordoubleprefix_sum(n1,0.0);std::vectordoubleprefix_sq(n1,0.0);for(inti0;in;i){prefix_sum[i1]prefix_sum[i]rs[i];prefix_sq[i1]prefix_sq[i]rs[i]*rs[i];}constdoubletotal_sumprefix_sum[n];constdoubletotal_sqprefix_sq[n];// 3) 枚举所有可能的分裂点doublebest_ssestd::numeric_limitsdouble::infinity();intbest_split-1;for(inti1;in;i){if(xs[i-1]xs[i])continue;// 相同值无法分裂constintnli;constintnrn-i;constdoublesum_lprefix_sum[i];constdoublesum_rtotal_sum-sum_l;constdoublesq_lprefix_sq[i];constdoublesq_rtotal_sq-sq_l;// SSE Σy² - (Σy)²/nconstdoublesse(sq_l-sum_l*sum_l/nl)(sq_r-sum_r*sum_r/nr);if(ssebest_sse){best_ssesse;best_spliti;}}// 4) 退化情形所有 x 相同无法分裂 预测常数均值if(best_split0){constdoublemeantotal_sum/n;s.threshold0.0;s.left_valuemean;s.right_valuemean;returns;}// 5) 计算左右叶子的均值constintnlbest_split;constintnrn-best_split;constdoublesum_lprefix_sum[best_split];constdoublesum_rtotal_sum-sum_l;s.threshold0.5*(xs[best_split-1]xs[best_split]);s.left_valuesum_l/nl;s.right_valuesum_r/nr;returns;}// // GAM 模型// classGAM{public:intn_iter300;// 与 fitrgam 默认值一致doublelearning_rate0.1;// 与 fitrgam 默认值一致doubleintercept0.0;std::vectorstd::vectorStumpshapes;voidfit(conststd::vectorstd::vectordoubleX,conststd::vectordoubley,boolverbosetrue){constintnstatic_castint(y.size());constintpstatic_castint(X[0].size());// 1) 截距初始化 响应变量均值intercept0.0;for(doublev:y)interceptv;intercept/n;// 2) 形状函数初始化为 0shapes.assign(p,{});std::vectorstd::vectordoublef(p,std::vectordouble(n,0.0));// 3) 循环梯度提升for(intiter0;itern_iter;iter){for(intj0;jp;j){// 3a) 残差: r_i y_i - (intercept Σ_k f_k)当前全量预测的负梯度// 注意必须包含 f_j 自身否则增量更新 f_j lr*h 会重复累计// 同一特征信号导致循环梯度提升发散GAMBoost 标准残差定义std::vectordoubleresid(n);for(inti0;in;i){doublepartialintercept;for(intk0;kp;k){partialf[k][i];}resid[i]y[i]-partial;}// 3b) 用树桩拟合残差std::vectordoublexj(n);for(inti0;in;i)xj[i]X[i][j];Stump strain_stump(xj,resid);shapes[j].push_back(s);// 3c) 更新形状函数: f_j lr * h_j(x_j)for(inti0;in;i){f[j][i]learning_rate*s.predict(xj[i]);}}// 3d) 打印训练进度if(verbose((iter1)%300||iter0)){doublermse0.0;for(inti0;in;i){constdoubleey[i]-predict(X[i]);rmsee*e;}rmsestd::sqrt(rmse/n);std::coutIteration (iter1) | RMSE: rmse\n;}}}// 单样本预测y_pred intercept Σ_j f_j(x_j)doublepredict(conststd::vectordoublex)const{doublesintercept;for(size_t j0;jshapes.size();j){for(constStumpst:shapes[j]){slearning_rate*st.predict(x[j]);}}returns;}// 查询某个形状函数在给定点的取值doubleshape_value(intj,doublexj)const{doubles0.0;for(constStumpst:shapes[j]){slearning_rate*st.predict(xj);}returns;}};// // 主程序// intmain(){// 1. 生成模拟数据constintn200;constintp2;std::mt19937rng(42);std::normal_distributiondoublenoise(0.0,0.1);std::uniform_real_distributiondoubleunif(-1.0,1.0);std::vectorstd::vectordoubleX(n,std::vectordouble(p));std::vectordoubley(n);for(inti0;in;i){X[i][0]unif(rng);X[i][1]unif(rng);// 真实模型: y 2 3*x1 sin(x2) εy[i]2.03.0*X[i][0]std::sin(X[i][1])noise(rng);}// 2. 打印设置std::cout--- GAM Training (Gradient Boosting, Stumps) ---\n;std::coutObservations: n\n;std::coutPredictors: p\n;std::coutBoosting Iterations (M): 300\n;std::coutLearning Rate: 0.1\n\n;// 3. 训练GAM gam;gam.n_iter300;gam.learning_rate0.1;gam.fit(X,y,/*verbose*/true);// 4. 输出模型信息std::cout\n--- Training Complete ---\n;std::coutIntercept: gam.intercept\n;for(intj0;jp;j){std::coutShape Function f(j1): gam.shapes[j].size() stumps\n;}// 5. 对新查询点预测constdoubleqx10.5,qx2-0.2;std::vectordoubleqx{qx1,qx2};constdoublepf1gam.shape_value(0,qx1);constdoublepf2gam.shape_value(1,qx2);constdoublepred_ygam.predict(qx);std::cout\nPrediction for query point (x1qx1, x2qx2):\n;std::cout Intercept: gam.intercept\n;std::cout f1(qx1): pf1\n;std::cout f2(qx2): pf2\n;std::cout Predicted y: pred_y\n;constdoubletrue_y2.03.0*qx1std::sin(qx2);std::cout\n True y (noiseless): true_y\n;std::cout Error: std::abs(pred_y-true_y)\n;return0;}

相关新闻

旋转数组最优解:三次翻转实现原地O(1)空间交换

旋转数组最优解:三次翻转实现原地O(1)空间交换

第一次在面试里遇到旋转数组这道题,是好几年前的事了。当时我的思路还停留在“开一个新数组,把每个元素放到正确位置”的阶段,一两分钟写完,自我感觉良好。结果面试官轻轻补了一句:“能不能不用额外空间?”…

2026/10/10 2:48:05 阅读更多 →
IDEA中文乱码排查指南:从编码链路到解决方案

IDEA中文乱码排查指南:从编码链路到解决方案

1. 先从那个"�"说起:乱码问题到底卡在编码链路的哪一环你看到的这个标题末尾就带了一个"�",这其实是乱码问题里最经典的一个标志性字符。在IDEA里遇到中文乱码,大多数人的第一反应是"文件坏了…

2026/10/10 2:48:05 阅读更多 →
2026跨境新规落地后,第一批吃透“本土店+半托管”的卖家,已经在偷偷换车了

2026跨境新规落地后,第一批吃透“本土店+半托管”的卖家,已经在偷偷换车了

跨境卖家换车:本土店与半托管组合正在重构运营逻辑 九月跨境圈有个微妙变化:一些卖家不再讨论怎么把货发出去,而是研究怎么把货“留”在当地。 新规落地后,清关时效、税务合规、平台责任划分都更细化。原先靠直邮小包冲量的模式&a…

2026/10/10 2:47:05 阅读更多 →

最新新闻

2024数学建模国赛C题代码与数据:快速求解种植策略

2024数学建模国赛C题代码与数据:快速求解种植策略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 3:30:18 阅读更多 →
低功耗MCU与可编程PMIC的组合设计:从硬件到寄存器的电源管理实战

低功耗MCU与可编程PMIC的组合设计:从硬件到寄存器的电源管理实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 3:30:18 阅读更多 →
智慧病房APP原型模板:从护士站到床旁终端的交互设计思路

智慧病房APP原型模板:从护士站到床旁终端的交互设计思路

1. 内容整体设计与思路拆解1.1 医疗场景下“画原型”这件事的特殊性智慧病房APP原型模板,说白了就是把病房里护士、患者、医生三方的日常动作,数字化之后沉淀成一套可以直接复用、改改就能用的界面方案。为什么这事儿值得单独做一套模板?因为…

2026/10/10 3:30:18 阅读更多 →
StarGantt 星甘 v3.1.0 工作日/自然日双模式:让甘特图排期不再失真

StarGantt 星甘 v3.1.0 工作日/自然日双模式:让甘特图排期不再失真

1. 为什么 StarGantt 星甘这次更新值得关注做项目管理这些年,工具换了一茬又一茬。从最早的表格排期,到后来的在线协作软件,再到各种专业项目管理平台,我发现自己最离不开的仍然是甘特图,那个横条视图一摆出来&#xf…

2026/10/10 3:30:18 阅读更多 →
Unity New Input System 改键全攻略:从绑定覆盖到存档恢复

Unity New Input System 改键全攻略:从绑定覆盖到存档恢复

1. 改键方案的选型与设计思路1.1 为什么不能直接在Inspector里改Asset不少刚接触Unity NewInputSystem的开发者,第一反应是打开Input Actions编辑器,把W改成别的键位,然后发现运行时完全没变化,或者改了之后所有玩家共用一套键位&…

2026/10/10 3:30:18 阅读更多 →
Fortify SCA 插件实战:从环境搭建到 CI 集成的静态代码扫描避坑指南

Fortify SCA 插件实战:从环境搭建到 CI 集成的静态代码扫描避坑指南

简介:Fortify SCA工具插件是一套面向开发人员与安全团队的白盒安全测试解决方案,可在编码阶段对源代码及依赖项进行静态分析,提前发现SQL注入、跨站脚本、不安全数据存储等常见漏洞。资源包共36个文件,约12.59MB,以30个…

2026/10/10 3:29:18 阅读更多 →

日新闻

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

1. 从“卫星轨道分类”这个标题说起:为什么值得花时间搞懂第一次接触“卫星轨道分类”这个概念,很多人会觉得它离自己很远——不就是天上的星星怎么转吗?但如果你正在做航天任务规划、遥感数据接收、星座设计,甚至只是准备一场航天…

2026/10/10 0:00:39 阅读更多 →
Spring AOP 核心原理与实战:从概念到日志切面落地

Spring AOP 核心原理与实战:从概念到日志切面落地

1. 从一个真实痛点说起:为什么你的代码里到处都是重复逻辑刚入行那会儿,我写过一个用户管理模块,注册、登录、改密码、注销四个接口。每个接口里都塞了几乎一样的日志打印、参数校验、事务开启和提交。当时觉得没什么,能跑就行。直…

2026/10/10 0:00:40 阅读更多 →
Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

简介:这是一套面向计算机相关专业学生与项目实战学习者的Python数据采集与分析可视化完整项目,以Boss直聘岗位数据为对象,适合用作毕业设计、课程设计或期末大作业。资源包共38个文件,约246KB,以13个py源码文件为核心&…

2026/10/10 0:00:40 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 1:36:08 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →