Debugging 为什么逻辑回归中较高的学习率会产生NaN成本? 总结
我正在使用Octave和Ling垃圾邮件语料库构建垃圾邮件与火腿电子邮件的分类器;我的分类方法是逻辑回归 较高的学习率会导致计算成本的NaN值,但不会破坏/降低分类器本身的性能 我的尝试 NB:我的数据集已经使用平均归一化进行了归一化。 当我尝试选择学习速率时,我从0.1和400次迭代开始。这导致了以下绘图: 1-图1 当he行在几次迭代后完全消失时,这是由于产生了NaN值;我原以为这会导致参数值不正确,从而导致精度不高,但在检查精度时,我发现测试集的精度为95%(这意味着梯度下降显然仍在发挥作用)。我检查了学习率和迭代次数的不同值,以查看图表是如何变化的: 2-图2 线条不再消失,这意味着没有NaN值,但准确率为87%,大大降低了 我又做了两次测试,迭代次数更多,学习率略高,在这两次测试中,图形都如预期的那样随着迭代次数的增加而减少,但准确率约为86-88%。那里也没有南 我意识到我的数据集是扭曲的,只有481封垃圾邮件和2412封火腿邮件。因此,我计算了这些不同组合的FScore,希望发现后面的组合具有更高的FScore,并且精度是由于倾斜。事实也并非如此——我已将我的结果总结在一个表格中: 3-表格 因此,不存在过度拟合和倾斜似乎不是问题;我不知道现在该怎么办 我能想到的唯一一件事是,我对精确度和FScore的计算是错误的,或者我对行“消失”的初始调试是错误的 编辑:这个问题至关重要,它是关于为什么选择的学习率会出现NaN值。因此,我暂时采取的降低学习率的措施并没有真正回答我的问题——我一直认为较高的学习率只是分散而不是汇聚,不会产生NaN值。 我的代码 My main.m代码(从文件获取数据集的条形图): 我的gradDescent.m代码:Debugging 为什么逻辑回归中较高的学习率会产生NaN成本? 总结,debugging,machine-learning,octave,logistic-regression,Debugging,Machine Learning,Octave,Logistic Regression,我正在使用Octave和Ling垃圾邮件语料库构建垃圾邮件与火腿电子邮件的分类器;我的分类方法是逻辑回归 较高的学习率会导致计算成本的NaN值,但不会破坏/降低分类器本身的性能 我的尝试 NB:我的数据集已经使用平均归一化进行了归一化。 当我尝试选择学习速率时,我从0.1和400次迭代开始。这导致了以下绘图: 1-图1 当he行在几次迭代后完全消失时,这是由于产生了NaN值;我原以为这会导致参数值不正确,从而导致精度不高,但在检查精度时,我发现测试集的精度为95%(这意味着梯度下降显然仍在发挥
function [optimParams] = gradDescent(features, labels, learningRate, iterations, paramStart, featuresCV, labelsCV)
x_axis = [];
J_axis = [];
J_CV = [];
params = paramStart;
for i=1:iterations,
[cost, grad] = costFunction(features, labels, params);
[cost_CV] = costFunction(featuresCV, labelsCV, params);
params = params - (learningRate.*grad);
x_axis = [x_axis;i];
J_axis = [J_axis;cost];
J_CV = [J_CV;cost_CV];
endfor
graphics_toolkit("gnuplot")
plot(x_axis, J_axis, 'r', x_axis, J_CV, 'b');
legend("Training", "Cross-Validation");
xlabel("Iterations");
ylabel("Cost");
title("Cost as a function of iterations");
optimParams = params;
endfunction
My costFunction.m代码:
function [cost, grad] = costFunction(features, labels, params)
numRecords = length(labels);
hypothesis = sigmoid(features*params);
cost = (-1/numRecords)*sum((labels).*log(hypothesis)+(1-labels).*log(1-hypothesis));
grad = (1/numRecords)*(features'*(hypothesis-labels));
endfunction
我的predict.m代码:
function [accuracy, precision, recall] = predict(features, labels, params, threshold)
numRecords=length(labels);
predictions = sigmoid(features*params)>threshold;
correct = predictions == labels;
truePositives = sum(predictions == labels == 1);
falsePositives = sum((predictions == 1) != labels);
falseNegatives = sum((predictions == 0) != labels);
precision = truePositives/(truePositives+falsePositives);
recall = truePositives/(truePositives+falseNegatives);
accuracy = 100*(sum(correct)/numRecords);
endfunction
到期信用:
一个很大的帮助是这个答案:所以这个问题有点重复,但我没有意识到,一开始也不明显。。。我将尽我所能解释为什么解决方案也有效,以避免简单地复制答案
解决方案:
问题实际上是我的数据中出现的0*log(0)=NaN结果。为了解决这个问题,在我计算成本时,它变成了:
cost = (-1/numRecords)*sum((labels).*log(hypothesis)+(1-labels).*log(1-hypothesis+eps(numRecords, 1)));
(关于变量值等,请参见问题,仅当这一行发生变化时,包含其余变量似乎是多余的)
说明:
eps()函数的定义如下:
返回一个标量、矩阵或N维数组,其元素均为
eps,该机精度高
更准确地说,eps是任意两个相邻的
机器浮点系统中的数字。此数字为
显然是系统依赖的。在支持IEEE浮动的计算机上
点运算,eps约为2.2204e-16,用于双精度
单精度为1.1921e-07
当使用多个参数调用时,前两个参数是
作为行数、列数和任何其他参数
指定其他矩阵尺寸。可选参数类
指定返回类型,可以是“双精度”或“单精度”
这意味着将这个值添加到由Sigmoid函数计算的值上(它以前非常接近0,所以被认为是0)意味着它是最接近0的值,而不是0,使得log()不返回-Inf
在学习率为0.1、迭代次数为2000/1000/400的情况下进行测试时,绘制了完整的图形,检查时未生成NaN值
注意:如果有人想知道,在这之后,精确度和FScores没有变化,因此精确度确实很高,尽管在计算成本时存在错误,但学习率较高。学分到期:
一个很大的帮助是这个答案:所以这个问题有点重复,但我没有意识到,一开始也不明显。。。我将尽我所能解释为什么解决方案也有效,以避免简单地复制答案
解决方案:
问题实际上是我的数据中出现的0*log(0)=NaN结果。为了解决这个问题,在我计算成本时,它变成了:
cost = (-1/numRecords)*sum((labels).*log(hypothesis)+(1-labels).*log(1-hypothesis+eps(numRecords, 1)));
(关于变量值等,请参见问题,仅当这一行发生变化时,包含其余变量似乎是多余的)
说明:
eps()函数的定义如下:
返回一个标量、矩阵或N维数组,其元素均为
eps,该机精度高
更准确地说,eps是任意两个相邻的
机器浮点系统中的数字。此数字为
显然是系统依赖的。在支持IEEE浮动的计算机上
点运算,eps约为2.2204e-16,用于双精度
单精度为1.1921e-07
当使用多个参数调用时,前两个参数是
作为行数、列数和任何其他参数
指定其他矩阵尺寸。可选参数类
指定返回类型,可以是“双精度”或“单精度”
这意味着将这个值添加到由Sigmoid函数计算的值上(它以前非常接近0,所以被认为是0)意味着它是最接近0的值,而不是0,使得log()不返回-Inf
<