c++ 多项式拟合_多项式回归(Polynomial Curve Fitting)

本文介绍了使用C++进行多项式拟合的方法,通过实例展示了如何利用sklearn库拟合不同项次的多项式。讨论了过拟合问题,随着项数增加,虽然训练集上的均方误差接近于0,但在验证集上误差剧增。此外,随着数据量的增加,过拟合情况得以改善。文章还提到了正则化技术,用于限制模型复杂度,防止过拟合。
摘要由CSDN通过智能技术生成

020b66bdc8eb2863107fa9f8c59e016c.png

PRML这序章写的太好了,用代码实现一下切身体会一下知识点.

  • 假设有N个观察样例x,我们的目标函数是 (2 )加上一个高斯分布的噪声.这与我们实际工作中遇到的数据集其实也很相似:数据有一定的规律性,但每个数据点也都存在一定的噪声。噪声的产生可能是由于数据的随机性造成的,但更多的情况下是因为有我们未观察到的规律
  • 我们的目标是利用多项式去探索隐含在 (2 )下的方程式。更蛋疼的是我们观察到的数据都是有噪声的,但这章节我们还是先用多项式去拟合.多项式的方程范式如下:

equation?tex=%5Clarge+y%28x%2Cw%29%3Dw_0%2Bw_1x%2Bw_2x%5E2%2B...%2Bw_Mx%5EM%3D%5Csum_%7Bj%3D1%7D%5EMw_jx%5Ej
  • 这个下标没啥好多解释,就是个m项的多项式回归,需要注意的事,虽然多项式f(x,w)是关于x的非线性方程,但多项式回归可以理解为是W的线性方程。
  • 在这个例子中我们使用均方误差来作为损失函数,注意这个1/2是为了后续的计算方便才这么操作的。一个均方误差为0的损失函数代表我们拟合的返程可以穿过所有的数据点
    equation?tex=%5Clarge+E%28w%29%3D%5Cfrac12%5Csum_%7Bn%3D1%7D%5EN%7Cy%28x_n%2Cw%29-tn%7C%5E2
  • 我们可以优化这个方程的方式就是:找到一组能够使得E(W)最小化的系数w。因为我们的损失函数是关于w的二次方程(Quadratic Function),所以损失关于w的导数是线性的,所以我们的损失函数一定有一个最优解(W*).
  • 接下来我们要解决的问题就是找到一个超参数M,也就是多项式的项数,我们随机生成一些sinpx的数据点,并使用sklearn来拟合四个不同项次的方程来看看。<
#ifndef FUNCTION_H_ #define FUNCTION_H_ #include #include #include "polyfit.h" #include using namespace std; dxs::dxs() { ifstream fin("多项式拟合.txt"); fin>>n; x=new float[n]; y=new float[n]; for(int i=0;i>x[i]; } for(i=0;i>y[i]; } cout<>nn; m=nn+1; u=new float*[m]; for(i=0;i<m;i++) { u[i]=new float[m+1]; }//创建m行,m+1列数组 } void dxs::dfine() { for(int i=0;i<m;i++) { for(int j=0;j<m+1;j++) { u[i][j]=0; } } for(i=0;i<m;i++) { for(int j=0;j<m;j++) { for(int k=0;k<n;k++) { u[i][j]=u[i][j]+pow(x[k],j+i); } } } for(i=0;i<m;i++) { for(int k=0;k<n;k++) { u[i][m]=u[i][m]+pow(x[k],i)*y[k]; } } } void dxs::show() { for(int i=0;i<m;i++) { for(int j=0;j<m+1;j++) { cout<<u[i][j]<<" ";//<<endl; } cout<<endl; } ////显示具有m行m+1列u数组的各元素值 } void dxs::select_main(int k,float **p,int m) { double d; d=*(*(p+k)+k); //cout<<d; int l=k; int i=k+1; for(;i fabs(d)) { d=*(*(p+i)+k); l=i; } else continue; } if(d==0) cout<<"错误"; else { if(k!=l) { for(int j=k;j<m+1;j++) { double t; t=*(*(p+l)+j); *(*(p+l)+j)=*(*(p+k)+j); *(*(p+k)+j)=t; } } } } void dxs::gaosi() { for(int k=0;k<m;k++) { select_main(k,u,m);//调用列主元函数 for(int i=1+k;i<m;i++) { // *(*(p+i)+k)=(float) *(*(p+i)+k) / *(*(p+k)+k); u[i][k]=(float) u[i][k] / u[k][k]; } for(i=k+1;i<m;i++) { for(int j=k+1;j=0;i--) { float a=0; for(int j=i+1;j<m;j++) { //a=a + (*(*(p+i)+j) * *(*(p+j)+m)); a=a+u[i][j] * u[j][m]; } //*(*(p+i)+n-1)= (*(*(p+i)+n-1) - a) / *(*(p+i)+i); u[i][m]= (u[i][m] -a) / u[i][i]; } cout<<"方程组的解为:"<<endl; for(i=0;i<m;i++) { cout<<"a"<<i+1<<"="; cout<<u[i][m]<<endl; // l[i]=*(*(p+i)+n-1); } cout<<"y="<<u[0][m]; for(i=1;i<m;i++) { cout<<showpos<<u[i][m]<<"x"; if(i!=1)cout<<"^"<<noshowpos<<i; } cout<<endl; } dxs::~dxs() { delete[]x,y; delete []*u; } #endif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值