カーブフィッティング ( 回帰分析 ) の練習
線形最小二乗フィッティング
: R, python, excel非線形最小二乗フィッティング
: mathematica目次
1
最小二乗法
22
線形フィッティング
(線形回帰
) 32.1
線形フィティングの要件
. . . 32.2
線形最小二乗法の理論の概要
. . . 42.3
定数項
. . . 53
直線偏光測定のモデル
5 3.1線形モデルへの変換
. . . 63.2
特別な場合(離散フーリエ変換)
. . . 64
線形フィッティング
–統計解析言語
R編
7 4.1 Rの作業ディレクトリ
. . . 74.2 R
の使い方
. . . 74.3
データ入力
. . . 94.4
フィッティング
. . . 104.5
グラフの作成
. . . 114.6
ひとまとめにする
. . . 115
線形フィッティング
–スクリプト言語
python編
12 5.1基本的操作法
. . . 125.2
スクリプト作成
. . . 135.3
ライブラリーの使用
. . . 145.4
計画行列作成
. . . 145.5
データ入力と読み込み
. . . 155.6
フィッティング
. . . 165.7
グラフの完成
. . . 175.8
解析をおこなう関数の作成
. . . 186
線形フィッティング
– Excel編
19 7非線形フィッティング
– mathematica編
20 7.1データ入力
. . . 207.2
モデルの入力
. . . 217.3
フィッティングの実行
. . . 22付録
A Mathematicaの基礎
23 A.1起動
. . . 23A.2
式の入力
. . . 23A.3
単純な定義
. . . 23A.4
関数定義
. . . 23A.5
リスト
. . . 24測定可能な
2つの量の間の関係が理論式であらわされていて,その式が未知のパラメータを含んでいる場 合,いろいろな条件で得た複数の測定データから未知パラメータの値を求めることができる. これをカーブ フィッティング
(curve fitting),あるいは回帰分析
(regression analysis)という.理論式はモデル式ともいう.
多くの場合,測定誤差のため,モデル式を測定データに完全に一致させることはできないので,できるだけ 多くの測定データを使ってパラメータの値を推定する. これはデータとモデルの「不一致の程度」が最小に なるようなパラメータの値を求めるということである. 「不一致の程度」としては,残差
(測定データとモデル の差
)の二乗和が使われる
*1.測定誤差がランダムに生じるものであるならば,残差の二乗和を最小にするよ うなパラメータ値が最も確からしいパラメータ値であるということが言えるからである
(ガウス・マルコフの 定理
).この考え方を最小二乗法という.
1 最小二乗法
モデル式が従属変数
yを独立変数
xの関数としてあらわすようなものであるとする.未知パラメータ
aを含 めると,次のように,
yは
xと
aの
2変数関数として書ける.
y= f(x,a) (1)
n
組の測定値を
(x1,y1), (x2,y2), ..., (xn,yn)とあらわす.
i番目の測定値の残差を
eiであらわすと,
y1 = f(x1,a) +e1
y2 = f(x2,a) +e2
...
yn = f(xn,a) +en
(2)
残差の二乗和を
Jは,
J=e12+e22+...+en2 (3)
*1
空間の
2点間の距離を座標の差の二乗和から求めるのと同じである.
e1, ...,en
をひとまとめにして
n次元列ベクトル
eにする.
Jはこのベクトルの大きさの
2乗であり,
eと
eの 内積でもある.
e=
e1
e2
... en
, J=kek2=e·e (4)
パラメータ
aを変えれば,
f(xi,a)の値が変わり,
Jも変化する.ただし,
J=0であるから
Jの値には下限 がある.未知パラメータの推定とは,
aの関数である
Jの最小点を求めることである.
パラメータが複数あっても同じである.
m個のパラメータ
a1,a2, ...,amがあるなら,これらをまとめて一つ の
m次元列ベクトル
aとみなし,
a=
a1
a2
... am
(5)
f(x,a)
は
f(x,a)に変えればよい.
f(x,a)
がどういう式であらわされるかに関係ない方法は非線形フィッティング
(nonlinear fitting)という.
f(x,a)
が
a1,a2, ...の
1次式であらわされる場合に特化した方法は線形フィッティング,あるいは線形回帰と
いう.特に,
f(x,a)が
xについても
1次式になっている場合は,
f(x,a) =a1x+a2という形になってしまう が,この場合は直線回帰
(linear regression)という.
直線回帰は計算量が少ないので手計算でもなんとかなるし,統計機能を備えた電卓や表計算ソフトのグラフ 作成機能を使えば手軽におこなえる.一般の線形フィッティングでは,連立方程式を解かなければならないの で,その機能を備えたコンピュータープログラムを使用することが多い.非線形フィッティングには,複雑な アルゴリズムによって大量の計算をおこなうコンピュータープログラムを使う.
後で見るように,線形フィッティングは連立1次方程式を解くことに帰着するので,答えが得られるどうか は単純な条件で決まる.非線形フィッティングは試行錯誤によって
Jの最小点を探し出すので,正しい答えが 得られたかどうかを判断することが難しい場合がある.また,問題によって最適なアルゴリズムが異なるかも しれないし,使用するアルゴリズムによって答えが異なる.そのため,未知パラメータになんらかの置き換え をおこなうことで,線形な式にすることができるかどうかを検討するのが得策である.
2 線形フィッティング ( 線形回帰 )
2.1 線形フィティングの要件
m
個の未知パラメータに対して線形のモデル式は,
f(x) =a1g1(x) +a2g2(x) +...+amgm(x) (6)
のように書ける.これは
m個の関数
g1(x),g2(x), ...,gm(x)を係数とする
m個の未知パラメータ
a1,a2, ...,amの線型結合である.
f(x1) =a1g1(x1) +a2g2(x1) +...+amgm(x1)などを式
(2)に代入すると,
y1 =a1g1(x1) +a2g2(x1) +...+amgm(x1) +e1
y2 =a1g1(x2) +a2g2(x2) +...+amgm(x2) +e2
...
yn =a1g1(xn) +a2g2(xn) +...+amgm(xn) +en
(7)
g1(x1)
などはモデル式の
m個の関数にそれぞれ
n個の測定点の値を代入して得られる
m×n個の値である.
式
(7)は
a1,a2, ...を未知数とする線形連立方程式とほぼ同じであるから,ベクトルと行列を使って簡潔に表
現しよう.
y1, ...,ynと
e1, ...,enを
n次元列ベクトル,
a1, ...,amを
m次元列ベクトル,
g1(x1), ...,gm(xn)を
n行
m列の行列にする.
y=
y1
... yn
, e=
e1
... en
, a=
a1
... am
, G=
g1(x1) · · · gm(x1)
... ... ...
g1(xn) · · · gm(xn)
(8)
すると,式
(7)は次のようにまとめられる.
y=Ga+e (9)
G
は計画行列
(design matrix)と呼ばれる.その
i行
j列の成分は
Gi j =gj(xi)である.
残差の二乗和
(J=e·e)を最小にするという意味でこの方程式
(9)を「解く」ことができる.これが線形最
小二乗法
(linear least-squares method)で,その解を最小二乗解という.ただし,未知パラメータを決めるに
は,未知パラメータの数
mよりも測定値の数
nが多いことが必要である.よって,
Gは縦長の行列である.
2.2 線形最小二乗法の理論の概要
a
の微小変化
daに対する
Jの変化
dJを計算しよう.式
(9)から
e = y−Gaであるから,
eの変化は
de=−Gdaとなる.また,
J=e·eであるから,
dJ= 2de·e.よって,
dJ=−2(Gda)·(y−G a) =−2da·
G∗(y−Ga)
となる.ただし,
∗で随伴行列をあらわす.
Jの極小点では
aのどの向きへの微小変化に対しても
Jの変化は
0であるから,
G∗(y−Ga)はゼロでなければならない
*2.よって,
G∗Ga=G∗y (10)
G∗G
は
n×nの半正定値対称行列である
*3.
(10)が一意的に解けるには,
G∗Gは正則でなければならない ので,
Gはフルランク
(階数が
mに等しい,単射
)でなければならない.これは
Gの各列が独立ということで あるが,式
(8)を見ればわかるように,それには,少なくともモデル中の関数
g1(x), ...,gm(x)が独立でなけれ ばならない.これはモデル式が冗長ではないということである. また,少なくとも
m個の独立な測定点が必 要である.だから,同じ測定値をコピーして増やすのはだめ.
*2G∗(y−Ga) = 0
の左辺は
m次元ベクトルで,その各成分,G の
i列目を
giとして,
gi·(y−Ga)となる.右辺は
0ベクトルだか ら,この内積はすべて
0である.これは,G の全縦ベクトルと
y−Gaが垂直であることを意味する.よって,線形変換
Gの像で ある
m次元超平面に点
yから下ろした垂線の足が
Gaである.
*3
内積の性質から
a·(G∗G)a= (Ga)·(Ga)=0である
(半正定値
).また,(G
∗G)∗=G∗(G∗)∗=G∗Gである
(対称
).
パラメータ数
mが小さい場合は,式
(10)を直接解いて
aを求めることができる.直線回帰はそういう場合 にあたる.
mが大きい場合にも使われるコンピュータープログラムでは,計画行列を巧妙に処理して解くよ うになっている
*4.2.3 定数項
パラメータの
1つが定数項になっている場合は,モデル式は
h(x,a,b) = f(x,a) +bのように書ける.ここで,定数項はパラメータ
bであり,他のパラメータは
a,
f(x,a)は
aをパラメータとす る
xの関数である.
J=Pni=1
yi−f(xi,a)−b2
を最小にする
bは容易に求められ,
b=1 n
n
X
i=1
(yi−f(xi,a))
となる.そこで,平均値
(y1 +...+yn)/nを
yとし,平均値
f(x1,a) +...+ f(xn,a)
/n
を
f(x,a)とし,
Yi=yi−y,F(xi,a) =h(xi,a)−f(x,a)
と置くと,
yi= f(x,a,b) +eiは
Yi=F(xi,a) +eiとなって,未知パラメータが
1つ減る.線形モデルでは,
f(x,a)は
f(x,a) =a1g1(x) +· · ·+amgm(x)のように計算することができる.よって,まず
aを求め,その結果を使って
bの値を計算すればよい.
3 直線偏光測定のモデル
偏光フィルターは,入射光の偏光の向きに対して回転させることによって光の透過率が変化するものであ る.理想的な偏光フィルターでは,回転角度
xに対する透過率
tの関係は次の式であらわされる.
t=Pcos2(x−b) +P0 (11)
b
は偏光フィルターへの入射光の「最大偏光方向」の角度である.係数
Pと
P0は入射光の偏光状態で決ま る
*5.実際には偏光フィルターには偏光によらない反射や吸収があるし,直接測定するのは偏光フィルターを 通過した光の強さを光センサーで何らかの量に変換したものであるが,これらの過程が線形性を有し,入射光 強度が一定である場合は,測定値
yは
y=acos2(x−b) +c (12)
となる.パラメータの
aと
cは入射光強度やセンサーの感度に依存するし,
cはセンサーのゼロ点のずれを含 むかもしれない.しかし,
bにはそのような依存性は無いと考えられる.
*4QR
分解や特異値分解が利用される.
QR分解はグラム・シュミットの直交化のアイデアを行列の分解に適用するもので,直交行 列
Qと上三角行列
Rによって
G=QRと分解され,a
=R−1Q∗yとなる.
特異値分解では,行列
Gは2つの直交行列
U,Vと対角行列
Sによって
G=USV∗と分解される.ただし
Sは
G∗Gのすべて の固有値の平方根からなる対角行列である.S のゼロでない成分をすべて逆数に変えたものを
S+とし,G
+ =VS+U∗とする.
G+
は
Gの「擬似逆行列」という.G が縦長でフルランクの場合,式
(10)の解は
a=G+y.*5
形式的に,強さ
Sの光を,強さ
S1の直線偏光成分と,それに独立な強さ
S2の成分とに分けて考えることができ,式
(11)の係数
Pと
P0は,P
=S1/S,P
0=S2/(2S) = (1−P)/2とあらわせる.
3.1 線形モデルへの変換
式
(12)は
aと
cについて線形であるが,
bは非線形な関数
cosの中に入っているので,
bについては非線形 である. そこで,パラメータの変換によって線形の式にすることができるかどうかを検討する.倍角公式と 加法定理を使って式
(12)を変形すると,
y=acos2b
2 cos2x+asin2b
2 sin2x+a 2 +c
よって,次のように,パラメータを
A, B,Cに置き換えれば線形になる.
y=Acos2x+Bsin2x+C, (13)
A= a
2cos2b, B=a
2sin2b, C=a
2 +c (14)
a= 2p
A2+B2, b=1
2arctan(A,B), c=C−a
2 (15)
ここで,
arctan(A,B)は平面のベクトル
(A,B)の方位角である. プログラミング言語や数値計算パッケージ
の多くはこの関数が計算できる
*6.普通の
arctanを使う場合は,
A>0なら
arctan(B/A),それ以外で
B<0なら
−(π/2)−arctan(A/B),それ以外なら
(π/2)−arctan(A/B)とする.
3.2 特別な場合(離散フーリエ変換)
式
(13)は
yを周期
πの
2つの成分と定数成分に分解した形になっているから,
A, B,Cは「周波数成分」で ある.特に,独立変数
xの値が正確に全周期にわたって等間隔に取られた場合には,次の離散フーリエ変換に よってこれらを求めることができる.
A= 2 N
m
X
i=1
yicos(2xi), B= 2 N
m
X
i=1
yisin(2xi), C= 1 N
m
X
i=1
yi (16)
xi,yi
はデータ点,
mはデータ点数である.
xiは
2Nπ(i+h)/mの形
(Nは偏光フィルターの回転数,
hは任意 の定数
)に書けなければならない.偏光フィルターの回転数は
1/2の整数倍ならよい.離散フーリエ変換が直 交変換であることから,この計算が最小二乗法になっていることが言える
*7.また,線形最小二乗法の式
(10)にモデルを代入して計算すれば,上式が直接得られる.
一般の線形フィッティングはコンピュータープログラムで簡単にできるので,わざわざ
xの取り方に制約を 付けて離散フーリエ変換で計算するメリットはあまり無い.
*6C
言語など多くの言語にある
atan2という関数は
atan2(B,A)のように使用する.
Y座標が先,
X座標が後である.
Excelや 計算サイト
http://keisan.casio.jpの
atan2や,Mathematica の
ArcTanは
X座標が先.
*7
「パーセバルの等式」が成り立つ.
4 線形フィッティング – 統計解析言語 R 編
R
言語は統計解析に特化したシステムなので,データ・フィッティングは比較的楽にできる.
4.1 R の作業ディレクトリ
Windows
ではスタートメニューやタイルで
Rを起動する.
Linuxではメニューやデスクトップ・アイコン
で起動するか,端末エミュレーターの中で
Rと打って起動する.
Rを終了するには,
Rの中で
quit()と打 つ.このとき,作業内容を保存するかどうかを答える必要がある.
ファイルの読み書きのために「作業ディレクトリ」が重要である.端末エミュレーターで
Rを起動する場合 は
Rを起動したときの端末の現在のディレクトリが
Rの作業ディレクトリになる.これは
Rを起動する前に
pwdコマンドで見ることができる.また,
cdコマンドによって変更することもできる.しかし,
Rを
GUIで 起動すると,作業ディレクトリがわからないかもしれない.
Rでは次のコマンドで作業ディレクトリを確認す ることができる.
1 getwd()
これは
”getwd”という名前の関数を引数無しで呼び出す式であり,この式の評価結果が表示される.
getwdの
wdは
”working directory”から来ている.また,
dir()で作業ディレクトリにあるファイルとサブディレ
クトリのリストが得られる.サブディレクトリのみのリストは
list.dirs(recursive=0)で得られる.作業 ディレクトリを変更する必要がある場合は
setdir関数を使う.たとえば,現在の作業ディレクトリの中にあ る
xxxxという名前のサブディレクトリに移るには,
setwd("xxxx")とすればよいし,現在のディレクトリ の親ディレクトリに移るには,
setwd("..")とすればよい.これらは現在の作業ディレクトリからの相対パ スである.ユーザーのホームディレクトリに移るには,
setwd("~")とする.
Windowsでは,以上のような 操作を
GUIでもおこなうことができる.
4.2 R の使い方
R
では簡単な数値計算がすぐにできる
*8.四則演算の演算子は
+,-,*,/である.べき乗は
^でも
**でも よい.式をくくる括弧にはすべて
( )を使う.関数呼び出しはすべての引数を括弧で囲んで関数名の後ろに 付ける.
1 (1+2)/2
2 sin(0.1)
3 tan(0.1)
複数の数値からなるデータは
cという関数を使って作る.たとえば,
1 v <- c(1,3,5,4)
*8
これ以降は,4.3 の「データ入力」と
4.6の「ひとまとめにする」のセクション以外は読むのを省略することもできるが,推奨はし
ない.
2 v
3 v+10
4 v*10
のようにすると,4つの数値からなるデータを作って
vという名前を付け,
vの各要素に数値を足したりかけ たりした結果を表示する.このようなデータは「ベクトル」と呼んでいる.たくさんの要素からなるベクトル を簡単に作る方法もいろいろ用意されている.重要なのは等差数列である.コロン
”:”を使って,たとえば
1 0:40
と書くと,
0から
40までの公差
1の等差数列
(0,1, ...,40)ができる.次のように,このベクトルに
0.5をかけ ると,
(0,0.5, ...,20)になり,さらに
10を引くと,
(−10,−9.5, ...,10)になる.
1 x <- 0:40*0.5-10
2 x
同じことは,
seqという関数を使ってもできる.
1 x <- seq(-10,10,0.5)
2 x
seq
はたぶん
sequenceから来ている
*9.
数値データをプロットする関数は
plotである.
y=x2のグラフを描いてみる.
1 x <- seq(-10,10)
2 y <- x^2
3 plot(x,y)
21
点しか計算していないので,表示もそれだけである.
「任意の数値に対してその2乗を計算する」といった計算方法自体は「関数」である.関数を定義してそれ に名前を付け,後でその関数を使って計算をおこなうことができる.
1 f <- function(x){x^2}
2 f(2)
3 f(10)
4 f(2)+f(10)
5 f(0:10)
関数定義のところは,
*9
関数の説明を見るには,
?seqのようにすればよい.
Unixでは,カーソルキーで表示をスクロールし
Qで元に戻る.
1 function(
仮引数
){仮引数を含んだ式
}という形式である.中括弧の中には関数の定義が入る.簡単な計算では結果をあらわす式だけでよいが,もっ と複雑な処理の記述もできる.
関数定義を使うと,
plot関数によって曲線も描くことができるが,左端と右端を指定する必要がある.
1 plot(f, -10, 10)
これにデータ点を重ねるには,
points関数を使う.
1 x <- seq(-10,10,2)
2 points(x, f(x))
4.3 データ入力
測定データは任意のテキストエディタを使って入力して適当なファイル名で保存する.保存する場所は
Rの作業ディレクトリにする.次のは練習用データである.
#はコメント行を示している.
1 #
レーザーの偏光
4月
1日
2 #
回転角
(度
) :透過光強度
(ボルト
)3 0 0.809
4 30 0.403
5 60 0.039
6 90 0.077
7 120 0.477
8 150 0.836
9 180 0.794
10 210 0.400
11 240 0.040
12 270 0.081
13 300 0.481
14 330 0.843
15 360 0.782
このファイルを
Rで読み込む.ファイル名を
xxyy.datとすれば,
1 data = read.table("xxyy.dat")
読み込んだデータに
dataという名前を付けたが, 日本語のほうがよければ, 生データ
=read.table("xxyy.dat")のようにしてもよい.測定データのプロットは次のようにすればすぐにできる.
1 plot(data)
データ・プロットをよく見れば,誤った測定点が見つかる可能性がある.
1 data
で
dataを表示すると,
1列目に回転角,2列目に透過光強度が入っていることがわかる.
dataから各列の データを取り出すには,次のように2重の大括弧を使う.
1 x = data[[1]]
2 y = data[[2]]
回転角が独立変数なので,それに
xという名前を付け, 透過光強度には
yという名前を付けた.
4.4 フィッティング
あらためて,データプロットを作っておく.今度は横軸とグラフ全体に名前を付けよう.
1 plot(x,y,xlab="
角度
(度
)",main="テストデータ
")角度の単位を度にしたので,モデル式
(13)は,
Acos
(π/90)x
+Bsin
(π/90)x +C
という形になる.線形フィッティングには
lm関数を使う.
1 r <- lm( y ~ cos(x*pi/90)+sin(x*pi/90) )
lm
に指定するのは,従属変数
yと
~とモデル式から未知パラメータを取ってしまったものである.名前
rを 使って計算結果を見ることができる.
lm
関数が計算したさまざまな結果全体を見るには,
summary(r)とすればよいが,未知パラメータの値だ け取り出すには次のようにする.
1 p = r$coefficients
2 p
p
の各要素に対応しているモデル式の項が表示され,定数項
Cがはじめに来て,次に
cosの係数
A,
sinの係 数
Bの順になっていることがわかるので,
1 C <- p[[1]]
2 A <- p[[2]]
3 B <- p[[3]]
式
(15)を使って
a,b,cの計算もやっておく.
Rでは
atan2関数が使える.
1 a <- 2*sqrt(A^2+B^2)
2 batan2(B,A)*(180/pi)
3 c <- C-a/2
4 a;b;c
4.5 グラフの作成
理論曲線を描くために,フィッティングの結果を入れて関数を定義する.
(12)式に戻ろう.
1 f <- function(x) a*cos((x-b)*pi/180)^2+c
角度は度からラジアンに直した.準備ができたので,データ点と理論曲線を描く.
1 plot(f,0,360,xlab="
角度
(度
)",main="テストデータのフィッティング
")2 points(x,y)
3 grid()
始めの
plotでは少し飾りを付けた.また,
grid()で目盛線を入れている.
グラフは
PNGか
JPEGファイルに保存するのが簡単である.保存してから印刷したりレポートに入れた りすればよい.
1 savePlot("xxxxyyyy.png","png")
4.6 ひとまとめにする
データの読み込みからグラフの保存までを1つの関数に入れ,
analyzeという名前をつけよう.この関数に は,データファイルの名前を引数として与えることにする.下の関数定義を
PDFから
Rへコピー&ペース トしても動くかもしれない
*10.
1 analyze <- function(datafile) {
2 data <- read.table(datafile) #
データ読み込み
3 x <- data[[1]]; y <- data[[2]] # x
列,
y列
4 r = lm(y ~ cos(x*pi/90)+sin(x*pi/90)) #
フィッティング
5 p <- r$coefficients # $
で未知係数の値を得る
6 C <- p[[1]]; A <- p[[2]]; B <- p[[3]]
7 a <- 2*sqrt(A^2+B^2)
8 b <- 0.5*atan2(B,A)*(180/pi)
9 c <- C-a/2
*10
これが入っているファイルを入手することができた場合は,R で一度だけ
source(”ファイル名”) のようにすればよい.
10 print(c(a=a,b=b,c=c)) #
結果をまとめて表示
11 #
グラフを描く
12 h <- max(y)*1.1-min(y)*0.1 #
上に
10%余裕
13 l <- min(y)*1.1-max(y)*0.1 #
下に
10%余裕
14 plot(function(x) a*cos((x-b)*pi/180)^2+c, 0, 360,
15 xlab="
角度
(度
)", ylab="強度
(V)", ylim=c(l,h),16 main=paste(datafile, ", b=", b) )
17 points(x, y)
18 grid()
19 savePlot(paste(datafile,"png", sep="."), type="png")
20 }
これで,次のようにするだけで,パラメータ値を計算して表示し,グラフを画像ファイルに保存してくれる.
1 analyze("xxyy.dat")
R
を終了するときに,
”Save workspace image? [y/n/c]: ”と訊かれたら,
yで答える.すると,次に同じ ディレクトリで
Rを起動すると,前におこなった定義がそのまま使える.この情報は
”.RData”という隠し ファイルに保存されている.何もかも終わったら,このファイルを消去する.
5 線形フィッティング – スクリプト言語 python 編
データ解析をプログラミング言語でおこなうにはいろいろな選択肢がある.豊富な科学計算機能と素早いテ ストができることと正確な情報が得やすいことから
Pythonを使うことにしよう.
Pythonのデータ処理ライ
ブラリの
1つである
pandas*11と
pylab*12を使って線形フィッティングをやってみる。
Pythonの文法の理
解はいらない
*13。
Pythonを実行する環境はいろいろあるが,
spyderというユーザー・インタフェース を使 うことにする
*14 *15。
5.1 基本的操作法
spyder
を起動するには,たとえば端末に次のようにタイプする.
1 spyder
あるいは,メニューから
spyderを起動できるかもしれない.
*11http://pandas.pydata.org/
*12http://docs.scipy.org/doc/
*13http://www.python.jp/doc/release/
*14spyder
を準備するには,Linux ではパッケージシステムを使って
spyderを導入する.Windows と
Macでは,Anaconda を
webで探して導入する. 簡単.
*15spyder
を使わず,
15ページのデータファイルの形式を見,スクリプトファイル
henkou.pyをダウンロードし,
19ページの脚注
の最後の3行を見れば,解析だけはできる.
spyder
のウィンドウは大きく3つの枠に分かれているが,そのうち
IPython consoleに式やコマンドを 打ち込めば,その場で計算の実行ができる.
1+2とか
2*3とか
12/-4などとやってみれば,ただの電卓とし ての使い方がわかるが,注意すべき点が少しある.
• 1, 2, 3
は
1.0, 2.0, 3.0とは異なる. 前者は「整数型」後者は「実数型」である.
Python 2では,整 数型どうしの割り算は小数部が切り捨てられてしまう.実数の結果が必要な場合は,整数でも
2.0とか
2.のように小数点を付けて書く.
•
べき乗には
^ではなく
**を使う.
^は違う意味に使われる.
2×109のようなものは
2*10**9のよ うに書くよりも,
2e9のように書く方がよい.
•
行の左の空白(インデント)の量は文法上意味があり,
if文のような複合文のブロックの始まりで空白 を増やし終わりで元に戻す.
• log(2.718)
のように,関数呼び出しはいつも小括弧を付けて書く.
Variable explorer
で は 変 数 の 値 を 見 る こ と が で き る.
IPython consoleに
a=b=0.1と 打 っ て,
Variable explorer
を見ると,
aと
bの値が表示されているのがわかる.また,
del a, bと打てば,
aと
bが消去される.
上向き矢印キー
h↑
iで前のコマンドを再現し,修正してから
henteriキーで再実行することができる. こ れは「ヒストリー機能」である.
5.2 スクリプト作成
Editor
ウィンドウにはプログラムなどを書いて保存することができる.まず,
Fileメニューの
New file...で新しい
Editorウィンドウを開く.すでに開いている
Editorウィンドウは閉じてしまってよい.
Spyder
では,
Editorウィンドウに書いたプログラムのどの部分でも任意に実行してテストすることがで
きる.たとえば,
hF9iを押すと,あらかじめ選択した部分が
IPython consoleで実行される.もう1つの 方法は,
hCtrlihEnteri,または
Run current cellである.こちらはマークによって区切られた範囲を実行 するものである.便利なので練習しておこう.
Editorウィンドウ中に次のように書く
(初めから書いてある ものは置いておく. 左端から書く. 文字列は半角のシングルクォート
’かダブルクォート
”で囲む
).
1 #%%
2 a='
たら
'3 print a
4 #%%
5 a=a+a
6 print a
#%%
の行は,
Editorウィンドウを「セル」という部分に区切るための記号である.今書いたものは
2つのセ ルに分かれている.境界は横線でわかる.上側のセルの中のどこかにカーソルを置いておき,
Runメニューで
Run current cellを実行する.するとそのセルの中身が
IPython consoleで実行される.
Run current cellは
hCtrlihEnteriを押してもできるし,ツールバーにもこれをおこなうボタンがある.
上側のセルと下側のセルをいろいろな順番で実行してみてほしい.試し終わったら,この意味のないプログラ ムは区切り記号と一緒に消してしまう.
5.3 ライブラリーの使用
Python
は汎用プログラミング言語なので,原子的なもの以外の機能はプログラムモジュール
(ライブラ
リー
)として提供され,必要なモジュールを指定して使用する.数値計算や図表示のさまざまな機能を使用す
るには,
pylabモジュールが適している.また,
pandasモジュールを併用するともう少し便利になる.これら
のモジュールを使用するため,
Editorウィンドウに次のコードを書き,
Run current cellで実行し,エラー にならないことを確認しておく
*16.
1 from pylab import *
2 from pandas import *
3 #%%
ここでファイル名を付けて保存しておく.ファイル名は
henkou.pyのように適当でよいが,拡張子として
.pyを付けておく.何か書き足したときには,忘れないで保存をおこなう.
なお,コマンド,関数,ファイル名などは,入力の途中で
htabiキーを押せば残りが自動的に入る.また,
関数名を入力した直後に
hcontroliキーと
Iを押すと説明が
Object inspectorに表示される.関数呼び出 しを括弧まで書くだけで自動的に説明があらわれるようになっている場合もある.このような入力補助機能を 利用して,記憶力を節約するのがよい.
5.4 計画行列作成
線形モデルの式
(13)を使って式
(8)の計画行列
Gを構成するには,独立変数
xの値リスト
x1,x2, ...,xnが 必要である.
pythonでは,単純なリストはたとえば
[1, 2, 3]のように表現する
*17.しかし,このリスト 構造は一般的すぎて扱いが面倒なので,実数のベクトルや行列を効率よく扱うことができるリッチな機能を備 えた
arrayや
DataFieldというタイプのデータ構造を使う
*18.
array([1,2,3])などとすれば変換することがで きる.そこで,
[1,2,3]*2の結果と
array([1,2,3])*2の結果の違いを見てほしい.用途の違いがわかる.
x
のリストを与えれば計画行列を作ってくれる関数を定義しておこう
*19.
Editorウィンドウに次のコード を入力する
(先ほどの区切り記号の下に続けて
).
def ...の行は左端から書く.
2行目以降には自動的に空 白が入る.これらの空白を変更してはいけない.
4行目で改行した後
5行目にできる空白は消しておく.括弧 の種類に注意.関数名
make_gは
makeとアンダースコアと
gである.
*16import *
はそれぞれのモジュールで定義されたすべてのものを読み込んでしまい,同じ名前のものがたまたま複数あると取り返
しがつかないので,一般的には推奨されない.ここではそのようなことが起きる可能性を無視し,手軽さを優先している.
*17
これは整数
1, 2, 3を並べてひとまとめにしたものであり,
a=[1,2,3]のようにして全体にひとつの名前を付けることができる.
その中のひとつずつの要素は,0 から始まる要素番号を使って,
a[0], a[1]のように書き表す.
a=[[1,2],[3,4,5]]のような リストのリストは要素を
a[0][0], a[1][2]のようにあらわす.
*18array
は
numpyモジュールによって,DataField は
pandasモジュールによって定義されている.
numpyモジュールは
pylabモジュールの一部である.
*19
この程度の計算は実質的に
1行のプログラムですんでしまうが,それでもわざわざ新しい関数を定義するのは,関数名を見ればど
んなことをするのかわかるからである
(子供の名前を見れば少なくとも親の思いはわかる.).1 def make_g(xx):
2 u"
測定点リストから計画行列を作る関数:定数項省略
"3 rr = array(xx) * pi/90
4 return DataFrame( [ [cos(r),sin(r)] for r in rr ] )
5 #%%
カーソルをこの定義の中に入れて,
Run current cellで実行する.この実行は
make_gという名前の関数の 定義
(すなわちどのように計算すればいいかということの記憶
)を
pythonが行っただけである
*20.
こ の 関 数 の 動 作 を テ ス ト す る た め,
IPython consoleで, 次 の よ う に, 測 定 点 の リ ス ト と し て
[0,15,30,45]を
make_gに与えて実行してみる.
1 make_g([0,15,30,45])
これで
4行
×2列の配列ができる.これは次のような計算をしたのである.各行は各測定点に対応している.
cos(2×0°) sin(2×0°) cos(2×15°) sin(2×15°) cos(2×30°) sin(2×30°) cos(2×45°) sin(2×45°)
5.5 データ入力と読み込み
測定データはテキストファイルに入れておくのがよい.テキストファイルは作るのも変更するのも容易だか らである.
Fileメニューの
New fileで新しい
Editorウィンドウを開き,ここに測定データを入れて保存し よう.何か書いてあるのを全部消してしまってから,次のように書き込む
(これは例である
).はじめの行には
xと
yを列名として書く.2行目から偏光フィルターの角度と透過光強度のデータを空白で区切って書き込ん でいく.各行の右側に
#で注釈を入れてもよい.空行や注釈のみの行は許されないかもしれない.
1 x y #
スクロース溶液
1, 5/162 0 0.809
3 30 0.403
4 60 0.039
5 90 0.077
6 120 0.477
7 150 0.836
8 180 0.794
9 210 0.400
*20
1行目のキーワード
defは
‘define’(定義)ということで,関数定義の開始をあらわす.この行には関数名と仮パラメータを書 く.関数のパラメータにどのようなデータを想定するのかを明示するような文法は無い.2行目の文字列は
‘docstring’といい,
IPython console
で
make_g ?と打ったりした時に表示される説明文である.3行目はこの関数に与えられたリストの全成分
に
π/90を掛けている.三角関数には円周角
(ラジアン
)で角度を与えなければならない.4行目は上の結果を使って行列のすべ
ての行を作り全体をまとめて結果としている.array や
DataFrameはリストや行列データの特性を数値計算向きにするものであ
る.未知パラメータは
A,B,Cと
3つあるので,計画行列は本来
3列になるが,C は定数項であるため別扱いになる.
10 240 0.040
11 270 0.081
12 300 0.481
13 330 0.843
14 360 0.782
これを
Fileメニューの,
Save as...で保存する.ファイル名には英語アルファベットと数字が使えるが,ひ らがなや漢字を使うこともできる.説明の都合上,今はファイル名を
data10としておこう.もし拡張子を付 けるなら,テキストファイルという意味で
.txtを付けるとよい.
Desktopに保存しよう.
ファイルに保存されているデータを計算に使うには,それを
pythonに読み込んでやる必要があるが,ま ず,
IPython consoleで
pwdと打って作業ディレクトリを表示し,これがデータファイルの保存場所と異 なる場合は,作業ディレクトリをファイルの保存場所に変更する
*21.
データファイルを読込むために,
IPython consoleで次のように打つ.
1 file = 'data10'
2 data = read_table(file, sep='\s+', comment='#')
ファイル名はいろいろ変わるので,代わりに
“file”のような変数を使うのがよい.
sep='\s+'は,
read_table関数に,データが1つ以上の空白によって区切られていることを教えるために必要なパラメータである.ま
た,
comment='#'は注釈文字を指定するパラメータである.読み込んだデータには
“data”という変数名が
付いたので,
dataと打てば中身を確認することができる.
x
-yグラフを表示するには次のようにする.
1 data.plot(x='x', y='y', kind='scatter')
'scatter'
とは
Excelなどの「散布図」と同じ意味である.測定の間違いがわかる場合があるから,グラフ
を表示してよく見ることは重要である.
5.6 フィッティング
線形フィッティングを
pandasモジュールの
ols関数でおこなう.
IPython consoleで試してみよう.
1 ols(x=make_g(data.x), y=data.y)
ols
には,
x=で計画行列を与え,
y=で 測定値リストを与える.
data.xは
data中の
x列を意味する.
data.yは
y列.
ols
の結果は多くの数値からなるので,それらを一旦適当な変数名でまとめて保存するのがよい.そこから パラメータの推定値を取り出して
A, B, Cに入れ,それらの標準誤差を
dA, dB, dCに入れる.
*21Editor
ウィンドウのタブ
(左上の出っ張り)の右クリックメニューで
Set console working directoryを選ぶと,作業ディ
レクトリがファイルの保存ディレクトリに変更される.ファイル保存場所と作業ディレクトリが一致している場合は,ファイル名
のみでファイル指定ができる.pwd は
print working directoryのこと.
1 fit = ols(x=make_g(data.x), y=data.y)
2 A, B, C = fit.beta
3 dA,dB,dC = fit.std_err
ここで,
A, dA, B, dB, C, dCと打てば,
3つのパラメータの推定値と標準誤差がわかる.
式
(15)から,元の非線形モデルのパラメータは次のようにして得られる
(角度はラジアンから度に変換
).
1 a = 2 * sqrt( A ** 2 + B ** 2 )
2 b = math.atan2( B, A ) * 90 / pi
3 c = C - a/2
atan2()
には
math.を付けなければならない.これらのパラメータの値の標準誤差は
A, B, Cの標準誤差か
ら求められるが,ここでは
bが大事なので
bの標準誤差だけを求める.誤差の伝播則で計算すると
∆b= s ∂b
∂A∆A
!2
+ ∂b
∂B∆B
!2
= 2 a2
q
(B∆A)2+ (A∆B)2
となる
*22.よって,
bの標準誤差は次のように計算すればよい.
1 db = sqrt( (B*dA)**2 + (A*dB)**2 ) * (2/a**2) * (180/pi)
5.7 グラフの完成
決定したパラメータを使ってモデルのグラフを表示しよう.それには,
fit.predictという関数
(オブジェク ト
fitのメソッドともいう
)を使って,測定点以外での値を計算する.細かい間隔で計算しないとなめらかな 曲線にならないので,
1°ごとに計算する
*23.
1 xfine = arange(data.x.min(), data.x.max())
2 plot(xfine, fit.predict(x=make_g(xfine)))
グラフのタイトルを入れることができるが,そこに計算結果を入れておく.
1 title('{}: a={:.4}, b={:.4}(sigma={:.2}), c={:.4}\n'
2 .format(file, a, b, db, c))
.format
の前の文字列の中の中括弧の部分が
file, a, b, db,および
cの値に置き換えられて表示される.中括 弧の中には,
{:.4}のように,表示精度を入れることができる.
*22
式
(14)または式
(15)から,∂b/∂A
=−2B/a2,∂b/∂A
= 2A/a2.∆
b,∆A,∆Bは各パラメータの標準誤差.ただし,これらの式 では角度の単位はラジアンである.
*23
測定データの独立変数の最大値と最小値を
data.x.min()と
data.x.max()で取得し,arange 関数によって,最小値と最大値
の間で間隔
1の数値列を作り,この数値列を
make_g関数に与えて細かい間隔での計画行列を組み立てる.それを
fit.predictに与えると,すでに
fitの中に収められている情報を使って,関数値リストが計算される.plot 関数には横軸データとして
xfineも与える必要がある.
グラフに画像保存のボタンがあれば,それでファイルに保存することができるが,プログラムで保存するに は,
gcf().savefig(file+'.png')のようにやればよい.
file+'.png'は,データファイルの名前に拡張
子として
‘.png’を追加したものを意味する.
gcf()はいま表示している図の情報.
5.8 解析をおこなう関数の作成
データを読み込んでグラフを作るまでの手続きを
analyseという名前の関数にまとめよう.この関数はデー タファイル名を与えて呼び出すようにする.
Editorウィンドウの
make_gの定義に続いて,次のコードを入 力する.
1 def analyse(file):
2 u"file
で与えられたデータを解析し結果を図ファイルに出力
"3 data = read_table(file, sep='\s+', comment='#')
4 fit = ols(x=make_g(data.x), y=data.y) #
推定計算
5 A, B, C = fit.beta #
推定値
6 dA,dB,dC = fit.std_err #
推定値標準誤差
7 a = 2 * sqrt( A ** 2 + B ** 2 ) #
振幅
8 b = math.atan2( B, A ) * 90 / pi #
偏光方向
9 c = C - a/2 #
最低値
10 db=sqrt( (B*dA)**2 + (A*dB)**2 )*(2/a**2)*(180/pi) #b
誤差
11 data.plot(x='x', y='y', kind='scatter') #
測定点プロット
12 xfine = arange(data.x.min(),data.x.max()) #1°
ごとに分割
13 plot(xfine, fit.predict(x=make_g(xfine)) ) #
曲線プロット
14 title('{}: a={:.4}, b={:.4}(sigma={:.2}), c={:.4}\n'
15 .format(file, a, b, db, c))
16 gcf().savefig(file+'.png') #
画像ファイルへ保存
17 return {'a':a, 'b':b, 'db':db, 'c':c}
18 #%%
return
文はキーと値の形式で結果を返している.
Run current cellをしてから,
IPython consoleで
1 analyse('data10')
と打って呼び出す.結果が
data10.pngというファイルに保存されることを確認し,うまくいったら,ここま でのプログラムを
1つのセルにまとめるため,区切り記号をすべて消すか
#%に変え,このプログラムを保存 する.以後は,
IPython consoleで
from henkou import analyseとするだけで,
analyse関数が使える ようになる.
なお,以上の計算では単位の表示を考慮していないが,報告書では当然単位の明示が必要である.
Linux
や
Mac OS Xでは,このプログラムを独立した完全なコマンドにすることもできる.それには,プログラムの
1行目に
#! /usr/bin/python
と書き
(これはshebangという).最後のところに次のコードを追加して保存する.
import sys
if __name__ == "__main__":
for f in sys.argv[1:]:
analyse(f)
最後に,このファイルに実行権を付ける
(たとえばファイルのプロパティーで).端末を開いて,./henkou.py data10 data11 data12
のように打てば,複数のデータファイルの解析が一度にできる.データは任意のテキストエディタで入力することができる.
6 線形フィッティング – Excel 編
Excel
のような表計算プログラムでは,
LINESTという関数で線形フィッティングをおこなうことができ
る. 表を埋めたりグラフを表示するのに手間がかかるが,結果を着実に得ることができる.
次の図のように,測定値として,
xと
yの値を縦向きに並べる. ここでは三角関数を使うので,
xはラジア ンに直している. その右にモデル行列を入れる. ここでは「パラメータ係数」と称している.定数項はモデ ル行列ではすべて
1であるが,表計算の場合はそれを入れる必要は無い. 「フィットパラメータ」の2行下の 3つのセルをセレクトして,そこに
LINEST関数を入れる.
=LINEST(C3:C15,D3:E15,1)
LINEST
関数には,
yの範囲とモデル行列の範囲を指定する. 定数項の計算もさせるために,
3番目のパラ
メータを1にする. この式を配列式として確定するため,
controlキーと
shiftキーを押しながら
enterする.
パラメータの推定値が表示されるが,定数項以外の順序がなぜか逆になる.
推定曲線は推定値を使って別に計算して表示しなければならない. なぜなら,測定点だけで計算しても滑
らかな線にはならないからである. 図では,表のこの部分は上の方の一部だけが見えている.グラフは「散布
図」として作成する. 2系列のデータを一つのグラフに入れる方法を調べるには,とにかくいろいろ試して
みればよい.
測定値 パラメータ係数
degree x y cos sin
0.4165 1
30 0.524 0.2264 0.5 0.866 60 1.047 0.0318 -0.5 0.866 90 1.571 0.0432 -1 1E-016 120 2.094 0.2223 -0.5 -0.866 150 2.618 0.4315 0.5 -0.866 180 3.142 0.4371 1 -2E-016 210 3.665 0.2548 0.5 0.866 240 4.189 0.0408 -0.5 0.866 270 4.712 0.0215 -1 4E-016 300 5.236 0.2149 -0.5 -0.866 330 5.76 0.4266 0.5 -0.866 360 6.283 0.4128 1 -5E-016
フィット・パラメータ
B A C
-0.11 0.1982 0.2294 degree x y
0.4275 6 0.105 0.401 12 0.209 0.3669 18 0.314 0.3268 24 0.419 0.2824 30 0.524 0.2358
0 50 100 150 200 250 300 350 400
0 0.05 0.1 0.15 0.2 0.25 0.3 0.35 0.4 0.45
0.5 列 C
列 C
角度(degree)
透過率(任意単位)
A B C D E F G H I J K
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
7 非線形フィッティング – mathematica 編
数学ソフトの
Mathematicaを使って非線形フィッティングをおこなってみよう. どういう計算をしてい るかがわかるようにする. 答えは一意的に求まる.
まずは
Mathematicaを起動して,ノートブックを表示する. 起動法や基本的な操作法は附録に書いたの
で,適宜参照してほしい.
7.1 データ入力
データを次のように入力する.ノートブックで,
dat=とタイプし,続けて,挿入メニューの表・行列 の 新 規作成で,ダイアログを出し, 「列数」を
2にして
OKボタンを押す. 測定値を下のように入力する. 左側は 回転角度,右側は透過光強度である. 行を追加するには,入力済みデータの一番下の行で,
hcontroli-henteriを打つ.
dat=
0 0.809 30 0.403 60 0.039 90 0.077 120 0.477 150 0.836 180 0.794 210 0.400 240 0.040 270 0.081 300 0.481 330 0.843 360 0.782
;
空白データが無いようにする. データがすべて入ったら,表の右側にセミコロンを付けて,
hshifti-henteriを 打つ. 間違えたらデータを修正してから
hshifti-henteriを打てばよい.
datとすると,内容を確認すること ができる. 回転角度と透過光強度からなる複数のリストが全体としてひとつのリストにまとめられている.
Mathematica
では,何か動作をさせるには
hshifti-henteriを打つ必要があることを忘れないこと.
次に,今入力したデータをグラフ表示する.
ListPlot[dat]
50 100 150 200 250 300 350
0.2 0.4 0.6 0.8
念のため,これから使う名前を洗浄する. 何か変なことが起こるとき,名前の洗浄をしなかったのが原因 ということは多い.
Clear[x,a,b,c]
7.2 モデルの入力
モデル関数を定義する.
f[ x_, a_, b_, c_ ] := a Cos[(Pi/180)(x-b)]∧2 + c;
モデルに適当なパラメータを入れてみて,グラフでデータと比較する.
Show[Plot[f[x,0.8,160,0], {x,0,360}], ListPlot[dat]]
50 100 150 200 250 300 350
0.2 0.4 0.6 0.8
dat
の中の角度と強度を別々のリストにする.
{X, Y}=Transpose[data];
残差の二乗和を関数にする.
J[a_, b_, c_] := Total[(Y-f[X,a,b,c])∧2]
7.3 フィッティングの実行
次のようにして,
J(a,b,c)の最小点を求める.
a,b,cの初期値として,上で推定した値を使う.
r = FindMinimum[J[a,b,c], {a,0.8}, {b,160}, {c,0}]
r
から結果を取り出す.
s = r[[2]]
グラフを見る.
Show[Plot[f[x,a,b,c]/.s, {x,0,360}], ListPlot[dat], Frame->True]
0 50 100 150 200 250 300 350
0.0 0.2 0.4 0.6 0.8
もう一度結果を見る.
s