环境是node 4.x
先定义一个函数: y = f(x) = 3x^2 + 2x
然后在 [-50,50) 上采样一组数据,并添加白噪声。
<code class="language-js">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++){></code>
此时,input数组包含[-50,50)上的一组输入值,output数组包含对应的输出值。
问题:已知原函数的形式是 y = f(x) = ax^2 + bx,求 a 和 b。
首先定义我们的假设:y = p0x^2 + p1x,接受x为输入,以及params为参数数组。
<code class="language-js">function hypothesis(x,params){ return params[0] * x * x + params[1] * x } </code>
然后给待求参数指定一个初始值 (p0,p1) = (0,0)
<code class="language-js">var solution = [0,0] </code>
然后我们定义误差函数。误差的定义是[给定参数下,函数的输出值(output)和实际输出值的RMSE]
<code class="language-js">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 } </code>
然后定义[梯度计算及下降]函数。[梯度]就是误差函数在点(p1,p2)处对p1,p2分别求偏导得到的矢量。说白了就是求那个点的“上坡方向”的矢量。
此处求偏导使用了数值方法。
<code class="language-js">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 } </code>
上面可以看到:每运行一次下降函数,solution矢量就会朝当前梯度方向的反方向前进stepsize距离。
这会让我们越来越接近谷底。
下面定义我们的梯度下降循环:
<code class="language-js">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++){></code>
结果:
<code class="language-plaintext">------------- 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. </code>
时段 | 个数 |
---|---|
{{f.startingTime}}点 - {{f.endTime}}点 | {{f.fileCount}} |