An English version is here.
前回の記事では ErrorNum クラスの基本的な使い方を解説しましたが、今回は一歩進んだ内容を解説します。内容は次の3点です。
- 共分散がある変数同士の演算
- 値の統計的有意性の検定
- 任意の関数による誤差の伝搬
共分散がある変数同士の演算
2つの変数が独立でない場合、誤差に相関が生じることがあり、単純な誤差の伝搬をすると適切な結果を得られないことがあります。具体的には次の例のような場合です。
>> x = 4 + randn(100, 1);
>> y = x + 0.5 * randn(100, 1);
>> figure;plot(x, y, '.');
>> axis([0, 8, 0, 8]);
この結果を図にすると、
となりますが。一つの点を一つの測定値とすると、xの誤差とyの誤差が相関している様子がわかると思います。xが大きいときはyも大きく、xが小さいときはyも小さくなります。このような場合、次の図からもわかる通り相関によって x + y の誤差は x – y の誤差よりも大きくなります。
この共分散を考慮に入れずに計算した場合、誤差の計算は誤ったものになってしまいます。
>> x_en = ErrorNum.create(x, 1);
>> y_en = ErrorNum.create(y, 1);
>> x_en + y_en % ErrorNum は単純な二乗和平方根を計算します。
ans =
ErrorNum:
8.3 ± 1.5
>> x_en - y_en % こちらの誤差の方が小さいはずですが…
ans =
ErrorNum:
0.0 ± 1.5
これを正しくするにはあらかじめ計算した共分散の値を ErrorNum の計算に教えてやります。
% 共分散を計算してそれを考慮した加算(covadd)をさせる
>> cov_xy = cov(x, y); % cov は分散"行列"を返すので、cov_xy(1, 2) か (2, 1) 要素を使います。
>> x_en.covadd(y_en, cov_xy(1, 2))
ans =
ErrorNum:
8 ± 2
>> x_en.covsub(y_en, cov_xy(1, 2))
ans =
ErrorNum:
0.0 ± 0.4
x – y の誤差が 1.5 から 0.4 に減少しています。上で y の値を作るときに x に 0.5 * randn を加えて構築したので、x – y が 0.5 に近い誤差を持つ、というのは整合性がとれています。
値の統計的有意性の検定
値を計算しても多くの場合は、統計的有意性の確認をしないと意味を持ちません。ErrorNum クラスは ANOVA (analysis of variance) ベースの簡単な統計テストをしてくれます。
%% ANOVA テスト (0 との 比較をし、p値を返します。)
>> a = ErrorNum(3, 1);
>> b = ErrorNum(2, 1);
>> a.sig % 最も簡単な記法
ans =
0.0027
>> sig(a) % これもいけます
ans =
0.0027
>> sig(a - b) % これもいけますが…
ans =
0.4795
>> (a - b).sig % この記法は使えません。
Error: File: ErrorNum_demo_advanced.m Line: 34 Column: 8
Invalid use of operator.
Matlab でメソッドを使う記法はドットを使うものと、関数のように書く方法の2つがありますが、演算した結果に適用したい場合、ドットを使う方法はエラーを返します。これは ErrorNum の仕様というよりは、 Matlab 自体のクラスの扱いかたによるものだと思います。
任意の関数による誤差の伝搬
四則演算などの単純な計算なら誤差の伝搬も簡単ですが、他の演算(関数など)に誤差の伝搬を適用したい場合はより複雑な計算が必要になります。完全とは言えませんが、ErrorNumはそのような事例にも対応しています。次の例を見てください。
>> x = ErrorNum([1, 2, 3], 0.1 * ones(1, 3))
ErrorNum:
1.00 ± 0.10, 2.00 ± 0.10, 3.00 ± 0.10
>> y = x.convert(@log, @(t) 1./t)
ErrorNum:
0.00 ± 0.10, 0.69 ± 0.05, 1.10 ± 0.03
convert の第一引数は適用したい関数のハンドルで、第二引数はその導関数のハンドルです。ほとんどの Matlab 関数は ErrorNum には適用できませんが、このように導関数を与えてやることで誤差の伝搬も考慮した計算が可能になります。(xの値に応じてyの変分も小さくなるので誤差が縮んでいるのがわかると思います。) 誤差の伝搬は線形近似を使って行われているので、誤差が大きくなって関数の非線形性が無視できなくなる場合この方法はあまり好ましくありません。