簡體   English   中英

NNLS如何用於非負多元線性回歸?

[英]How to use NNLS for non-negative multiple linear regression?

我正在嘗試解決Java中的非負多重線性回歸問題。 我找到了用Scala編寫的求解器類org.apache.spark.mllib.optimization.NNLS 但是,我不知道該如何使用。

讓我感到困惑的是,以下方法的界面似乎很奇怪。 我以為A是一個MxN矩陣, b是一個M向量,自變量ataatb應該分別是NxN矩陣和N向量。 但是, ata的實際類型是double[]

public static double[] solve(double[] ata, double[] atb, NNLS.Workspace ws)

我搜索了示例代碼,但找不到。 誰能給我示例代碼? 該庫是用Scala編寫的,但如果可能,我需要Java代碼。

免責聲明我從未使用過NNLS而且對非負多元線性回歸一無所知。

您將看到Spark 2.1.1的NNLS您的要求,但是自從最新的Spark 2.2.1標記為private [spark]以來, 並不是走的路。

private[spark] object NNLS {

更重要的是,從Spark 2.0開始, org.apache.spark.mllib軟件包(包括NNLS所屬的org.apache.spark.mllib.optimization )處於維護模式

基於MLlib RDD的API現在處於維護模式。

從Spark 2.0開始,spark.mllib軟件包中基於RDD的API已進入維護模式。 Spark的主要機器學習API現在是spark.ml軟件包中基於DataFrame的API。

換句話說,您應該遠離軟件包,尤其是NNLS

那有什么選擇呢?

您可以查看NNLS的測試,即NNLSSuite ,可以在其中找到一些答案。

但是,ata的實際類型是double []。

那是一個矩陣,因此元素再次加倍。 實際上, ata直接傳遞給BLAS的dgemv在此處此處 ),在LAPACK文檔中進行了描述:

DGEMV執行矩陣矢量運算之一

 y := alpha*A*x + beta*y, or y := alpha*A**T*x + beta*y, 

其中alpha和beta是標量,x和y是向量,A是m×n矩陣。

那應該給你足夠的答案。


另一個問題是Spark MLlib中用於類似NNLS的計算的推薦方式是什么?

看起來Spark MLLib的ALS算法在幕后使用了 NNLS (對於機器學習從業人員來說並不奇怪)。

當ALS配置為在非負參數打開(即為true (默認為禁用)時訓練模型時,將使用該部分代碼。

非負參數是否應用非負約束。

默認值:false

是否對最小二乘使用非負約束

我建議您回顧一下Spark MLlib的這一部分,以更深入地了解NNLS在解決非負線性回歸問題中的用途。

我寫了一個測試代碼。 盡管我Failed to load implementation from: com.github.fommil.netlib.NativeSystemBLAS收到了諸如Failed to load implementation from: com.github.fommil.netlib.NativeSystemBLAS類的警告,但在簡單情況下它Failed to load implementation from: com.github.fommil.netlib.NativeSystemBLAS很好地工作,但是當m非常大(約3000)時, beta經常變為0。

package test;

import org.apache.spark.mllib.optimization.NNLS;

public class NNLSTest {
    public static void main(String[] args) {
        int n = 6, m = 300;
        ExampleInMatLabDoc();
        AllPositiveBetaNoiseInY(n, m);
        SomeNegativesInBeta(n, m);
        NoCorrelation(n, m);
    }

    private static void test(double[][] X, double[] y, double[] b) {        
        int m = X.length; int n = X[0].length;

        double[] Xty = new double[n];
        for (int i = 0; i < n; i++) {
            Xty[i] = 0.0;
            for (int j = 0; j < m; j++) Xty[i] += X[j][i] * y[j];
        }
        double[] XtX = new double[n * n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                XtX[n * i + j] = 0.0;
                for (int k = 0; k < m; k++) XtX[n * i + j] += X[k][i] * X[k][j];
            }
        }

        double[] beta = NNLS.solve(XtX, Xty, NNLS.createWorkspace(n));
        System.out.println("\ntrue beta\tbeta");
        for (int i = 0; i < beta.length; i++) System.out.println(b[i] + "\t" + beta[i]);

    }

    private static void ExampleInMatLabDoc() {
        // https://jp.mathworks.com/help/matlab/ref/lsqnonneg.html
        double[] y = new double[] { 0.8587, 0.1781, 0.0747, 0.8405 };
        double[][] x = new double[4][];
        x[0] = new double[] { 0.0372, 0.2869 };
        x[1] = new double[] { 0.6861, 0.7071 };
        x[2] = new double[] { 0.6233, 0.6245 };
        x[3] = new double[] { 0.6344, 0.6170 };
        double[] b = new double[] { 0.0, 0.6929 };
        test(x, y, b);
    }

    private static void AllPositiveBetaNoiseInY(int n, int m) {
        double[] b = new double[n];
        for (int i = 0; i < n; i++) b[i] = Math.random() * 100.0;       // random value in [0:100]
        double[] y = new double[m];
        double[][] x = new double[m][];
        for (int i = 0; i < m; i++) {
            x[i] = new double[n];
            x[i][0] = 1.0;
            y[i] = b[0];
            for (int j = 1; j < n; j++) {
                x[i][j] = (2.0 * Math.random() - 1.0) * 100.0; // random value in [-100:100]
                y[i] += x[i][j] * b[j];
            }
            y[i] *= 1.0 + (2.0 * Math.random() - 1.0) * 0.1; // add noise
        }
        test(x, y, b);
    }

    private static void SomeNegativesInBeta(int n, int m) {
        double[] b = new double[n];
        for (int i = 0; i < n; i++) b[i] = (2.0 * Math.random() - 1.0) * 100.0; // random value in [-100:100]
        double[] y = new double[m];
        double[][] x = new double[m][];
        for (int i = 0; i < m; i++) {
            x[i] = new double[n];
            x[i][0] = 1.0;
            y[i] = b[0];
            for (int j = 1; j < n; j++) {
                x[i][j] = (2.0 * Math.random() - 1.0) * 100.0; // random value in [-100:100]
                y[i] += x[i][j] * b[j];
            }
        }
        test(x, y, b);
    }

    private static void NoCorrelation(int n, int m) {
        double[] y = new double[m];
        double[][] x = new double[m][];
        for (int i = 0; i < m; i++) {
            x[i] = new double[n];
            x[i][0] = 1.0;
            for (int j = 1; j < n; j++) 
                x[i][j] = (2.0 * Math.random() - 1.0) * 100.0; // random value in [-100:100]
            y[i] = (2.0 * Math.random() - 1.0) * 100.0;
        }
        double[] b = new double[n];
        for (int i = 0; i < n; i++) b[i] = 0;
        test(x, y, b);
    }
}

暫無
暫無

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

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