Beispiel #1
0
  @Test
  public void testInclinedPlane() throws IOException {
    DoubleMatrix1D normal = new DenseDoubleMatrix1D(3);
    normal.assign(new double[] {.0, .0, 1.0});

    InclinedPlane3D inclinedPlane = new InclinedPlane3D();
    inclinedPlane.setRandomGenerator(new MersenneTwister(123456789));
    inclinedPlane.setNormal(normal);
    inclinedPlane.setBounds(new Rectangle(-5, -5, 10, 10));
    inclinedPlane.setNoiseStd(0.5);
    DoubleMatrix2D data = inclinedPlane.generate(10);

    SVDPCA pca = new SVDPCA(data);

    System.out.println("Eigenvalues:");
    System.out.println(pca.getEigenvalues());

    System.out.println("Eigenvectors:");
    System.out.println(pca.getEigenvectors());

    System.out.println("Meanvector:");
    System.out.println(pca.getMean());

    // Recalculate the input from a truncated SVD, first calculate the mean
    DoubleMatrix1D mean = new SparseDoubleMatrix1D(3);
    for (int i = 0; i < data.rows(); ++i) {
      mean.assign(data.viewRow(i), Functions.plus);
    }
    mean.assign(Functions.div(data.rows()));

    // Truncate the SVD and calculate the coefficient matrix
    DenseDoubleMatrix2D coefficients = new DenseDoubleMatrix2D(data.rows(), 2);
    DoubleMatrix2D centeredInput = data.copy();
    for (int i = 0; i < data.rows(); ++i) {
      centeredInput.viewRow(i).assign(mean, Functions.minus);
    }
    centeredInput.zMult(
        pca.getEigenvectors().viewPart(0, 0, 2, 3), coefficients, 1, 0, false, true);

    // Reconstruct the data from the lower dimensional information
    DoubleMatrix2D reconstruction = data.copy();
    for (int i = 0; i < reconstruction.rows(); ++i) {
      reconstruction.viewRow(i).assign(mean);
    }
    coefficients.zMult(
        pca.getEigenvectors().viewPart(0, 0, 2, 3), reconstruction, 1, 1, false, false);

    // Output to file (can be read by GNU Plot)
    String fileName = "inclined-plane-svd-pca.dat";
    String packagePath = this.getClass().getPackage().getName().replaceAll("\\.", "/");
    File outputFile = new File("src/test/resources/" + packagePath + "/" + fileName);
    PrintWriter writer = new PrintWriter(outputFile);
    writer.write(data.toString());
    writer.close();
  }
  private double multiLL(DoubleMatrix2D coeffs, Node dep, List<Node> indep) {

    DoubleMatrix2D indepData =
        factory2D.make(internalData.subsetColumns(indep).getDoubleData().toArray());
    List<Node> depList = new ArrayList<>();
    depList.add(dep);
    DoubleMatrix2D depData =
        factory2D.make(internalData.subsetColumns(depList).getDoubleData().toArray());

    int N = indepData.rows();
    DoubleMatrix2D probs =
        Algebra.DEFAULT.mult(factory2D.appendColumns(factory2D.make(N, 1, 1.0), indepData), coeffs);

    probs =
        factory2D
            .appendColumns(factory2D.make(indepData.rows(), 1, 1.0), probs)
            .assign(Functions.exp);
    double ll = 0;
    for (int i = 0; i < N; i++) {
      DoubleMatrix1D curRow = probs.viewRow(i);
      curRow.assign(Functions.div(curRow.zSum()));
      ll += Math.log(curRow.get((int) depData.get(i, 0)));
    }
    return ll;
  }
Beispiel #3
0
  /**
   * Feature-specific contribution to the prediction of the value of an instance.
   *
   * @param x instance
   * @param i index of the feature of interest
   * @param xi value of the feature of interest
   * @return value of the contribution of the feature to the prediction
   */
  public double prediction(I x, int i, double xi) {
    double wi = w.getQuick(i);
    DoubleMatrix1D mi = m.viewRow(i);

    double pred = 0.0;

    pred += xi * wi;

    pred +=
        x.operate(
            (j, xj) -> {
              DoubleMatrix1D mj = m.viewRow(j);

              return xi * xj * mi.zDotProduct(mj);
            },
            (v1, v2) -> v1 + v2);

    return pred;
  }
 /**
  * Classifies an instance w.r.t. the partitions found. It applies a naive min-distance algorithm.
  *
  * @param instance the instance to classify
  * @return the cluster that contains the nearest point to the instance
  */
 public int clusterInstance(Instance instance) throws java.lang.Exception {
   DoubleMatrix1D u = DoubleFactory1D.dense.make(instance.toDoubleArray());
   double min_dist = Double.POSITIVE_INFINITY;
   int c = -1;
   for (int i = 0; i < v.rows(); i++) {
     double dist = distnorm2(u, v.viewRow(i));
     if (dist < min_dist) {
       c = cluster[i];
       min_dist = dist;
     }
   }
   return c;
 }
Beispiel #5
0
  /**
   * Predict the value of an instance.
   *
   * @param x instance
   * @return value of prediction
   */
  public double prediction(I x) {
    double pred = b;

    DoubleMatrix1D xm = new DenseDoubleMatrix1D(m.columns());
    pred +=
        x.operate(
            (i, xi) -> {
              double wi = w.getQuick(i);
              DoubleMatrix1D mi = m.viewRow(i);

              xm.assign(mi, (r, s) -> r + xi * s);

              return xi * wi - 0.5 * xi * xi * mi.zDotProduct(mi);
            },
            (v1, v2) -> v1 + v2);

    pred += 0.5 * xm.zDotProduct(xm);

    return pred;
  }
  /**
   * Returns the best cut of a graph w.r.t. the degree of dissimilarity between points of different
   * partitions and the degree of similarity between points of the same partition.
   *
   * @param W the weight matrix of the graph
   * @return an array of two elements, each of these contains the points of a partition
   */
  protected static int[][] bestCut(DoubleMatrix2D W) {
    int n = W.columns();
    // Builds the diagonal matrices D and D^(-1/2) (represented as their diagonals)
    DoubleMatrix1D d = DoubleFactory1D.dense.make(n);
    DoubleMatrix1D d_minus_1_2 = DoubleFactory1D.dense.make(n);
    for (int i = 0; i < n; i++) {
      double d_i = W.viewRow(i).zSum();
      d.set(i, d_i);
      d_minus_1_2.set(i, 1 / Math.sqrt(d_i));
    }
    DoubleMatrix2D D = DoubleFactory2D.sparse.diagonal(d);

    // System.out.println("DoubleMatrix2D :\n"+D.toString());

    DoubleMatrix2D X = D.copy();

    // System.out.println("DoubleMatrix2D copy :\n"+X.toString());

    // X = D^(-1/2) * (D - W) * D^(-1/2)
    X.assign(W, Functions.minus);
    // System.out.println("DoubleMatrix2D X: (D-W) :\n"+X.toString());
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++)
        X.set(i, j, X.get(i, j) * d_minus_1_2.get(i) * d_minus_1_2.get(j));

    // Computes the eigenvalues and the eigenvectors of X
    EigenvalueDecomposition e = new EigenvalueDecomposition(X);
    DoubleMatrix1D lambda = e.getRealEigenvalues();

    // Selects the eigenvector z_2 associated with the second smallest eigenvalue
    // Creates a map that contains the pairs <index, eigenvalue>
    AbstractIntDoubleMap map = new OpenIntDoubleHashMap(n);
    for (int i = 0; i < n; i++) map.put(i, Math.abs(lambda.get(i)));
    IntArrayList list = new IntArrayList();
    // Sorts the map on the value
    map.keysSortedByValue(list);
    // Gets the index of the second smallest element
    int i_2 = list.get(1);

    // y_2 = D^(-1/2) * z_2
    DoubleMatrix1D y_2 = e.getV().viewColumn(i_2).copy();
    y_2.assign(d_minus_1_2, Functions.mult);

    // Creates a map that contains the pairs <i, y_2[i]>
    map.clear();
    for (int i = 0; i < n; i++) map.put(i, y_2.get(i));
    // Sorts the map on the value
    map.keysSortedByValue(list);
    // Search the element in the map previuosly ordered that minimizes the cut
    // of the partition
    double best_cut = Double.POSITIVE_INFINITY;
    int[][] partition = new int[2][];

    // The array v contains all the elements of the graph ordered by their
    // projection on vector y_2
    int[] v = list.elements();
    // For each admissible splitting point i
    for (int i = 1; i < n; i++) {
      // The array a contains all the elements that have a projection on vector
      // y_2 less or equal to the one of i-th element
      // The array b contains the remaining elements
      int[] a = new int[i];
      int[] b = new int[n - i];
      System.arraycopy(v, 0, a, 0, i);
      System.arraycopy(v, i, b, 0, n - i);
      double cut = Ncut(W, a, b, v);
      if (cut < best_cut) {
        best_cut = cut;
        partition[0] = a;
        partition[1] = b;
      }
    }

    // System.out.println("Partition:");
    // UtilsJS.printMatrix(partition);

    return partition;
  }
  /**
   * Gibt die Lösung x des Gleichungssystems zurück: nur eindeutige (d.h. parameterunabhängige xi)
   * werden zurückgegeben. index 0: Wert = 0 bedeutet xi unbestimmt, Wert = 1 bedeutet xi bestimmt
   * index 1: eigentlicher Wert (nur wenn xi bestimmt, dh index 0 = 1, sonst Wert 0)
   */
  public final double[][] solve() throws ArithmeticException {

    // --------------------------------------------------------------------------
    // EIGENTLICHER SOLVER für bestimmte Lösungsvariablen in unbestimmen Systemen
    // --------------------------------------------------------------------------

    int gebrauchteUnbestParam = 0;
    x =
        new double[A.columns()]
            [2 + anzUnbestParam]; // Status 1 (bestimmt), kN, alpha, beta (Parameter)

    int z = A.rows() - 1; // Zeilenvariable, beginnt zuunterst

    // Gleichungen mit lauter Nullen
    while (R.viewRow(z).cardinality() == 0 // nachfolgende Tests massgebend, dieser jedoch schnell
        || (Fkt.max(R.viewRow(z).toArray()) < TOL && Fkt.min(R.viewRow(z).toArray()) > -TOL)) {
      double cwert;
      if (z < c.rows()) cwert = c.get(z, 0);
      else cwert = 0;
      if (Math.abs(cwert) > TOL) {
        System.out.println("widersprüchliche Gleichungen im System! Zeile " + z);
        throw new ArithmeticException("Widerspruch im Gleichungssystem!");
      }
      z--;
      if (z <= 0) {
        System.out.println("lauter Nullen im GLS");
        break;
      }
    }

    // Verarbeiten der Gleichungen (von unten her)
    for (z = z; z >= 0; z--) {
      // finde erste nicht-Null in Zeile (Pivot)
      int p = -1; // Pivot: erste Zahl welche nicht null ist
      pivotfinden:
      for (int i = 0; i < R.columns(); i++) {
        if (Math.abs(R.get(z, i))
            > TOL) { // Versuch, numerische Probleme (Überbestimmtheit) zu vermeiden
          p = i;
          break pivotfinden;
        }
      }

      // Fall Kein Pivot gefunden (d.h. linker Teil der Gleichung aus lauter Nullen)
      if (p < 0) {
        if (debug) System.out.println("Warnung: kein Pivot gefunden in Zeile " + z);
        // Kontrolle, ob rechte Seite (c) auch null --> ok, sonst Widerspruch im GLS
        if (Math.abs(c.get(z, 0)) > TOL) {
          System.out.println("widersprüchliche Gleichungen im System! Zeile " + z);
          throw new ArithmeticException("Widerspruch im Gleichungssystem!");
        } else {
          if (debug)
            System.out.println("Entwarnung: Zeile " + z + " besteht aus lauter Nullen (ok)");
          continue;
        }
      }

      // kontrollieren, ob es in der Gleichung (Zeile) eine neue Unbestimmte Variable (i.d.R. Pivot)
      // hat.
      boolean alleVarBestimmt = true;
      int effPivot = p; // effektiver Pivot (1. Unbestimmte Variable der Zeile), i.d.R. Pivot
      for (int i = p; i < R.columns(); i++) {
        if (x[i][0] == 0 && Math.abs(R.viewRow(z).get(i)) > TOL) {
          alleVarBestimmt = false;
          effPivot = i; // i.d.R. effPivot=p, aber nicht immer.
          break;
        }
      }

      if (alleVarBestimmt) { // alle Variablen (inkl.Pivot) schon bestimmt!
        // CHECKEN, ob (Zeile "+z+") nicht widersprüchlich
        double[] kontrolle = new double[1 + anzUnbestParam];
        for (int j = 0; j < kontrolle.length; j++) kontrolle[j] = 0;
        for (int i = p; i < R.columns(); i++) {
          for (int j = 0; j < kontrolle.length; j++) {
            kontrolle[j] += R.viewRow(z).get(i) * x[i][j + 1];
          }
        }
        kontrolle[0] -= c.get(z, 0);

        // TODO TESTEN!
        boolean alleParamNull = true;
        int bekParam = -1; // Parameter der aus der Gleichung bestimmt werden kann.
        for (int j = kontrolle.length - 1; j > 0; j--) {
          if (Math.abs(kontrolle[j]) > TOL) {
            alleParamNull = false;
            if (bekParam < 0) bekParam = j;
          }
        }
        // Überprüfen, ob Gleichung widersprüchlich ist
        if (alleParamNull) { // TODO ev. nochmals prüfen ob alle 0 mit geringerer Toleranz (Problem
                             // fastNull*Param ≠ 0 könnte bedeuten dass Param = 0). Zumindestens
                             // wenn noch Parameter zu vergeben.
          double obnull = Math.abs(kontrolle[0]);
          if (obnull > TOL) {
            System.out.println("");
            System.out.println(
                "Widerspruch im Gleichungssystem! (Zeile "
                    + z
                    + ") "
                    + obnull
                    + " ungleich 0"); // TODO: URSPRÜNGLICH ZEILE (piv) ANGEBEN!
            System.out.println("eventuell numerisches Problem");
            throw new ArithmeticException("Widerspruch im Gleichungssystem!");
          } else continue; // nächste Gleichung
        }
        // else
        // Ein schon vergebener Parameter kann ausgerechnet werden

        // Schlaufe über bisherige Lösung
        assert bekParam > 0;
        for (int xi = 0; xi < x.length; xi++) {
          double faktor = x[xi][1 + bekParam];
          if (Math.abs(faktor) < TOL) continue;
          // Einsetzen
          assert x[xi][0] > 0; // bestimmt
          for (int j = 0; j < kontrolle.length; j++) {
            if (j != bekParam) {
              x[xi][j + 1] += -kontrolle[j] * faktor / kontrolle[bekParam];
            }
          }
        }
        for (int xi = 0; xi < x.length; xi++) {
          // Parameter nachrutschen
          if (bekParam < anzUnbestParam) { // d.h. nicht der letzte zu vergebende Parameter.
            for (int j = bekParam; j < anzUnbestParam; j++) {
              x[xi][j + 1] = x[xi][j + 2];
              x[xi][j + 2] = 0;
            }
          } else x[xi][bekParam + 1] = 0;
        }
        if (debug)
          System.err.println(
              "VORSICHT, wenig GETESTETES Modul des Solvers im Einsatz."); // TODO Warnung
                                                                           // entfernen, da
                                                                           // vermutlich i.O.
        gebrauchteUnbestParam--;
      }

      // Normalfall, unbestimmter (effektiver) Pivot vorhanden
      else {

        // unbekannte
        x[effPivot][1] = c.get(z, 0) / R.viewRow(z).get(effPivot);
        for (int i = R.columns() - 1; i >= p; i--) { // R.Spalten, da dies AnzUnbek x entspricht
          if (i == effPivot) continue;
          if (x[i][0] == 0) { // unbestimmt, aber nicht Pivot
            if (Math.abs(R.viewRow(z).get(i)) > TOL) { // TODO testen!!!
              if (gebrauchteUnbestParam >= anzUnbestParam) {
                System.err.println(
                    "Programmfehler in solver: gebrauchteUnbestParam >= anzUnbestParam");
                throw new AssertionError(
                    "Programmfehler in solver: gebrauchteUnbestParam >= anzUnbestParam");
              }
              x[i][gebrauchteUnbestParam + 2] = 1; // neuer Parameter (alpha, beta) setzen
              x[i][0] = 1; // bestimmt (auch wenn von Parameter abhängig).

              gebrauchteUnbestParam++;
            }
          }

          x[effPivot][1] += -R.viewRow(z).get(i) * x[i][1] / R.viewRow(z).get(effPivot);
          for (int j = 0; j < gebrauchteUnbestParam; j++) {
            x[effPivot][2 + j] += -R.viewRow(z).get(i) * x[i][2 + j] / R.viewRow(z).get(effPivot);
          }
        }
        x[effPivot][0] = 1;
      }
    }

    if (debug) {
      System.out.println("");
      for (int i = 0; i < x.length; i++) {
        System.out.print("x" + i + " = " + Fkt.nf(x[i][1], 3));
        for (int j = 2; j < x[i].length; j++) {
          System.out.print(", P" + (j - 1) + " = " + Fkt.nf(x[i][j], 3));
        }
        System.out.println("");
      }
    }

    // ------------------
    // Lösung zurückgeben
    // ------------------

    // Lösung x: nur eindeutige (d.h. parameterunabhängige xi) werden zurückgegeben
    // index 0: Wert = 0 bedeutet xi unbestimmt,  Wert = 1 bedeutet xi bestimmt
    // index 1: eigentlicher Wert (nur wenn xi bestimmt, dh index 0 = 1, sonst Wert 0)
    xLsg = new double[R.columns()][2];

    for (int i = 0; i < x.length; i++) {
      boolean bestimmt;
      if (x[i][0] > 0) {
        bestimmt = true;
        // schauen, ob Lösungsvariable xi bestimmt, dh unabhängig von überzähligen Parametern
        for (int j = 2; j < x[i].length; j++) {
          if (Math.abs(x[i][j]) > TOL) bestimmt = false;
        }
      } else bestimmt = false;

      if (bestimmt) {
        xLsg[i][0] = 1;
        xLsg[i][1] = x[i][1];
      } else xLsg[i][0] = 0;
    }

    solved = true;
    return xLsg;
  }
Beispiel #8
0
 private void copyInstanceTo(int destinationRow, DataSet source, int sourceRow) {
   y[destinationRow] = source.y[sourceRow];
   x.viewRow(destinationRow).assign(source.x.viewRow(sourceRow));
 }