サイトアイコン Unity+AssetStoreおすすめ情報

Chainer に IoU評価関数 を追加する(Evaluatorを自作)

更新履歴

概要

Signate では機械学習についてコンペが開催されており、
私が参加しているコンペには、評価関数「IOU」を使用してランクが決定する事が多いので学習中にも以下のように iou の結果が必要になったため実装してみました。

epoch       iou           main/loss   main/accuracy  ...
1           0             0.042866    0.993138       ...
2           0.000329707   0.0347965   0.993241       ...
3           0.00700626    0.0307309   0.993857       ...

上記を実装する上で、Chainerのデータ構造・機械学習(深層学習)の理解を深める事および、学習済みモデルの唯一の評価方法として有用と考えております。
この実装が皆様のお役に立てれば幸いです。

ちなみにお恥ずかしい話ではありますが、Signate は全然勝てておりません(涙)

IoUとは

https://signate.jp/competitions/110#evaluation

Evaluatorとは

DNNの訓練中にモデルの訓練が意図通りに進んでいるかを評価するための機構となります。
また、モデルとは関係無い値などもログ(レポート)として出力できるため、そのような用途にも使用する事ができます。

ソースコード

Evaluatorを読み解く

ソースコード全体は Qiita にて公開しておりますのでこちらをご参照ください。

呼び出し側

trainer.extend(IouEvaluator(test_iter, model, device=gpu_id))

呼び出される側

    def evaluate(self):
        iterator = self._iterators['main']
        model = self._targets['main']
        eval_func = self.eval_func or model
        summary = reporter_module.DictSummary()
        for batch in it:
            observation = {}

            (中略)

        summary.add(observation)
                in_arrays = self.converter(batch, self.device)
            with reporter_module.report_scope(observation):
                in_arrays = self.converter(batch, self.device)
                with function.no_backprop_mode():
                    if isinstance(in_arrays, tuple):
                        eval_func(*in_arrays)
                        ac, oc = self.iou(in_arrays)
                    elif isinstance(in_arrays, dict):
                        eval_func(**in_arrays)
                        ac, oc = self.iou(in_arrays)
                    else:
                        eval_func(in_arrays)
                        ac, oc = self.iou(in_arrays)
                    and_count = and_count + ac
                    or_count = or_count + oc
    def iou(self, in_arrays):
        model = self._targets['main']

        _, labels = in_arrays
        if self.device >= 0:
            labels = chainer.cuda.to_cpu(labels)

        y = model.y.data
        if self.device >= 0:
            y = chainer.cuda.to_cpu(y)
        # print(y)
        y = y.argmax(axis=1)

        # print('labels', labels)
        # print('predct', y)
        and_count = (labels & y).sum()
        or_count = (labels | y).sum()
        return and_count, or_count
        iou_observation = {}
        if(or_count == 0):
            iou_observation['iou'] = 0.
        else:
            iou_observation['iou'] = float(and_count) / or_count
        summary.add(observation)
        return summary.compute_mean()

ソースコード

ソースコード全体は Qiita にて公開しておりますのでこちらをご参照ください。

モバイルバージョンを終了