数学とPython 4 3次関数の係数の算出 ~ 微分・連立方程式・可視化
はじめに
シリーズ数学とPythonのご案内
「シリーズ数学とPython」は、数学の学習中に「解けない、無理~」と焦ったときに、Pythonで数値の動きや可視化を行って、理解の糸口を見つけたときのことを記事にします。
データサイエンス数学ストラテジスト上級公式問題集
この記事は「データサイエンス数学ストラテジスト上級公式問題集」の問題の解読中に見つけたヒントを取り扱います。
今回取り組む問題
問題27「与えられた条件から3次関数の係数を求めよう!」
Python実装
やりたいこと
与えられた3次関数と極値を使って3次関数の係数を求めて、可視化します。
問題集の条件を次のように改変します。
・3次関数$${f(x)=px^3+qx^2+rx+s}$$
・$${x=-4}$$のとき極大値$${35}$$、$${x=2}$$のとき極小値$${-19}$$
実装ポイントは次のとおりです。
・3次関数$${f(x)}$$を微分して$${f\ '(x)}$$を求めます。
・$${f\ '(-4)=f\ '(2)=0,\ f(-4)=35,\ f(2)=-19 }$$の連立方程式を解いて、係数$${p,q,r,s}$$の係数を算出します。
・係数の算出後、3次関数をグラフに描画します。
作戦
SymPyだけで、微分、連立方程式、グラフ描画の全部を頑張ります!
実装の開始
インポート
sympyだけです!
import sympy
$${\boldsymbol{f(x)}}$$の定義
5つの変数$${x, p, q, r, s}$$と3次関数を定義します。
問題集どおりに解く場合は、$${p, q, r, s}$$の部分を問題集の係数に変更しましょう。
# 表示設定
sympy.init_printing
# 変数の定義
sympy.var('x, p, q, r, s')
# f(x)の定義
f = p*x**3 + q*x**2 + r*x + s
f
fに設定した3次関数を表示しました。
$${\boldsymbol{f(x)}}$$を微分
微分計算はsympyの diff を利用します。
引数は、diff( 関数, 変数 )です。
微分の結果を変数f_diffに格納します。
# f(x)を微分してf'(x)を求める
f_diff = sympy.diff(f, x)
f_diff
式を整理して方程式の形式を整える
$${ap+bq+cr+ds=0}$$の形式を作って左辺を eq1~eq4 に格納します。
問題集どおりに解く場合は、代入する$${x}$$の値と極値を問題集の数値に変更しましょう。
まずは$${f\ '(-4)}$$。
f_diff($${f\ '(x)}$$)に subs メソッドを用いて、$${x}$$に$${-4}$$を代入します。
# f'(x)にx=-4を代入(=0になるように式を整理済み)
eq1 = f_diff.subs(x, -4)
eq1
次は$${f\ '(2)}$$。
# f'(x)にx=2を代入(=0になるように式を整理済み)
eq2 = f_diff.subs(x, 2)
eq2
そして$${f(-4)}$$。
$${f(-4)=35}$$を$${f(-4)-35=0}$$に整理するので、subs メソッドで$${x}$$に$${-4}$$を代入した後に、$${-35}$$を設定します。
# f(x)x=-4を代入して極大値35を加味して、=0になるように式を整理
eq3 = f.subs(x, -4) -35
eq3
最後は$${f(2)}$$。
$${f(2)=-19}$$を$${f(2)+19=0}$$に整理するので、subs メソッドで$${x}$$に$${2}$$を代入した後に、$${+19}$$を設定します。
# f(x)にx=2を代入して極小値-19を加味して、=0になるように式を整理
eq4 = f.subs(x, 2) +19
eq4
4つの方程式が揃いました。
連立方程式を解いて係数$${\boldsymbol{p,q,r,s}}$$の値を得る
sympy の solve で連立方程式を解きます。
solveの引数に リスト形式で4つの方程式eq1~eq4を設定します。
解は辞書型で出力されます。
# 連立方程式の計算 戻り値は辞書型
sol = sympy.solve([eq1, eq2, eq3, eq4])
# 解の表示
for key, val in sol.items():
print(f'{key} = {val}, ', end='')
4つの係数の値が分かりました!
$${p=1/2,\ q=3/2,\ r=-12,\ s=-5}$$です。
$${\boldsymbol{p+q+r+s}}$$の計算
解を格納した辞書型の sol から 解を values() で取り出して sum で合計します。
# 辞書型solの値をsumで合計する
display(sum(sol.values()))
$${\boldsymbol{f(x), f\ '(x)}}$$の係数$${\boldsymbol{p,q,r,s}}$$に計算結果を代入
subs メソッドで係数$${p,q,r,s}$$に計算値を代入します。
複数の変数に代入する場合、変数と値のペアをタプルで、全ペアをリストで記述します。
係数の計算値は、解を格納した sol から辞書のキーである$${p,q,r,s}$$を指定して、取得します。
問題集どおりに解く場合は、$${p,q,r,s}$$の部分を問題集の係数に変更しましょう。
まずは$${f(x)}$$から。
# f(x)の係数p,q,r,sに計算結果を代入
f_2 = f.subs([(p, sol[p]), (q, sol[q]), (r, sol[r]), (s, sol[s])])
f_2
次に$${f\ '(x)}$$。
# f'(x)の係数p,q,rに計算結果を代入
f_diff_2 = f_diff.subs([(p, sol[p]), (q, sol[q]), (r, sol[r])])
f_diff_2
$${\boldsymbol{f(x), f\ '(x)}}$$の描画
sympyの plot 関数でグラフ描画ができます。
複数の関数の描画を1行のコードで指定できます。
引数は、plot( 関数1, 関数2, ( 変数, 描画区間下端, 描画区間上端 ) ) 。
legend=True で凡例を表示し、show=False で描画表示をぐっと堪えます。
# sympyのplotを用いてf_2とf_diff_2を描画
g = sympy.plot(f_2, f_diff_2, (x, -7, 5), legend=True, show=False)
g[1].line_color = 'darkorange'
g.show()
グラフの完成です!
増減表を手作業で作りました。
$$
\begin{array}{c|c:c:c:c:c}
x & \cdots & -4 & \cdots & 2 & \cdots \\
\hline
f\ '(x) & + & 0 & - & 0 & + \\
\hline
f(x) & \nearrow & 35 & \searrow & -19 & \nearrow \\
\end{array}
$$
可視化できてよかったです!
(数式と比べて優しい温もりを感じます😉)
おわりに
またまた SymPy に頼ってしまいました。
自力で計算した結果を SymPy で検算する使い方ができそうです。
解いた関数をそのまま可視化できるのは便利です~♪
おわり
ブログの紹介
noteで3つのシリーズ記事を書いています。
ぜひ覗いていってくださいね!
1.のんびり統計
統計検定2級の問題集を手がかりにして、確率・統計をざっくり掘り下げるブログです。
雑談感覚で大丈夫です。ぜひ覗いていってくださいね。
統計検定2級公式問題集CBT対応版に対応しています。
2.Python機械学習プログラミング実践記
書籍「Python機械学習プログラミング PyTorch & scikit-learn編」を学んだときのさまざまな思いを記事にしました。
この書籍は、scikit-learnとPyTorchの教科書です。
よかったらぜひ、お試しくださいませ。
3.データサイエンスっぽいことを綴る
統計、データ分析、AI、機械学習、Pythonのコラムを不定期に綴っています。