最小二乘法
【摘要】 本文结合对ChatGTP的提问,用自己的理解讲一讲最小二乘法。
本文结合对ChatGTP的提问,用自己的理解讲一讲最小二乘法。
最小二乘法:
yi是实际值,yhat是理论值,就是拟合值,比方说使用一元一次的线性函数做拟合,那就是在这个x点位置时的值。累加所有yi-yhat的平方,得到E并保证E最小,即最小二乘。
当然这个E的结果并不是固定的,不同的函数,不同的参数都会导致结果不同。
然后再将拟合函数带入原公式,这个计算过程网上有很多,硬算或者求导或者用矩阵等。
注意:最小二乘是求得线性回归的方法,但不是一样东西
代码实现
所以这其实是一个数学问题,代码实现也只是对偏导公式的一个数值解而已,不过结合ChatGTP,它还是给出了结合协方差和方差的拟合方案,用Unity实现一下:
最后在面板上填入一些采样点,可以得到最接近的拟合函数参数。
using UnityEngine;
public class LeastSquaresMethod : MonoBehaviour
{
public Vector2[] samplePoints;//采样点,需要在编辑器面板自己设置
void OnDrawGizmos()
{
float xSum = 0f, ySum = 0f;
for (int i = 0; i < samplePoints.Length; i++)
{
var item = samplePoints[i];
xSum += item.x;
ySum += item.y;
}
//x和y的平均值
var xAve = xSum / samplePoints.Length;
var yAve = ySum / samplePoints.Length;
//sx是x轴的方差,sy是y轴的方差,方差反应了数据的离散程度
//sxy是协方差,协方差大于零y与x正相关,小于零是负相关,等于零是无关
float sx = 0f, sy = 0f, sxy = 0f;
for (int i = 0; i < samplePoints.Length; i++)
{
sx += Mathf.Pow(samplePoints[i].x - xAve, 2);
sy += Mathf.Pow(samplePoints[i].y - yAve, 2);
sxy += (samplePoints[i].x - xAve) * (samplePoints[i].y - yAve);
}
Debug.Log("sxy:" + sxy);
//此处套用公式
var r = sxy / (Mathf.Sqrt(sx) * Mathf.Sqrt(sy));
var a = r * (sy / sx);
var b = yAve - a * xAve;
//Unity绘制逻辑
Vector3? lastPos = null;
for (float i = 0f, step = 0.1f; i <= 1f; i += step)
{
var x = i / 1f;
var y = a * x + b;
var pos = new Vector3(x, y, 0f);
if (lastPos.HasValue)
Gizmos.DrawLine(lastPos.Value, pos);
lastPos = pos;
}
for (int i = 0; i < samplePoints.Length; i++)
{
var item = samplePoints[i];
Gizmos.DrawWireSphere(new Vector3(item.x, item.y, 0f), 0.03f);
}
}
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)