クライアントの質問に答えやすい実験をするにはどうすればいいのか

# この記事で書くこと

何かしら実験タスクを持っていて、実験結果をクライアントに示すという文脈。

まだ開発段階ではないので、システム設計の良さよりも__早く結果を出せること__に重点を置いている。

という文脈で次のことを実現するチェック項目を紹介します。

- やり直し少なく、クライアントのよくある質問に答えられるように準備するにはどうしたらいいのか？
- なるべくミスが発生しないように実験するにはどうしたらいいのか？

# この記事で書かないこと

- クライアントと上手なコミュニケーションするにはどうすればいいか？
- どの評価を示すべきか？
- 具体的にどんな実験デザインをするべきなのか？

# チェックリスト

- 実験結果の表を作成したか？
    - 先に実験の結果を記入する表を作っておく。
    - 表はExcelとかGoogle Spreadsheetでもいい [^1]
- 実験データセットは複数通りの分割をしているか？
    - 実験用のデータは複数回の実験が前提か？Train/Testに複数の異なる組み合わせはあるか？
    - 実験用のスクリプトは複数回の実験をして、平均を求める作業が自動化されているか？手動の作業はミスの元。
- 実験は学習曲線を描けるようになっているか？
    - 学習データ量を調整して、データを用意しているか？
    - testデータは共通化されているか？
    - 実験スクリプトは学習曲線を描けるようになっているか？ 

# 実験結果の表を作成したか？

先にイメージを作っておくことは大切だ。特に実験を始める前は頭がごちゃごちゃしている。

ぼくの場合は特に、実験を始めるときに気持ちがアガる☆ので、早く実験を始めたくなる。

そうすると、「達成すべき目標値」を見失うことになってしまう。その先には何があるのか？スクリプトの修正と実験のやり直しである。

だから、最初から実験結果表を作っておいて、完成イメージを形にしておく。できることならば、クライアントに予め完成イメージを共有しておくのが良いだろう。

<img width="561" alt="SnapCrab_NoName_2020-4-14_12-45-27_No-00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33533/f7dff172-2d94-2ad6-ec93-200bd454663d.png">

# 実験データセットは複数通りの分割をしているか？

実験結果をクライアントを見せたとき、よくある質問は次のとおりだ。

- その実験はもしかしたら、偶然ではないの？
- たまたま、Trainデータに良いデータが揃っていただけではないの？

この質問に回答するために「異なるTrain/Testの組み合わせ」で複数回のテストが推奨される。

だから、はじめから複数通りのTrain/Testの実験する前提で実験デザインとスクリプトの設計をするべきである。さらに、手動で複数通りの実験を施行するのは避けたい。手動作業はミスの元である。

では、全自動化の仕組みをPythonで書くか？ファイル処理をいちいち書くのも面倒くさい。それにtrain/test/evalのスクリプトはそれぞれ独立させておきたい。独立させておいた方が依存関係を考えなくてもいいので、実験のときは楽だ（train/testは一緒のスクリプトにしてしまうことも多い。コマンドライン引数でモードを変更できるようにする）。

実験段階では、「この指標も必要。実験結果をすっきり出したい・・・etc.」など手直しの発生が多い。そのたびに依存関係を考えておくのは面倒なものだ。

では、「スクリプトを独立させて」、「実験を自動化できる構成」はどうするのが良いだろうか？

経験則的にこういうbashスクリプトで実験してしまう。

```

スクリプトの使い方
COMMENTOUT
 
 
if [[ -z "$PATH_SCRIPT_DIR" ]]; then
    echo "PATH_SCRIPT_DIR is not defined"
    exit 1
fi
 
if [[ -z "$PATH_MODEL_DIR" ]]; then
    echo "PATH_MODEL_DIR is not defined"
    exit 1
fi
 
if [[ -z "$PATH_DATASET_DIR" ]]; then
    echo "PATH_DATASET_DIR is not defined"
    exit 1
fi
 
for path_data_dir in ${PATH_DATASET_DIR};
do
	data_name=`basename ${path_data_dir}`
	path_model_dir=${PATH_MODEL_DIR}/model/${data_name}
	path_result_dir=${PATH_MODEL_DIR}/result/${data_name}
	path_result_csv=${PATH_MODEL_DIR}/result/${data_name}/prediction.csv
 
	path_train_file=${PATH_DATASET_DIR}/train.csv
	path_test_file=${PATH_DATASET_DIR}/test.csv
 
	mkdir -p ${path_model_dir}
	mkdir -p ${path_result_dir}
 
	# training
	python ${PATH_SCRIPT_DIR}/[training script]
 
	# prediction
	python ${PATH_SCRIPT_DIR}/[prediction script]
 
	# eval
	python ${PATH_SCRIPT_DIR}/[eval script]
done
 
python ${PATH_SCRIPT_DIR}/[aggregation script]
```

# 実験は学習曲線を描けるようになっているか？

学習曲線とは、データ量を減らして実験した場合の性能変化を示したグラフのこと。
イメージ的には下のグラフ。ScoreはPrecision/Recall/Fがよく入る。

<img width="565" alt="SnapCrab_NoName_2020-4-14_12-15-54_No-00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33533/adab9697-7f4c-b27c-3d22-a8715a566f1d.png">

用意できる全データを使って、実験結果をクライアントに見せたとき、よくある質問。

- もっとデータを用意したら性能は良くなるの？
- たくさんのデータを用意するのはオペレーション上で現実的じゃない。少ないデータで性能を再現できる？

この質問に答えるために学習曲線がある。学習曲線があれば、次のように回答できる。

- Q: もっとデータを用意したら性能は良くなるの？
    - A: 全データの時点で、性能値の上がり幅が小さくなっていれば、十分と言える。
- Q: たくさんのデータを用意するのはオペレーション上で現実的じゃない。少ないデータで性能を再現できる？
    - A: 少ないデータ量と全データでの性能を比較すれば、回答できる。

データ量は一般的には４分割が使われる。つまり、0.25, 0.5, 0.75, 1.0

学習曲線を描くためには、実験スクリプトはさっきと同じで良い。
データの用意の方法を少し変えるだけで良い。

ここでは、split-数字 が分割したデータ。その下のディレクトリにデータ量を調整したデータを置く。
大切なことは split-0/以下のtestデータはすべて共通しているということ。
違いはtrainデータの量が違うだけ。

```bash
--- split-0
	- data-0.25
	- data-0.5
	- data-0.75
	- data-1.0
--- split-1
	- data-0.25
	- data-0.5
	- data-0.75
	- data-1.0
--- split-2
	- data-0.25
	- data-0.5
	- data-0.75
	- data-1.0
```

- - -

その他、細かい細々としたことは[ブログ記事](https://www.spielzeugkiste-der-technology.net/%e3%82%af%e3%83%a9%e3%82%a4%e3%82%a2%e3%83%b3%e3%83%88%e3%81%ab%e6%ba%80%e8%b6%b3%e3%81%97%e3%81%a6%e3%82%82%e3%82%89%e3%81%86%e5%ae%9f%e9%a8%93%e7%b5%90%e6%9e%9c%e3%82%92%e5%87%ba%e3%81%99%e3%81%9f/?preview=true)に書きました。

私個人の考えで書いている部分が多いので、__ポエム__としています。

違う方法が効率的だと思われるときはぜひ、コメントいただいけると嬉しいです。




[^1]: 昔は実験の一連の流れをPythonで書いて、実験結果もPythonで出力して・・・という工夫をしてたこともありました。でも、細かい修正のたびに面倒くさくなった。