分散共分散行列pcovの理解と可視化
はじめに
scipy.optimize.curve_fit
の戻り値であるpcov
は何かと思い検索すると、分散共分散行列であると出てくる。
名前から分散と共分散が入ってる行列なんだろうなと想像される。
だからと言ってそんな認識でいてはいけないと思い調べてみる。
データの準備
お決まりのiris
を使う。
import seaborn as sns import matplotlib.pyplot as plt df = sns.load_dataset('iris') sns.pairplot(df) plt.show()
相関してそうなpetal_length
とpetal_width
を使ってフィッティングする。
とりあえずどんな数字か見てみよう
from scipy.optimize import curve_fit f = lambda x, a, b: a*x + b popt, pcov = curve_fit(f, df['petal_length'], df['petal_width']) print(pcov) #[[ 9.18230745e-05 -3.45071113e-04] # [-3.45071113e-04 1.58101581e-03]] plt.imshow(pcov, cmap='jet') plt.colorbar() plt.show()
分散共分散行列の構造
分散共分散行列は以下のようになっていて、対角成分に分散、その他に共分散が入っている。
対角成分のルートを取れば標準偏差になるはず。
perr = np.sqrt(np.diag(pcov)) print(perr) # array([9.18230745e-05, 1.58101581e-03])
...ふーん、て感じ。
決定係数を求める
フィッティングしたのだから、うまくできているか気になる。
というわけで指標となる決定係数を求める。
素直に求める方法
r2 = 1 - (np.sum((df['petal_width'] - f(df['petal_length'], *popt))**2) / np.sum((df['petal_width'] - np.mean(df['petal_width']))**2)) print(r2) #0.9271098389904927
sklearn
実務ではこれ一択でしょ。
from sklearn.metrics import r2_score r2 = r2_score(df['petal_width'], f(df['petal_length'], *popt)) print(r2) #0.9271098389904927
決定係数を2乗する方法
最小二乗法による直線フィッティングの場合,相関係数の二乗と決定係数は一致する
だそうなので*1、決定係数を求め2乗する。
rho = pcov[0,1]/np.multiply(*perr) print(rho**2) #0.8202177539001069
なんか違う値出てきちゃうんだけどなんで??