最近看了一个三次样条拟合,用在浓度与检测值转换上
环境是node 4.x
先定义一个函数: y = f(x) = 3x^2 + 2x
然后在 [-50,50) 上采样一组数据,并添加白噪声。
function target(x){
return 3 * x * x + 2 * x // y = 3x^2 + 2x
}
var input = [], output = []
for(i=-50;i<50;i++){ fill test data input.push(i) output.push(target(i)+math.random()*3) with random errors } < code></50;i++){>
此时,input数组包含[-50,50)上的一组输入值,output数组包含对应的输出值。
问题:已知原函数的形式是 y = f(x) = ax^2 + bx,求 a 和 b。
首先定义我们的假设:y = p0x^2 + p1x,接受x为输入,以及params为参数数组。
function hypothesis(x,params){
return params[0] * x * x + params[1] * x
}
然后给待求参数指定一个初始值 (p0,p1) = (0,0)
var solution = [0,0]
然后我们定义误差函数。误差的定义是[给定参数下,函数的输出值(output)和实际输出值的RMSE]
function error_of_hypothesis(params){
var total_square_err = 0.0;
for(i in input){
var x = input[i]
var difference = hypothesis(x,params) - output[i]
total_square_err += difference * difference
}
return Math.sqrt(total_square_err/input.length) //RMSE
}
然后定义[梯度计算及下降]函数。[梯度]就是误差函数在点(p1,p2)处对p1,p2分别求偏导得到的矢量。说白了就是求那个点的“上坡方向”的矢量。
此处求偏导使用了数值方法。
function calculate_gradient_and_descend(stepsize){
// calculate error(p0,p1)
var err = error_of_hypothesis(solution)
// calculate gradient of error(p0,p1)
var delta = 0.00000001
var gradient = []
for(i in solution){
// calculate partial derivative of error(p0,p1)
var delta_solution = []
delta_solution[0] = solution[0]
delta_solution[1] = solution[1]
delta_solution[i] += delta
gradient[i] = (error_of_hypothesis(delta_solution) - err)/delta
}
// descend (p0,p1)
for(i in solution){
solution[i] -= gradient[i]*stepsize
}
return err
}
上面可以看到:每运行一次下降函数,solution矢量就会朝当前梯度方向的反方向前进stepsize距离。
这会让我们越来越接近谷底。
下面定义我们的梯度下降循环:
function run_descent(iterations,stepsize){
for(var i=0;i<iterations;i++){ var err="calculate_gradient_and_descend(stepsize)" if(i%(iterations 10)="=0||i">iterations-10){
console.log('-------------');
console.log('gradient descent iteration',i);
console.log('RMSE=',err);
console.log('solution:',solution,'after descent.');
}
}
return err
}
run_descent(1000,0.001)
run_descent(1000,0.0001)
run_descent(1000,0.00001)
run_descent(10000,0.000001)
</iterations;i++){>
结果:
-------------
gradient descent iteration 9997
RMSE= 1.2756225981845384
solution: [ 3.001084043830482, 2.001937055426506 ] after descent.
-------------
gradient descent iteration 9998
RMSE= 1.275622596459923
solution: [ 3.0010840438762454, 2.001937096928974 ] after descent.
-------------
gradient descent iteration 9999
RMSE= 1.275622594737627
solution: [ 3.0010840439171016, 2.0019371384060625 ] after descent.
引用 Cirno:ConvnetJS by Andrej Karparthy
Is there any matrix calculation packages for JavaScript? Just Like Numpy for Python
200字以内,仅用于支线交流,主线讨论请采用回复功能。