PolyFitMultivariate constructor

PolyFitMultivariate(
  1. Array2d x,
  2. Array2d y,
  3. int degree
)

Fits the polynomial.

  • x : samples, one row per sample and one column per feature
  • y : outputs, one row per sample and one column per output
  • degree : degree of the polynomial, >= 0

Implementation

PolyFitMultivariate(Array2d x, Array2d y, this.degree)
    : featureCount = x.isEmpty ? 0 : x[0].length,
      outputCount = y.isEmpty ? 0 : y[0].length,
      powers = _powers(x.isEmpty ? 0 : x[0].length, degree),
      _sse = Array.fixed(y.isEmpty ? 0 : y[0].length, initialValue: 0.0),
      _sst = Array.fixed(y.isEmpty ? 0 : y[0].length, initialValue: 0.0) {
  if (degree < 0) {
    throw FormatException('expected degree >= 0');
  }
  if (x.isEmpty || featureCount == 0) {
    throw FormatException('expected at least one sample and one feature');
  }
  if (y.length != x.length) {
    throw FormatException('expected x and y to have the same number of rows');
  }
  if (outputCount == 0) {
    throw FormatException('expected at least one output');
  }
  for (var i = 0; i < x.length; i++) {
    if (x[i].length != featureCount || y[i].length != outputCount) {
      throw FormatException('row $i has a different number of columns');
    }
    if (x[i].any((v) => !v.isFinite) || y[i].any((v) => !v.isFinite)) {
      throw FormatException('expected only finite values in x and y');
    }
  }

  var design = Array2d(x.map(_terms).toList());
  if (!isFiniteMatrix(design)) {
    throw FormatException('a power of x overflows, reduce the degree');
  }
  var scale = normalizeColumns(design);
  var (solution, solutionRank) = leastSquares(design, y.copy());
  rank = solutionRank;
  for (var t = 0; t < solution.row; t++) {
    for (var o = 0; o < outputCount; o++) {
      solution[t][o] = solution[t][o] / scale.maxAbs[t] / scale.rootSum[t];
    }
  }
  coefficients = solution;

  for (var o = 0; o < outputCount; o++) {
    var meanY = 0.0;
    for (var i = 0; i < y.length; i++) {
      meanY += y[i][o];
    }
    meanY /= y.length;
    for (var i = 0; i < y.length; i++) {
      var dev = y[i][o] - meanY;
      _sst[o] += dev * dev;
    }
  }
  for (var i = 0; i < x.length; i++) {
    var predicted = predict(x[i]);
    for (var o = 0; o < outputCount; o++) {
      var residual = predicted[o] - y[i][o];
      _sse[o] += residual * residual;
    }
  }
}