Slide 1

Slide 1 text

ランダムに 振る舞う機能を   JUnit  する 渋⾕谷Java #3 2013.9.28 at BizReach KOMIYA Atsushi ( @komiya_atsushi )

Slide 2

Slide 2 text

by batigolix http://www.flickr.com/photos/batigolix/925301391/ イントロダクション 2

Slide 3

Slide 3 text

KOMIYA Atsushi @komiya_atsushi 3

Slide 4

Slide 4 text

分析⼒力力をコアとする マーケティングソリューションカンパニー レコメンデーション&機械学習系   Java エンジニア 4

Slide 5

Slide 5 text

分析⼒力力をコアとする マーケティングソリューションカンパニー レコメンデーション&機械学習系   Java エンジニア 代々⽊木の緑⾊色の会社 5

Slide 6

Slide 6 text

#TokyoWebmining 事務局 分析/機械学習/アドテク等のネタで お話していただける講師を募集中デス! 6

Slide 7

Slide 7 text

by Sebastian Bergmann http://www.flickr.com/photos/sebastian_bergmann/8127016855/   みなさん、 JUnit してますか? 7

Slide 8

Slide 8 text

今⽇日のお話 • 動機 • Random#nextInt() などで得られる乱数に 従って振る舞い、出⼒力力が決まる機能を   JUnit  でテストしたい • でも、普通に  JUnit  を使っただけでは結果 が不不定なテストとなってしまう… 8

Slide 9

Slide 9 text

今⽇日のお話 • 動機 • Random#nextInt() などで得られる乱数に 従って振る舞い、出⼒力力が決まる機能を   JUnit  でテストしたい • でも、普通に  JUnit  を使っただけでは結果 が不不定なテストとなってしまう… データサイエンスを⽣生業としている企業らしく… 統計的な⼿手法を 使って解決しよう! 9

Slide 10

Slide 10 text

今回対象とするランダムに振る舞う機能 • 前提条件 1.  1回の試⾏行行につき発⽣生する事象が1つで あること •  試⾏行行:機能を実⾏行行して何らかの結果を 得ようとする⾏行行為 •  事象:出⼒力力される・得られる値 2.  事象は離離散値でかつ種類数が有限個数で あること 3.  事象の⽣生起確率率率が事前に明らかである・ 推定できること 10

Slide 11

Slide 11 text

今回対象とするランダムに振る舞う機能 • 前提条件 • 1回の試⾏行行につき発⽣生する事象が1つで あること •  試⾏行行:機能を実⾏行行して何らかの結果を 得ようとする⾏行行為 •  事象:出⼒力力される・得られる値 • 事象は離離散値でかつ種類数が有限個数で あること • 事象の⽣生起確率率率が事前に明らかである・ 推定できること 早い話が、 「コイントスする」 「サイコロを振る」 に相当する機能と思えばOK 11

Slide 12

Slide 12 text

by Bartmani http://www.flickr.com/photos/8349201@N04/503039124/ いかにしてランダムな 振る舞いをする機能を   ユニットテスト するか? 12

Slide 13

Slide 13 text

ユニットテストへの統計学的アプローチ • 推計統計学における「仮説検定」の考え⽅方 を利利⽤用する • コイントスによる仮説検定の例例    (⼆二項検定) • 「コイントスを  20 回試してみたんだけど、 表が  15  回も出たんだよね。このコインって、 歪んでる(1/2の確率率率じゃない)のかな?」 • 「歪んでないコインと仮定した場合、20 回 コイントスしてたまたま表が  15  回出る確率率率は   5%  以下(4.139%)だよ〜~?  だから、5%  の 確率率率で間違いかもしれないけど歪んでいると ⾔言えそうだねっ!」 13

Slide 14

Slide 14 text

ユニットテストへの統計学的アプローチ • 推計統計学における「仮説検定」の考え⽅方 を利利⽤用する • コイントスによる仮説検定の例例    (⼆二項検定) • 「コイントスを  20 回試してみたんだけど、 表が  15  回も出たんだよね。このコインって、 歪んでる(1/2の確率率率じゃない)のかな?」 • 「歪んでないコインと仮定した場合、20 回 コイントスしてたまたま表が  15  回出る確率率率は   5%  以下(4.139%)だよ〜~?  だから、5%  の 確率率率で間違いかもしれないけど歪んでいると ⾔言えそうだねっ!」 100% の精度度ではない 14

Slide 15

Slide 15 text

ユニットテストへの統計学的アプローチ • 推計統計学における「仮説検定」の考え⽅方 を利利⽤用する • コイントスによる仮説検定の例例    (⼆二項検定) • 「コイントスを  20 回試してみたんだけど、 表が  15  回も出たんだよね。このコインって、 歪んでる(1/2の確率率率じゃない)のかな?」 • 「歪んでないコインと仮定した場合、20 回 コイントスしてたまたま表が  15  回出る確率率率は   5%  以下(4.139%)だよ〜~?  だから、5%  の 確率率率で間違いかもしれないけど歪んでいると ⾔言えそうだねっ!」 試⾏行行回数 p 値 有意⽔水準 15

Slide 16

Slide 16 text

ユニットテストに応⽤用する • テスト対象の機能によって得られる事象 (出⼒力力結果)の⽣生起確率率率が、想定してい る確率率率に近しいことを検証する • 例例 • 60% の確率率率で  “晴れ”  を、 25% の確率率率で  “曇り”  を、 15% の確率率率で  “⾬雨” を返すメソッド String  weather()  をテストしたい! 16

Slide 17

Slide 17 text

ユニットテストに応⽤用する • 例例 • 60% の確率率率で  “晴れ”  を、 25% の確率率率で  “曇り”  を、 15% の確率率率で  “⾬雨” を返すメソッド String  weather()  をテストしたい! • 100 回呼び出したときの各事象の頻度度 事象 推定値  [回] 観測値  [回] 晴れ 100 * 0.60 = 60 55 曇り 100 * 0.25 = 25 27 ⾬雨 100 * 0.15 = 15 18 17

Slide 18

Slide 18 text

ユニットテストに応⽤用する • 例例 • 60% の確率率率で  “晴れ”  を、 25% の確率率率で  “曇り”  を、 15% の確率率率で  “⾬雨” を返すメソッド String  weather()  をテストしたい! • 100 回呼び出したときの各事象の頻度度 事象 推定値  [回] 観測値  [回] 晴れ 100 * 0.60 = 60 55 曇り 100 * 0.25 = 25 27 ⾬雨 100 * 0.15 = 15 18 この「ずれ」は 果たして妥当 なのだろうか? 18

Slide 19

Slide 19 text

具体的な仮説検定の⼿手法:カイ⼆二乗検定 • カイ⼆二乗検定による適合度度検定 • 試⾏行行した・観測した結果得られた、各事象 の頻度度の分布が想定・推定される頻度度の分 布とどれだけ近しいか?  を確認する 19

Slide 20

Slide 20 text

具体的な仮説検定の⼿手法:カイ⼆二乗検定 • カイ⼆二乗検定による適合度度検定 • 試⾏行行した・観測した結果得られた、各事象 の頻度度の分布が想定・推定される頻度度の分 布とどれだけ近しいか?  を確認する ずれっぷりが 妥当なのかを 判断できる! 20

Slide 21

Slide 21 text

ユニットテストの 観点で仮説検定を ⾒見見ていきます 21

Slide 22

Slide 22 text

仮説検定の注意点 • 「想定される状況からずれていること」 を積極的に⽰示したい動機が背景にある • 医療療などの⽅方⾯面で特に顕著 • ユニットテストの場合は 「想定からずれていないこと」、 すなわち  OK であることを⽰示したい • 「有意⽔水準」など、⾔言葉葉の意味が「逆」に 思えるケースがあるので要注意 22

Slide 23

Slide 23 text

仮説検定を利利⽤用したユニットテストの検出精度度   偽陽性と偽陰性 • 先に述べた通り、仮説検定の精度度は  100% ではない • ユニットテストにおける偽陽性・偽陰性を考えてみよ う • 偽陽性(第⼀一種過誤、False positive) • OK と判定されるテストケースが、実⾏行行の結果、誤って   NG  として検出されてしまう状況(誤検知) • 偽陰性(第⼆二種過誤、False negative) • 偽陽性とは逆に、NG として検出されるべき テストケースが  OK 判定になる状況(バグ検出漏漏れ) • 両⽅方ともに少ない状況が望ましい • 状況によっては、偽陰性がより重視されることも 23

Slide 24

Slide 24 text

有意⽔水準 • NG を検出する精度度を左右する重要な要素 • ⼀一般的な仮説検定では  5% or 1% とする • ユニットテストにおいて、有意⽔水準を • ⼤大きくする •  J NG  結果の検知漏漏れは減る •  L OK →  NG  の誤検知が増える • ⼩小さくする •  J OK →  NG  の誤検知は減る •  L NG 結果の検知漏漏れが増える 24

Slide 25

Slide 25 text

試⾏行行回数 • 「サイコロを振る回数」 「コイントスする回数」に相当する • 回数が多ければ多いほど、得られた 判定結果の信ぴょう性が増してくる • 事象の数(≒⾃自由度度)が⼤大きい場合は、 試⾏行行回数も多めに設定する必要がある • L スローテスト問題が起きやすくなる 25

Slide 26

Slide 26 text

by marissa http://www.flickr.com/photos/44124363951@N01/4369776892/ 実装 26

Slide 27

Slide 27 text

実装に関する疑問 • 理理屈はなんとなくわかったよ、だから コードを⾒見見せろ! • カイ⼆二乗検定なんてどう実装すりゃいい ねん… • これ本当に  JUnit  で扱えるの…? 27

Slide 28

Slide 28 text

実装に関する疑問 • カイ⼆二乗検定関係 • JUnit での利利⽤用 • BaseMatcher を継承したクラスを⽤用意 28

Slide 29

Slide 29 text

実装に関する疑問 • カイ⼆二乗検定関係 • JUnit での利利⽤用 • BaseMatcher を継承したクラスを⽤用意 gist.github.com/komiya-­‐atsushi/6736271 29

Slide 30

Slide 30 text

使い⽅方 //  試⾏行行により観測された各事象の回数   long[]  counts  =  {55,  27,  18};   //  期待される各事象の⽣生起確率率率   double[]  probs  =  {0.60,  0.25,  0.15};   //  有意⽔水準   double  significanceLevel  =  0.05;     //  assertion  は次のように書く   assertThat(          observedCounts(counts),  //  観測された各事象の回数          wellFit(probs)  //  期待される確率率率                  .at(significanceLevel));  //  有意⽔水準 30

Slide 31

Slide 31 text

ちょっとした デモ 31

Slide 32

Slide 32 text

まとめ • ランダムな振る舞いを持って出⼒力力をする 機能も  ユニットテストできるんだよ • そう、カイ⼆二乗検定ならね • BaseMatcher 継承して実装すれば、 JUnit からも使えるよ! • ただ利利⽤用するにはちょっと統計の知識識が 必要ネ • 有意⽔水準、⾃自由度度、試⾏行行回数… 32

Slide 33

Slide 33 text

ありがとう ございました! 33