博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
最小二乘法拟合:原理,python源码,C++源码
阅读量:4096 次
发布时间:2019-05-25

本文共 9403 字,大约阅读时间需要 31 分钟。

一,原理

二,根据原理得到的  python 源码。

import matplotlib.pyplot as plt  import math  import numpy  import random    fig = plt.figure()  ax = fig.add_subplot(111)    #阶数为9阶  order=9  #生成曲线上的各个点  x = numpy.arange(-1,1,0.02)  y = [((a*a-1)*(a*a-1)*(a*a-1)+0.5)*numpy.sin(a*2) for a in x]  #ax.plot(x,y,color='r',linestyle='-',marker='')  #,label="(a*a-1)*(a*a-1)*(a*a-1)+0.5"    #生成的曲线上的各个点偏移一下,并放入到xa,ya中去  i=0  xa=[]  ya=[]  for xx in x:      yy=y[i]      d=float(random.randint(70,130))/100      #ax.plot([xx*d],[yy*d],color='m',linestyle='',marker='.')      i+=1      xa.append(xx*d)      ya.append(yy*d)    '''''for i in range(0,5):     xx=float(random.randint(-100,100))/100     yy=float(random.randint(-60,60))/100     xa.append(xx)     ya.append(yy)'''  ax.plot(xa,ya,color='m',linestyle='',marker='.')  #plt.show()#print(ax)  #进行曲线拟合  matA=[]  for i in range(0,order+1):      matA1=[]      for j in range(0,order+1):          tx=0.0          for k in range(0,len(xa)):              dx=1.0              for l in range(0,j+i):                  dx=dx*xa[k]              tx+=dx          matA1.append(tx)      matA.append(matA1)    #print(len(xa))  #print(matA[0][0])  matA=numpy.array(matA)    matB=[]  for i in range(0,order+1):      ty=0.0      for k in range(0,len(xa)):          dy=1.0          for l in range(0,i):              dy=dy*xa[k]          ty+=ya[k]*dy      matB.append(ty)     matB=numpy.array(matB)    matAA=numpy.linalg.solve(matA,matB)  print (matAA)print (matA)print (matB)#画出拟合后的曲线  #print(matAA)  xxa= numpy.arange(-1,1.06,0.01)  yya=[]  for i in range(0,len(xxa)):      yy=0.0      for j in range(0,order+1):          dy=1.0          for k in range(0,j):              dy*=xxa[i]          dy*=matAA[j]          yy+=dy      yya.append(yy)  ax.plot(xxa,yya,color='g',linestyle='-',marker='')    ax.legend("aw")  plt.show()

python的结果

三,下面是c++实现。

c++第一部分:这里用了一个自己写的Matrix 类,作为头文件Matrix.h

#include
#include
// std::ifstream#include
#include
using namespace std;class Matrix{private: unsigned row, col, size; double *pmm;//数组指针 public: Matrix(unsigned r, unsigned c) :row(r), col(c)//非方阵构造 { size = r*c; if (size>0) { pmm = new double[size]; for (unsigned j = 0; j
0) { pmm = new double[size]; for (unsigned j = 0; j
>(istream&, Matrix&); friend ofstream &operator<<(ofstream &out, Matrix &obj); friend ostream &operator<<(ostream&, Matrix&); friend Matrix operator+(const Matrix&, const Matrix&); friend Matrix operator*(const Matrix&, const Matrix&); Matrix cov(_In_opt_ bool flag = true); //协方差阵 或者样本方差 double det(); //行列式 Matrix solveAb(Matrix &obj); // b是行向量或者列向量 Matrix diag(); //返回对角线元素 //Matrix asigndiag(); //对角线元素 Matrix T()const; //转置 void sort(bool);//true为从小到大 Matrix adjoint(); Matrix inverse(); void QR(_Out_ Matrix&, _Out_ Matrix&)const; Matrix eig_val(_In_opt_ unsigned _iters = 1000); Matrix eig_vect(_In_opt_ unsigned _iters = 1000); unsigned Row()const{ return row; } unsigned Col()const{ return col; } double norm1();//1范数 double norm2();//2范数 double*operator[](int i){ return pmm + i*col; }//注意this加括号, (*this)[i][j] void zeromean(_In_opt_ bool flag = true);//默认参数为true计算列 void normalize(_In_opt_ bool flag = true);//默认参数为true计算列 Matrix exponent(double x);//每个元素x次幂 Matrix eye();//对角阵 void maxlimit(double max,double set=0);//对角阵};//友元仅仅是指定了访问权限,不是一般意义的函数声明,最好在类外再进行一次函数声明。 //istream &operator>>(istream &is, Matrix &obj); //ostream &operator<<(ostream &is, Matrix &obj); //对称性运算符,如算术,相等,应该是普通非成员函数。 //Matrix operator*( const Matrix&,const Matrix& ); //Matrix operator+( const Matrix&,const Matrix& ); //dets递归调用 double dets(int n, double *&aa){ if (n == 1) return aa[0]; double *bb = new double[(n - 1)*(n - 1)];//创建n-1阶的代数余子式阵bb int mov = 0;//判断行是否移动 double sum = 0.0;//sum为行列式的值 for (int arow = 0; arow
brow ? 0 : 1; //bb中小于arow的行,同行赋值,等于的错过,大于的加一 for (int j = 0; j
max ? 0 : pmm[i*col + j]; } } }Matrix Matrix::eye()//对角阵{ for (unsigned i = 0; i< row; i++) { for (unsigned j = 0; j < col; j++) { if (i == j) { pmm[i*col + j] = 1.0; } } } return *this;}void Matrix::zeromean(_In_opt_ bool flag){ if (flag == true) //计算列均值 { double *mean = new double[col]; for (unsigned j = 0; j < col; j++) { mean[j] = 0.0; for (unsigned i = 0; i < row; i++) { mean[j] += pmm[i*col + j]; } mean[j] /= row; } for (unsigned j = 0; j < col; j++) { for (unsigned i = 0; i < row; i++) { pmm[i*col + j] -= mean[j]; } } delete[]mean; } else //计算行均值 { double *mean = new double[row]; for (unsigned i = 0; i< row; i++) { mean[i] = 0.0; for (unsigned j = 0; j < col; j++) { mean[i] += pmm[i*col + j]; } mean[i] /= col; } for (unsigned i = 0; i < row; i++) { for (unsigned j = 0; j < col; j++) { pmm[i*col + j] -= mean[i]; } } delete[]mean; }}void Matrix::normalize(_In_opt_ bool flag){ if (flag == true) //计算列均值 { double *mean = new double[col]; for (unsigned j = 0; j < col; j++) { mean[j] = 0.0; for (unsigned i = 0; i < row; i++) { mean[j] += pmm[i*col + j]; } mean[j] /= row; } for (unsigned j = 0; j < col; j++) { for (unsigned i = 0; i < row; i++) { pmm[i*col + j] -= mean[j]; } } ///计算标准差 for (unsigned j = 0; j < col; j++) { mean[j] = 0; for (unsigned i = 0; i < row; i++) { mean[j] += pow(pmm[i*col + j],2);//列平方和 } mean[j] = sqrt(mean[j] / row); // 开方 } for (unsigned j = 0; j < col; j++) { for (unsigned i = 0; i < row; i++) { pmm[i*col + j] /= mean[j];//列平方和 } } delete[]mean; } else //计算行均值 { double *mean = new double[row]; for (unsigned i = 0; i< row; i++) { mean[i] = 0.0; for (unsigned j = 0; j < col; j++) { mean[i] += pmm[i*col + j]; } mean[i] /= col; } for (unsigned i = 0; i < row; i++) { for (unsigned j = 0; j < col; j++) { pmm[i*col + j] -= mean[i]; } } ///计算标准差 for (unsigned i = 0; i< row; i++) { mean[i] = 0.0; for (unsigned j = 0; j < col; j++) { mean[i] += pow(pmm[i*col + j], 2);//列平方和 } mean[i] = sqrt(mean[i] / col); // 开方 } for (unsigned i = 0; i < row; i++) { for (unsigned j = 0; j < col; j++) { pmm[i*col + j] /= mean[i]; } } delete[]mean; }}double Matrix::det(){ if (col == row) return dets(row, pmm); else { cout << ("行列不相等无法计算") << endl; return 0; }}/ istream &operator>>(istream &is, Matrix &obj){ for (unsigned i = 0; i
> obj.pmm[i]; } return is;}ostream &operator<<(ostream &out, Matrix &obj){ for (unsigned i = 0; i < obj.row; i++) //打印逆矩阵 { for (unsigned j = 0; j < obj.col; j++) { out << (obj[i][j]) << "\t"; } out << endl; } return out;}ofstream &operator<<(ofstream &out, Matrix &obj)//打印逆矩阵到文件 { for (unsigned i = 0; i < obj.row; i++) { for (unsigned j = 0; j < obj.col; j++) { out << (obj[i][j]) << "\t"; } out << endl; } return out;}Matrix operator+(const Matrix& lm, const Matrix& rm){ Matrix ret(lm.row, lm.col); for (unsigned i = 0; i
pmm[j]) { tem = pmm[i]; pmm[i] = pmm[j]; pmm[j] = tem; } } else { if (pmm[i]
<< endl; return m; } Matrix m(row); for (unsigned i = 0; i
= 0; --m) { sum = 0; for (unsigned j = m + 1; j < col; ++j) { sum += pmm[m * col + j] * ret.pmm[j * ret.col + count]; } sum = -sum / pmm[m * col + m]; midSum += sum * sum; ret.pmm[m * ret.col + count] = sum; } midSum = sqrt(midSum); for (unsigned i = 0; i < ret.row; ++i) { ret.pmm[i * ret.col + count] /= midSum; //每次求出一个列向量 } } *this = matcopy;//恢复原始矩阵; return ret;}Matrix Matrix::cov(bool flag){ //row 样本数,column 变量数 if (col == 0) { Matrix m(0); return m; } double *mean = new double[col]; //均值向量 for (unsigned j = 0; j
bi) //ai行的代数余子式是:小于ai的行,aa与bb阵,同行赋值 pi = 0; else pi = 1; //大于等于ai的行,取aa阵的ai+1行赋值给阵bb的bi行 if (aj>bj) //ai行的代数余子式是:小于ai的行,aa与bb阵,同行赋值 pj = 0; else pj = 1; //大于等于ai的行,取aa阵的ai+1行赋值给阵bb的bi行 bb[bi*(n - 1) + bj] = pmm[(bi + pi)*n + bj + pj]; } } if ((ai + aj) % 2 == 0) q = 1;//因为列数为0,所以行数是偶数时候,代数余子式为-1. else q = (-1); ret.pmm[ai*n + aj] = q*dets(n - 1, bb); //加符号变为代数余子式 } } delete[]bb; return ret;}Matrix Matrix::inverse(){ double det_aa = det(); if (det_aa == 0) { cout << "行列式为0 ,不能计算逆矩阵。" << endl; Matrix rets(0); return rets; } Matrix adj = adjoint(); Matrix ret(row); for (unsigned i = 0; i

c++第二部分:主函数部分

#include "matrix.h"#include 
#include
#include
const int N = 100;double fun(double x){ return (pow((x*x - 1), 3.0) + 0.5)*sin(x * 2);}int main(){ Matrix x(1, N); Matrix y(1, N); ofstream ofs; ofs.open("pydata.txt", ofstream::out); double src = -1.0; for (int i = 0; i < N; i++) { src += 0.02; x[0][i] = src; y[0][i] = fun(src); } Matrix sx(x);//加入随机因素前的x for (int i = 0; i < N; i++) { double ran = rand() % 600 / 1000.0 + 0.7; // 0.7~1.3 倍的随机 x[0][i] = x[0][i]*ran; y[0][i] = y[0][i] * ran; } //构建矩阵 int k = 8; //次方数 Matrix xx(k + 1, k + 1); //累加矩阵k+1阶 for (size_t r = 0; r < k+1; r++) { for (size_t c = r; c < k+1; c++) { double sum = 0; for (size_t i = 0; i < N; i++) { sum += pow(x[0][i], r+c); } xx[c][r]=xx[r][c] = sum; } } cout << "xx:\n"<

c++第三部分: 根据c++的输出  pydata.txt 用python画图

 

import matplotlib.pyplot as plt  import numpy  fin = open("pydata.txt", "r")    line = fin.readline()   x=[]y=[]py=[]while line:        #print(line)    line=line.strip()        line=line.split()        x.append(float(line[0]))    y.append(float(line[1]))    py.append(float(line[2]))    line = fin.readline()    fin.close()    ax = plt.subplot(111)  xa= numpy.arange(-1,1,0.02)  ax.plot(xa,y,color='m',linestyle='',marker='.')  ax.plot(xa,py,color='g',linestyle='-',marker='')  plt.show()

画图的结果

你可能感兴趣的文章
《python+opencv实践》四、图像特征提取与描述——31 Shi-Tomasi 角点检测& 适合于跟踪的图像特征
查看>>
OpenCV meanshift目标跟踪总结
查看>>
人工神经网络——神经元模型介绍
查看>>
人工神经网络——感知器介绍
查看>>
人工神经网络——反向传播算法(BackPropagation)
查看>>
进程的地址空间概述
查看>>
Windows 窗口底层原理
查看>>
一种函数指针的运用
查看>>
Win32程序之进程的原理
查看>>
C++虚函数原理
查看>>
MySQL的索引
查看>>
今天,Python信息量很大!
查看>>
Flash 已死,Deno 当立?
查看>>
编程差的程序员,90%都是吃了数学的亏!骨灰级开发:方法不对,努力也白费...
查看>>
编程差的程序员,90%都是吃了数学的亏!骨灰级开发:方法不对,努力也白费...
查看>>
都无代码了,还要程序员吗?
查看>>
程序员:凭自己能力吃饭,有什么理由瞧不起?
查看>>
面试想拿 10K,HR 说我只配7k?
查看>>
副业过万的程序员都知道的网站有哪些
查看>>
那些人生“开挂”的程序员,都在干什么?
查看>>