21
2018
09

最小二乘法拟合直线

物理实验里边经常会用到,测得一堆点,然后拟合一条直线。

之前学过梯度下降算法(关于梯度下降算法的的一些总结),也写过,但是直到现在都不理解,倒是能照着写出来。

如果只是拟合直线的话,可以用这个:最小二乘法 拟合平面直线

可以看一下这个:https://www.zhihu.com/question/37031188

可以直接里边用到的结论:





求出了a,b,直线也就有了y=ax+b。

用线性代数的知识,也可以解出ab。参考:http://open.163.com/movie/2010/11/P/U/M6V0BQC4M_M6V2AOJPU.html

写了个demo:

<canvas id = 'canvas' width = '1000' height = '600' style = 'width:1000px;height:600px;'></canvas>
<script type="text/javascript">
	var canvas = document.getElementById('canvas');
	var ctx = canvas.getContext('2d');
	var arr = [
		{x: 100, y: 100}
		, {x: 200, y: 220}
		, {x: 300, y: 300}
	];

	var ab = nihe(arr);
	console.log(ab);

	for(var i = 0; i < arr.length; i++){
		var o = arr[i];
		var w = 10;
		ctx.strokeStyle="#ff0000";
		ctx.strokeRect(o.x - w / 2, o.y - w / 2, w, w);
	}
	ctx.strokeStyle="#00ff00";
	ctx.beginPath();
	ctx.moveTo(0, getY(0));
	ctx.lineTo(1000, getY(1000));
	ctx.stroke();

	var ab = nihe2(arr);
	console.log(ab);

	function getY(x){
		return ab.a * x + ab.b;
	}

	function nihe(arr) {
		// https://blog.csdn.net/ouyangying123/article/details/53996403
		let len = arr.length;
		let xy = 0;
		let x2 = 0;
		let nx = 0;
		let ny = 0;
		for (let i = 0; i < len; i++) {
		  let o = arr[i];
		  xy += o.x * o.y;
		  nx += o.x;
		  ny += o.y;
		  x2 += o.x * o.x;
		}
		let a = (xy - nx * ny / len) / (x2 - nx * nx / len);
		let b = (ny - a * nx) / len;
		return {a: a, b: b};
	}

	function nihe2(arr){
		// ax + b = y
		// 求a,b
		// |x1 , 1|       |y1|
		// |x2 , 1|*|a| = |y2|
		// |x3 , 1| |b|   |y3|
		// ...
		// |xn , 1|       |yn|
		// 
		// 上边数组用Ax = b表示,A、b已知,求x。
		// 大多数时候无解。
		// 左乘A'(A的转置),A'Ax = A'b,可使方程有解。
		// 
		let a = 0;
		let b = 0;
		let c = 0;
		let d = 0;
		let e = 0;
		let f = 0;
		let len = arr.length;
		for(let i = 0; i < len; i++){
			let o = arr[i];
			a += o.x * o.x;
			b += o.x;
			c += o.x;
			d += 1;
			e += o.x * o.y;
			f += o.y;
		}
		let y = (f * a - e * c) / (d * a - b * c);//(f - e * c / a) / (d - b * c / a);
		let x = (e - b * y) / a;
		return {a: x, b: y};
	}
</script>

如果只是拟合直线,第二种方法比较好,简单,准确。

第一种方法不止可以拟合直线,还可以拟合其他类型的曲线。目前用不到。



« 上一篇下一篇 »

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。