LM(3pm)

πŸ“¦
version 2.101 Β· 2 versions
, in ubuntu stonking

✨ LM(3pm) β€” PDL::Fit::LM ✨

okay bestie, welcome to PDL::Fit::LM, aka the Levenberg-Marquardt fitting routine for PDL πŸ’– this is your manual page, and yes it's a 3pm perl module doc, and yes we're gonna make it cute. buckle up πŸŽ€


🌸 NAME 🌸

PDL::Fit::LM β€” Levenberg-Marquardt fitting routine for PDL. that's it, that's the name, slay πŸ’…


πŸ¦‹ DESCRIPTION πŸ¦‹

so this module hands you fitting functions for PDL. Currently, only Levenberg-Marquardt fitting is implemented. other procedures should be added as required (i.e. when somebody needs them, bestie). and if you want a fairly concise overview on fitting, go read Numerical Recipes, chapter 15, "Modeling of data". iykyk πŸ“š


✨ SYNOPSIS ✨

use PDL::Fit::LM;
$ym = lmfit $x, $y, $sigma, \&expfunc, $initp, {Maxiter => 300};

literally that's the whole vibe check πŸ‘‘


πŸ’… FUNCTIONS πŸ’…

🌈 lmfit

Levenberg-Marquardt fitting of a user supplied model function. no cap, you bring the model, it brings the fit πŸ”₯

($ym,$finalp,$covar,$iters) =
     lmfit $x, $y, $sigma, \&expfunc, $initp, {Maxiter => 300, Eps => 1e-3};

here's the tea on the args, bestie, listen up 🫢:

  • $x is the independent variable β€” your x-axis energy ✨
  • $y is the value of the dependent variable at each $x
  • $sigma is the estimate of the uncertainty (i.e., standard deviation) of $y at each data point
  • the fourth argument is a subroutine reference (more on that below, stay with me)
  • $initp is the initial values of the parameters to be adjusted

Options:

  • Maxiter β€” maximum number of iterations before giving up 😭
  • Eps β€” convergence criterion for fit; success when normalized change in chisquare smaller than Eps ✨

🧚 the user supplied subroutine

your sub reference should accept 4 arguments, and no we're not negotiating:

  • a vector of independent values $x
  • a vector of fitting parameters
  • a vector of dependent variables that will be assigned upon return
  • a matrix of partial derivatives with respect to the fitting parameters that will be assigned upon return

as an example, take this definition of a single exponential with 3 parameters (width, amplitude, offset) πŸ“:

sub expdec {
  my ($x,$par,$ym,$dyda) = @_;
  my ($width,$amp,$off) = map {$par->slice("($_)")} (0..2);
  my $arg = $x/$width;
  my $ex = exp($arg);
  $ym .= $amp*$ex+$off;
  my (@dy) = map {$dyda->slice(",($_)")} (0..2);
  $dy[0] .= -$amp*$ex*$arg/$width;
  $dy[1] .= $ex;
  $dy[2] .= 1;
}

Note usage of the ".=" operator for assignment. not =, bestie, ".=". this matters. πŸ’€

πŸŽ€ what you get back

  • In scalar context β€” returns a vector of the fitted dependent variable.
  • In list context β€” returns the fitted y-values, the vector of fitted parameters, an estimate of the covariance matrix (as an indicator of goodness of fit), and the number of iterations performed.

πŸ‘‘ the extended example

an extended example script that uses lmfit is included below. this nice example was provided by John Gehman and should help you to master the initial hurdles. it can also be found in the Example/Fit directory πŸ¦‹

use PDL;
use PDL::Math;
use PDL::Fit::LM;
use strict;

### fit using pdl's lmfit (Marquardt-Levenberg non-linear least squares fitting)
###
### `lmfit' Syntax:
###
### ($ym,$finalp,$covar,$iters)
###  = lmfit $x, $y, $sigma, \&fn, $initp, {Maxiter => 300, Eps => 1e-3};
###
### Explanation of variables
###
### OUTPUT
### $ym     = pdl of fitted values
### $finalp = pdl of parameters
### $covar  = covariance matrix
### $iters  = number of iterations actually used
###
### INPUT
### $x      = x data
### $y      = y data
### $sigma  = ndarray of y-uncertainties for each value of $y (can be set to scalar 1 for equal weighting)
### \&fn    = reference to function provided by user (more on this below)
### $initp  = initial values for floating parameters
###               (needs to be explicitly set prior to use of lmfit)
### Maxiter = maximum iterations
### Eps     = convergence criterion (maximum normalized change in Chi Sq.)

### Example:
# make up experimental data:
my $xdata = pdl sequence 5;
my $ydata = pdl [1.1,1.9,3.05,4,4.9];

# set initial prameters in a pdl (order in accord with fit function below)
my $initp = pdl [0,1];

# Weight all y data equally (else specify different uncertainties in a pdl)
my $sigma = 1;

# Use lmfit. Fourth input argument is reference to user-defined
# subroutine ( here \&linefit ) detailed below.
my ($yf,$pf,$cf,$if) = lmfit $xdata, $ydata, $sigma, \&linefit, $initp;

# Note output
print "\nXDATA\n$xdata\nY DATA\n$ydata\n\nY DATA FIT\n$yf\n\n";
print "Slope and Intercept\n$pf\n\nCOVARIANCE MATRIX\n$cf\n\n";
print "NUMBER ITERATIONS\n$if\n\n";

# simple example of user defined fit function. Guidelines included on
# how to write your own function subroutine.
sub linefit {

    # leave this line as is
    my ($x,$par,$ym,$dyda) = @_;

    # $m and $c are fit parameters, internal to this function
    # call them whatever make sense to you, but replace (0..1)
    # with (0..x) where x is equal to your number of fit parameters
    # minus 1
    my ($m,$c) = map { $par->slice("($_)") } (0..1);

    # Write function with dependent variable $ym,
    # independent variable $x, and fit parameters as specified above.
    # Use the .= (dot equals) assignment operator to express the equality
    # (not just a plain equals)
    $ym .= $m * $x + $c;

    # Edit only the (0..1) part to (0..x) as above
    my (@dy) = map {$dyda -> slice(",($_)") } (0..1);

    # Partial derivative of the function with respect to first
    # fit parameter ($m in this case). Again, note .= assignment
    # operator (not just "equals")
    $dy[0] .= $x;

    # Partial derivative of the function with respect to next
    # fit parameter ($y in this case)
    $dy[1] .= 1;

    # Add $dy[ ] .= () lines as necessary to supply
    # partial derivatives for all floating parameters.
}

πŸ’œ tlmfit

broadcasted version of Levenberg-Marquardt fitting routine mfit 🌈

tlmfit $x, $y, float(1)->dummy(0), $na, float(200), float(1e-4),
      $ym=null, $afit=null, \&expdec;

 Signature: tlmfit(x(n);y(n);sigma(n);initp(m);iter();eps();[o] ym(n);[o] finalp(m);
          OtherPar => subref)

a broadcasted version of "lmfit" by using perl broadcasting. direct broadcasting in "lmfit" seemed difficult since we have an if condition in the iteration. in principle that can be worked around by using "where" but .... Send a broadcasted "lmfit" version if you work it out! πŸ‘€ (yes that's a real invitation, bestie, the author literally wants your PR)

so since we're using perl broadcasting here, speed is not really great 😭 but it is just convenient to have a broadcasted version for many applications (no explicit for-loops required, etc). suffers from some of the current limitations of perl level broadcasting. periodt πŸ’…


πŸ’€ BUGS πŸ’€

Not known yet. iconic honestly. no known bugs, we love that for us ✨


🫢 AUTHOR 🫢

this file copyright (C) 1999, Christian Soeller (c.soeller@auckland.ac.nz). All rights reserved. There is no warranty. You are allowed to redistribute this software documentation under certain conditions β€” for details, see the file COPYING in the PDL distribution. and if this file is separated from the PDL distribution, the copyright notice should be included in the file πŸ“Ž


and that's the whole page, bestie πŸŽ€ this was perl v5.42.3, dated 2026-08-21, and you've been reading LM(3pm). go fit something gorgeous πŸ’–βœ¨πŸ¦‹

πŸ“¦ where this page comes from