NS78
@NS78 (NS)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

polyfitやcurve_fitでの多項式回帰分析の決定係数及び精度を上げる方法はありますでしょうか?

■解決したいこと

Pythonのpolyfit(numpy)やcurve_fit(scipy)などで多項式回帰を行っております。仕事で決定係数が0.9985以上になる近似式を使いたいのですが、2次式回帰で条件(決定係数0.9985以上)に満たなかったので3次式回帰でトライしてみました。

下記と同じ条件(a,b要素)でExcelのグラフで算出すると精度の高い3次近似式が出てきますが、polyfitだと"Polyfit may be poorly conditioned"とコンディションが悪いとされてまい、近似式の精度が低い状態です。curve_fitで算出された値もExcelで算出されものよりも決定係数が低く近似式がの精度が低い状態です。

■質問

質問と致しましては、

①決定係数を上げるために元データをコンディションの良いデータへ加工するなど、何かよい方法が何かあるものなのか?

②そもそも2次式回帰で決定係数が低いものを3次式回帰にしたところで決定係数が上がるものなのか、また3次曲線ではない曲線(ただの緩やかな曲線)に3次式回帰が適用できるものなのか?

です。機械学習の土台となる数学知識があまりなく、勉強したいのですが時間がなく、様々なサイトを見て見様見真似でやっておりまして、至らない部分もあるかとございますが、ご教授いただけると助かります。

皆様お忙しいところ申し訳ありませんが何卒宜しくお願い致します。

a = [132.90183, 132.90082, 132.899859, 132.898943, 132.898088, 132.897294, 132.896503, 132.895693]
b = [33.794023, 33.793724, 33.793335, 33.792861, 33.792326, 33.791718, 33.791102, 33.790507]

"""
polyfitによる回帰分析
"""
p = np.polyfit(a, b, 3)
print("3次関数式係数 : %s"%(p))

# 2次多項式計算
yfit = np.polyval(p, a)
r2_1 = r2_score(b, yfit)
r2_1 = round(r2_1, 5)
print("決定係数 : %s"%(r2_1))

"""
curve_fitによる回帰分析
"""

# 3次近似式用の関数
def func(x, a, b, c, d):
    return a * pow(x, 3) + b * pow(x, 2) + c * x + d

# 近似式の作成
popt, pcov = optimize.curve_fit(func, a, b)

print("popt : %s"%(popt))
print("pcov : %s"%(pcov))

df_a = pd.DataFrame(a)
df_b = pd.DataFrame(b)

# 決定係数
r2_2 = r2_score(df_b[0], func(df_a[0], *popt))
r2_2 = round(r2_2, 5)
print("決定係数 : %s"%(r2_2))
0

2Answer

同じスクリプトで計算してみましたが、polyfitでr2=0.99922, curvefitで0.97666でした。curvfitではグラフ上ほぼ直線になっています。
a=(a-132)*1000、b=(b-33)*1000とスケールするとr2=0.99971, 0.99942になり、グラフ上でも曲線になりフィッテイングでされています。原因は桁数の問題かもしれませんが、詳しくはわかりません。

2についてですが、一般的に項数を上げるとr2は同じか良くなります。ただしover fittingする可能性がありますので注意が必要です。

1Like

Comments

  1. @NS78

    Questioner

    返信が遅れましてしまい申し訳ございません。回答ありがとうございます。内容理解致しました。項数上げて目的の条件が達成できるか試してみます(over fittingにも気を付けます)!

    貴重なアドバイスありがとうございました!

私も実際に動かしてみました。とりあえず、polyfit だけです。
結果は以下のようになりました。

3次関数式係数 : [-1.92828323e-01  2.56282380e+01  3.40591038e+03 -4.52635609e+05]
決定係数 : 0.99922

ここで例えば a[0] について検算してみます。

print( "{:+.3f}".format(132.90183 ** 3 * -1.92828323e-01) )
print( "{:+.3f}".format(132.90183 ** 2 *  2.56282380e+01) )
print( "{:+.3f}".format(132.90183      *  3.40591038e+03) )
print( "{:+.3f}".format(                 -4.52635609e+05) )

答えは以下のようになりました。

-452651.233
+452668.913
+452651.722
-452635.609

これを見るとわかる通り、各項の絶対値がほぼ同じで符号が異なります。

つまり浮動小数点演算の「桁落ち」が起きて、有効桁数が極端に減っている(誤差が大きくなっている)のだと思います。

対策方法はすぐに思いつきませんが、Excel では精度を保っているということは、桁落ちを避ける計算方法があるのかもしれませんね。
(curve_fitではそれが避けられていないのかも)

1Like

Comments

  1. @NS78

    Questioner

    返信が遅れましてしまい申し訳ございません。回答ありがとうございます。

    なるほどです。桁落ち、全く気がつきませんでした。Excelも割と優秀なのですね!

    記載いただいた内容を鑑み、curve_fitでも試してみます。貴重なアドバイスありがとうございました。
  2. 言葉が足りなかった気がするので、少しだけ補足です。

    記載しませんでしたが、polyfitで「Polyfit may be poorly conditioned」のワーニングは出ています。

    つまり polyfit での警告も、curve_fitでの精度が低いのも、桁落ちが原因じゃないかな、と思っています。

    excelの結果がそれなりに良い精度ですが、これだけでは桁落ちが回避できているとは限らないと思います。桁落ちが回避できているかもしれないし、あるいはpolyfitのようにはワーニングを出さないだけで精度が低いかもしれない結果を出している可能性もあります。
    必ずしもexcelが優秀とは限らないです。優秀なのかもしれないですけど。

    (特に返信とかは不要です)

Your answer might help someone💌