Example #1
0
File: FLD.java Project: grue/smile
  @Override
  public double[] project(double[] x) {
    if (x.length != p) {
      throw new IllegalArgumentException(
          String.format("Invalid input vector size: %d, expected: %d", x.length, p));
    }

    double[] y = new double[scaling[0].length];
    Math.atx(scaling, x, y);
    Math.minus(y, smean);
    return y;
  }
Example #2
0
File: FLD.java Project: grue/smile
  @Override
  public double[][] project(double[][] x) {
    double[][] y = new double[x.length][scaling[0].length];

    for (int i = 0; i < x.length; i++) {
      if (x[i].length != p) {
        throw new IllegalArgumentException(
            String.format("Invalid input vector size: %d, expected: %d", x[i].length, p));
      }

      Math.atx(scaling, x[i], y[i]);
      Math.minus(y[i], smean);
    }

    return y;
  }
Example #3
0
File: FLD.java Project: grue/smile
  /**
   * Constructor. Learn Fisher's linear discriminant.
   *
   * @param x training instances.
   * @param y training labels in [0, k), where k is the number of classes.
   * @param L the dimensionality of mapped space.
   * @param tol a tolerance to decide if a covariance matrix is singular; it will reject variables
   *     whose variance is less than tol<sup>2</sup>.
   */
  public FLD(double[][] x, int[] y, int L, double tol) {
    if (x.length != y.length) {
      throw new IllegalArgumentException(
          String.format("The sizes of X and Y don't match: %d != %d", x.length, y.length));
    }

    // class label set.
    int[] labels = Math.unique(y);
    Arrays.sort(labels);

    for (int i = 0; i < labels.length; i++) {
      if (labels[i] < 0) {
        throw new IllegalArgumentException("Negative class label: " + labels[i]);
      }

      if (i > 0 && labels[i] - labels[i - 1] > 1) {
        throw new IllegalArgumentException("Missing class: " + labels[i] + 1);
      }
    }

    k = labels.length;
    if (k < 2) {
      throw new IllegalArgumentException("Only one class.");
    }

    if (tol < 0.0) {
      throw new IllegalArgumentException("Invalid tol: " + tol);
    }

    if (x.length <= k) {
      throw new IllegalArgumentException(
          String.format("Sample size is too small: %d <= %d", x.length, k));
    }

    if (L >= k) {
      throw new IllegalArgumentException(
          String.format("The dimensionality of mapped space is too high: %d >= %d", L, k));
    }

    if (L <= 0) {
      L = k - 1;
    }

    final int n = x.length;
    p = x[0].length;

    // The number of instances in each class.
    int[] ni = new int[k];
    // Common mean vector.
    mean = Math.colMean(x);
    // Common covariance.
    double[][] T = new double[p][p];
    // Class mean vectors.
    mu = new double[k][p];

    for (int i = 0; i < n; i++) {
      int c = y[i];
      ni[c]++;
      for (int j = 0; j < p; j++) {
        mu[c][j] += x[i][j];
      }
    }

    for (int i = 0; i < k; i++) {
      for (int j = 0; j < p; j++) {
        mu[i][j] = mu[i][j] / ni[i] - mean[j];
      }
    }

    for (int i = 0; i < n; i++) {
      for (int j = 0; j < p; j++) {
        for (int l = 0; l <= j; l++) {
          T[j][l] += (x[i][j] - mean[j]) * (x[i][l] - mean[l]);
        }
      }
    }

    for (int j = 0; j < p; j++) {
      for (int l = 0; l <= j; l++) {
        T[j][l] /= n;
        T[l][j] = T[j][l];
      }
    }

    // Between class scatter
    double[][] B = new double[p][p];
    for (int i = 0; i < k; i++) {
      for (int j = 0; j < p; j++) {
        for (int l = 0; l <= j; l++) {
          B[j][l] += mu[i][j] * mu[i][l];
        }
      }
    }

    for (int j = 0; j < p; j++) {
      for (int l = 0; l <= j; l++) {
        B[j][l] /= k;
        B[l][j] = B[j][l];
      }
    }

    EigenValueDecomposition eigen = EigenValueDecomposition.decompose(T, true);

    tol = tol * tol;
    double[] s = eigen.getEigenValues();
    for (int i = 0; i < s.length; i++) {
      if (s[i] < tol) {
        throw new IllegalArgumentException("The covariance matrix is close to singular.");
      }

      s[i] = 1.0 / s[i];
    }

    double[][] U = eigen.getEigenVectors();
    double[][] UB = Math.atbmm(U, B);

    for (int i = 0; i < k; i++) {
      for (int j = 0; j < p; j++) {
        UB[i][j] *= s[j];
      }
    }

    Math.abmm(U, UB, B);

    eigen = EigenValueDecomposition.decompose(B, true);

    U = eigen.getEigenVectors();
    scaling = new double[p][L];
    for (int i = 0; i < p; i++) {
      System.arraycopy(U[i], 0, scaling[i], 0, L);
    }

    smean = new double[L];
    Math.atx(scaling, mean, smean);
    smu = Math.abmm(mu, scaling);
  }