ABEJA Platform向け学習コードのローカル実行とPyCharmを使ったデバッグ


[ABEJA Platform Advent Calendar](https://qiita.com/advent-calendar/2018/abejaplatform) 2018の6日目です。

# 概要

学習コードを開発するのは今後機械学習を使って独自サービスを作る上で必須になってくると思います。本記事は、ABEJA Platformのための学習コードを効率よく開発するためのtipsについて解説します。最初に、学習コードをローカル環境で動かすための、ローカル学習機能について簡単に紹介します。続いて、PyCharmに付属する強力なデバッガを用いて開発する方法について書いていきます。まぁ、僕は普段はVimを使ってるのでPyCharmは使っていないですんですけどね。

# ABEJA Platformにおける開発

ABEJA Platformは一言で言えば、コードをアップロードすると、クラウド上で学習や推論を行なってくれるプラットフォームです。コードには、プラットフォーム特有の作法が幾つかあるため、直接はローカルのPCでは動きません。例えば、推論コードは以下のようなルールになりますし、学習も同様です。

![Kobito.G7FsoI.png](https://qiita-image-store.s3.amazonaws.com/0/146529/1bb1e710-af69-fd0e-82d8-0adb6ad329e3.png "Kobito.G7FsoI.png")

この場合、どうやって開発をすれば良いでしょう。

直接コードをアップロードして動作を確認しようとするのでは、後ろのクラウド側のリソースの確保やログの出力に多少の時間がかかってしまいます。数分待ってインデントエラーで終了とか、残念すぎますよね。モジュール単位でならテストコードである程度は確認できるものの、学習全体パスについては実際に動かしてみないと分かりません。

# ローカル学習機能

そこで、ABEJA Platformは、ローカル学習機能というものを備えています。ローカル学習機能とは、プラットフォームにコードをアップロードせず手元の環境で動作させる機能です。これはリソースの確保が不要なため、通常のコードと同様に立ち上げることができ、素早く動作を確認できます。

ローカル学習を動かすためにはABEJA CLIというプラットフォームを操作するためのコマンドラインツールを使います。例えば以下のように使います。

```bash
$ abeja training train-local -h train:handler \
    -i abeja/all-cpu:18.10 \
    -o XXXXXXXXXX \
    -d train:XXXXXXX
```

`-h`でエントリポイントを指定します。`-i`は学習のベースイメージです。ABEJA PlatformのコードはDockerの技術を使っており、上記ベースイメージから作成したコンテナに、アップロードしたコードを載せて実行されます。`-o`はオーガニゼーション、`-d`は学習データの指定となります。上記であれば、IDがXXXXXXというDataSet（アノテーション済みデータ）にtrainという名前をつけることを意味します。上記を実行すると手元の環境で学習が走ります。詳細な使い方は公式ドキュメントを参照してください。

# PyCharmによるデバッグ

即座に動作できるので即座に動作を確認できますが、実際の開発ではDebuggerを使って動作を検証できると、想定していなかった動作の検証が素早くできます。ここで、非常に優秀なDebuggerを備えているツールとしてPyCharmがあります。PyCharmを使うと、グラフィカルにブレークポイントを仕掛け、内容を把握することができます。僕は普段はpdbですが、正直PyCharmはめちゃめちゃ優秀です。

さて、ようやく本題ということで、PyCharmを使ったデバッグ方法について解説していきます。

## 準備

まずは、PyCharmに課金をします。ABEJA PlatformはDockerの技術を使ってコードを動かしているので、Docker内で動くコードをデバッグする必要があります。PyCharmのProfessionalがその機能を持つのでLet's 課金。Professionalは、sshを使ったリモートデバッグなども持っており、非常に便利ですよ。

続いて、Pythonを実行するためのDocker環境を用意します。実は上記ABEJA Platformのローカル学習機のは、Dockerイメージを作るだけの機能を備えており、下記を実行するとPlatformと同じ環境でPythonをコードが動くDockerイメージが出来上がります。

```bash
$ abeja training train-local -h train:handler \
    -i abeja/all-cpu:18.10 \
    -o XXXXXXXXXX \
    -d train:XXXXXXX
    --no_cache --build-only
```

`--build-only`をつけるとイメージのみ作成します。場合によっては不要ですが、`--no_cache`オプションを使って、不要なキャッシュが読み込まれないようにします。すると、`abeja/all-cpu/18.10/train-local-model:latest`というイメージができます。

## PyCharmの設定

### インタプリタの設定

さて、まずはインタプリタの設定から始めます。これは、Pythonを走らせる際に、どこにあるどのバージョンのPythonを走らせるか、という設定です。ここで先ほどのイメージの中のpythonを指定します。

最初に自身のプロジェクトを立ち上げましょう。これはPyCharmを立ち上げて、作成中のコードのルートディレクトリを指定するだけです。これによってPyCharmで作成中のコードを編集できるようになります。

まずは、Dockerを使うモードを準備します。メニューのPreferenceを選び、「Build, Excution, Deployment」の項目を選択し、さらにDockerを選びます。僕の環境ではDocker for Macを選び、Dockerの箱を作成します。なお、Ubuntuや、その他のDockerのツールを使っている場合は、環境に合わせてください。

![Kobito.dQRWUb.png](https://qiita-image-store.s3.amazonaws.com/0/146529/c0db2ddb-ae35-fdb2-bf6f-55c5911b50ef.png "Kobito.dQRWUb.png")

![Kobito.yJ4u5n.png](https://qiita-image-store.s3.amazonaws.com/0/146529/ac85b2d1-d784-d1f1-de12-8981b7145058.png "Kobito.yJ4u5n.png")

続いてインタプリタを設定します。同様にPreferenceのダイアログから、Project: XXXXを開き、その中の、Project Interpreterを選んでください。

![Kobito.JKUTCK.png](https://qiita-image-store.s3.amazonaws.com/0/146529/a6cae5fb-0b45-9cfc-b7cc-6e617caa8ac3.png "Kobito.JKUTCK.png")

上の選択ボックスに利用するインタプリタが入りますが最初は空だと思います。右のAddを選択し、先ほど作ったDockerイメージを設定しましょう。メニューからDockerを選び、先ほどのImage nameと、イメージ内のインタプリタの場所を指定します。なお、ABEJA Platformの動くpythonのインタプリタは`/usr/bin/python3`です。

![Kobito.ko7gW3.png](https://qiita-image-store.s3.amazonaws.com/0/146529/5c297152-b429-7729-efae-ecd36729fbdc.png "Kobito.ko7gW3.png")


### デバッグの設定

さて、本記事はデバッグの設定ということで、すでにコードはある程度形になっており、実行できるものとします。ということで、デバッガの設定をしていきましょう。デバッガの設定は以下のメニューから設定します。

![Kobito.OIr13r.png](https://qiita-image-store.s3.amazonaws.com/0/146529/cc9f3392-dd4f-fcee-5f05-cfc2f3cf3a54.png "Kobito.OIr13r.png")

項目としては、
- Script pathに、`/usr/local/bin/abeja-model`を設定
- Parametersに`train`を設定
の２点を入れてください。これらはDockerの中で学習コードが動く起点です。`abeja-model`スクリプトの中から、アップロードしたコードの`handler`が呼ばれるという仕組みになっているのですね。

![Kobito.b7G17R.png](https://qiita-image-store.s3.amazonaws.com/0/146529/4f735062-247a-7a8d-bfb6-f4bcf95f40ab.png "Kobito.b7G17R.png")

### コードの修正

ローカルからABEJA Platform上のデータを扱うためには、クレデンシャル（認証情報）の設定が必要となります。ABEJA Platfom内で直接動作するコードについてはクレデンシャルは不要なのですが、ローカルから動かす場合は、ABEJA Platformからローカルに学習データをダウンロードする必要があるので、そこで利用します。変更ポイントとしては以下のようにしてください。ソースコード内でABEJA PlatformのデータにアクセスするためのClientオブジェクトを用意しているかと思いますが、そこに以下のようにクレデンシャルを設定します。

```
credential = {
    'user_id': 'user-XXXXXXXXXXXXXXXX',
    'personal_access_token': 'XXXXXXXXXXXXXXXXXXXXXXXXXX'
}
client = Client(organization_id='XXXXXXXXXXXX', credential=credential)
```

### 実行

さて、これで準備は完了です。あとは、メニューからDebugを選び、先ほど作ったConfigurationを選択すれば、以下のようにデバッグができます。以下では40行目にブレークポイントを仕掛けデータを確認している、という状態です。

![Kobito.VBNaCg.png](https://qiita-image-store.s3.amazonaws.com/0/146529/e9f4839b-f2f9-6cef-4f45-ca54827392f2.png "Kobito.VBNaCg.png")

# まとめ

本記事では、ABEJA Platformの学習コードをローカルで実行する方法と、PyCharmを使ってデバッグする方法について紹介しました。これらを利用することで、迅速な開発ができるようになるかと思います。また、Docker内のコードをデバッグする方法は、VSCodeにも用意されているので、そちらにも応用できるかと思います。良い開発ライフが送れることを！