hidekatsu-izuno 日々の記録

プログラミング、経済政策など伊津野英克が興味あることについて適当に語ります(旧サイト:A.R.N [日記])

最後の工数見積りの海を彷徨う(外れ値分析編)

過去、幾度となくIPAの資料に基づき工数見積りを計算するためのエントリを書いた。

hidekatsu-izuno.hatenablog.com

最後のエントリを書いてからしばらくが経ち「ソフトウェア開発データ白書2018-2019」が出ていたのも知っていたけど、前回の分析データで概ね満足を得ていたので放置していた。

とはいえ、課題がなかったわけでもなく、次の点はなんとかしたいな、と思っていた。

  • ソフトウェア開発データ白書2016-2017 だけで分析した時の数値が 2014-2015 の時の数値と大きく違っており、原因を調べる必要がある。
  • 画面、帳票、バッチの比率 1.5 : 1.0 : 0.7 という数値は感覚的なもので根拠がない

前者については、一旦、両方のデータをひとつにして分析することでむりやり解決したのだが、本来はきちんとデータを見る必要がある。今回のエントリは、そこらへんを検討しようという趣旨となっている。

実際どれくらい違うのかというと

データ 分位点回帰で得られた係数
2014-2015 65.05
2016-2017 116.27
2018-2019 137.05
全体 87.23

2014-2015 と 2018-2019 では倍の開きがある。分析手法に難がある証拠だ。

まず、データとなるソフトウェア開発データ白書は3回分ある。2014-2015、2016-2017、2018-2019 の3つ。このデータを工数でマッチングし、人時工数、画面数、帳票数、バッチ数の一覧を作成した。

どう分析するのがいいかなと思ったのだが、多次元のデータをそのまま分析するのは難しいので、人時工数、機能数(=画面数+帳票数+バッチ数)、機能あたりの人時工数の3つの指標を箱ひげ図で表示してみた。

人時工数

まず、人時工数を見ていく。

f:id:hidekatsu-izuno:20201122091333p:plain
人時工数(箱ひげ図)

予想はしていたが、想像を上回る外れ値の多さ。とはいえ、実は中央値にはさほどの開きがない(オレンジの線が中央値)。箱ひげ図が見えるように範囲を絞ってみる。

f:id:hidekatsu-izuno:20201122092508p:plain
人時工数(箱ひげ図/50000人時以下)

分位点回帰は、本当の分位点とは異なり各分位点から遠いデータの重みを下げることで調整しているため、外れ値のデータの影響を完全に除去できていないのではと思われる。

機能数

次に機能数。

f:id:hidekatsu-izuno:20201122102258p:plain
機能数(箱ひげ図)

こちらも人時工数ほどではないが、同様の傾向が見られる。

f:id:hidekatsu-izuno:20201122102522p:plain
機能数(箱ひげ図/500機能以下)

機能あたりの工数

では、機能あたりの工数はどうか。傾向が同じということは打ち消し合うかと思ったが、そうでもない。

f:id:hidekatsu-izuno:20201122102807p:plain
機能あたりの人時工数(箱ひげ図)

f:id:hidekatsu-izuno:20201122103024p:plain
機能あたりの人時工数(箱ひげ図/800人時以下)

外れ値の除去

とりあえず外れ値が問題になっていそうなことはあきらかだ。外れ値の除去の方法としては、

  • スミルノフ・グラブス検定を使う
  • 箱ひげ図の第3分位点と第1分位点からIQR(第3分位点-第1分位点)の1.5倍以上離れたデータを外れ値とする
  • 機械学習の異常値検知を行う

がある。統計で使うのは、最初の2つだが、スミルノフ・グラブス検定は正規分布に従うことが前提であるので、今回のデータに使うのは適切とは言えない。箱ひげ図を使うべきだろう。

また、外れ値の除去の影響を緩和する方法として

  • ウィンソライズ:外れ値を最大値や最小値、特定のパーセンタイル値に置き換える
  • トリミング:外れ値を削除する

の2方式がある。影響緩和という意味ではウィンソライズの方がよさそうに思えるが、実際のデータを見ると、3バッチで201人月のような特殊すぎるものも含まれているし、経験的にも工数の極端に大きい機能があるようなプロジェクトは特殊なものだと思われるため、除去する方が適切だろう。

機能ごとの人時工数の外れ値を実際に除去した上で分位点回帰を行ったのが下記の結果となる。年ごとの結果のばらつきが多少は抑えられていることがわかる。

データ 分位点回帰で得られた係数
2014-2015 63.72
2016-2017 116.27
2018-2019 115.23
全体 78.36

とはいえ、まだまだばらつきが大きいようだ。

さらに除去するとどうなるか

だいぶ除去できたとはいえ、それでも1機能あたり5人月弱のデータが含まれている。これを第3分位点で切れば、1機能あたり3人月弱までのデータに制限することができる。統計的に適切かはわからないが、第1分位点~第3分位点のデータに限定して実施してみた結果は次のようになる。

データ 分位点回帰で得られた係数
2014-2015 116.27
2016-2017 117.79
2018-2019 137.05
全体 122.38

結果のばらつきがほとんどなくなってきたのがわかる。この結果を正とするなら、

人月工数=1.14 * 画面数 + 0.76 * 帳票数 + 0.54 * バッチ数

となる。