ランサーズ(Lancers)エンジニアブログ > Python > サンプルデータを使ってリアルタイムレコメンデーションを作る – 3. Webアプリケーションとしての実装 –

サンプルデータを使ってリアルタイムレコメンデーションを作る – 3. Webアプリケーションとしての実装 –

blog_admin|2017年11月17日
Python

サンプルデータを使ってリアルタイムレコメンデーションを作る – 3. Webアプリケーションとしての実装 –

  1. はじめに
    • 参考書
    • レコメンドとは
    • データセット
    • 特徴エンジニアリング
  2. 類似度計算
    • TF-IDF
    • 次元圧縮
    • コサイン類似度
    • バイナリデータ
  3. Webアプリケーションとしての実装

エンドポイント設計

Lancers社ではレコメンドシステムをREST APIとして実装しています。Lancers社のメインサービスはPHP×CakePHPで構築されているのですが、scikit-learnを使いたいので、別アプリケーションとして分離する必要があります。分離した以上は何かしらの方法で通信する必要があるので、直感的に理解しやすいRESTを採用しました。RESTはHTTPプロトコルの上で、特定のリソースに対してGET, POST, PUT, DELETEの4パターンで全ての操作を実現しようというものです。

RESTを学ぶには「Web API: The Good Parts」こちらの書籍がわかりやすいです。

RESTでは、操作する対象データをリソースと呼びます。
RESTでは、特定のリソースをURIで表現します。
URIをどのように設計するかがエンドポイント設計です。

Lancers社の仕事に関するレコメンドシステムのエンドポイントは次の通りです(内部ネットワークのみに解放しているエンドポイントです。外からは繋がりません)

/v1/recommend/works/:work_id

/バージョン/アプリケーション名/リソース名/リソースID

アプリケーション名をエンドポイントに含めることで、将来的にアプリケーションが増えた際に拡張するのが容易です。例えば、機械学習を用いて特定のworkがスパムかどうかを判定するアプリケーションを作成する場合は、次のようにアプリケーション名を変更するだけでエンドポイント設計が完了します。

/v1/spam/works/:work_id

RESTのエンドポイントを設計するにあたっては、Github REST APIがわかりやすく、参考になります。

flask × gunicorn

Lancers社で運用しているレコメンドサービスにはWebフレームワークとしてflaskを採用しています。pythonのWebフレームワークとしては
djangoも有名ですが、単純なREST APIを構築する程度であればflaskで十分です。アプリケーションサーバにはgunicornを採用し、起動停止管理ためにinitスクリプトを書いています。

initスクリプトのサンプルです。
https://gist.github.com/shigeomi-takada/bf5f8f12cf01cc2e9d1346ab6b5f6474

アプリケーションのディレクトリ構成は下記のようにしています(一部省略)。
mlはmachine learningの略です。

├── README.md
├── app
│   ├── __init__.py
│   ├── controller.py
│   ├── http
│   │   ├── recommend.py
│   │   └── validation.py
│   ├── ml
│   │   ├── __init__.py
│   │   ├── similarity.py
│   │   └── wakati.py
│   ├── mysql
│   │   ├── __init__.py
│   │   ├── connect.py
│   │   └── works.py
│   └── redis
│       ├── __init__.py
│       ├── connect.py
│       └── works.py
├── batch.py
├── config.py
├── guniconf.py
├── logs
│   └── app.log
├── requirements.txt
├── run.py
└── tests

エンドポイント設計に従ってルーティングを書きます。

controller.py

@app.route('/v1/recommend/works/<work_id>', methods=['GET'])
def get_wokrs(work_id):
    Validation().get_works(work_id)
    return Recommend().get(work_id)

2. 類似度計算で計算した類似度をRecommendクラスのgetメソッド内で返すようにすれば、Webアプリケーションとして成立します。

2.類似度計算へ戻る

Posted by Shigeomi Takada(takada.shigeomi@lancers.co.jp)