title: Exponential decay curve fitting in numpy and scipy
body: <p>I'm having a bit of trouble with fitting a curve to some data, but can't work out where I am going wrong. </p>
  
  <p>In the past I have done this with <strong>numpy.linalg.lstsq</strong> for exponential functions and <strong>scipy.optimize.curve_fit</strong> for sigmoid functions. This time I wished to create a script that would let me specify various functions, determine parameters and test their fit against the data. While doing this I noticed that Scipy <code>leastsq</code> and Numpy <code>lstsq</code> seem to provide different answers for the same set of data and the same function. The function is simply <code>y = e^(l*x)</code> and is constrained such that <code>y=1</code> at <code>x=0</code>.</p>
  
  <p>Excel trend line agrees with the Numpy <code>lstsq</code> result, but as Scipy <code>leastsq</code> is able to take any function, it would be good to work out what the problem is.</p>
  
  <pre><code>import scipy.optimize as optimize
  import numpy as np
  import matplotlib.pyplot as plt
  
  ## Sampled data
  x = np.array([0, 14, 37, 975, 2013, 2095, 2147])
  y = np.array([1.0, 0.764317544, 0.647136491, 0.070803763, 0.003630962,     0.001485394,     0.000495131])
  
  # function
  fp = lambda p, x: np.exp(p*x)
  
  # error function
  e = lambda p, x, y: (fp(p, x) - y)
  
  # using scipy least squares
  l1, s =  optimize.leastsq(e, -0.004, args=(x,y))
  print l1
  # [-0.0132281]
  
  
  # using numpy least squares
  l2 = np.linalg.lstsq(np.vstack([x, np.zeros(len(x))]).T,np.log(y))[0][0]
  print l2
  # -0.00313461628963 (same answer as Excel trend line)
  
  # smooth x for plotting
  x_ = np.arange(0, x[-1], 0.2)
  
  plt.figure()
  plt.plot(x, y, 'rx', x_, fp(l1, x_), 'b-', x_, fp(l2, x_), 'g-')
  plt.show()
  </code></pre>
  
  <h1>Edit - additional information</h1>
  
  <p>The MWE above includes a small sample of the dataset. When fitting the actual data the <strong>scipy.optimize.curve_fit</strong> curve presents an R^2 of 0.82, while the <strong>numpy.linalg.lstsq</strong> curve, which is the same as that calculated by Excel, has an R^2 of 0.41.</p>