matrix * NMFpopulateClassPredictionsMatrix(matrix * data, matrix * model)
/*Returns predictions for each column in data*/
{
//create a one-row matrix to hold predicted class ixs
matrix * result = init_matrix(1, data->cols);
safef(result->rowLabels[0], MAX_LABEL, "prediction");
copy_matrix_labels(result, data, 2,2);
result->labels=1;

//make sure data is positive
shift_matrix(data);

//calc correlations for each class, then assign each sample to highest correlated class
matrix * correlations = populateCorrMatrix_NArm(data, model, NULL_FLAG);
float max;
int maxIx, i, j;
for(j = 0; j < correlations->cols; j++)
    {
    maxIx = 0;
    max = correlations->graph[0][j];
    for(i = 1; i < correlations->rows; i++)
        {
        if(correlations->graph[i][j] > max)
            {
            max = correlations->graph[i][j];
            maxIx = i;
            }
        }
    result->graph[0][j] = maxIx;
    }
return result;
}
Exemplo n.º 2
0
/// Given an indefinite matrix w.A, find a shift sigma
/// such that (A + sigma I) is positive definite.
/// @param sigma :: The result (shift).
/// @param d :: A solution vector to the system of linear equations
///    with the found positive defimnite matrix. The RHS vector is -w.v.
/// @param options :: The options.
/// @param inform :: The inform struct.
/// @param w :: The work struct.
void get_pd_shift(double &sigma, DoubleFortranVector &d,
                  const nlls_options &options, nlls_inform &inform,
                  more_sorensen_work &w) {
  int no_shifts = 0;
  bool successful_shift = false;
  while (!successful_shift) {
    shift_matrix(w.A, sigma, w.AplusSigma);
    solve_spd(w.AplusSigma, negative(w.v), w.LtL, d, inform);
    if (inform.status != NLLS_ERROR::OK) {
      // reset the error calls -- handled in the code....
      inform.status = NLLS_ERROR::OK;
      inform.external_return = 0;
      inform.external_name = "";
      no_shifts = no_shifts + 1;
      if (no_shifts == 10) { // too many shifts -- exit
        inform.status = NLLS_ERROR::MS_TOO_MANY_SHIFTS;
        return;
      }
      sigma = sigma + (pow(10.0, no_shifts)) * options.more_sorensen_shift;
    } else {
      successful_shift = true;
    }
  }
}
Exemplo n.º 3
0
/// Solve the trust-region subproblem using
/// the method of More and Sorensen
///
/// Using the implementation as in Algorithm 7.3.6
/// of Trust Region Methods
///
/// main output  d, the soln to the TR subproblem
/// @param J :: The Jacobian.
/// @param f :: The residuals.
/// @param hf :: The Hessian (sort of).
/// @param Delta :: The raduis of the trust region.
/// @param d :: The output vector of corrections to the parameters giving the
///       solution to the TR subproblem.
/// @param nd :: The 2-norm of d.
/// @param options :: The options.
/// @param inform :: The inform struct.
/// @param w :: The work struct.
void more_sorensen(const DoubleFortranMatrix &J, const DoubleFortranVector &f,
                   const DoubleFortranMatrix &hf, double Delta,
                   DoubleFortranVector &d, double &nd,
                   const nlls_options &options, nlls_inform &inform,
                   more_sorensen_work &w) {

  // The code finds
  //  d = arg min_p   v^T p + 0.5 * p^T A p
  //       s.t. ||p|| \leq Delta
  //
  // set A and v for the model being considered here...

  // Set A = J^T J
  matmult_inner(J, w.A);
  // add any second order information...
  // so A = J^T J + HF
  w.A += hf;
  // now form v = J^T f
  mult_Jt(J, f, w.v);

  // if scaling needed, do it
  if (options.scale != 0) {
    apply_scaling(J, w.A, w.v, w.apply_scaling_ws, options, inform);
  }

  auto n = J.len2();
  auto scale_back = [n, &d, &options, &w]() {
    if (options.scale != 0) {
      for (int i = 1; i <= n; ++i) {
        d(i) = d(i) / w.apply_scaling_ws.diag(i);
      }
    }
  };

  auto local_ms_shift = options.more_sorensen_shift;
  // d = -A\v
  DoubleFortranVector negv = w.v;
  negv *= -1.0;
  solve_spd(w.A, negv, w.LtL, d, inform);
  double sigma = 0.0;
  if (inform.status == NLLS_ERROR::OK) {
    // A is symmetric positive definite....
    sigma = zero;
  } else {
    // reset the error calls -- handled in the code....
    inform.status = NLLS_ERROR::OK;
    inform.external_return = 0;
    inform.external_name = "";
    min_eig_symm(w.A, sigma, w.y1);
    if (inform.status != NLLS_ERROR::OK) {
      scale_back();
      return;
    }
    sigma = -(sigma - local_ms_shift);
    // find a shift that makes (A + sigma I) positive definite
    get_pd_shift(sigma, d, options, inform, w);
    if (inform.status != NLLS_ERROR::OK) {
      scale_back();
      return;
    }
  }

  nd = norm2(d);
  if (boost::math::isnan(nd) || boost::math::isinf(nd)) {
    inform.status = NLLS_ERROR::NAN_OR_INF;
    throw std::runtime_error("Step is NaN or infinite.");
  }

  // now, we're not in the trust region initally, so iterate....
  auto sigma_shift = zero;
  int no_restarts = 0;
  // set 'small' in the context of the algorithm
  double epsilon =
      std::max(options.more_sorensen_tol * Delta, options.more_sorensen_tiny);
  int it = 1;
  for (; it <= options.more_sorensen_maxits; ++it) {

    if (nd <= Delta + epsilon) {
      // we're within the tr radius
      if (fabs(sigma) < options.more_sorensen_tiny ||
          fabs(nd - Delta) < epsilon) {
        // we're good....exit
        break;
      }
      if (w.y1.len() == n) {
        double alpha = 0.0;
        findbeta(d, w.y1, Delta, alpha, inform);
        if (inform.status == NLLS_ERROR::OK) {
          DoubleFortranVector tmp = w.y1;
          tmp *= alpha;
          d += tmp;
        }
      }
      // also good....exit
      break;
    }

    // w.q = R'\d
    // DTRSM( "Left", "Lower", "No Transpose", "Non-unit", n, 1, one, w.LtL, n,
    // w.q, n );
    for (int j = 1; j <= w.LtL.len1(); ++j) {
      for (int k = j + 1; k <= w.LtL.len1(); ++k) {
        w.LtL(j, k) = 0.0;
      }
    }
    w.LtL.solve(d, w.q);

    auto nq = norm2(w.q);
    sigma_shift = (pow((nd / nq), 2)) * ((nd - Delta) / Delta);
    if (fabs(sigma_shift) < options.more_sorensen_tiny * fabs(sigma)) {
      if (no_restarts < 1) {
        // find a shift that makes (A + sigma I) positive definite
        get_pd_shift(sigma, d, options, inform, w);
        if (inform.status != NLLS_ERROR::OK) {
          break;
        }
        no_restarts = no_restarts + 1;
      } else {
        // we're not going to make progress...jump out
        inform.status = NLLS_ERROR::MS_NO_PROGRESS;
        break;
      }
    } else {
      sigma = sigma + sigma_shift;
    }

    shift_matrix(w.A, sigma, w.AplusSigma);
    DoubleFortranVector negv = w.v;
    negv *= -1.0;
    solve_spd(w.AplusSigma, negv, w.LtL, d, inform);
    if (inform.status != NLLS_ERROR::OK) {
      break;
    }

    nd = norm2(d);
  }

  if (it == options.more_sorensen_maxits) {
    // maxits reached, not converged
    inform.status = NLLS_ERROR::MS_MAXITS;
  }
  scale_back();
}