【问题标题】:Gradient descent in JavaJava中的梯度下降
【发布时间】:2015-11-17 03:35:47
【问题描述】:

我最近在 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,这里称为 learningRate。如果高于 0.00001,则发散。

您对如何优化实施有任何建议,或者对“Alpha-Issue”的解释和可能的解决方案吗?

更新:

这是主要的,包括一些示例输入:

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));
}

梯度下降的数学表达式如下:

【问题讨论】:

  • 您可能应该在main 方法中提供一些示例数据/输入,并可能提供指向您“翻译”的论坛的反向链接。
  • 我已经更新了问题,也发现了一个小问题。修复后,我现在可以将学习率设置为 0.0001。但我认为它仍然很低,但比以前好多了。
  • Coursera ML / AI 课程中的哪一个?斯坦福的机器学习?
  • 是的,这是斯坦福机器学习课程。一开始很有趣,但我不喜欢 Octave 中的练习(他们觉得太通用了),所以我开始用 Java 实现算法。

标签: java artificial-intelligence gradient-descent


【解决方案1】:

为了解决这个问题,有必要用这个公式对数据进行归一化:(Xi-mu)/s。 Xi是当前训练集的值,mu是当前列的平均值,s是最大值减去当前列的最小值。这个公式将使训练数据大约在 -1 和 1 之间的范围内,这允许选择更高的学习率和梯度下降来更快地收敛。 但之后有必要对预测结果进行非规范化。

【讨论】:

    【解决方案2】:
    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;
    

    在这个函数中。结果变量覆盖每次迭代,旧值丢失。输入值时,仅计算数组中的最后一项。其余的都无所谓。

    【讨论】:

    • 你是对的!谢谢你的建议!结果证明这是一个非常缓慢的随机梯度下降......仍然有效但速度很慢,因为所有样本都将被处理以仅使用一个样本更新参数。
    【解决方案3】:

    您应该使用 java.math.BigDecimal 进行算术运算。
    double 在执行任何算术运算时都有其舍入问题。

    【讨论】:

    • 这是一个疯狂的猜测,我几乎要否决这一点:只需将 double 替换为 BigDecimal 不一定能解决问题,这可能(!)与精度完全无关。 ...
    猜你喜欢
    • 2016-09-25
    • 1970-01-01
    • 2016-06-13
    • 1970-01-01
    • 2014-07-22
    • 2017-06-23
    • 2021-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多