title: Optimizing a piecewise linear regression
body: <p>I have written a function that, given parameters, can apply a piecewise linear fit, with arbitrarily many piecewise sections, to some data.</p>
  
  <p>I am trying to fit the function to my data using scipy.optimize.curve_fit, but I am receiving an "OptimizeWarning: Covariance of the parameters could not be estimated" error. I believe this may be because of the nested lambda functions I am using to define the piecewise sections.</p>
  
  <p>Is there an easy way to tweak my code to get round this, or a different scipy optimisation function that might be more suitable?</p>
  
  <pre><code>#The piecewise function
  def piecewise_linear(x, *params):
  
      N=len(params)/2
  
      if N.is_integer():N=int(N)
      else:raise(ValueError())
  
      c=params[0]
      xbounds=params[1:N]
      grads=params[N:]
  
  
      #First we define our conditions, which are true if x is a member of a given
      #bin.
      conditions=[]
      #first and last bins are a special case:
      cond0=lambda x: x&lt;xbounds[0]
      condl=lambda x: x&gt;=xbounds[-1]
      conditions.append(cond0(x))
  
      for i in range(len(xbounds)-1):
          cond=lambda x : (x &gt;= xbounds[i]) &amp; (x &lt; xbounds[i+1])
          conditions.append(cond(x))
  
      conditions.append(condl(x))
  
      #Next we define our linear regression function for each bin. The offset
      #for each bin depends on where the previous bin ends, so we define
      #the regression functions recursively:
  
      functions=[]
      func0 = lambda x: grads[0]*x +c
  
      functions.append(func0)
  
      for i in range(len(grads)-1):
          func = (lambda j: lambda x: grads[j+1]*(x-xbounds[j])\
                 +functions[j](xbounds[j]))(i)
  
          functions.append(func)
  
      return np.piecewise(x,conditions,functions)
  #Some data
  
  x=np.arange(100)
  y=np.array([*np.arange(0,19,1),*np.arange(20,59,2),\
  *np.arange(60,20,-1),*np.arange(21,42,1)]) + np.random.randn(100)
  
  #A first guess of parameters
  cguess=0
  boundguess=[20,30,50]
  gradguess=[1,1,1,1]
  p0=[cguess,*boundguess,*gradguess]
  
  fit=scipy.optimize.curve_fit(piecewise_linear,x,y,p0=p0)
  </code></pre>