最小二乘法学习笔记

一维数据拟合

参考自https://blog.csdn.net/shenliang1985/article/details/112327554?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2aggregatepagefirst_rank_ecpm_v1~rank_aggregation-1-112327554.pc_agg_rank_aggregation&utm_term=%E6%9C%80%E5%B0%8F%E4%BA%8C%E4%B9%98%E6%B3%95%E7%9A%84%E5%81%8F%E5%AF%BC%E6%95%B0%E6%8E%A8%E5%AF%BC&spm=1000.2123.3001.4430

设目标一维方程为

[Y= ax+b+ε ]

a 斜率
b Y的截距
ε 误差

一维方程可得

[ε=Y - ax - b ]

[Q=sum_{i=1}^{n}{ε_i^2}=sum_{i=1}^{n}({Y_i} -{y_i})^2 = sum_{i=1}^{n}(Yi - ax-b)^2 ]

Q 残差平方和
ε 差量
Y 实际值
y 拟合函数值
a 斜率
b Y的截距.

将a,b设为变量,求Q对两个待估函数的偏导数:

[egin{cases} frac{∂Q}{∂a}=-2sum_{i=1}^{n}(Y-a{x_i}-b){x_i}=0\ frac{∂Q}{∂b}=-2sum_{i=1}^{n}(Y-a{x_i}-b)=0 end{cases} ]

[a=frac{nsum_{i = 1}^{n}{x_i}{y_i}-sum_{i=1}^{n}{x_i}sum_{i = 1}^{n}{y_i}}{nsum_{i = 1}^{n}{x_i}^2-(sum_{i = 1}^{n}{x_i})^2}\ b=frac{sum_{i = 1}^{n}{x_i}^2sum_{i = 1}^{n}{y_i}-sum_{i=1}^{n}{x_i}sum_{i = 1}^{n}{x_i}{y_i}}{nsum_{i = 1}^{n}{x_i}^2-(sum_{i = 1}^{n}{x_i})^2} ]

由C++实现代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;

int n;

vector<double>x, y;

template <typename T>
inline void read(T& x) {
	x = 0;
	T op = 1;
	char c = getchar();
	for (; c < '0' || c > '9'; c = getchar())
		if (c == '-') op = -1;
	for (; c <= '9' && c >= '0'; c = getchar())
		x = (x << 3) + (x << 1) + c - '0';
	x *= op;
}

inline double Get_a() {
	double sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0;
	for (int i = 0; i < n; ++i)
		sum1 += x[i] * y[i], sum2 += x[i], sum3 += y[i], sum4 += x[i] * x[i];
	return (sum1 * n - sum2 * sum3) / (sum4 * n - sum2 * sum2);
}

inline double Get_b() {
	double sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0;
	for (int i = 0; i < n; ++i)
		sum1 += x[i] * y[i], sum2 += x[i], sum3 += y[i], sum4 += x[i] * x[i];
	return (sum4 * sum3 - sum1 * sum2) / (sum4 * n - sum2 * sum2);
}

int main() {
	freopen("data.txt", "r", stdin);
	read(n);
	for (int i = 1; i <= n; ++i) {
		double nx, ny;
		scanf("%lf%lf", &nx, &ny);
		x.push_back(nx);
		y.push_back(ny);
	}
	double a = Get_a();
	double b = Get_b();
	printf("y = %lfx + %lf", a, b);
	return 0;
}

多维拟合

多维拟合和一维拟合在本质上差别不大,即对多维方程求偏导,解出各个未知量。(因为不会求了,所以水不下去了)

原文地址:https://www.cnblogs.com/ZmeetL/p/15345078.html