web-dev-qa-db-ja.com

scipyでUnivariateSplineを使用してデータを近似するpython

私はscipyでUnivariateSpline関数を使用して曲線をフィットさせようとしている実験データがあります。データは次のようになります。

 x         y
13    2.404070
12    1.588134
11    1.760112
10    1.771360
09    1.860087
08    1.955789
07    1.910408
06    1.655911
05    1.778952
04    2.624719
03    1.698099
02    3.022607
01    3.303135    

これが私がやっていることです:

import matplotlib.pyplot as plt
from scipy import interpolate
yinterp = interpolate.UnivariateSpline(x, y, s = 5e8)(x) 
plt.plot(x, y, 'bo', label = 'Original')
plt.plot(x, yinterp, 'r', label = 'Interpolated')
plt.show()

それはそれがどのように見えるかです:

Curve fit

誰かが他のカーブフィッティングオプションを考えているのだろうか?私はscipyに比較的新しいです。

ありがとう!

13

いくつかの問題があります。

最初の問題は、x値の順序です。 scipy.interpolate.UnivariateSplineのドキュメントから

x : (N,) array_like
    1-D array of independent input data. MUST BE INCREASING.

私が追加したストレス。 xに指定したデータは逆の順序です。これをデバッグするには、「通常の」スプラインを使用して、すべてが適切であることを確認すると便利です。

2番目の問題、および問題に直接関連するもう1つの問題は、sパラメーターに関連しています。それは何をするためのものか?再び、私たちが見つけたドキュメントから

s : float or None, optional
    Positive smoothing factor used to choose the number of knots.  Number
    of knots will be increased until the smoothing condition is satisfied:

    sum((w[i]*(y[i]-s(x[i])))**2,axis=0) <= s

    If None (default), s=len(w) which should be a good value if 1/w[i] is
    an estimate of the standard deviation of y[i].  If 0, spline will
    interpolate through all data points.

したがって、sは、最小二乗の意味で、補間された曲線がデータポイントにどれだけ近づく必要があるかを決定します。値を非常に大きく設定した場合、スプラインはデータポイントの近くに来る必要はありません。

完全な例として、以下を検討してください

import scipy.interpolate as inter
import numpy as np
import pylab as plt

x = np.array([13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1])
y = np.array([2.404070, 1.588134, 1.760112, 1.771360, 1.860087,
          1.955789, 1.910408, 1.655911, 1.778952, 2.624719,
          1.698099, 3.022607, 3.303135])
xx = np.arange(1,13.01,0.1)
s1 = inter.InterpolatedUnivariateSpline (x, y)
s1rev = inter.InterpolatedUnivariateSpline (x[::-1], y[::-1])
# Use a smallish value for s
s2 = inter.UnivariateSpline (x[::-1], y[::-1], s=0.1)
s2crazy = inter.UnivariateSpline (x[::-1], y[::-1], s=5e8)
plt.plot (x, y, 'bo', label='Data')
plt.plot (xx, s1(xx), 'k-', label='Spline, wrong order')
plt.plot (xx, s1rev(xx), 'k--', label='Spline, correct order')
plt.plot (xx, s2(xx), 'r-', label='Spline, fit')
# Uncomment to get the poor fit.
#plt.plot (xx, s2crazy(xx), 'r--', label='Spline, fit, s=5e8')
plt.minorticks_on()
plt.legend()
plt.xlabel('x')
plt.ylabel('y')
plt.show()

Result from example code

39
Craig J Copi