Search code examples
pythonlinear-algebracurve-fittingcurvescipy-optimize-minimize

Find offset and scaling of 2 curves (solve linear problem)


I've got 2 curves that have an offset and scaling, which I would like to know. Now finding a factor without offset would not be to hard, as solving Curve1*a = Curve2 is not to hard. Also the offset, solving Curve1+b = Curve2 is not the problem.

It just a linear problem, however, i get stuck when looking for Curve1*a +b = Curve2.

I looked into scipy.minimize, and np.solve, but I'm having a hard time with it.

So I'm trying to minimize f(a,b) = (Curve1*a + b) - Curve2. I can't figure out how.

So imagine craeting two curves;

t = np.arange(0, 10, 0.1);
c1 = np.sin(t)
c2 = c1*2.5 + 4

I want to get a=2.5 and b=4. I tried creating a function

def func(x, c1,c2):
    x1=x[0]
    x2=x[1]
    y= np.mean(c1 - (c2*x1 + x2))
    return y

Then minimizing it

x_start = [2, 10]
result = scipy.optimize.minimize(func, c1, c2, x_start)

But I don't think this is really the correct way, plus it errors ttributeError: 'list' object has no attribute 'lower'

If anyone could help me out, that would be really appreciated! :)


Solution

  • You were not far from the solution but I have found at least three problems in your code.

    1. You are not giving the arguments to the minimize() method correctly :

      scipy.optimize.minimize(func,x_start,args=(c1,c2))

    2. You have inverted c1 and c2 in the error function func()

    3. Given the residuals y= c2 - (c1*x1 + x2) can be either positive or negative, calculate their sum or their mean is not a good marker for the discrepancy between c2 and the optimization. You should better calculate the sum of the square of the residual return np.sum(y*y). This way you will perform a least square minimisation.

    Finally I have this code working :

    import scipy
    import scipy.optimize
    import numpy as np
    
    t = np.arange(0, 10, 0.1);
    c1 = np.sin(t)
    c2 = c1*2.5 + 4
    
        def func(x,c1,c2):
    
        x1=x[0]
        x2=x[1]
        y= c2 - (c1*x1 + x2)
        return np.sum(y*y)
    
    
    x_start = [2, 10]
    result = scipy.optimize.minimize(func,x_start,args=(c1,c2))
    print(result)
    

    This gives :

    fun: 6.604621880500689e-15
     hess_inv: array([[ 0.01133786, -0.00211422],
           [-0.00211422,  0.00539425]])
          jac: array([-9.06677028e-13, -3.57935903e-13])
      message: 'Optimization terminated successfully.'
         nfev: 32
          nit: 5
         njev: 8
       status: 0
      success: True
            x: array([2.5       , 3.99999999])