CodaLabでのコンペ開催方法

[CodaLab.org](https://competitions.codalab.org)はコンペティション開催プラットフォーム（でもある）．[github上に公開されているオープンソース](https://github.com/codalab/codalab-competitions)で自前サーバでも構築できる．

CodaLab.orgでコンペ開催するためのノウハウの忘備録．

ドキュメントはこちら：
- http://codalab-competitions.readthedocs.io/en/latest/
- https://github.com/codalab/codalab-competitions/wiki


# テンプレート

参考にするのは[Iris example challenge](https://competitions.codalab.org/competitions/15349)．
ここからbundleをダウンロードして（"Learn the Details"タブの「DOWNLOAD THE BUNDLE OF THE CHALLENGE」をクリック），yamlファイルを書き換えて新しいものを作成．適当に書いても後でwebで修正可能．

Bundleはzip圧縮してアップロードするが，フォルダを圧縮したらだめ．zipを展開したらファイルだけが出て来るようにしないとエラーになる．




## 参考資料

- [Help一覧](https://github.com/codalab/codalab-competitions/wiki)
- [How to organize a competition](https://github.com/codalab/codalab-competitions/wiki/User_Competition-Roadmap)
 - [Running a Competition](https://github.com/codalab/codalab-competitions/wiki/User_Running-a-Competition)
 - [Building a Competition Bundle](https://github.com/codalab/codalab-competitions/wiki/User_Building-a-Competition-Bundle)
 - [Building a Scoring Program for a Competition](https://github.com/codalab/codalab-competitions/wiki/User_Building-a-Scoring-Program-for-a-Competition)


# コードを提出するコンペ

[Iris example challenge](https://competitions.codalab.org/competitions/15349)はコードを提出するコンペなので，何が起きているのか分かりにくい．以下が概要．

## submission

- ユーザーはzipをsubmitする．ディレクトリなしで以下のファイルをzip圧縮したもの
 - metadata
 - cat.py
 - submittion.txt

metadataがコード実行コマンドを指定．

```sh:metadata
command: python $program/cat.py $input $output
description: Compute scores for the competition
```

一緒に提出するファイル．なんでもOK．

```text:submission.txt
0
1
0
....
```

実行されるファイル．一緒に提出するファイルをrun_dirから読み込んで，実行して，
結果のファイルをoutput_dirに書き込む（これがあとで評価プログラムから呼び出される）

```py:cat.py
#!/usr/bin/env python

import os
from sys import argv
from shutil import copyfile

if __name__=="__main__":

    if len(argv)==1:
        input_dir  = os.path.join('..', 'input')
        output_dir = os.path.join('..', 'output')
    else:
        input_dir  = argv[1]
        output_dir = argv[2]

    run_dir = os.path.abspath(".")

    copyfile(os.path.join(run_dir, 'program', 'submission.txt'),
             os.path.join(output_dir, 'submission.txt'))
```

上記のサンプルでは，単に提出ファイルをoutput_dirにコピーしているだけ．

コード提出コンペの場合，スクリプトと学習済みモデルを一緒に提出すればよい．
その場合，input_dirにあるテストデータ（非公開）を読み込む必要がある．

## 評価

- オーガナイザはzipをscoring programとしてアップロードしておく．ディレクトリなしで以下のファイルをzip圧縮したもの
 - metadata
 - evaluate.py
- もうひとつ，reference dataとしてzipをアップロードしておく．ディレクトリなしで以下のファイルをzip圧縮したもの
 - test_labels.csv

metadataがコード実行コマンドを指定．

```sh:metadata
command: python $program/evaluate.py $input $output
description: Compute scores for the competition
```

実行されるファイル．

```py:evaluate.py
#!/usr/bin/env python

import os
from sys import argv
import numpy as np

if __name__=="__main__":

    if len(argv)==1:
        input_dir  = os.path.join('..', 'input')
        output_dir = os.path.join('..', 'output')
    else:
        input_dir  = argv[1]
        output_dir = argv[2]

    y_submit_file = os.path.join(input_dir, 'res', 'submission.txt')
    y_ref_file = os.path.join(input_dir, 'ref', 'test_labels.csv')

    load_y_ref = np.loadtxt(y_ref_file)
    load_y_submission = np.loadtxt(y_submit_file)

    score = np.abs(load_y_ref - load_y_submission).sum() / float(load_y_ref.size)
    print("score: %.2f\n" % score)

    score_file = open(os.path.join(output_dir, 'scores.txt'), 'w')
    score_file.write("score: %.2f\n" % score)

    score_file.close()
```


上記のサンプルの動作．

- まずユーザーのコードが実行され（prediction step），そこでoutput_dirに結果が書き込まれる（前述の通り）
- その結果が，評価（scoring step）のinput_dir/resにコピーされている（これがややこしい）
- 真値のラベルtest_labels.csvはinput_dir/refにアップロードされている
- それを比較して，結果をoutput_dirに"scores.txt"という名前で保存（ファイル名固定）

```txt:scores.txt
score: 0.98
```

この結果ファイルがleader boardに表示される．「score:」というキーワードはyamlファイルで指定（もしくはweb GUIで）．


### 注意

現状では，pythonやモジュールのライブラリのバージョンが古いので（pythonは2），最新のモジュールを使うコードは失敗する．

```txt:pythonモジュール2017/02/14
Python version: 2.7.10 |Anaconda 2.4.0 (64-bit)| (default, Oct 19 2015, 18:04:42) 
numpy==1.10.1
scikit-learn==0.16.1
scipy==0.16.0
```

python以外にも使えるかどうか不明．サーバがwindowsらしいので（ドキュメントによると），コンパイル済みのバイナリファイルをアップロードすることも可能．最新pythonモジュールも使用可，他のスクリプトもOK，などいろいろやりたいなら，自前サーバを構築するほうが良い．




# 結果だけを提出するコンペ

web GUIで，「Results Scoring Only」にチェックを入れるだけ．

ユーザーのsubmissionがダイレクトに評価のinput_dir/resに保存されるので，評価はそれを読み込んでinput_dir/refの真値も読み込んで評価してoutput_dir/scores.txtに書き込むだけ．

注意：submissionファイルが一つだけでも，zip圧縮してzipファイルにしないとsubmitできない．