可视化梯度下降线性回归 - 拦截参数未得到很好的学习。

时间:2014-07-07 19:01:39

标签: javascript d3.js statistics data-visualization gradient-descent

我正在为单变量线性回归编写一个小的d3.js可视化,其中两个参数是通过成本函数的梯度下降来学习的(平方误差之和a.k. a。 SSE ))。

到目前为止,我们可以看到最适合调整的线条,因为梯度下降会逐渐减少成本最小化的参数选择,“alpha'和' beta'”,其中

 y_i = alpha + beta * x_i

在javascript中,数据表示为具有' x'的对象数组。并且' y'属性。数据生成如下:

  1. 首先, X 是从'lowBound'之间的均匀分布中采样的。和' upBound'
  2. 接下来,根据数据生成过程对 Y 进行采样: y = 3x - 10 +错误,
  3. 其中误差从正态分布中采样,均值为零且方差 errorVariance

    我已经编写了一些d3.js代码来实现渐变下降,当我观察可视化时,似乎没有正确学习拦截术语。这是因为算法经常调整斜率参数,但仅从其初始值(随机选择)稍微调整截距参数。有三种可能性:

    1. 我在数学方面犯了错误(或者数学的javascript代表)。
    2. 我在我的可视化中犯了一个错误(例如d3 SVG的东西)。
    3. 我没有犯过任何错误, SSE 相对于拦截参数 alpha 的偏导数远小于斜率参数因此,梯度下降不会很多地调整 alpha 是有道理的。
    4. 我无法弄清楚答案是什么。因此,我将发布一个简化的代码设置,希望有人能够为我提供一些启示。您还可以以当前形式查看可视化(并查看完整源代码)here。我们现在只担心数学问题。如果有人希望我发布将数据加入svg元素的代码,我很乐意,但我认为这个问题更可能出现在这里。

        // Section 1: GENERATE DATA                                                      
      
      
        var n = 60;                                                                      
        var upBound = 20;                                                                
        var lowBound = -20;                                                              
        var errorVariance = 6;                                                           
        var data = []                                                                    
      
      
        // grab a random x value.                                                        
        var randomX = function() {                                                       
            return Math.random() * (upBound - lowBound) + lowBound;                      
        }                                                                                
      
        // zero-mean normally distributed error.                                         
        var error = d3.random.normal(0, errorVariance);                                  
      
        // The following function defines the "data-generating-process":                 
        // y = 3x - 10 + error                                                           
        var dgp = function(x) {                                                          
            return 3*x - 10 + error();                                                   
        }                                                                                
      
        // Randomly generate data according to the dgp.                                  
        for (var i = 0; i < n; i++) {                                                    
            var newX = randomX()                                                         
            var newY = dgp(newX);                                                        
            data.push({                                                                  
                "x": newX,                                                               
                "y": newY                                                                
            });                                                                          
        } 
      

      这一切都很好,花花公子。然后在第2节中,我提供了用于执行梯度描述的实用程序。

        // define parameters for Gradient Descent                                                                                                       
        var learningRate = 0.00001;                                                                                                                     
        var convThreshold = 0.005;                                                                                                                      
      
      
        // Per Observation Cost Function                                                                                                                
        var obsCost = function(alpha, beta, data, i) {                                                                                                  
            return .5 * Math.pow(((alpha + beta * data[i]["x"]) - data[i]["y"]), 2);                                                                    
        }                                                                                                                                               
      
        // Sum of Squared Errors                                                                                                                        
        var costFuncLR = function(alpha, beta, data) {                                                                                                  
            var sse = 0;                                                                                                                                
            for (var j = 0; j < n; j++) {                                                                                                               
                sse += obsCost(alpha, beta, data, j);                                                                                                   
            }                                                                                                                                           
            return sse;                                                                                                                                 
        }                                                                                                                                               
      
        var obsErr = function(alpha, beta, data, i) {                                                                                                   
            return (alpha + data[i]["x"] * beta) - data[i]["y"];                                                                                        
        }                                                                                                                                               
      
        // Partial derivative of cost w.r.t. alpha                                                                                                      
        var pJpAlpha = function(alpha, beta, data) {                                                                                                    
            var sum = 0;                                                                                                                                
            for (var i = 0; i < n; i++) {                                                                                                               
                sum += obsErr(alpha, beta, data, i);                                                                                                    
            }                                                                                                                                           
            //return sum;                                                                                                                               
            return Math.sqrt(2 * costFuncLR(alpha, beta, data));                                                                                        
        }                                                                                                                                               
      
        // Partial derivative of cost w.r.t. beta                                                                                                       
        var pJpBeta = function(alpha, beta, data) {   
           var sum = 0                                                                                                                                 
            for (var j = 0; j < n; j++ ) {                                                                                                              
                sum += obsErr(alpha, beta, data, j) * data[j]["x"];                                                                                     
            }                                                                                                                                           
            return sum;                                                                                                                                 
        }                                                                                                                                               
      
        // Performs one iteration of Gradient Descent.                                                                                                  
        var gradientDescentIter = function(data, alphaOld, betaOld, learningRate) {                                                                     
            var pjpa = pJpAlpha(alphaOld, betaOld, data)                                                                                                
            var pjpb = pJpBeta(alphaOld, betaOld, data)                                                                                                 
            var temp0 = alphaOld - (learningRate * pjpa);                                                                                               
            var temp1 = betaOld - (learningRate * pjpb);                                                                                                
            var alphaNew = temp0;                                                                                                                       
            var betaNew = temp1;                                                                                                                        
            var out = [];                                                                                                                               
            out.push(alphaNew);                                                                                                                         
            out.push(betaNew);                                                                                                                          
            console.log(costFuncLR(alphaNew, betaNew, data));                                                                                           
            return out;                                                                                                                                 
        }                       
      

      我提前感谢您的帮助。

      有些不相关,我想通过参数空间中的等高线图或欧几里德3空间中嵌入的表面(z轴为成本)显示成本函数的水平集,并观察参数也改变了那个空间。我找到了mike bostock关于如何使用等高线图的帖子,但是

0 个答案:

没有答案