内挿と外挿の範囲を理解するために作ったコード.
過学習への注意も必要だが,外挿の範囲において,
得られた近似式が適用可能かどうかは十分に吟味しないといけない.
また,近似する目的が「予測」ではなく,「分析」である場合,
必要以上に変数を多くしたり,次数を上げると,解釈が難しくなるので,
如何に簡単,というかシンプルに仕立てられるか,が課題(腕の見せ所?).
赤破線部:外挿範囲,青実線部:内挿範囲 としています.
interpolation_and_extrapolation
import numpy as np
import matplotlib.pyplot as plt
x = np.array([2.0, 3.5, 4.0, 4.5, 5.0, 5.5])
y = np.array([3.0, 3.2, 3.9, 5.2, 8.4, 10.5])
xp = np.linspace(2, 5.5, 100)
xp1 = np.linspace(0, 2, 100)
xp2 = np.linspace(5.5, 8, 100)
for val in range(1, 6):
fx = np.poly1d(np.polyfit(x, y, val))
plt.rcParams["font.size"] = 20
fig, ax = plt.subplots(figsize=(15, 10))
ax.plot(xp, fx(xp), '-', color='blue')
ax.plot(xp1, fx(xp1), '-', color='red', linestyle='dashed')
ax.plot(xp2, fx(xp2), '-', color='red', linestyle='dashed')
ax.scatter(x, y, color='deepskyblue', s=32)
s = '$y =$'
for idx, deg in enumerate(reversed(range(0, val+1))):
if (fx.coef[idx] > 0) & (idx != 0):
s += '$ +$'
if deg > 1:
s += f' ${fx.coef[idx]:.2f} x^{deg}$'
if deg == 1:
s += f' ${fx.coef[idx]:.2f} x$'
if deg == 0:
s += f' ${fx.coef[idx]:.2f}$'
# ax.text(0.05, 0.8, s=s, size='x-large', transform=ax.transAxes)
ax.axhline([0], color='black')
ax.axvline([2], color='gray', linestyle='dotted')
ax.axvline([5.5], color='gray', linestyle='dotted')
ax.set_xlim(0, 8)
ax.set_ylim(-3, 14)
ax.set_title(s)
ax.set_ylabel('response variable')
ax.set_xlabel('explanatory variables')
fig.savefig(f'./data/img/inter_and_extrapolation{val}.png')