PolyFitMultivariate constructor
Fits the polynomial.
x: samples, one row per sample and one column per featurey: outputs, one row per sample and one column per outputdegree: 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;
}
}
}