{ "cells": [ { "cell_type": "markdown", "id": "db3ddf94-3c3e-43e2-93f6-56abeca09776", "metadata": {}, "source": [ "# MovieLens\n", "Movie Lens is a website that helps users find the movies they like and where they will rate the recommended movies. [MovieLens 1M dataset](https://grouplens.org/datasets/movielens/1m/) is a dataset including the observations collected in an online movie recommendation experiment and is widely used to generate data for online bandit simulation studies. The goal of the simulation studies below is to learn the reward distribution of different movie genres and hence to recommend the optimal movie genres to the users to optimize the cumulative user satisfaction. In other words, every time a user visits the website, the agent will recommend a movie genre ($A_t$) to the user, and then the user will give a rating ($R_t$) to the genre recommended. We assume that users' satisfaction is fully reflected through the ratings. Therefore, the ultimate goal of the bandit algorithms is to optimize the cumulative ratings received by finding and recommending the optimal movie genre that will receive the highest rating. In this tutorial, we mainly focus on the following 4 Genres, including \n", "\n", "- **Comedy**: $a=0$,\n", "- **Drama**: $a=1$\n", "- **Action**: $a=2$,\n", "- **Thriller**: $a=3$,\n", "- **Sci-Fi**: $a=4$.\n", "\n", "Therefore, $K=5$. For each user, feature information, including age, gender and occupation, are available:\n", "\n", "- **age**: numerical, from 18 to 56,\n", "- **gender**: binary, =1 if male,\n", "- **college/grad student**: binary, =1 if a college/grad student,\n", "- **executive/managerial**: binary, =1 if a executive/managerial,\n", "- **technician/engineer**: binary, =1 if a technician/engineer,\n", "- **other**: binary, =1 if having other occupations other than the rest of the four occupations,\n", "- **academic/educator**: if an academic/educator, then all the previous occupation-related variables = 0 (baseline).\n", "\n", "The realized reward $R_t$ is a numerical variable, taking the value of $\\{1,2,3,4,5\\}$,with 1 being the least satisfied and 5 being the most satisfied. In the following, we first perform causal effect learning on the logged data and output the estimated reward for each movie genre. Then, we conduct online learning to efficiently explore the optimal policy utilizing both the estimation results and new information collected through real-time online iteraction." ] }, { "cell_type": "markdown", "id": "931b6180-ebc9-4a45-bcb3-2a993146355b", "metadata": {}, "source": [ "## Causal Effect Learning" ] }, { "cell_type": "code", "execution_count": 8, "id": "2bfb5e7f", "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import numpy as np\n", "from sklearn.linear_model import LinearRegression\n", "from causaldm.learners.CPL4.CMAB import _env_realCMAB as _env\n", "from causaldm.learners.CPL4.CMAB import LinTS\n", "import warnings\n", "warnings.filterwarnings('ignore')\n", "env = _env.Single_Contextual_Env(seed = 0, Binary = False)\n", "logged_data, arms = env.get_logged_dat()" ] }, { "cell_type": "code", "execution_count": 9, "id": "2d916f6d", "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "dict_keys(['Comedy', 'Drama', 'Action', 'Thriller', 'Sci-Fi'])" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "logged_data.keys()" ] }, { "cell_type": "code", "execution_count": 10, "id": "fad9aa26", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
user_idmovie_idratingageComedyDramaActionThrillerSci-Figender_Moccupation_academic/educatoroccupation_college/grad studentoccupation_executive/managerialoccupation_otheroccupation_technician/engineer
685706482042.02.025.01.00.00.00.00.01.00.01.00.00.00.0
499683482424.04.025.01.00.00.00.00.01.00.01.00.00.00.0
69486053330.03.025.01.00.00.00.00.01.00.00.00.01.00.0
2076911693671.04.025.01.00.00.00.00.01.00.00.01.00.00.0
4258391693869.03.025.01.00.00.00.00.01.00.00.01.00.00.0
................................................
2136384140.0153.02.025.01.00.00.00.00.01.00.00.00.01.00.0
2422714140.0435.01.025.01.00.00.00.00.01.00.00.00.01.00.0
7173224411910.05.018.01.00.00.00.00.01.00.01.00.00.00.0
3459274411.045.02.018.01.00.00.00.00.01.00.01.00.00.00.0
87011358781226.05.025.01.00.00.00.00.00.00.00.00.01.00.0
\n", "

406 rows × 15 columns

\n", "
" ], "text/plain": [ " user_id movie_id rating age Comedy Drama Action Thriller \\\n", "685706 48 2042.0 2.0 25.0 1.0 0.0 0.0 0.0 \n", "499683 48 2424.0 4.0 25.0 1.0 0.0 0.0 0.0 \n", "694860 53 330.0 3.0 25.0 1.0 0.0 0.0 0.0 \n", "207691 169 3671.0 4.0 25.0 1.0 0.0 0.0 0.0 \n", "425839 169 3869.0 3.0 25.0 1.0 0.0 0.0 0.0 \n", "... ... ... ... ... ... ... ... ... \n", "213638 4140.0 153.0 2.0 25.0 1.0 0.0 0.0 0.0 \n", "242271 4140.0 435.0 1.0 25.0 1.0 0.0 0.0 0.0 \n", "717322 4411 910.0 5.0 18.0 1.0 0.0 0.0 0.0 \n", "345927 4411.0 45.0 2.0 18.0 1.0 0.0 0.0 0.0 \n", "870113 5878 1226.0 5.0 25.0 1.0 0.0 0.0 0.0 \n", "\n", " Sci-Fi gender_M occupation_academic/educator \\\n", "685706 0.0 1.0 0.0 \n", "499683 0.0 1.0 0.0 \n", "694860 0.0 1.0 0.0 \n", "207691 0.0 1.0 0.0 \n", "425839 0.0 1.0 0.0 \n", "... ... ... ... \n", "213638 0.0 1.0 0.0 \n", "242271 0.0 1.0 0.0 \n", "717322 0.0 1.0 0.0 \n", "345927 0.0 1.0 0.0 \n", "870113 0.0 0.0 0.0 \n", "\n", " occupation_college/grad student occupation_executive/managerial \\\n", "685706 1.0 0.0 \n", "499683 1.0 0.0 \n", "694860 0.0 0.0 \n", "207691 0.0 1.0 \n", "425839 0.0 1.0 \n", "... ... ... \n", "213638 0.0 0.0 \n", "242271 0.0 0.0 \n", "717322 1.0 0.0 \n", "345927 1.0 0.0 \n", "870113 0.0 0.0 \n", "\n", " occupation_other occupation_technician/engineer \n", "685706 0.0 0.0 \n", "499683 0.0 0.0 \n", "694860 1.0 0.0 \n", "207691 0.0 0.0 \n", "425839 0.0 0.0 \n", "... ... ... \n", "213638 1.0 0.0 \n", "242271 1.0 0.0 \n", "717322 0.0 0.0 \n", "345927 0.0 0.0 \n", "870113 1.0 0.0 \n", "\n", "[406 rows x 15 columns]" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "logged_data['Comedy']" ] }, { "cell_type": "code", "execution_count": 11, "id": "a0169329", "metadata": {}, "outputs": [], "source": [ "userinfo_index = np.array([3,9,11,12,13,14])\n", "movie_generes = ['Comedy', 'Drama', 'Action', 'Thriller', 'Sci-Fi']" ] }, { "cell_type": "code", "execution_count": 12, "id": "5588f06b", "metadata": {}, "outputs": [], "source": [ "# convert the sampled dataset of interest to dataframe format\n", "data_CEL_sample = logged_data['Comedy']\n", "for movie_genere in movie_generes[1:5]:\n", " data_CEL_sample = pd.concat([data_CEL_sample, logged_data[movie_genere]])" ] }, { "cell_type": "code", "execution_count": 13, "id": "c015ebce", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1286" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len(data_CEL_sample) # the total sample size we selected: n=1286" ] }, { "cell_type": "markdown", "id": "53f234b9", "metadata": { "id": "Tcwr9EQB_btu" }, "source": [ "### nonlinear model fitting" ] }, { "cell_type": "code", "execution_count": 14, "id": "f44c395d", "metadata": { "id": "m_357p5PHrSi" }, "outputs": [], "source": [ "models_CEL = {}\n", " \n", "# initialize the models we'll fit in Causal Effect Learning\n", "for i in movie_generes:\n", " models_CEL[i] = None \n", "from lightgbm import LGBMRegressor\n", "for movie_genere in movie_generes: \n", " models_CEL[movie_genere] = LGBMRegressor(max_depth=3)\n", " models_CEL[movie_genere].fit(data_CEL_sample.iloc[np.where(data_CEL_sample[movie_genere]==1)[0],userinfo_index],data_CEL_sample.iloc[np.where(data_CEL_sample[movie_genere]==1)[0],2] )\n" ] }, { "cell_type": "code", "execution_count": 15, "id": "f8aa7005", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "executionInfo": { "elapsed": 8, "status": "ok", "timestamp": 1676663330569, "user": { "displayName": "Yang Xu", "userId": "12270366590264264299" }, "user_tz": 300 }, "id": "1LWOEFXNNiOw", "outputId": "bee7be34-4cab-4d87-fd24-5535c5760628" }, "outputs": [], "source": [ "# record thev estimated expected reward for each movie genere, under each possible combination of state variable\n", "age_range = np.linspace(min(data_CEL_sample['age']),max(data_CEL_sample['age']),int(max(data_CEL_sample['age'])-min(data_CEL_sample['age'])+1)).astype(int)" ] }, { "cell_type": "code", "execution_count": 16, "id": "c2ca9d72", "metadata": { "executionInfo": { "elapsed": 602, "status": "ok", "timestamp": 1676663332414, "user": { "displayName": "Yang Xu", "userId": "12270366590264264299" }, "user_tz": 300 }, "id": "ZjV4BSJ717cm" }, "outputs": [], "source": [ "import itertools\n", "\n", "gender = np.array([0,1])\n", "occupation_college = np.array([0,1])\n", "occupation_executive = np.array([0,1])\n", "occupation_other = np.array([0,1])\n", "occupation_technician = np.array([0,1])\n", "\n", "# result contains all possible combinations.\n", "combinations = pd.DataFrame(itertools.product(age_range,gender,occupation_college,\n", " occupation_executive,occupation_other,occupation_technician))\n", "combinations.columns =['age','gender','occupation_college', 'occupation_executive','occupation_other','occupation_technician']" ] }, { "cell_type": "code", "execution_count": 17, "id": "79622c3d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([3.1224, 3.0439, 3.7664, ..., 3.5822, 3.6663, 3.6364])" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "models_CEL['Comedy'].predict(combinations)\n", "#models_CEL['Comedy'].predict(data_CEL_sample.iloc[np.where(data_CEL_sample['Comedy']==1)[0],userinfo_index])" ] }, { "cell_type": "code", "execution_count": 11, "id": "c50dbb1f", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "executionInfo": { "elapsed": 484, "status": "ok", "timestamp": 1676663532795, "user": { "displayName": "Yang Xu", "userId": "12270366590264264299" }, "user_tz": 300 }, "id": "sToJaW2I7JDR", "outputId": "dae5165b-6023-43b5-c557-19c831b649db" }, "outputs": [], "source": [ "values = np.zeros((5,1312))\n", "i=0\n", "for movie_genere in movie_generes:\n", " values[i,:] = models_CEL[movie_genere].predict(combinations)\n", " i=i+1\n", " #print(values)" ] }, { "cell_type": "code", "execution_count": 12, "id": "aa105642", "metadata": { "executionInfo": { "elapsed": 327, "status": "ok", "timestamp": 1676663610385, "user": { "displayName": "Yang Xu", "userId": "12270366590264264299" }, "user_tz": 300 }, "id": "ftSFf4P62_A8" }, "outputs": [], "source": [ "result_CEL_nonlinear = combinations.copy()\n", "i=0\n", "for movie_genere in movie_generes:\n", " #values = models_CEL[movie_genere].predict(combinations)\n", " result_CEL_nonlinear.insert(len(result_CEL_nonlinear.columns), movie_genere, values[i,:])\n", " i=i+1" ] }, { "cell_type": "code", "execution_count": 13, "id": "22fb7206", "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 488 }, "executionInfo": { "elapsed": 312, "status": "ok", "timestamp": 1676663615813, "user": { "displayName": "Yang Xu", "userId": "12270366590264264299" }, "user_tz": 300 }, "id": "3b44q4xD8Gvh", "outputId": "a2846ad8-a2ef-4677-ff8f-1b0f3b87f386" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
agegenderoccupation_collegeoccupation_executiveoccupation_otheroccupation_technicianComedyDramaActionThrillerSci-Fi
016000003.1223793.5764713.0664483.5833823.133766
116000013.0438623.2059393.2327273.5833823.133766
216000103.7664413.9102813.3366233.7176033.160268
316000113.6879243.3314633.3452333.7176033.160268
416001003.3773403.6498883.0390563.9236353.133766
....................................
130756110113.2975533.0901103.0242213.6584423.151436
130856111003.6121663.6959113.6084583.7408303.151436
130956111013.5822103.1657073.5528893.7408303.151436
131056111103.6663113.2833113.1291953.7408303.151436
131156111113.6363553.1036473.1159873.7408303.151436
\n", "

1312 rows × 11 columns

\n", "
" ], "text/plain": [ " age gender occupation_college occupation_executive occupation_other \\\n", "0 16 0 0 0 0 \n", "1 16 0 0 0 0 \n", "2 16 0 0 0 1 \n", "3 16 0 0 0 1 \n", "4 16 0 0 1 0 \n", "... ... ... ... ... ... \n", "1307 56 1 1 0 1 \n", "1308 56 1 1 1 0 \n", "1309 56 1 1 1 0 \n", "1310 56 1 1 1 1 \n", "1311 56 1 1 1 1 \n", "\n", " occupation_technician Comedy Drama Action Thriller Sci-Fi \n", "0 0 3.122379 3.576471 3.066448 3.583382 3.133766 \n", "1 1 3.043862 3.205939 3.232727 3.583382 3.133766 \n", "2 0 3.766441 3.910281 3.336623 3.717603 3.160268 \n", "3 1 3.687924 3.331463 3.345233 3.717603 3.160268 \n", "4 0 3.377340 3.649888 3.039056 3.923635 3.133766 \n", "... ... ... ... ... ... ... \n", "1307 1 3.297553 3.090110 3.024221 3.658442 3.151436 \n", "1308 0 3.612166 3.695911 3.608458 3.740830 3.151436 \n", "1309 1 3.582210 3.165707 3.552889 3.740830 3.151436 \n", "1310 0 3.666311 3.283311 3.129195 3.740830 3.151436 \n", "1311 1 3.636355 3.103647 3.115987 3.740830 3.151436 \n", "\n", "[1312 rows x 11 columns]" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "result_CEL_nonlinear" ] }, { "cell_type": "code", "execution_count": 14, "id": "3b49ef75", "metadata": { "executionInfo": { "elapsed": 297, "status": "ok", "timestamp": 1676663762150, "user": { "displayName": "Yang Xu", "userId": "12270366590264264299" }, "user_tz": 300 }, "id": "ZPelPjli1oTF" }, "outputs": [], "source": [ "# save the result to\n", "result_CEL_nonlinear.to_csv('result_CEL_nonlinear.csv')" ] }, { "cell_type": "code", "execution_count": 15, "id": "62a7c999", "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 488 }, "executionInfo": { "elapsed": 18, "status": "ok", "timestamp": 1676663918591, "user": { "displayName": "Yang Xu", "userId": "12270366590264264299" }, "user_tz": 300 }, "id": "alx6VRzn8v-W", "outputId": "6bfbeeec-1a6c-4e68-bad9-39c0853b34a7" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
agegenderoccupation_collegeoccupation_executiveoccupation_otheroccupation_technicianComedyDramaActionThrillerSci-Fi
016000003.1223793.5764713.0664483.5833823.133766
116000013.0438623.2059393.2327273.5833823.133766
216000103.7664413.9102813.3366233.7176033.160268
316000113.6879243.3314633.3452333.7176033.160268
416001003.3773403.6498883.0390563.9236353.133766
....................................
130756110113.2975533.0901103.0242213.6584423.151436
130856111003.6121663.6959113.6084583.7408303.151436
130956111013.5822103.1657073.5528893.7408303.151436
131056111103.6663113.2833113.1291953.7408303.151436
131156111113.6363553.1036473.1159873.7408303.151436
\n", "

1312 rows × 11 columns

\n", "
" ], "text/plain": [ " age gender occupation_college occupation_executive occupation_other \\\n", "0 16 0 0 0 0 \n", "1 16 0 0 0 0 \n", "2 16 0 0 0 1 \n", "3 16 0 0 0 1 \n", "4 16 0 0 1 0 \n", "... ... ... ... ... ... \n", "1307 56 1 1 0 1 \n", "1308 56 1 1 1 0 \n", "1309 56 1 1 1 0 \n", "1310 56 1 1 1 1 \n", "1311 56 1 1 1 1 \n", "\n", " occupation_technician Comedy Drama Action Thriller Sci-Fi \n", "0 0 3.122379 3.576471 3.066448 3.583382 3.133766 \n", "1 1 3.043862 3.205939 3.232727 3.583382 3.133766 \n", "2 0 3.766441 3.910281 3.336623 3.717603 3.160268 \n", "3 1 3.687924 3.331463 3.345233 3.717603 3.160268 \n", "4 0 3.377340 3.649888 3.039056 3.923635 3.133766 \n", "... ... ... ... ... ... ... \n", "1307 1 3.297553 3.090110 3.024221 3.658442 3.151436 \n", "1308 0 3.612166 3.695911 3.608458 3.740830 3.151436 \n", "1309 1 3.582210 3.165707 3.552889 3.740830 3.151436 \n", "1310 0 3.666311 3.283311 3.129195 3.740830 3.151436 \n", "1311 1 3.636355 3.103647 3.115987 3.740830 3.151436 \n", "\n", "[1312 rows x 11 columns]" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# read the result file\n", "result_CEL_nonlinear = pd.read_csv('result_CEL_nonlinear.csv')\n", "result_CEL_nonlinear = result_CEL_nonlinear.drop(result_CEL_nonlinear.columns[0], axis=1)\n", "result_CEL_nonlinear" ] }, { "cell_type": "markdown", "id": "9a8a68cb", "metadata": { "id": "nhhsw-DOwxzx" }, "source": [ "#### Analysis" ] }, { "cell_type": "code", "execution_count": 16, "id": "7e8d8c90", "metadata": { "executionInfo": { "elapsed": 343, "status": "ok", "timestamp": 1676664442590, "user": { "displayName": "Yang Xu", "userId": "12270366590264264299" }, "user_tz": 300 }, "id": "Dk9-vMRIQCyg" }, "outputs": [], "source": [ "# calculate the expected reward of Comedy for female\n", "TE_female=result_CEL_nonlinear.iloc[np.where(result_CEL_nonlinear['gender']==0)[0],6:11]/(41*(2**4))\n", "TE_female=pd.DataFrame(TE_female.sum(axis=0))\n", "TE_female.columns =['Expected Rating']" ] }, { "cell_type": "code", "execution_count": 17, "id": "06d13401", "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 206 }, "executionInfo": { "elapsed": 17, "status": "ok", "timestamp": 1676664443598, "user": { "displayName": "Yang Xu", "userId": "12270366590264264299" }, "user_tz": 300 }, "id": "KfCTrgBDSyWv", "outputId": "896d8116-a377-484f-e9eb-7abca4cad453" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Expected Rating
Comedy3.500268
Drama3.309777
Action3.562432
Thriller3.605472
Sci-Fi2.960134
\n", "
" ], "text/plain": [ " Expected Rating\n", "Comedy 3.500268\n", "Drama 3.309777\n", "Action 3.562432\n", "Thriller 3.605472\n", "Sci-Fi 2.960134" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "TE_female" ] }, { "cell_type": "code", "execution_count": 18, "id": "428ea969", "metadata": { "executionInfo": { "elapsed": 310, "status": "ok", "timestamp": 1676664467325, "user": { "displayName": "Yang Xu", "userId": "12270366590264264299" }, "user_tz": 300 }, "id": "xNU7ibG4_UNF" }, "outputs": [], "source": [ "# calculate the expected reward of Comedy for female\n", "TE_male=result_CEL_nonlinear.iloc[np.where(result_CEL_nonlinear['gender']==1)[0],6:11]/(41*(2**4))\n", "TE_male=pd.DataFrame(TE_male.sum(axis=0))\n", "TE_male.columns =['Expected Rating']" ] }, { "cell_type": "code", "execution_count": 19, "id": "7eae7c50", "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 206 }, "executionInfo": { "elapsed": 316, "status": "ok", "timestamp": 1676664470347, "user": { "displayName": "Yang Xu", "userId": "12270366590264264299" }, "user_tz": 300 }, "id": "4YBh4ljh_UNG", "outputId": "f54358c5-fe05-44fc-8693-f6a33ccf204e" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Expected Rating
Comedy3.365749
Drama3.321332
Action3.256846
Thriller3.447365
Sci-Fi2.960134
\n", "
" ], "text/plain": [ " Expected Rating\n", "Comedy 3.365749\n", "Drama 3.321332\n", "Action 3.256846\n", "Thriller 3.447365\n", "Sci-Fi 2.960134" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "TE_male" ] }, { "cell_type": "markdown", "id": "169be1ee", "metadata": { "id": "-OwDCcYP_XiE" }, "source": [ "**Conclusion**: Among these five selected movie generes, `Comedy` is the most popular one that received the highest expected rating. On the contrary, the estimated rating for `Schi-Fi` is the lowest, both for males and females. In addition, the expected ratings of women are generally slightly higher than men, except for `Drama` movies where men's rating is expected to be 0.02/5 points higher than women." ] }, { "cell_type": "markdown", "id": "ff203c46", "metadata": { "id": "S6_rREHz_i8r" }, "source": [ "### linear model fitting" ] }, { "cell_type": "code", "execution_count": 20, "id": "8a0b53ec", "metadata": { "executionInfo": { "elapsed": 301, "status": "ok", "timestamp": 1676664659108, "user": { "displayName": "Yang Xu", "userId": "12270366590264264299" }, "user_tz": 300 }, "id": "RTBk0DSMADT0" }, "outputs": [], "source": [ "models_CEL_linear = {}\n", " \n", "# initialize the models we'll fit in Causal Effect Learning\n", "for i in movie_generes:\n", " models_CEL_linear[i] = None \n", " \n", "from sklearn.linear_model import LinearRegression\n", "for movie_genere in movie_generes: \n", " models_CEL_linear[movie_genere] = LinearRegression()\n", " models_CEL_linear[movie_genere].fit(data_CEL_sample.iloc[np.where(data_CEL_sample[movie_genere]==1)[0],userinfo_index],data_CEL_sample.iloc[np.where(data_CEL_sample[movie_genere]==1)[0],2] )\n" ] }, { "cell_type": "code", "execution_count": 21, "id": "c32620a4", "metadata": { "executionInfo": { "elapsed": 300, "status": "ok", "timestamp": 1676664695417, "user": { "displayName": "Yang Xu", "userId": "12270366590264264299" }, "user_tz": 300 }, "id": "gvpnxYTE_nSN" }, "outputs": [], "source": [ "import itertools\n", "\n", "gender = np.array([0,1])\n", "occupation_college = np.array([0,1])\n", "occupation_executive = np.array([0,1])\n", "occupation_other = np.array([0,1])\n", "occupation_technician = np.array([0,1])\n", "\n", "# result contains all possible combinations.\n", "combinations = pd.DataFrame(itertools.product(age_range,gender,occupation_college,\n", " occupation_executive,occupation_other,occupation_technician))\n", "combinations.columns =['age','gender','occupation_college', 'occupation_executive','occupation_other','occupation_technician']\n" ] }, { "cell_type": "code", "execution_count": 22, "id": "5d38fd08", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "executionInfo": { "elapsed": 428, "status": "ok", "timestamp": 1676664715886, "user": { "displayName": "Yang Xu", "userId": "12270366590264264299" }, "user_tz": 300 }, "id": "ZY9IE6Wt_nSR", "outputId": "b5d43244-a65c-4e69-8369-c91a26f42e7f" }, "outputs": [], "source": [ "values = np.zeros((5,1312))\n", "i=0\n", "for movie_genere in movie_generes:\n", " values[i,:] = models_CEL_linear[movie_genere].predict(combinations)\n", " i=i+1\n", " #print(values)" ] }, { "cell_type": "code", "execution_count": 23, "id": "8195a7b7", "metadata": { "executionInfo": { "elapsed": 463, "status": "ok", "timestamp": 1676664728008, "user": { "displayName": "Yang Xu", "userId": "12270366590264264299" }, "user_tz": 300 }, "id": "PS7DNCGp_nSR" }, "outputs": [], "source": [ "result_CEL_linear = combinations\n", "i=0\n", "for movie_genere in movie_generes:\n", " #values = models_CEL[movie_genere].predict(combinations)\n", " result_CEL_linear.insert(len(result_CEL_linear.columns), movie_genere, values[i,:])\n", " i=i+1" ] }, { "cell_type": "code", "execution_count": 24, "id": "05449c57", "metadata": { "executionInfo": { "elapsed": 290, "status": "ok", "timestamp": 1676664747841, "user": { "displayName": "Yang Xu", "userId": "12270366590264264299" }, "user_tz": 300 }, "id": "da-uqtdb_nSS" }, "outputs": [], "source": [ "# the result is saved to\n", "result_CEL_linear.to_csv('result_CEL_linear.csv')" ] }, { "cell_type": "code", "execution_count": 25, "id": "32713df8", "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 488 }, "executionInfo": { "elapsed": 297, "status": "ok", "timestamp": 1676664757858, "user": { "displayName": "Yang Xu", "userId": "12270366590264264299" }, "user_tz": 300 }, "id": "-geZLYVv_nSS", "outputId": "e17fd598-6f3e-451d-ab1d-f6a8fda18572" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
agegenderoccupation_collegeoccupation_executiveoccupation_otheroccupation_technicianComedyDramaActionThrillerSci-Fi
016000003.3231693.4536503.6921673.4828833.357668
116000013.3257823.0989453.6281773.1457053.886814
216000103.5782373.6662343.4642503.3927273.691633
316000113.5808503.3115293.4002613.0555494.220779
416001003.5300903.5667013.4559293.7413103.570002
....................................
130756110113.4949233.2596522.8993593.0069802.469963
130856111003.4441643.5148242.9550273.6927421.819186
130956111013.4467763.1601202.8910383.3555642.348332
131056111103.6992313.7274082.7271113.6025852.153151
131156111113.7018443.3727042.6631223.2654072.682297
\n", "

1312 rows × 11 columns

\n", "
" ], "text/plain": [ " age gender occupation_college occupation_executive occupation_other \\\n", "0 16 0 0 0 0 \n", "1 16 0 0 0 0 \n", "2 16 0 0 0 1 \n", "3 16 0 0 0 1 \n", "4 16 0 0 1 0 \n", "... ... ... ... ... ... \n", "1307 56 1 1 0 1 \n", "1308 56 1 1 1 0 \n", "1309 56 1 1 1 0 \n", "1310 56 1 1 1 1 \n", "1311 56 1 1 1 1 \n", "\n", " occupation_technician Comedy Drama Action Thriller Sci-Fi \n", "0 0 3.323169 3.453650 3.692167 3.482883 3.357668 \n", "1 1 3.325782 3.098945 3.628177 3.145705 3.886814 \n", "2 0 3.578237 3.666234 3.464250 3.392727 3.691633 \n", "3 1 3.580850 3.311529 3.400261 3.055549 4.220779 \n", "4 0 3.530090 3.566701 3.455929 3.741310 3.570002 \n", "... ... ... ... ... ... ... \n", "1307 1 3.494923 3.259652 2.899359 3.006980 2.469963 \n", "1308 0 3.444164 3.514824 2.955027 3.692742 1.819186 \n", "1309 1 3.446776 3.160120 2.891038 3.355564 2.348332 \n", "1310 0 3.699231 3.727408 2.727111 3.602585 2.153151 \n", "1311 1 3.701844 3.372704 2.663122 3.265407 2.682297 \n", "\n", "[1312 rows x 11 columns]" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# read the result file\n", "result_CEL_linear = pd.read_csv('result_CEL_linear.csv')\n", "result_CEL_linear = result_CEL_linear.drop(result_CEL_linear.columns[0], axis=1)\n", "result_CEL_linear" ] }, { "cell_type": "markdown", "id": "8f1058a4", "metadata": { "id": "gBUDJ7pF_nST" }, "source": [ "#### Analysis" ] }, { "cell_type": "code", "execution_count": 26, "id": "44dffb75", "metadata": { "executionInfo": { "elapsed": 367, "status": "ok", "timestamp": 1676664791192, "user": { "displayName": "Yang Xu", "userId": "12270366590264264299" }, "user_tz": 300 }, "id": "vaCTRmcg_nSU" }, "outputs": [], "source": [ "# calculate the expected reward of Comedy for female\n", "TE_female_linear=result_CEL_linear.iloc[np.where(result_CEL_linear['gender']==0)[0],6:11]/(41*(2**4))\n", "TE_female_linear=pd.DataFrame(TE_female_linear.sum(axis=0))\n", "TE_female_linear.columns =['Expected Rating']" ] }, { "cell_type": "code", "execution_count": 27, "id": "6f1bc168", "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 206 }, "executionInfo": { "elapsed": 292, "status": "ok", "timestamp": 1676664794563, "user": { "displayName": "Yang Xu", "userId": "12270366590264264299" }, "user_tz": 300 }, "id": "GeRnCtDm_nSU", "outputId": "192e750a-4732-4342-ea20-ac0d39c4dea2" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Expected Rating
Comedy3.579924
Drama3.402675
Action3.282099
Thriller3.511989
Sci-Fi3.082199
\n", "
" ], "text/plain": [ " Expected Rating\n", "Comedy 3.579924\n", "Drama 3.402675\n", "Action 3.282099\n", "Thriller 3.511989\n", "Sci-Fi 3.082199" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "TE_female_linear" ] }, { "cell_type": "code", "execution_count": 28, "id": "46297093", "metadata": { "executionInfo": { "elapsed": 305, "status": "ok", "timestamp": 1676664826089, "user": { "displayName": "Yang Xu", "userId": "12270366590264264299" }, "user_tz": 300 }, "id": "WXe5ahtO_nSV" }, "outputs": [], "source": [ "# calculate the expected reward of Comedy for female\n", "TE_male_linear=result_CEL_linear.iloc[np.where(result_CEL_linear['gender']==1)[0],6:11]/(41*(2**4))\n", "TE_male_linear=pd.DataFrame(TE_male_linear.sum(axis=0))\n", "TE_male_linear.columns =['Expected Rating']" ] }, { "cell_type": "code", "execution_count": 29, "id": "8e59b318", "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 206 }, "executionInfo": { "elapsed": 13, "status": "ok", "timestamp": 1676664826612, "user": { "displayName": "Yang Xu", "userId": "12270366590264264299" }, "user_tz": 300 }, "id": "d3cpJ3hG_nSV", "outputId": "30c5dd64-f5e2-4a70-e2ed-17bb8a987c68" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Expected Rating
Comedy3.445089
Drama3.423679
Action3.073189
Thriller3.236301
Sci-Fi2.957766
\n", "
" ], "text/plain": [ " Expected Rating\n", "Comedy 3.445089\n", "Drama 3.423679\n", "Action 3.073189\n", "Thriller 3.236301\n", "Sci-Fi 2.957766" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "TE_male_linear" ] }, { "cell_type": "markdown", "id": "c0a91313", "metadata": {}, "source": [ "**Conclusion**: The expected ratings obtained under linear model is generally consistent with the result under nonlinear model. " ] }, { "cell_type": "markdown", "id": "9bce2c09-db8c-464a-bdd3-c3ea3f97c166", "metadata": {}, "source": [ "## Online Learning\n", "\n", "In this section, we aim to implement the contextual TS to learn the optimal policy online. Specifically, we assume that, for each arm $i$, \n", "$$R_t(i)\\sim \\mathcal{N}(\\boldsymbol{s}_i^T \\boldsymbol{\\gamma},\\sigma^2).$$" ] }, { "cell_type": "code", "execution_count": 30, "id": "220cf366-d18b-4d17-9a8a-6f934d8e07dc", "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import numpy as np\n", "from sklearn.linear_model import LinearRegression\n", "from causaldm.learners.CPL4.CMAB import _env_realCMAB as _env\n", "from causaldm.learners.CPL4.CMAB import LinTS\n", "env = _env.Single_Contextual_Env(seed = 0, Binary = False)\n", "K = env.K\n", "p = env.p\n", "logged_data, arms = env.get_logged_dat()\n", "CEL_results = pd.read_csv('result_CEL_nonlinear.csv').iloc[:,1:] " ] }, { "cell_type": "markdown", "id": "db11b7b7-79e8-40aa-9fe3-f902f3e8e27e", "metadata": {}, "source": [ "### Estimated $\\sigma$ and $\\boldsymbol{\\gamma}$\n", "\n", "Here, we estimated the $\\sigma$ and $\\boldsymbol{\\gamma}$ based on the logged data and the estimated results obtained from the causal effect learning (CEL) step." ] }, { "cell_type": "code", "execution_count": 31, "id": "2d03c533-4b65-46c8-8611-e6392a83a7e4", "metadata": {}, "outputs": [], "source": [ "mean_error = []\n", "for genere in arms:\n", " genere_dat = logged_data[genere][['age','gender_M',\n", " 'occupation_college/grad student', 'occupation_executive/managerial',\n", " 'occupation_other', 'occupation_technician/engineer','rating']] \n", " model = LinearRegression().fit(CEL_results.iloc[:,:-5], CEL_results[genere])\n", " genere_error = genere_dat.rating.to_numpy() - model.predict(np.array(genere_dat.iloc[:,:-1]))\n", " mean_error += genere_error.tolist()\n", "sigma = np.std(mean_error,ddof=1)\n", "\n", "gamma = []\n", "for genere in arms:\n", " model = LinearRegression().fit(CEL_results.iloc[:,:-5], CEL_results[genere])\n", " gamma+=[model.intercept_] + list(model.coef_)" ] }, { "cell_type": "markdown", "id": "a46a0843-5f72-40ff-87e8-0c6d9d807a06", "metadata": {}, "source": [ "### Run Informative TS\n", "\n", "Here, we run an informative TS with informative prior information, including the estimated $\\sigma$ and $\\gamma$. Specifically, we use $\\mathcal{N}(\\hat{\\boldsymbol{\\gamma}},.05I)$ as the prior distribution of $\\gamma$. In total, we ran 50 replicates, each with 5000 total steps, to get the expected performance of online learning." ] }, { "cell_type": "code", "execution_count": 32, "id": "ee43e7f0", "metadata": {}, "outputs": [], "source": [ "T = 20000\n", "S = 50\n", "sigma1 = .3\n", "cum_reward_informative = []\n", "for seed in range(S):\n", " env = _env.Single_Contextual_Env(seed = seed, Binary = False)\n", " prior_theta_u = np.array(gamma)\n", " prior_theta_cov = sigma1*np.identity(p)\n", " informative_TS= LinTS.LinTS_Gaussian(sigma = sigma, prior_theta_u = prior_theta_u, \n", " prior_theta_cov = prior_theta_cov, \n", " K = K, p = p,seed = seed)\n", " cum_reward_informative_t = []\n", " rec_action_informative_t = []\n", " for t in range(T):\n", " X, feature_info= env.get_Phi(t)\n", " A = informative_TS.take_action(X)\n", " R = env.get_reward(t,A)\n", " informative_TS.receive_reward(t,A,R,X)\n", " cum_reward_informative_t.append(R)\n", " rec_action_informative_t.append(A)\n", " cum_reward_informative_t = np.cumsum(cum_reward_informative_t)/(np.array(range(T))+1)\n", " cum_reward_informative.append(cum_reward_informative_t)" ] }, { "cell_type": "markdown", "id": "6f3f447b-53bd-43d6-8e68-9835ff0e275a", "metadata": {}, "source": [ "### Run Uninformative TS\n", "\n", "To further show the advantages of integrating the information from a CEL step, we run an uninformative TS with uninformative prior information. Specifically, we use $\\mathcal{N}(\\boldsymbol{0},1000I)$ as the prior distribution of $\\gamma$. In total, we ran 50 replicates, each with 5000 total steps, to get the expected performance of online learning." ] }, { "cell_type": "code", "execution_count": 33, "id": "394623b1", "metadata": {}, "outputs": [], "source": [ "T = 20000\n", "S = 50\n", "cum_reward_uninformative = []\n", "for seed in range(S):\n", " env = _env.Single_Contextual_Env(seed = seed, Binary = False)\n", " K = env.K\n", " p = env.p\n", " prior_theta_u = np.zeros(p)\n", " prior_theta_cov = 1000*np.identity(p)\n", " uninformative_TS= LinTS.LinTS_Gaussian(sigma = sigma, prior_theta_u = prior_theta_u, \n", " prior_theta_cov = prior_theta_cov, \n", " K = K, p = p,seed = seed)\n", " cum_reward_uninformative_t = []\n", " rec_action_uninformative_t = []\n", " for t in range(T):\n", " X, feature_info = env.get_Phi(t)\n", " A = uninformative_TS.take_action(X)\n", " R = env.get_reward(t,A)\n", " uninformative_TS.receive_reward(t,A,R,X)\n", " cum_reward_uninformative_t.append(R)\n", " rec_action_uninformative_t.append(A)\n", " cum_reward_uninformative_t = np.cumsum(cum_reward_uninformative_t)/(np.array(range(T))+1)\n", " cum_reward_uninformative.append(cum_reward_uninformative_t)" ] }, { "cell_type": "markdown", "id": "34b1ac77-c6db-4b31-a44c-cedeb8ddeba2", "metadata": {}, "source": [ "### Run Personalized Greedy\n", "\n", "We also run a greedy algorithm using the results of the CEL-HTE step as a natural baseline. In particular, for each round, we estimated the expected reward for each arm solely based on the estimated results from the CEL step and then pulled the arm with the highest expected reward." ] }, { "cell_type": "code", "execution_count": 34, "id": "8a3ac8d3", "metadata": {}, "outputs": [], "source": [ "T = 20000\n", "S = 50\n", "cum_reward_greedy = []\n", "for seed in range(S):\n", " env = _env.Single_Contextual_Env(seed = seed, Binary = False)\n", " cum_reward_greedy_t = []\n", " rec_action_greedy_t = []\n", " for t in range(T):\n", " X, feature_info= env.get_Phi(t)\n", " A = np.argmax(X.dot(np.array(gamma)))\n", " R = env.get_reward(t,A)\n", " cum_reward_greedy_t.append(R)\n", " rec_action_greedy_t.append(A)\n", " cum_reward_greedy_t = np.cumsum(cum_reward_greedy_t)/(np.array(range(T))+1)\n", " cum_reward_greedy.append(cum_reward_greedy_t)" ] }, { "cell_type": "markdown", "id": "0958c189", "metadata": {}, "source": [ "### Run Naive Greedy\n", "\n", "We also run a greedy algorithm on the CEL-ATE results, which serve as another natural baseline. For each round, we recommend thrillers to the user, as it has the highest expected average reward for both male and female users." ] }, { "cell_type": "code", "execution_count": 35, "id": "8d624fce", "metadata": {}, "outputs": [], "source": [ "T = 20000\n", "S = 50\n", "cum_reward_nvgreedy = []\n", "for seed in range(S):\n", " env = _env.Single_Contextual_Env(seed = seed, Binary = False)\n", " cum_reward_nvgreedy_t = []\n", " rec_action_nvgreedy_t = []\n", " for t in range(T):\n", " A = 3\n", " R = env.get_reward(t,A)\n", " cum_reward_nvgreedy_t.append(R)\n", " rec_action_nvgreedy_t.append(A)\n", " cum_reward_nvgreedy_t = np.cumsum(cum_reward_nvgreedy_t)/(np.array(range(T))+1)\n", " cum_reward_nvgreedy.append(cum_reward_nvgreedy_t)" ] }, { "cell_type": "markdown", "id": "5c377ca8-53db-4018-b3bd-ee008e4c9db4", "metadata": {}, "source": [ "### Results\n", "\n", "On the one hand, while the greedy algorithm outperforms the TS algorithms in the early stages due to extra exploration, both TS algorithms continue to learn new information from the environment and eventually outperform the greedy algorithm. On the other hand, when the results of the uninformative TS are compared to the results of the informative TS, it is clear that the TS algorithm with an informative prior outperforms the uninformative TS, especially in the early stages, due to the use of prior information obtained from the CEL step. Based on the result of the last replicate of the informative TS, the mean of the final estimation of the posterior distribution of $\\boldsymbol{\\gamma}$ is summarized as follows (it can be retrieved by `informative_TS.u`):\n", "\n", "| | intercept | age | gender | college/grad student | executive/managerial | other | technician/engineer |\n", "|----------|:---------:|-------|--------|----------------------|----------------------|-------|---------------------|\n", "| Comedy | 3.426 | 0.001 | -0.045 | -0.191 | -0.062 | -0.223 | -0.149 |\n", "| Drama | 3.884 | -0.010 | -0.029 | -0.161 | -0.011 | 0.039 | -0.117 |\n", "| Action | 2.429 | 0.023 | -0.287 | 0.151 | 0.391 | -0.391 | -0.182 |\n", "| Thriller | 3.674 | -0.008 | -0.040 | -0.267 | -0.028 | -0.000 | -0.061 |\n", "| Sci-Fi | 3.114 | 0.004 | -0.041 | 0.088 | -.004 | -0.063 | -0.578 |\n", "\n", "To use the estimated results greedily, we can calculate the mean reward of each movie genre using the estimated $\\boldsymbol{\\gamma}$ and the incoming user's information, and then recommend the genre with the highest estimated mean reward." ] }, { "cell_type": "code", "execution_count": 37, "id": "9386bd02", "metadata": {}, "outputs": [ { "data": { "image/png": "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R3+5PwkCSUhISHgGEASBLFu2bOXVV1+9+corrxzTVbF27drMnXfeueb+++9f+dnPfranUqnID37wg00TJkzw77zzzjUf+9jHej/wgQ/0LF68uLhmzZoVV1111dY3vOENB+WK2ZtNmzZlLr300t61a9cub21tDa+//vr2A42/5JJLdh599NHHvPjFL57zmc98pqtYLD5h59xnCofN8mFs05iR6Fsv+jeu5dsYsx3YHr0eFpGVwBTgaSsGo0kKjSUkJCTswxNYKJ4OXvva1/YDnHrqqYX3v//9qbHGnHPOOQPZbNZks9mgo6PD37Jliztnzhy/ccx9993X/L//+79rAV7+8pcPX3LJJe6ePXuczs7O8MnMa8qUKZVTTz21BHDCCScUN2zYkD7Q+M9+9rPb3/SmN/XddtttLT/60Y86f/zjH3fed999q5/MuY80DmvAqYg4IvIw0AvcYYy5d4xhzxORpSLyCxFZNMYxZgInAI37vktEHhGRb4rIAZXjocQkpo+EhISEIwLXdY3W9YfCcrlcW88ymYyJxhCG4ZjWgnQ6XftAdxyHIAj2GTdW41URedILQSqVajynGeuce7No0aLKBz/4wV333HPP6lWrVmV37Nix3+DVZxKHVXwYY0JjzPHAVGCJiByz15C/ADMi18yXgFsa3xSRJuB/gXcbY+Joz68Cc7CunO3A58Y6t4hcIiIPiMgDu3btGmvIk7meQ3KchISEhIS/jqlTpwZ9fX3ujh07nFKpJLfffnvroT7Hc5/73OFvfetbnQC33XZbc3t7e9DR0fGUmcFvuOGG1lhgLVu2LOM4junq6npSVpcjjack28UYMyAivwfOBR5t2D7U8PrnIvLfItJljNktIh5WeHzfGPOThnE749ci8nXgtv2c8zrgOoCTTjrpkKiGxPWSkJCQcGSQTqfNe9/73u1Lliw5eurUqZW5c+ce8mDMq6++etsFF1wwc/78+Quz2az+9re/vf5A42+66abO22+/vS3+/p577ln515z/e9/7XueHPvShaZlMRruua77xjW+sd91nR5KqHK6neRHpBvxIeGSBXwFXG2NuaxgzCdhpjDEisgS4CZgRvf0doM8Y8+69jjs5iglBRN4DnGKMOf9AcznppJPMAw88cNDX8Kn/dyYzHt7BJ893uOG8GwjCgMUTFh/0cRISEhKeiYjIg8aYk/be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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "import seaborn as sns\n", "import matplotlib.pyplot as plt\n", "result = pd.DataFrame({'rep':np.concatenate([np.ones(T)*rep for rep in range(S)]*4),\n", " 't':np.concatenate([range(T)]*4*S),\n", " 'Reward':np.concatenate(cum_reward_informative+cum_reward_uninformative+cum_reward_greedy+cum_reward_nvgreedy),\n", " 'Algo':['info_LinTS']*T*S+['uninfo_LinTS']*T*S+['personalized greedy']*T*S+['naive greedy']*T*S})\n", "sns.lineplot(data=result[result.t>0], x='t', y=\"Reward\", hue=\"Algo\", ci = 95,\n", " n_boot = 20, linewidth = 1.0, markers = False)\n", "plt.legend(bbox_to_anchor=(1.02, 1), loc='upper left', borderaxespad=0)\n", "plt.ylabel('Average Reward')\n", "plt.ylim(3.35, 3.55)\n", "plt.savefig('my_figure.png', bbox_inches='tight')" ] }, { "cell_type": "code", "execution_count": null, "id": "f648587e", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.13" } }, "nbformat": 4, "nbformat_minor": 5 }