最小二乗法でカーブフィッティング。関数3つを使い比べ-python


python でカーブフィッティングをやる関数は1つじゃないようです。次の3つを見つけました。

  • Numpy の polyfit
  • Scipy の optimize.leastsq
  • Scipy の optimize.curve_fit

なぜ3つもあるのか悩みますが、とりあえず使い比べてみました。
機能に違いがあるのか、使いやすいのはどれか・・・

結論を先にいうと、計算結果はほぼ同じ(ごく微小な差異あり)、使い勝手は polyfit が一番簡単でした。

ちなみに、polyfit は最小二乗法によるカーブフィットであることが、こちらに記載されています ⇒ Scipy.org

- 目次 -

スポンサーリンク

まず テストデータ

使用するデータは Numpy で生成します。

curve_fit1

このデータを直線、または曲線で近似しますが、3つの関数でそれぞれ次数を変えながら結果を確認してみます。

次数 1 \(ax + b\)
次数 2 \(ax^2 + bx + c\)
次数 3 \(ax^3 + bx^2 + cx + d\)
    :

曲線の次数があがるほどデータの分布に近づきますが、近ければいいわけでもありません。

polyfitを使ってみる

次数を 1、つまり一次式 \(ax + b\) で近似してみます。
引数の3番目が次数です。

配列が返ってきました。
この戻り値がそのまま 係数 a、b に相当するので

\(y = 19.39774436x – 59.92857143\)

が近似式になります。
この式で 自力で y を計算してもいいのですが poly1d という便利な関数があります。

poly1d

poly1d は、係数 a、b をもとに関数を生成してくれます。

この関数に x を渡せば計算までこなしてくれます。

一行でまとめると

次の一行で、計算 ~ 描画ができてしまいます。

curve_fit_d1

次数を2にすると

polyfit のパラメータを変えるだけで次数は簡単に変更できます。
2次式 \(ax^2 + bx + c\) で近似すると

curve_fit_d2
polyfit の戻り値は [ 1.0702324 , -0.93667122, 1.07467532]
つまり、数式は \(y = 1.0702324x^2 – 0.93667122x + 1.07467532\) です。

次数を増やす

次数を 3、5、10、15 とどんどん増やして過学習させると次のようになりました。
curve_fit_d3_5_10_15
次数 10 や 15 がデータに過剰適応しているのが見て取れます。

過学習
数式を導き出すさい、特定の学習データ(この場合、x と y)に近づけすぎて、一般的な予測モデルとして使えなくなること。

たとえば、次数 15 の近似式は学習データに近づこうとするあまり、データの偏りに強くひきづられている。そのため、新たなデータとして x=n を与えても、計算結果 y は予測値として信頼がおけない。

leastsqを使ってみる

leastsq で近似してみます。
(polyfit、curve_fit との比較結果をページ後半に載せてあります)

次数 1

結果:\(y = 19.39774436x – 59.92857143\)

次数 2

結果:\(y = 1.07023241x^2 – 0.93667149x + 1.07467603\)

次数 3

結果:\(y = -0.00231212x^3 + 1.13612786x^2 – 1.42475939x + 1.74680471\)

curve_fitを使ってみる

curve_fit で近似してみます。
(polyfit、leastsq との比較結果をページ後半に載せてあります)

次数 1

結果:\(y = 19.39774436x – 59.92857143\)

次数 2

結果:\(y = 1.0702324x^2 – 0.93667122x + 1.07467532\)

次数 3

結果:\(y = -0.00231212x^3 + 1.13612793x^2 – 1.42476056x + 1.74680971\)

比べてみる

関数3つの結果を表にしました。次数は1~3です。
polyfit と curve_fit は値が完全に同じです。leastsq は、10 の-5乗あたりで他の2つと差が出るケースがあるようですが、実際上は同じと考えてよさそうです。

次数 1

\(y = ax + b\)

a b
polyfit 19.39774436 -59.92857143
leastsq 19.39774436 -59.92857143
curve_fit 19.39774436 -59.92857143

次数 2

\(y = ax^2 – bx + c\)

a b c
polyfit 1.0702324 -0.93667122 1.07467532
leastsq 1.07023241 -0.93667149 1.07467603
curve_fit 1.0702324 -0.93667122 1.07467532

次数 3

\(y = ax^3 – bx^2 + cx + d\)

a b c d
polyfit -0.00231212 1.13612793 -1.42476056 1.74680971
leastsq -0.00231212 1.13612786 -1.42475939 1.74680471
curve_fit -0.00231212 1.13612793 -1.42476056 1.74680971
スポンサーリンク
その他の記事
  1. こんにちは。いつもお世話になっております。^^

    これらのコードの続きで、決定係数、R2を求めるコードってどんな感じでしょうか?回答頂けましたら幸いです。どうぞよろしくお願い申し上げます。

  2. 分かりやすい内容で助かっております。ありがとうございます。

    一点だけ、
    「次数 10 や 15 がデータに過剰適応しているのが見て取れます。」
    までは良いのですが、
    「過学習:数式を導き出すさい、特定の学習データ(この場合、x と y)に近づけすぎて・・・」との記述部分は、今回の記事にそぐわないように思います。そもそも機械学習とか深層学習のように「学習させて」フィッティングせずに「polyfitで厳密に決定」されています。
    あくまで、人間側が次数のモデルを予測して選択する範疇なので、「過剰適応してしまうモデルを選択すると良くない。」といった表現が適切に思えました。

秋雪 へ返信する コメントをキャンセル