Tutorial

Given log-transformed data x and y, we can create a fit with K terms with a single command:

f = fit(x, y, K)

The default behaviour generates an implict softmax affine fit. A fit can also be generated by directly invoking the specific class you want:

f = ImplicitSoftmaxAffine(x, y, K)  # equivalent to f = fit(..., fit_type="isma")
f = SoftmaxAffine(x, y, K)          # equivalent to f = fit(..., fit_type="sma")
f = MaxAffine(x, y, K)              # equivalent to f = fit(..., fit_type="ma")

Once a fit is generated, we can plot it:

fig, ax = f.plot() # for 1D fits
fig, ax = f.plot_slices() # for 2D fits
fig, ax = f.plot_surface() # for 2D fits

and save it:

f.savetxt(filename="fit.txt") # saves string of fit to text file
f.save(filename="fit.pkl") # saves fit object to pickle file

We can even generate a GPkit constraint set:

fcs = f.constraint_set()

Examples

Both examples come from Section 6 of this paper.

Example 1

Fit convex portion of \(w = \frac{u^2 + 3}{(u+1)^2}\) on \(1 \leq u \leq 3\).

"""Example 6.1 from Hoburg et al."""
import numpy as np
from gpfit.fit import MaxAffine, SoftmaxAffine, ImplicitSoftmaxAffine

SEED = 33404

u = np.logspace(0, np.log10(3), 101)
w = (u**2 + 3)/(u + 1)**2
x = np.log(u)
y = np.log(w)
K = 3

fma = MaxAffine(x, y, K, verbosity=1, seed=SEED)
fsma = SoftmaxAffine(x, y, K, verbosity=1, seed=SEED)
fisma = ImplicitSoftmaxAffine(x, y, K, verbosity=1, seed=SEED)

Output:

Generated MaxAffine fit with 3 terms.

Fit
---
w = 0.807159*(u_1)^-0.0703921
w = 0.995106*(u_1)^-0.431386
w = 0.92288*(u_1)^-0.247099

Error
-----
RMS: 0.24%
Max: 0.55%

Generated SoftmaxAffine fit with 3 terms.

Fit
---
w^3.44109 = 0.15339*(u_1)^0.584655
    + 0.431128*(u_1)^-2.14831
    + 0.415776*(u_1)^-2.14794

Error
-----
RMS: 0.0024%
Max: 0.0086%

Generated ImplicitSoftmaxAffine fit with 3 terms.

Fit
---
1 = (0.947385/w^0.0920329)*(u_1)^0.0176859
  + (0.992721/w^0.349639)*(u_1)^-0.201861
  + (0.961596/w^0.116677)*(u_1)^-0.0112199

Error
-----
RMS: 8.1e-05%
Max: 0.00035%

Note

The maximum and root-mean-square errors printed above are calculated between the fit and the original (i.e. not log-transformed) data. It is important to note, however, that the fitting algorithm minimizes RMS error between the fit and the data in logspace. For more information, see section 6 of the paper.

Example 2

"""Example 6.3 from Hoburg et al."""
import numpy as np
from gpfit.fit import MaxAffine, SoftmaxAffine, ImplicitSoftmaxAffine

SEED = 33404

rng = np.random.RandomState(SEED)
Vdd = rng.random_sample(1000) + 1
Vth = 0.2*rng.random_sample(1000) + 0.2
P = Vdd**2 + 30*Vdd*np.exp(-(Vth - 0.06*Vdd)/0.039)

u = np.vstack((Vdd, Vth))
w = P
x = np.log(u)
y = np.log(P)
K = 4

fma = MaxAffine(x, y, K, verbosity=1, seed=SEED)
fsma = SoftmaxAffine(x, y, K, verbosity=1, seed=SEED)
fisma = ImplicitSoftmaxAffine(x, y, K, verbosity=1, seed=SEED)

Output:

Generated MaxAffine fit with 4 terms.

Fit
---
w = 0.38541*(u_1)^2.13119*(u_2)^-0.826143
w = 0.0175649*(u_1)^2.84017*(u_2)^-2.78935
w = 0.0877784*(u_1)^2.3499*(u_2)^-1.86683
w = 0.824389*(u_1)^2.02321*(u_2)^-0.203195

Error
-----
RMS: 0.74%
Max: 3.3%

Generated SoftmaxAffine fit with 4 terms.

Fit
---
w^2.22466 = 5.42048e-05*(u_1)^5.24448*(u_2)^-6.68342
    + 3.61261e-08*(u_1)^9.61297*(u_2)^-9.48927
    + 1.07668e-05*(u_1)^0.538372*(u_2)^-6.12093
    + 1.0777*(u_1)^4.4337*(u_2)^0.097843

Error
-----
RMS: 0.016%
Max: 0.081%

Generated ImplicitSoftmaxAffine fit with 4 terms.

Fit
---
1 = (0.889775/w^0.242028)*(u_1)^0.485343*(u_2)^-0.0942001
  + (0.012176/w^0.67353)*(u_1)^2.61311*(u_2)^-2.59033
  + (0.309986/w^0.309511)*(u_1)^0.632701*(u_2)^-0.813932
  + (1.00588/w^0.075305)*(u_1)^0.149933*(u_2)^0.0116638

Error
-----
RMS: 0.018%
Max: 0.12%