我最近在Coursera上开始了AI课程,我想请教一个关于我实现的梯度下降算法的问题。
这是我当前的实现(实际上我只是将数学表达式“翻译”成了Java代码):
public class GradientDescent { private static final double TOLERANCE = 1E-11; private double theta0; private double theta1; public double getTheta0() { return theta0; } public double getTheta1() { return theta1; } public GradientDescent(double theta0, double theta1) { this.theta0 = theta0; this.theta1 = theta1; } public double getHypothesisResult(double x){ return theta0 + theta1*x; } private double getResult(double[][] trainingData, boolean enableFactor){ double result = 0; for (int i = 0; i < trainingData.length; i++) { result = (getHypothesisResult(trainingData[i][0]) - trainingData[i][1]); if (enableFactor) result = result*trainingData[i][0]; } return result; } public void train(double learningRate, double[][] trainingData){ int iteration = 0; double delta0, delta1; do{ iteration++; System.out.println("SUBS: " + (learningRate*((double) 1/trainingData.length))*getResult(trainingData, false)); double temp0 = theta0 - learningRate*(((double) 1/trainingData.length)*getResult(trainingData, false)); double temp1 = theta1 - learningRate*(((double) 1/trainingData.length)*getResult(trainingData, true)); delta0 = theta0-temp0; delta1 = theta1-temp1; theta0 = temp0; theta1 = temp1; }while((Math.abs(delta0) + Math.abs(delta1)) > TOLERANCE); System.out.println(iteration); }}
这段代码运行得相当好,但前提是我选择了一个非常小的alpha,这里称为学习率。如果学习率高于0.00001,它就会发散。
你有什么关于如何优化这个实现的建议吗,或者对“Alpha问题”有一个解释以及可能的解决方案吗?
更新:
这是包含一些样本输入的主函数:
private static final double[][] TDATA = {{200, 20000},{300, 41000},{900, 141000},{800, 41000},{400, 51000},{500, 61500}};public static void main(String[] args) { GradientDescent gd = new GradientDescent(0,0); gd.train(0.00001, TDATA); System.out.println("THETA0: " + gd.getTheta0() + " - THETA1: " + gd.getTheta1()); System.out.println("PREDICTION: " + gd.getHypothesisResult(300));}
梯度下降的数学表达式如下:
回答:
为了解决这个问题,有必要使用以下公式对数据进行归一化:(Xi-mu)/s。Xi是当前训练集的值,mu是当前列中值的平均值,s是当前列的最大值减去最小值。这个公式将训练数据大致调整到-1到1之间的范围,这样可以选择更高的学习率,使得梯度下降更快地收敛。但之后需要对预测结果进行反归一化处理。