web-dev-qa-db-fra.com

Utilisez la méthode Fit.Polynomial de Math.NET sur les fonctions de plusieurs paramètres

J’avais précédemment utilisé la méthode Fit.Polynomial de la bibliothèque Math.NET Numerics pour ajuster un polynôme cubique à un ensemble de données pouvant être modélisées en fonction d’un paramètre y=f(x).
J'aimerais maintenant trouver un polynôme d'ordre 2 ou 3 qui corresponde à des données pouvant être modélisées comme une fonction en fonction de plusieurs paramètres y=f(x1, x2, x3, x4)

Existe-t-il déjà une fonction intégrée dans Math.NET capable de calculer ce polynôme?
Si non, voyez-vous comment je pourrais manipuler mes données afin de les soumettre à Fit.Polynomial?

13
wip

La classe Fit est simplement une façade qui convient assez bien dans la plupart des scénarios, mais vous pouvez toujours utiliser les algorithmes directement pour obtenir exactement ce dont vous avez besoin.

Fit.Polynomial: L'ajustement de la courbe polynomiale avec des ordres élevés est un peu problématique numériquement, donc des algorithmes spécialisés et des routines pour ajuster/affiner les paramètres à la fin ont été développés. Cependant, Math.NET Numerics n'utilise pour l'instant qu'une décomposition QR (bien qu'il soit prévu de remplacer l'implémentation à un moment donné):

public static double[] Polynomial(double[] x, double[] y, int order)
{
    var design = Matrix<double>.Build.Dense(x.Length, order + 1, (i, j) => Math.Pow(x[i], j));
    return MultipleRegression.QR(design, Vector<double>.Build.Dense(y)).ToArray();
}

Fit.MultiDim utilise par contre les équations normales, ce qui est beaucoup plus rapide mais moins robuste numériquement que la décomposition QR. C'est pourquoi vous avez constaté une précision réduite avec cette méthode.

public static double[] MultiDim(double[][] x, double[] y)
{
    return MultipleRegression.NormalEquations(x, y);
}

Dans votre cas, j'essaierais d'utiliser directement la classe MultipleRegression, avec soit QR (si assez bon) ou Svd (si vous avez besoin de plus de robustesse; beaucoup plus lent (envisagez d'utiliser un fournisseur natif si trop lent)):

var x1 = new double[] { ... };
var x2 = new double[] { ... };
var y = new double[] { ... };

var design = Matrix<double>.Build.DenseOfRowArrays(
    Generate.Map2(x1,x2,(x1, x2) => new double[] { x1*x1, x1, x2*x2, x2, 1d }));
double[] p = MultipleRegression.QR(design, Vector<double>.Build.Dense(y)).ToArray();

(Utilisation de Math.NET Numerics v3.0.0-alpha7)

13
Christoph Rüegg

RosettaCode propose cette solution pour la régression polynomiale (avec Math.Net ):

    public static double[] Polyfit(double[] x, double[] y, int degree)
    {
        // Vandermonde matrix
        var v = new DenseMatrix(x.Length, degree + 1);
        for (int i = 0; i < v.RowCount; i++)
            for (int j = 0; j <= degree; j++) v[i, j] = Math.Pow(x[i], j);
        var yv = new DenseVector(y).ToColumnMatrix();
        QR qr = v.QR();
        // Math.Net doesn't have an "economy" QR, so:
        // cut R short to square upper triangle, then recompute Q
        var r = qr.R.SubMatrix(0, degree + 1, 0, degree + 1);
        var q = v.Multiply(r.Inverse());
        var p = r.Inverse().Multiply(q.TransposeThisAndMultiply(yv));
        return p.Column(0).ToArray();
    }
4
Matthieu

Notez que lexdu modèle linéaire peut également être un vecteurx = [x1 x2 xk]et les fonctions arbitrairesfi (x) _ peut accepter les vecteurs au lieu des scalaires.
Ici correspond à peu près à ce que vous voulez.

1
GntS