まずはSurpriseというライブラリをインストールします。
pip install scikit-surprise
recommender.py
import json
from collections import defaultdict
from surprise import SVD
from surprise import Dataset
def get_top_n(predictions, n=10):
'''
予測セットに基いて各ユーザにトップN件のレコメンデーションを返す。
'''
# まず各ユーザに予測値をマップする。
top_n = defaultdict(list)
for uid, iid, true_r, est, _ in predictions:
top_n[uid].append((iid, est))
# そして各ユーザに対して予測値をソートして最も高いk個を返す。
for uid, user_ratings in top_n.items():
user_ratings.sort(key=lambda x: x[1], reverse=True)
top_n[uid] = user_ratings[:n]
return top_n
# まずmovielensデータセットでSVDアルゴリズムを学習させる。
data = Dataset.load_builtin('ml-100k')
trainset = data.build_full_trainset()
algo = SVD()
algo.fit(trainset)
# そして学習用データに含まれていない全ての(ユーザ、アイテムの)組み合わせに対して評価を予測する。
testset = trainset.build_anti_testset()
predictions = algo.test(testset)
top_n = get_top_n(predictions, n=10)
# 各ユーザにレコメンドされるアイテムを表示する。
for uid, user_ratings in top_n.items():
print(uid, [iid for (iid, _) in user_ratings])
# json形式で結果を保存する。
with open('./results.json', 'w') as f:
json.dump(top_n, f, indent=2, ensure_ascii=False)
api.py
import json
import flask
from flask import request, jsonify
app = flask.Flask(__name__)
app.config["DEBUG"] = True
app.config['JSON_AS_ASCII'] = False
# データの読み込み
with open('./results.json') as f:
movies = json.loads(f.read())
# ホーム
# http://127.0.0.1:5000/
@app.route('/', methods=['GET'])
def home():
return '''<h1>シンプルな推薦システム</h1>
<p>映画レコメンデーションのためのAPIプロトタイプ</p>'''
# 全てのアイテム
# http://127.0.0.1:5000/api/v1/resources/movies/all
@app.route('/api/v1/resources/movies/all', methods=['GET'])
def api_all():
return jsonify(movies)
# 特定のユーザIDのアイテム
# http://127.0.0.1:5000/api/v1/resources/movies?id=1
@app.route('/api/v1/resources/movies', methods=['GET'])
def api_id():
# URLにIDが含まれているか確認する。
# IDが含まれていれば、変数に代入する。
# IDが含まれていなければブラウザにエラーを表示する。
if 'id' in request.args:
id = str(request.args['id'])
else:
return "エラー: IDが含まれていません。IDを指定してください。"
items = movies.get(id)
# 結果のために空のリストを作成する。
results = []
# リストに映画を追加していく。
for i in range(len(items)):
item = items[i][0]
results.append(item)
# Pythonの辞書のリストをJSON形式に変換するためFlaskのjsonify関数を使う。
return jsonify(results)
app.run()
ターミナルもしくはコマンドプロンプトで
python recommender.py
を実行して、レコメンドするアイテム一覧を作成。
python api.py
を実行してFlaskアプリケーションを起動。
ブラウザで
http://127.0.0.1:5000/
がホーム画面
http://127.0.0.1:5000/api/v1/resources/movies/all
が全てのアイテム
http://127.0.0.1:5000/api/v1/resources/movies?id=1
がIDが1のユーザに対して推薦するアイテムのID
となります。
何かおかしな点やアドバイス等がございましたらコメントいただけますと幸いです。
参考:
https://surprise.readthedocs.io/en/stable/FAQ.html
https://programminghistorian.org/en/lessons/creating-apis-with-python-and-flask