Javascript 逻辑回归不可推广

Javascript 逻辑回归不可推广,javascript,machine-learning,linear-regression,gradient-descent,Javascript,Machine Learning,Linear Regression,Gradient Descent,根据Andrew Ng关于逻辑回归的讲座,可以使用以下更新表达式最小化以下成本函数: 在大约150个样本上运行该更新函数数百次,我得到了以下模式,尽管每次迭代后成本似乎会如预期的那样下降: 圆圈是我正在训练的样本,其中输入特征是每个点的x、y坐标,颜色是目标标签。红色或黄色背景是模型预测的x,y输入分类为红色=0,黄色=1 问题 更新程序不是相应成本函数J的正确偏导数吗? 此输出模式可以表示什么? 训练方法 样本训练数据 编辑 这里有一个JSBin:您的问题纯粹是数值问题,因为您直接实现了逻辑损

根据Andrew Ng关于逻辑回归的讲座,可以使用以下更新表达式最小化以下成本函数:

在大约150个样本上运行该更新函数数百次,我得到了以下模式,尽管每次迭代后成本似乎会如预期的那样下降:

圆圈是我正在训练的样本,其中输入特征是每个点的x、y坐标,颜色是目标标签。红色或黄色背景是模型预测的x,y输入分类为红色=0,黄色=1

问题 更新程序不是相应成本函数J的正确偏导数吗? 此输出模式可以表示什么? 训练方法 样本训练数据 编辑
这里有一个JSBin:

您的问题纯粹是数值问题,因为您直接实现了逻辑损耗,所以您的函数J需要取一个点的指数。同时,你的数据是巨大的,你的x/y坐标是巨大的。exp400导致JS中出现NAN,因此您的整个代码无法收敛。您只需将点放置在[0,2]x[0,4]而不是[0200]x[0,400]矩形中,即可正常工作

例如:

函数sumx,w{ 返回x.reduceacc,x,i=>acc+x*w[i],0; } 函数sigz{ 返回1/1+Math.exp-z; } 函数、分数、标签{ return-1/scores.length*scores.reduceac,score,i=>{ 变量y=标签[i][0]; 返回y*Math.logscore+1-y*Math.log1-score; }, 0; } 函数clearctx{ ctx.clearRect0,0400200; } 函数renderctx,点{ points.forEachpoint=>{ 如果点[2]>0{ ctx.fillStyle='3c5cf'; }否则{ ctx.fillStyle='f956ff'; } ctx.fillRectMath.max0,点[0]*100-2,点[1]*100-2,4,4; //ctx.fillRectpoint[0],point[1],1,1; } } 函数renderachctx,参数{ 对于设y=0;y<200;y++{ 对于设x=0;x<400;x++{ 如果sigsum[1,x/100,y/100],参数<0.5{ ctx.fillStyle='b22438'; }否则{ ctx.fillStyle='fff9b6'; } ctx.fillRectx,y,1,1; } } } 函数doEpochsamples,params,learningRate,lastCost,cycle,maxCycles{ var scores=samples.mapsample=>sigsumsample,params; var errors=scores.mapscore,i=>score-labels[i][0]; var p=document.getElementById'log'; 如果{ p=document.createElement'p'; p、 setAttribute'id','log'; document.body.p; } params=params.mapparam,col=>{ 返回参数-learningRate*errors.reduceacc,error,row=>acc+error*samples[row][col],0; }; var J=成本分数、标签; 如果lastCost==null{ 最后成本=J; } 如果周期%100==0{ p、 textContent=`Epoch=${cycle},Cost=${J}${J-lastCost},Params=${JSON.stringifyparams,null,2}`; clearctx; renderachctx,参数; renderctx,点; } 如果周期<最大周期{ setTimeoutfunction{ doEpochsamples,参数,学习率,J,周期+1,最大周期; }, 10; } } var canvas=document.createElement'canvas'; 画布宽度=400; 画布高度=200; document.body.appendChildcanvas; var ctx=canvas.getContext'2d'; var-lineY=150; var点=[]; 对于let i=0;i<500;i++{ var point=[parseIntMath.random*canvas.width,10/100,parseIntMath.random*canvas.height,10/100]; 点.pushNumberpoint[1][point[0],point[1]]; var labels=points.mappoint=>[point[2]]; log'Samples',JSON.stringifysamples.slice0,10; log'Labels',JSON.stringifylabels.slice0,10; var params=[1]。concatsamples[0]。map=>Math.random; var withBias=samples.mapsample=>[1].concatsample; var历元=100000; var学习率=0.01; var lastCost=null; doEpochwithBias,参数,学习率,最后成本,0,时代; 身体{ 背景:eee; 填充:0; 保证金:0; 字体系列:monospace; } 帆布{ 背景:fff; 宽度:100%; 图像渲染:像素化; }
你可能应该把这篇文章发到网上。@Derek朕會功夫: CS可能会得到更好的回答,但我认为这里的问题很好:这是一个特定的编程问题。@rodrigo silveira:你能给我们一个完整的MCVE驱动程序和一些示例案例的迭代输出吗?@Prune我已经编辑了我的帖子,其中有一个JSBIN链接。非常感谢!
// A single pass/epoch

const lr = 0.003;
let params = [0.5, 0.5, 0.5];

const scores = samples.map(sample => sig(sum(sample, params));
const errors = scores.map((score, i) => score - labels[i][0]);

params = params.map((param, col) => {
  return param - lr * errors.reduce((acc, error, row) => {
    return acc + error * samples[row][col];
  }, 0);
});
const samples = [
  [1, 142, 78],
  [1, 108, 182],
  [1, 396, 47],
  [1, 66,  102],
  [1, 165, 116],
  [1, 8,   106],
  [1, 245, 119],
  [1, 302, 17],
  [1, 96,  38],
  [1, 201, 132],
];

const labels = [
  [0],
  [1],
  [0],
  [0],
  [1],
  [1],
  [1],
  [0],
  [1],
];