MLプロジェクトを始める際に使えるフレームワーク・ツール達

# はじめに

　この記事は、アドベントカレンダー([機械学習ツールを掘り下げる by 日経 xTECH ビジネスAI③ Advent Calendar 2019](https://qiita.com/advent-calendar/2019/machine-learning-02))の24日目の記事です。

　著者は大学院で機械学習の応用研究をやりながら、アルバイトで機械学習系の業務にも1年ほど関わらせてもらっています。その中で様々なライブラリやMLプラットフォームを使って来た経験をまとめたいと思います。

※全体的に画像系の話になります


# 機械学習プロジェクトで考慮すること

　サービスに機会学習の要素を入れる場合、ほとんどのケースで再学習が必要になると思います。OSSでも学習済みモデルが公開されていることが多いですが、そのままではそのサービスに特化したものになっていないので、新たにデータを集め、アノテーションを施してデータセットを作り、学習済みモデルを転移させるというのが一般的なフローではないでしょうか。

再学習が必要な理由・ケースをあげていくと

#### 顔認識

- 女性の顔
    - アジア人顔など少ないケースが多い（特に化粧をしていても同じ人物、つまり同じクラスに属するので難しい）


#### 姿勢推定（OpenPoseが有名）

- 特定の姿勢に特化した推定を強化したい場合（投球フォーム、フィットネスジムでの運動など）
  - こちらも一般的なデータセットにあまり含まれない姿勢であり、精度が悪くなる傾向がある
- 姿勢は関係ないが、服の色が黒くても精度が落ちるので黒服データセットを作るなど


#### 形状評価

- 一般物体認識ではなく、ある特定の形状に特化した評価を行いたい問題ケース
    - 例えば船型形状の（造波抵抗）評価など特定の工業分野で適用したい場合
    - 全体の中で一部の形状が非常に評価に寄与したりする、それを学習したい


　ざっと挙げただけでもこれだけ考えられます。まだ業務経験をそこまで積んでるわけではありませんが、研究ではなく実際にサービスに組み込むことを考えだすと、研究段階で気にならない様々な問題が出てくるなあという印象を持ちました。ほとんどのケースで再学習は必要になると思います。

　再学習を行うためには、先ほど述べたデータの準備、アノテーションツールの作成、アノテーション実施の手順を踏んでデータセット自体を作る過程も必要です。

　また、サービスリリースの際には、再学習だけでなく他にも様々なことを考慮しなければなりません。具体的には、機械学習モデルをどこにデプロイするのか、前処理や後処理も含めたパイプラインはどのように構築するか。また、特にリアルタイム性が要求される場合は非常に難しくなると思います。

 以降では、これらを実現するために役立つものを簡単にまとめていきます。

# ライブラリ・フレームワーク・ツール群

## MLプラットフォーム
　基本的にサービスをAWSやGCPなどに構築するのであればそれらのML系プロダクト・サービスを利用することになると思います。AWSではSageMaker、GCPではCloudML Engineで学習・デプロイを行う感じになると思います。少し前までは、各クラウドサービスごとに固有の言語やフレームワーク、構成に制限された開発を行わなければならなかったのですが、現在ではどれを選んでもカスタムコンテナでの学習が可能になっています（つまり、github上に上がってるものをほとんどそのまま使いまわすことも可能です）。基盤選択による差はほとんどなくなってきてるんじゃないかと思います。

　ただ、これらのプラットフォームはデータセット管理の機能があまり重視されていない気がしました。データセットをいい感じに一覧表示しながら眺めたいなどの場合は、別のサービスかOSSを見つけてくる必要があります。

　これは、あくまでMLに特化しているわけではないので、優先度の問題で作られてないだけな気もしますが、MLのプラットフォームとして特化したものとしてはAbeja Platformの選択肢もいいと思います。料金設定は利用ケースによっては少し高めになるかもしれませんが、リッチなデータセット一覧ビューやアノテーションツールも備えています。


## アノテーションツール

　前節最後に述べたAbeja Platformを使うのであれば、アノテーション機能も搭載されているのでそれが使えます。筆者が利用した2019年夏時点では未実装の部分も多かったのですが、順次機能を追加していくという話は伺えました。人間の手だけでなく、学習済みモデルによる事前アノテーション機能も追加していくといっていたため、今後の可能性は大きいと思います。

　OSSで使えるものとしては、[jsbroks/coco-annotator](https://github.com/jsbroks/coco-annotator)が最も優れていると思います。cocoで対応しているアノテーションが全て行え、アノテーション結果はcoco形式のjsonではきだせます。wikiの説明書が薄くて、使い方は慣れるまで戸惑うかもしれませんが、データセット一覧画面もあり、mask-rcnnによる事前アノテーション機能もあります（ただし、画像一枚一枚に対しボタンをぽちぽち押して待たなきゃいけないという仕様）。標準で高機能であり、さらにpython-flaskとvueで実装されているのでカスタムしようと思えば比較的容易に可能だと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239881/0ceab03a-fbb5-2e8d-d341-4be3cd6a6f51.png)


　coco-annotatorはcoco形式のjsonファイルを読み込んでデータセットに反映させることもできるため、実際の運用としては、（大量のデータを一個一個見ながらアノテーションをするのは苦なので）再学習したいデータセットを事前に学習済みモデルでアノテートしてcoco形式のjsonファイルを入手し、それをcoco-annotatorにインポートすることで事前アノテーション済みのデータセットを扱うのがいいと思います。これによって人手による操作は、データセット一覧を眺めながら学習済みモデルの間違いを発見・修正するだけという簡単な手順に落とし込めます。

## 学習

　先ほど軽く述べたとおり、AWSならSageMaker、GCPならML Engineを使うことになると思います。ML Engineはもともと料金は安いと思いますが、SageMakerもスポットインスタンスを利用することで料金を抑えられます。それぞれハイパーパラメータ探索やモデルバージョン管理、メトリクス管理など、学習において必要な機能はもちろん備えてあります。

　その他の選択肢としてはAutoMLなども考えられます。AutoMLはデータセットさえ用意して突っ込めば適切なモデル設計、ハイパーパラメータチューニングを行ってくれて高精度な学習済みモデルを作成してくれるという素晴らしいサービスです。実際に、歩行の8フェーズの推定の学習に使ってみたこともありますが、本当に短時間で高精度なモデルを出力してくれます。KaggleやKaggle系のコンペでも話題になってるくらい精度がいいみたいです。特に、AutoAugmentも行うようになったのもすごいことだと思います。
　ただし、例えば姿勢推定（OpenPoseのようなかなりスタックしたやつ）や顔認識系（距離学習）のモデルなどのような内部構造がかなり複雑になってくる場合はまだAutoMLでは難しいと思うので、そのような場合は自分でモデルを用意する必要が出てくると思います。


## デプロイ

　こちらも先ほど述べたようにSageMakerやML Engineを使うと楽だと思います（もちろん自分でサーバ立てても可）。基本的に学習済みモデルをSavedModelなどのデプロイ用に標準化された形式にしておけばどこでもデプロイ可能だと思います（仮に形式が合わなくてもコンバートも容易にできるはず）。

　特にMl Engineなどを使うと、スケーリングも行ってくれるので楽です。ただし、普通のAPIと違い、機械学習の推論を行うAPIは、起動・リクエスト処理にかなり時間がかかります。これが非常に難しい点で、リクエストの急増にはスケーリングは基本的に間に合わないと思います。一つ一つの処理自体も時間がかかることが多いため、詰まる確率はかなり高まります。

　著者のケースでは、動画のアップロードをトリガーにしてフレームごとに切り出し、並列に前処理→推論というフローであり、動画は300フレームであったため、瞬間的に300のリクエストが発生するということになります。またコンテナの起動と推論処理にそれぞれ10秒ほどかかるタスクでした。これを正常にさばくには、例えば最初から100台以上起動した状態にしておくなどの方法もありますが、常にリクエストが飛んでくるわけでもないため、常駐させておくのはコスト的によくありませんでした。結果的に当時は20台ほど最初に立てておき、その上で失敗したリクエストは、指数バックオフを指定して再送する（スケールする余裕を持たせる）という方法で乗り切りました。その場しのぎな方法ですが、正直これ以上に方法が浮かびません。。（精度をある程度犠牲にモデルを小さくするなどは検討できそうですが）

## パイプライン

　実際の場面では、得られたデータをそのまま機械学習モデルに入力するということは稀だと思います。実際には、最終的な結果を得るために、「データの読み込み→前処理→推論→後処理→保存」のようなフローを経ることになります。このような順序関係を持ったパイプラインを構築するためのフレームワークとしては、luigiやapache beamが有名です。

　簡単に概要を書くと、luigiはpythonのフレームワークで、直感的なジョブのパイプラインを構築できます。luigiは書いたことはないですが、学習コストは低そうな感じがします。一方apache beamは、javaやpython、golangで書けるフレームワークで、学習コストは高めな印象でしたが、GCPのDataflowなどの基盤を使うこともできる利点があります。


# まとめ

　かなり殴り書きな感じになってしまいましたが、機械学習系の業務に関わる上で印象に残っている部分を書いていきました。いずれまたちゃんとまとめなおすかもしれません。誰かの参考になれば幸いです。
　もっといいツールがあるor間違いなどがあればご指摘の方よろしくお願いします。