簡體   English   中英

在Java Lambda中使用兩個流來計算協方差

[英]Using two streams in Java lambda to compute covariance

假設我有兩個double數組。 我一直在嘗試使用Java 8中的Stream。我想我已經理解了主要思想,但是后來我意識到我不確定如何同時操作兩個Stream。

例如,我要計算兩個數組的協方差。

public class foo {

    public static double mean(double[] xs) {
        return Arrays.stream(xs).average().getAsDouble();
}

    public static void main(String[] args) {
        double[] xs = {1, 2, 3, 4, 5, 6, 7, 8, 9};
        double[] ys = {1517.93, 1757.78, 1981.1, 2215.73, 2942.66, 3558.32, 4063.91, 4521.16, 5101.76, 5234.12};

        System.out.println("Mean of xs: " + mean(xs));
        double xs_sumDeviation = Arrays.stream(xs)
            .boxed()
            .mapToDouble(d -> d.doubleValue() - mean(xs))
            .sum();
       // Covariance
        double covXY = Arrays.stream(xs, ys)
            .mapToDouble(x,y -> {
                  double numerator = (x-mean(xs)* (y-mean(ys);
                  double denominator = Math.sqrt((x-mean(xs)* (x-mean(xs));
                  return numerator / denominator;
             })
            .sum();

    }
}

謝謝你的建議。

嘗試1。

public static double covariance(double[] xs, double[] ys) {
    double xmean = mean(xs);
    double ymean = mean(ys);
    double numerator = IntStream.range(0, Math.min(xs.length, ys.length))
            .parallel()
            .mapToDouble(i -> (xs[i] - xmean) * (ys[i] - ymean))
            .sum();
    double denominator = Math.sqrt(IntStream.range(0, xs.length)
            .parallel()
            .mapToDouble(i -> (xs[i] - xmean) * (xs[i] - xmean))
            .sum());
    return numerator / denominator;

在其他編程語言中,存在某種zip函數,該函數需要多個iterables ,並返回一個迭代器 ,該迭代器聚合每個iterables中的元素。 例如,請參見Python庫中的函數zip

盡管可以在Java中實現類似的功能,但是很難以這種方式實現它,因為它支持有效的並行執行。 但是,Java中有一個常用的模式,有些不同。 就您而言,它可能如下所示:

public static double covariance(double[] xs, double[] ys) {
    double xmean = mean(xs);
    double ymean = mean(ys);
    return IntStream.range(0, Math.min(xs.length, ys.length))
        .parallel()
        .mapToDouble(i -> {
                double numerator = (xs[i] - xmean) * (ys[i] - ymean);
                double denominator = ...;
                return numerator / denominator;
            })
        .sum();
}

無需合並兩個流,而是創建具有所有索引的IntStream ,然后按索引訪問不同集合的元素。 只要這些集合支持隨機訪問操作,它就可以很好地工作。

其他FP語言具有zip操作,該操作由兩個元素流組成一對對 Java尚未提供此功能。

但是,在使用數組的情況下,您可以輕松地生成數組索引流,並讓您的函數關閉數組,並通過index參數訪問它們。

我也應該警告你

.mapToDouble(d -> d.doubleValue() - mean(xs))

您使程序復雜度為O(n 2 ),因為在每一步都要重新計算mean 您應該對此進行預先計算並在lambda中關閉結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM