我正试图找到一个JavaScript代码,可以让我做三次回归最糟糕的时间。我想自己写,但我对多项式数学的理解是,嗯,次优的。
所以,这就是我要找的。给定一个数组的数组的输入,其中内部数组为[x,y],该函数将以具有四个参数的数组形式输出- [a,b,c,d],其中a,b,c和d是方程y = ax^3 + bx^2 + cx + d的参数。
的例子:输入数组这样的[[2、5],[5 10],[07年15],[12、20],[20 25],[32岁,30],[50岁,35]]。
本质上是表的表示:
<>之前| x | y ||-----------------|| 02 | 05 || 05 | 10 || 07 | 15 || 12 | 20 || 20 | 25 || 32 | 30 || 50 | 35 |之前现在,输出将是[0.000575085,-0.058861065,2.183957502,1.127605507]。这些是三次函数的a、b、c和d参数。
(仅供参考,我通过使用Excel的LINEST函数并使用数组函数{1,2,3}在上述一组数字上运行它获得的输出)。
这是怎么做到的?非常感谢您的指导。
最好的,汤姆
这是一个真实的,工作的代码位来解决立方使用numeric.js库的uncmin
无约束最小化作为最小二乘问题(jsbin在这里):
var data_x = [2,5,7,12,20,32,50];
var data_y = [5,10,15,20,25,30,35];
var cubic = function(params,x) {
return params[0] * x*x*x +
params[1] * x*x +
params[2] * x +
params[3];
};
var objective = function(params) {
var total = 0.0;
for(var i=0; i < data_x.length; ++i) {
var resultThisDatum = cubic(params, data_x[i]);
var delta = resultThisDatum - data_y[i];
total += (delta*delta);
}
return total;
};
var initial = [1,1,1,1];
var minimiser = numeric.uncmin(objective,initial);
console.log("initial:");
for(var j=0; j<initial.length; ++j) {
console.log(initial[j]);
}
console.log("minimiser:");
for(var j=0; j<minimiser.solution.length; ++j) {
console.log(minimiser.solution[j]);
}
我得到了结果:
0.0005750849851827991
-0.05886106462847641
2.1839575020602164
1.1276055079334206
解释一下:我们有一个函数'cubic',它对一组参数params
和一个值x
的一般三次函数求值。该函数被包装以创建目标函数,目标函数接受一组参数,并通过目标函数运行数据集中的每个x值,并计算平方和。这个函数通过一组初始值从numeric.js传递给uncmin
;uncmin
完成最困难的工作并返回一个对象,其solution
属性包含优化的参数集。
要做到这一点,不需要全局变量(调皮!),你可以有一个目标函数工厂:
var makeObjective = function(targetFunc,xlist,ylist) {
var objective = function(params) {
var total = 0.0;
for(var i=0; i < xlist.length; ++i) {
var resultThisDatum = targetFunc(params, xlist[i]);
var delta = resultThisDatum - ylist[i];
total += (delta*delta);
}
return total;
};
return objective;
};
可以用来制造目标函数:
var objective = makeObjective(cubic, data_x, data_y); // then carry on as before
知道如何实际地做这件事对很多人都有很大的帮助,所以我很高兴这个问题被提出来了。编辑:关于cubic
的澄清
var cubic = function(params,x) {
return params[0] * x*x*x +
params[1] * x*x +
params[2] * x +
params[3];
};
Cubic被定义为一个函数,它接受一个参数数组params
和一个值x
。给定params
,我们可以定义函数f(x)
。对于一个立方,也就是f(x) = a x^3 + b x^2 + c x + d
,所以有4个参数([0]
到[3]
),给定这4个参数值,我们有一个单一的函数f(x)
和一个输入x
。
代码的结构允许您用相同结构的另一个函数替换cubic
;它可以是linear
和2个参数:
var linear = function(params, x) {
return params[0]*x + params[1];
};
代码的其余部分将查看params
的长度,以便知道需要修改多少参数。
注意,这一整段代码试图找到一组参数值,产生最适合所有数据的曲线;如果您想找到适合某些数据的最后4个点,则只传递data_x
和data_y
中的这些值。
我将其表述为最小二乘问题。设M为n×4矩阵:
x_1^3 x_1^2 x_1 1
x_2^3 x_2^2 x_2 1
⋮ ⋮ ⋮
x_n^3 x_n^2 x_n 1
然后计算4×4矩阵<我> = <我><一口> T 一口>⋅<我> 和4×1列向量b <我> = <我><一口> T 一口>⋅y <我> 和解决线性方程组<我>ξ = <我> 。得到的向量ξ将包含系数a到d。我>我>我>我>我>我>我>我>
上面的描述可以很容易地从数学上理解发生了什么。对于实现,特别是对于非常大的n,上述方法可能是不可行的。在这些情况下,您可以直接构建A和b,而无需显式地构建M。例如A1,2= sum(x_i^3 * x_i^2 for all i)
。因此,您可以遍历所有i并将相应的值添加到相应的矩阵和向量项中。