From 97793c8e5dfa113046fe2bb8927ef54d8b6e998b Mon Sep 17 00:00:00 2001 From: cheng Date: Sun, 12 Nov 2023 16:10:33 +0000 Subject: [PATCH] add byom notebook --- notebooks/news_recommendation_byom.ipynb | 188 +++++++++++++++++++++++ src/learn_to_pick/pick_best.py | 2 +- 2 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 notebooks/news_recommendation_byom.ipynb diff --git a/notebooks/news_recommendation_byom.ipynb b/notebooks/news_recommendation_byom.ipynb new file mode 100644 index 0000000..c38e4c6 --- /dev/null +++ b/notebooks/news_recommendation_byom.ipynb @@ -0,0 +1,188 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# ! pip install ../\n", + "# ! pip install matplotlib" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This is an example of a news recommendation system. We have two users `Tom` and `Anna`, and some article topics that we want to recommend to them.\n", + "\n", + "The users come to the news site in the moring and in the afternoon and we want to learn what topic to recommend to which user at which time of day.\n", + "\n", + "- The action space here are the `article` topics\n", + "- The criteria/context are the user and the time of day\n", + "- The score is whether the user liked or didn't like the recommendation (simulated in the `CustomSelectionScorer`)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import random\n", + "from typing import Any, Dict, List, Optional\n", + "import re\n", + "\n", + "users = [\"Tom\", \"Anna\"]\n", + "times_of_day = [\"morning\", \"afternoon\"]\n", + "articles = [\"politics\", \"sports\", \"music\", \"food\", \"finance\", \"health\", \"camping\"]\n", + "\n", + "def choose_user(users):\n", + " return random.choice(users)\n", + "\n", + "\n", + "def choose_time_of_day(times_of_day):\n", + " return random.choice(times_of_day)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import learn_to_pick\n", + "\n", + "class CustomSelectionScorer(learn_to_pick.SelectionScorer):\n", + " def get_score(self, user, time_of_day, article):\n", + " preferences = {\n", + " 'Tom': {\n", + " 'morning': 'politics',\n", + " 'afternoon': 'music'\n", + " },\n", + " 'Anna': {\n", + " 'morning': 'sports',\n", + " 'afternoon': 'politics'\n", + " }\n", + " }\n", + "\n", + " # if the article was the one the user prefered for this time of day, return 1.0\n", + " # if it was a different article return 0.0\n", + " return int(preferences[user][time_of_day] == article)\n", + "\n", + " def score_response(\n", + " self, inputs, picked, event: learn_to_pick.PickBestEvent\n", + " ) -> float:\n", + " chosen_article = picked[\"article\"]\n", + " user = event.based_on[\"user\"]\n", + " time_of_day = event.based_on[\"time_of_day\"]\n", + " score = self.get_score(user[0], time_of_day[0], chosen_article)\n", + " return score" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Initializing two pickers, one with the default decision making policy `picker` and one with a random decision making policy `random_picker`.\n", + "\n", + "Both pickers are initialized with the `CustomSelectionScorer` and with `metrics_step` and `metrics_window` in order to keep track of how the score evolves in a rolling window average fashion." + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [], + "source": [ + "picker = learn_to_pick.PickBest.create(metrics_step=20, metrics_window_size=20, selection_scorer=CustomSelectionScorer())\n", + "random_picker = learn_to_pick.PickBest.create(metrics_step=20, metrics_window_size=20, policy=learn_to_pick.PickBestRandomPolicy(), selection_scorer=CustomSelectionScorer())" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [], + "source": [ + "# randomly pick users and times of day\n", + "\n", + "for i in range(500):\n", + " user = choose_user(users)\n", + " time_of_day = choose_time_of_day(times_of_day)\n", + " picker.run(\n", + " article = learn_to_pick.ToSelectFrom(articles),\n", + " user = learn_to_pick.BasedOn(user),\n", + " time_of_day = learn_to_pick.BasedOn(time_of_day),\n", + " )\n", + " random_picker.run(\n", + " article = learn_to_pick.ToSelectFrom(articles),\n", + " user = learn_to_pick.BasedOn(user),\n", + " time_of_day = learn_to_pick.BasedOn(time_of_day),\n", + " )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot the score evolution for the default picker and the random picker. We should observe the default picker to **learn** to make good suggestions over time." + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The final average score for the default policy, calculated over a rolling window, is: 1.0\n", + "The final average score for the random policy, calculated over a rolling window, is: 0.6\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from matplotlib import pyplot as plt\n", + "picker.metrics.to_pandas()['score'].plot(label=\"vw\")\n", + "random_picker.metrics.to_pandas()['score'].plot(label=\"random\")\n", + "plt.legend()\n", + "\n", + "print(f\"The final average score for the default policy, calculated over a rolling window, is: {picker.metrics.to_pandas()['score'].iloc[-1]}\")\n", + "print(f\"The final average score for the random policy, calculated over a rolling window, is: {random_picker.metrics.to_pandas()['score'].iloc[-1]}\")\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/src/learn_to_pick/pick_best.py b/src/learn_to_pick/pick_best.py index e0b53fc..dee6e80 100644 --- a/src/learn_to_pick/pick_best.py +++ b/src/learn_to_pick/pick_best.py @@ -325,7 +325,7 @@ def _call_after_scoring_before_learning( @classmethod def create( - cls: Type[PickBest], + # cls: Type[PickBest], policy: Optional[base.Policy] = None, llm=None, selection_scorer: Union[base.AutoSelectionScorer, object] = SENTINEL,