From dba2de1dbb1a64705f5c224879f671ca951d87f0 Mon Sep 17 00:00:00 2001 From: noakaplan675 Date: Sun, 17 Aug 2025 22:45:07 -0400 Subject: [PATCH 1/3] added mixUCB with EXP4 --- MixUCB_compare.xlsx | Bin 0 -> 5838 bytes run_allucb_NOA_Exp4.py | 410 ++++++++++++++++++++++ run_allucb.py => run_allucb_NOA_mixUCB.py | 71 +++- test_NOA_mixUCB.py | 280 +++++++++++++++ test_NOA_mixUCB_Exp4.py | 355 +++++++++++++++++++ test_NOA_mixUCB_MetaChoice.py | 280 +++++++++++++++ utils/regression_ucb.py | 32 ++ 7 files changed, 1417 insertions(+), 11 deletions(-) create mode 100644 MixUCB_compare.xlsx create mode 100644 run_allucb_NOA_Exp4.py rename run_allucb.py => run_allucb_NOA_mixUCB.py (79%) create mode 100644 test_NOA_mixUCB.py create mode 100644 test_NOA_mixUCB_Exp4.py create mode 100644 test_NOA_mixUCB_MetaChoice.py diff --git a/MixUCB_compare.xlsx b/MixUCB_compare.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..d1838b041fa2a1441605a5666ccaaa89b76aff4f GIT binary patch literal 5838 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 UfR!-;0AlPZhppefzXA#Hf8P^9uK)l5 literal 0 HcmV?d00001 diff --git a/run_allucb_NOA_Exp4.py b/run_allucb_NOA_Exp4.py new file mode 100644 index 00000000..e9c37f79 --- /dev/null +++ b/run_allucb_NOA_Exp4.py @@ -0,0 +1,410 @@ +#!/usr/bin/env python3 +import numpy as np +import pickle +from utils.regression_ucb import MixUCB, OnlineLogisticRegressionOracle +import argparse +from tqdm import tqdm +import logging +import os +import time +from icecream import ic +import argparse + +logging.basicConfig(filename='simulation.log', level=logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s') + + +######################################################################################## +######################################################################################## + +#NOA: + +def get_theta_star(d, K): + theta_star = {a: np.random.randn(d) for a in range(K)} + #normalize: + theta_star = {a: v / np.linalg.norm(v) for a, v in theta_star.items()} + return theta_star + +def f_star_Linear(x, a, theta_star): + # Linear Function Model (for synthetic experiments) + x = x / np.linalg.norm(x) # normalize + return np.dot(x, theta_star[a]) # theta_star is a dict of parameter vectors + +def f_star_Linear_noisy(x, a, theta_star, sigma=0.2, rng=None): + x = np.asarray(x, float) + x /= (np.linalg.norm(x) + 1e-12) # safe normalize + mu = float(np.dot(x, np.asarray(theta_star[a], float))) + if rng is None: rng = np.random.default_rng() + return mu + rng.normal(0.0, sigma) # noisy reward + +def query_expert(x_t, A, f_star, theta_star, feedback_type, reward_list_dict, expert_type, alpha_boltz=0.1, noise_std=0.0): + """ + Query a simulated expert based on MixUCB framework. + """ + # Compute true expected rewards + rewards = {a: f_star(x_t, a, theta_star) for a in A} + + action_set, reward_list = reward_list_dict[expert_type](rewards,x_t) # reward_list_dict[expert_type] is a function that gets the action set and reward list using get_ucb_lcb_subset (that has V_sq) + boltzmann_prob = np.exp(alpha_boltz * np.array(reward_list)) / np.sum(np.exp(alpha_boltz * np.array(reward_list))) + a_tilde = np.random.choice(action_set, p=boltzmann_prob) + if feedback_type == "mixI": + return a_tilde, None + if feedback_type == "mixII": + reward = rewards[a_tilde] + np.random.normal(0, noise_std) + return a_tilde, reward + if feedback_type == "mixIII": + # r_tilde = {a: r + np.random.normal(0, noise_std) for a, r in rewards.items()} + r_tilde = [r + np.random.normal(0, noise_std) for a, r in rewards.items()] + return a_tilde, r_tilde + return None, None + + +def expert_estimation(expert_types, Q_t, gamma, eta, query_expert_params): + + def update_expert_distribution(Q_t, est_rewards, eta): + logQ = np.log(Q_t + 1e-12) + eta * est_rewards + max_logQ = np.max(logQ) # for numerical stability + Q_new = np.exp(logQ - max_logQ) + return Q_new / np.sum(Q_new) + + # Estimate reward for each expert + M = len(expert_types) + est_rewards = np.zeros(M) + for i, etype in enumerate(expert_types): + _, simulated_reward = query_expert(*query_expert_params, etype, noise_std=0.1) + if simulated_reward is not None: + est_rewards[i] = simulated_reward / (Q_t[i] + gamma) + # Update Q_t using EXP4 algo + Q_t = update_expert_distribution(Q_t, est_rewards, eta) + return Q_t + + +def sample_expert(Q_t, w_t, delta, expert_types, expert_indices_per_timestep): + M = len(expert_types) + # Sample expert M_t∼Q_t: + expert_index = np.random.choice(range(M), p=Q_t) + expert_type = expert_types[expert_index] + expert_indices_per_timestep.append(expert_index if w_t >= delta else -1) + return expert_type, expert_indices_per_timestep + + +############################################################################################ +############################################################################################ + +def run_mixucb(data, T, n_actions, n_features, reward_list_dict, expert_types, delta, online_reg_oracle, Q_t, gamma, eta, mode=None): + assert mode in ['lin','mixI','mixII','mixIII'] + rationality = 1 + reward_per_time = np.zeros(T) + query_per_time = np.zeros(T) + action_per_time = [] + + data_len = len(data["rounds"]) + permutation = np.arange(data_len, dtype=int) + + theta_star = get_theta_star(n_features,n_actions) + + # init expert type per timestep: + expert_indices_per_timestep = [] + total_rewards = [] + total_reward = 0 + for i in tqdm(range(T)): + logging.info(f'Running UCB {mode} - round: {i}') + + # Compute data index if i > T + # (NOTE: np.random.shuffle is already seeded in the main block.) + if i == 0: + data_ind = i + else: + # if the data length is less than T, we loop over a randomly shuffled permutation of the data. + ind = i % data_len + if ind == 0: + np.random.shuffle(permutation) + data_ind = permutation[ind] + + # # Load pre-generated context and rewards for the current round + # context = data["rounds"][data_ind]["context"] + # # expected vs actual rewards + # expected_rewards = data["rounds"][data_ind]["expected_rewards"] # empty for classification datasets + # actual_rewards = data["rounds"][data_ind]["actual_rewards"] + # # noisy expert choice. + # noisy_expert_choice = data["rounds"][data_ind]["noisy_expert_choice"] + + # NOA: + context = np.random.randn(n_features) + # Calculate UCB and LCB + ucb,lcb = online_reg_oracle.get_ucb_lcb(context) + action_hat = np.argmax(ucb) + + actions_set = list(range(n_actions)) + expected_rewards = [f_star_Linear_noisy(context, a, theta_star) for a in actions_set] + actual_rewards = [f_star_Linear(context, a, theta_star) for a in actions_set] + noisy_expert_choice = 0 + + if mode in ['mixI', 'mixII', 'mixIII']: + # Determine if querying expert or not + width = ucb - lcb + width_Ahat = width[action_hat] + # Print i, action_hat, width_Ahat, delta. + logging.info(f'Round {i}, action_hat: {action_hat}, width_Ahat: {width_Ahat}, delta: {delta}') + + # Sample Expert type: Sample expert M_t∼Q_t + expert_type, expert_indices_per_timestep = sample_expert(Q_t, width_Ahat, delta, expert_types, expert_indices_per_timestep) + + if width_Ahat > delta: + # query expert and update online regression + query_per_time[i] = 1 + + if mode == 'mixIII': + if len(expected_rewards) == 0: + expert_action = np.argmax(actual_rewards) + else: + expert_action = np.argmax(expected_rewards) + else: + if len(expected_rewards) == 0: + expert_action = np.argmax(actual_rewards) + else: + # Here we need to insert your action choice based on expert feedback + expert_action, _ = query_expert(context, actions_set, f_star_Linear, theta_star, mode, reward_list_dict, expert_type, alpha_boltz=0.1, noise_std=0.1) + reward = actual_rewards[expert_action] + + if mode == 'mixIII': + if len(expected_rewards) == 0: + online_reg_oracle.update(context,rewards=actual_rewards) + else: + online_reg_oracle.update(context,rewards=expected_rewards) + elif mode == 'mixII': + online_reg_oracle.update(context, action=expert_action) + online_reg_oracle.update(context, action=expert_action, reward=reward) + elif mode == 'mixI': + online_reg_oracle.update(context, action=expert_action) + else: + # take action_hat and update online regression + reward = actual_rewards[action_hat] + online_reg_oracle.update(context, action=action_hat, reward=reward) + + else: + # Print i, action_hat, width_Ahat, delta. + logging.info(f'Round {i}, action_hat: {action_hat}') + reward = actual_rewards[action_hat] + online_reg_oracle.update(context, action=action_hat, reward=reward) + + reward_per_time[i] = reward + + if query_per_time[i]: + action_per_time.append(expert_action) + else: + action_per_time.append(action_hat) + + logging.info(f'{mode} UCB: reward {reward}, query: {query_per_time[i]}, totalq: {np.sum(query_per_time)}') + + # Expert type: Update expert estimation + Q_t = expert_estimation(expert_types, Q_t, gamma, eta, (context, actions_set, f_star_Linear, theta_star, mode, reward_list_dict)) + + total_reward += reward if reward else f_star_Linear(context, action_per_time[i], theta_star) + np.random.normal(0, 0.1) + total_rewards.append(total_reward / (i + 1) if i > 0 else 0) + + return reward_per_time, query_per_time, action_per_time, expert_indices_per_timestep, total_rewards + + +def run_linear_oracle(data, T, theta): + reward_per_time = np.zeros(T) + action_per_time = [] + + data_len = len(data["rounds"]) + permutation = np.arange(data_len, dtype=int) + + for i in tqdm(range(T)): + logging.info(f'Running linear oracle - round: {i}') + + # Compute data index if i > T + # (NOTE: np.random.shuffle is already seeded in the main block.) + if i == 0: + data_ind = i + else: + ind = i % data_len + if ind == 0: + np.random.shuffle(permutation) + data_ind = permutation[ind] + + # Load pre-generated context and rewards for the current round + context = data["rounds"][data_ind]["context"] + + actual_rewards = data["rounds"][data_ind]["actual_rewards"] + + est_rewards = np.dot(theta, context.ravel()) + action = np.argmax(est_rewards) + + reward = actual_rewards[action] + reward_per_time[i] = reward + action_per_time.append(action) + + logging.info(f'oracle: reward {reward}') + + return reward_per_time, action_per_time + + pass + +def run_expert(data, T, type='perfect_exp'): + """ + Runs the expert algorithm for T rounds (either perfect or noisy). + """ + reward_per_time = np.zeros(T) + action_per_time = [] + + data_len = len(data["rounds"]) + permutation = np.arange(data_len, dtype=int) + + for i in tqdm(range(T)): + logging.info(f'Running expert type {type} - round: {i}') + + # Compute data index if i > T + # (NOTE: np.random.shuffle is already seeded in the main block.) + if i == 0: + data_ind = i + else: + ind = i % data_len + if ind == 0: + np.random.shuffle(permutation) + data_ind = permutation[ind] + + # Load pre-generated expected and actual rewards for the current round + expected_rewards = data["rounds"][data_ind]["expected_rewards"] + actual_rewards = data["rounds"][data_ind]["actual_rewards"] + # noisy expert choice. + noisy_expert_choice = data["rounds"][data_ind]["noisy_expert_choice"] + + # Select either the perfect or noisy expert action based on the type. + # Identical to logic in run_mixucb for MixUCB-I/II/III expert logic. + if type == 'perfect_exp': + # Same as MixUCB-III expert logic + if len(expected_rewards) == 0: + expert_action = np.argmax(actual_rewards) + else: + expert_action = np.argmax(expected_rewards) + elif type == 'noisy_exp': + # Same as MixUCB-I/II expert logic. + if len(expected_rewards) == 0: + expert_action = np.argmax(actual_rewards) + else: + expert_action = noisy_expert_choice + + reward = actual_rewards[expert_action] + reward_per_time[i] = reward + action_per_time.append(expert_action) + + logging.info(f'expert: reward {reward}') + + return reward_per_time, action_per_time + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Run UCB Baseline + oracles + experts.') + parser.add_argument('--mode', type=str, default='lin', help='must be: lin, mixI, mixII, mixIII, sq_oracle, lr_oracle, perfect_exp, noisy_exp') + parser.add_argument('--T', type=int, default=0) + parser.add_argument('--delta', nargs='+', type=float, default=[4., 5., 6., 7., 8.]) + parser.add_argument('--lambda_', type=float, default=0.001, help='regularization weight') + parser.add_argument('--pickle_file', type=str, default='simulation_data.pkl', help='Path to the pickle file containing pre-generated data') + parser.add_argument('--seed', type=int, default=42, help='Random seed for reproducibility') + parser.add_argument("--data_name", type=str, default='', help="Name of the dataset to use.") + parser.add_argument('--learning_rate', type=float, default=0.1) + parser.add_argument('--alpha', type=float, default=100, help='squared loss confidence radius') + parser.add_argument('--beta', type=float, default=1000, help='log loss confidence radius') + + args = parser.parse_args() + + # Set random seed for reproducibility + np.random.seed(args.seed) + + # Load pre-generated data from the pickle file + with open(args.pickle_file, 'rb') as f: + data = pickle.load(f) + + # Extract n_actions and n_features from the data + n_actions = len(data["rounds"][0]["actual_rewards"]) + n_features = data["rounds"][0]["context"].shape[1] + # Extract the number of rounds (T) from the data + T = args.T if args.T > 0 else len(data["rounds"]) + + # Initialize parameters + delta_list = args.delta + alpha = args.alpha + beta = args.beta + lambda_ = args.lambda_ + learning_rate = args.learning_rate + data_name = args.data_name + mode = args.mode + seed = args.seed + + if mode in ['sq_oracle', 'lr_oracle']: + results = os.path.join(data_name, f"seed_{seed:02d}", '{}_results'.format(mode)) + os.makedirs(results, exist_ok=True) + print('Makedir {}'.format(results)) + + if mode == 'sq_oracle': + theta = data['true_theta'] + else: + theta = data['true_theta_classification'] + + # Run using the pre-generated data + reward_per_time, action_per_time = run_linear_oracle(data, T, theta) + + print(f"Finished running {mode} for {T} rounds.") + + pkl_name = os.path.join(results, f'{time.strftime("%Y%m%d_%H%M%S")}.pkl') + dict_to_save = { + 'reward_per_time': reward_per_time, + 'action_per_time': action_per_time, + 'delta_list': delta_list + } + with open(pkl_name, 'wb') as f: + pickle.dump(dict_to_save, f) + print('Saved to {}'.format(pkl_name)) + + elif mode in ['perfect_exp', 'noisy_exp']: + results = os.path.join(data_name, f"seed_{seed:02d}", '{}_results'.format(mode)) + os.makedirs(results, exist_ok=True) + print('Makedir {}'.format(results)) + + reward_per_time, action_per_time = run_expert(data, T, type=mode) + + print(f"Finished running {mode} for {T} rounds.") + + pkl_name = os.path.join(results, f'{time.strftime("%Y%m%d_%H%M%S")}.pkl') + dict_to_save = { + 'reward_per_time': reward_per_time, + 'action_per_time': action_per_time, + 'delta_list': delta_list + } + with open(pkl_name, 'wb') as f: + pickle.dump(dict_to_save, f) + print('Saved to {}'.format(pkl_name)) + + else: + if mode == 'lin': + delta_list = [0] + + for delta in delta_list: + results = os.path.join(data_name, f"seed_{seed:02d}", '{}_ucb_results'.format(mode), '{}'.format(delta)) + os.makedirs(results, exist_ok=True) + print('Makedir {}'.format(results)) + + online_reg_oracle = OnlineLogisticRegressionOracle(n_features, n_actions, learning_rate, lambda_, beta, rad_sq=alpha) + + # Run using the pre-generated data + reward_per_time, query_per_time, action_per_time = run_mixucb(data, T, n_actions, n_features, delta, online_reg_oracle, mode=mode) + + print(f"Finished running {mode} UCB for {T} rounds.") + + pkl_name = os.path.join(results, f'{time.strftime("%Y%m%d_%H%M%S")}.pkl') + dict_to_save = { + 'reward_per_time': reward_per_time, + 'query_per_time': query_per_time, + 'action_per_time': action_per_time, + 'alpha': args.alpha, + 'beta': args.beta, + 'lambda_': args.lambda_, + 'delta_list': delta_list + } + with open(pkl_name, 'wb') as f: + pickle.dump(dict_to_save, f) + print('Saved to {}'.format(pkl_name)) diff --git a/run_allucb.py b/run_allucb_NOA_mixUCB.py similarity index 79% rename from run_allucb.py rename to run_allucb_NOA_mixUCB.py index 65cbeff9..fe48dfc7 100644 --- a/run_allucb.py +++ b/run_allucb_NOA_mixUCB.py @@ -13,7 +13,47 @@ logging.basicConfig(filename='simulation.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') -def run_mixucb(data, T, n_actions, delta, online_reg_oracle, mode=None): + +def get_theta_star(d, K): + theta_star = {a: np.random.randn(d) for a in range(K)} + #normalize: + theta_star = {a: v / np.linalg.norm(v) for a, v in theta_star.items()} + return theta_star + +def f_star_Linear(x, a, theta_star): + # Linear Function Model (for synthetic experiments) + x = x / np.linalg.norm(x) # normalize + return np.dot(x, theta_star[a]) # theta_star is a dict of parameter vectors + +def f_star_Linear_noisy(x, a, theta_star, sigma=0.2, rng=None): + x = np.asarray(x, float) + x /= (np.linalg.norm(x) + 1e-12) # safe normalize + mu = float(np.dot(x, np.asarray(theta_star[a], float))) + if rng is None: rng = np.random.default_rng() + return mu + rng.normal(0.0, sigma) # noisy reward + +def query_expert(x_t, A, f_star, theta_star, feedback_type, reward_list_dict, expert_type, alpha_boltz=0.1, noise_std=0.0): + """ + Query a simulated expert based on MixUCB framework. + """ + # Compute true expected rewards + rewards = {a: f_star(x_t, a, theta_star) for a in A} + + action_set, reward_list = reward_list_dict[expert_type](rewards,x_t) + boltzmann_prob = np.exp(alpha_boltz * np.array(reward_list)) / np.sum(np.exp(alpha_boltz * np.array(reward_list))) + a_tilde = np.random.choice(action_set, p=boltzmann_prob) + if feedback_type == "mixI": + return a_tilde, None + if feedback_type == "mixII": + reward = rewards[a_tilde] + np.random.normal(0, noise_std) + return a_tilde, reward + if feedback_type == "mixIII": + r_tilde = {a: r + np.random.normal(0, noise_std) for a, r in rewards.items()} + return a_tilde, r_tilde + return None, None + + +def run_mixucb(data, T, n_actions, n_features, reward_list_dict, expert_type, delta, online_reg_oracle, mode=None): assert mode in ['lin','mixI','mixII','mixIII'] rationality = 1 reward_per_time = np.zeros(T) @@ -23,6 +63,7 @@ def run_mixucb(data, T, n_actions, delta, online_reg_oracle, mode=None): data_len = len(data["rounds"]) permutation = np.arange(data_len, dtype=int) + theta_star = get_theta_star(n_features,n_actions) for i in tqdm(range(T)): logging.info(f'Running UCB {mode} - round: {i}') @@ -37,18 +78,25 @@ def run_mixucb(data, T, n_actions, delta, online_reg_oracle, mode=None): np.random.shuffle(permutation) data_ind = permutation[ind] - # Load pre-generated context and rewards for the current round - context = data["rounds"][data_ind]["context"] - # expected vs actual rewards - expected_rewards = data["rounds"][data_ind]["expected_rewards"] # empty for classification datasets - actual_rewards = data["rounds"][data_ind]["actual_rewards"] - # noisy expert choice. - noisy_expert_choice = data["rounds"][data_ind]["noisy_expert_choice"] - + # # Load pre-generated context and rewards for the current round + # context = data["rounds"][data_ind]["context"] + # # expected vs actual rewards + # expected_rewards = data["rounds"][data_ind]["expected_rewards"] # empty for classification datasets + # actual_rewards = data["rounds"][data_ind]["actual_rewards"] + # # noisy expert choice. + # noisy_expert_choice = data["rounds"][data_ind]["noisy_expert_choice"] + + # NOA: + context = np.random.randn(n_features) # Calculate UCB and LCB ucb,lcb = online_reg_oracle.get_ucb_lcb(context) action_hat = np.argmax(ucb) + actions_set = list(range(n_actions)) + expected_rewards = [f_star_Linear_noisy(context, a, theta_star) for a in actions_set] + actual_rewards = [f_star_Linear(context, a, theta_star) for a in actions_set] + noisy_expert_choice = 0 + if mode in ['mixI', 'mixII', 'mixIII']: # Determine if querying expert or not width = ucb - lcb @@ -68,7 +116,8 @@ def run_mixucb(data, T, n_actions, delta, online_reg_oracle, mode=None): if len(expected_rewards) == 0: expert_action = np.argmax(actual_rewards) else: - expert_action = noisy_expert_choice + # Here we need to insert your action choice based on expert feedback + expert_action, _ = query_expert(context, actions_set, f_star_Linear, theta_star, mode, reward_list_dict, expert_type, alpha_boltz=0.1, noise_std=0.1) reward = actual_rewards[expert_action] if mode == 'mixIII': @@ -288,7 +337,7 @@ def run_expert(data, T, type='perfect_exp'): online_reg_oracle = OnlineLogisticRegressionOracle(n_features, n_actions, learning_rate, lambda_, beta, rad_sq=alpha) # Run using the pre-generated data - reward_per_time, query_per_time, action_per_time = run_mixucb(data, T, n_actions, delta, online_reg_oracle, mode=mode) + reward_per_time, query_per_time, action_per_time = run_mixucb(data, T, n_actions, n_features, delta, online_reg_oracle, mode=mode) print(f"Finished running {mode} UCB for {T} rounds.") diff --git a/test_NOA_mixUCB.py b/test_NOA_mixUCB.py new file mode 100644 index 00000000..60b72a32 --- /dev/null +++ b/test_NOA_mixUCB.py @@ -0,0 +1,280 @@ +# from generate_multilabel_data import generate_synthetic_data + + +# data = generate_synthetic_data(T=10, noise_std=0.2, seed=42) +# print(data) + + +from pathlib import Path +import numpy as np +import pandas as pd +import matplotlib.pyplot as plt + +from generate_multilabel_data import generate_synthetic_data +from run_allucb_NOA_mixUCB import run_mixucb, run_linear_oracle, run_expert # uses the repo’s run functions +from utils.regression_ucb import OnlineLogisticRegressionOracle # regression + UCB online oracle + + +def plot_query_reward( + query_nums, + rewards, + feedback_type, + expert_type, + delta, + *, + is_cumulative=True, # set False if query_nums are per-step counts already + smooth_window=20, # rolling mean window for rewards + show_query_markers=True +): + """ + query_nums : array-like + If is_cumulative=True, this is cumulative queries over time. + If is_cumulative=False, this is per-step query counts. + rewards : array-like + Per-step auto reward (not pre-averaged). + """ + + q = np.asarray(query_nums, dtype=float).ravel() + r = np.asarray(rewards, dtype=float).ravel() + T = min(len(q), len(r)) + q, r = q[:T], r[:T] + + # derive cumulative & per-step queries consistently + if is_cumulative: + cum_q = q + per_step_q = np.diff(np.r_[0.0, q]) + else: + per_step_q = q + cum_q = np.cumsum(q) + + # clamp any tiny negative diffs (numerical jitter) to zero + per_step_q = np.maximum(per_step_q, 0.0) + + # rolling mean for rewards + w = int(max(1, min(smooth_window, T))) + kernel = np.ones(w) / w + roll_mean = np.convolve(r, kernel, mode="same") + + # cumulative average reward + cum_avg = np.cumsum(r) / np.arange(1, T + 1) + + x = np.arange(T) + + plt.figure(figsize=(12, 5)) + + # -------- Left: queries -------- + ax1 = plt.subplot(1, 2, 1) + ax1.plot(x, cum_q, label="Cumulative Queries") + ax1.set_title("Cumulative & Per-Step Queries") + ax1.set_xlabel("Time Step") + ax1.set_ylabel("Cumulative") + + # ax1b = ax1.twinx() + # ax1b.plot(x, per_step_q, linestyle="--", beta_sq=0.8, label="Per-Step Queries") + # ax1b.set_ylabel("Per-Step") + + # combine legends from both axes + lines1, labels1 = ax1.get_legend_handles_labels() + # lines2, labels2 = ax1b.get_legend_handles_labels() + ax1.legend(lines1, labels1, loc="upper left") + + # -------- Right: rewards -------- + ax2 = plt.subplot(1, 2, 2) + # ax2.plot(x, r, beta_sq=0.5, label="Reward (per step)") + ax2.plot(x, roll_mean, linewidth=2, label=f"Rolling Mean (w={w})") + ax2.plot(x, cum_avg, linewidth=2, linestyle=":", label="Cumulative Average Auto Reward") + ax2.set_title("Auto Reward") + ax2.set_xlabel("Time Step") + ax2.set_ylabel("Reward") + ax2.legend(loc="best") + + # optional: show vertical markers where a query happened + if show_query_markers: + query_idxs = np.where(per_step_q > 0)[0] + for idx in query_idxs: + ax2.axvline(idx, beta_sq=0.15) + + plt.suptitle(f"Feedback: {feedback_type}, Expert: '{expert_type}', Δ={delta}", fontsize=14) + plt.tight_layout() + plt.show() + + +######################################################################################################## +######################################################################################################## + + +# --- config (edit freely) --- +T = 300 # timesteps to simulate (per run) +seed = 42 # numpy RNG seed +dataset = "synthetic" # "synthetic" | "spanet" | "heart_disease" | "MedNIST" +noise_std = 0.2 # only used for synthetic +deltas = [0.5, 0.75, 1.0] # query thresholds Δ +beta_sq = 1.25 # squared-loss radius (rad_sq) +beta_lr = 2.5 # log-loss radius +lambda_ = 1e-3 # L2 reg +lr = 0.1 # learning rate + +np.random.seed(seed) + +# --- get data dict exactly like the repo expects --- +if dataset == "synthetic": + data = generate_synthetic_data(T=1000, noise_std=noise_std, seed=seed) +elif dataset in ("heart_disease", "MedNIST", "yeast", "iris"): + # You can also generate these through generate_multilabel_data.py, + # but here we keep it simple and just re-use 'synthetic' for a quick demo. + raise ValueError("For non-synthetic datasets, generate a pickle via generate_multilabel_data.py and load it.") +else: + raise ValueError("Unknown dataset") + +# Infer shapes from the data +n_actions = len(data["rounds"][0]["actual_rewards"]) +n_features = data["rounds"][0]["context"].shape[1] + +def avg_autonomous_reward(rewards: np.ndarray, queries: np.ndarray) -> float: + """Average reward on steps where we did NOT query (Z_t = 0).""" + mask_no_query = (queries == 0).astype(int) + if mask_no_query.sum() == 0: + return 0.0 + return (rewards * mask_no_query).sum() / mask_no_query.sum() + + + +############################################################################################### + +#NOA: + + +def phi(x, a, K): + # Feature map + ea = np.zeros(K) + ea[a] = 1 + phi_val = np.kron(x, ea) + return phi_val # / np.linalg.norm(phi_val) # normalize + + +actions_set = list(range(n_actions)) + +# expert_types = ["compare", "demonstrate", "improve", "reward_punish", "off"] +expert_types = ["improve", "reward_punish", "off"] + +reward_list_dict = { + # "compare": lambda rewards, context: ( + # subset := oracle.get_ucb_lcb_subset(context, 2), + # [rewards[a] for a in subset if a in rewards] + # ), + # "demonstrate": lambda rewards, context: ( + # subset := actions_set, + # [rewards[a] for a in subset if a in rewards] + # ), + "improve": lambda rewards, context: ( + subset := oracle.get_ucb_lcb_subset(context, 1) + [max(rewards, key=rewards.get)], + [rewards[a] for a in subset if a in rewards] + ), + "reward_punish": lambda rewards, context: ( + subset := oracle.get_ucb_lcb_subset(context, 1) + [max(rewards, key=rewards.get)], + [-1,1] #-1 for robot, +1 for expert + ), + "off": lambda rewards, context: ( + subset := oracle.get_ucb_lcb_subset(context, 1) + [0], #define external "off" action as: 0 + [rewards[a] for a in subset if a in rewards] + ) +} + + +############################################################################################### + + + + +rows = [] + +# Baselines: perfect/noisy expert + linear oracles +# (shows how to call other helpers without touching the file system) +# perfect expert +# r_exp, a_exp = run_expert(data, T, type="perfect_exp") +# rows.append(dict(mode="perfect_exp", delta=None, +# queries=0, avg_auto_reward=0.0, +# avg_total_reward=r_exp.mean())) +# # noisy expert +# r_exp, a_exp = run_expert(data, T, type="noisy_exp") +# rows.append(dict(mode="noisy_exp", delta=None, +# queries=0, avg_auto_reward=0.0, +# avg_total_reward=r_exp.mean())) +# # squared/logistic “oracle” (uses data['true_theta*']) +# r_or, a_or = run_linear_oracle(data, T, data["true_theta"]) +# rows.append(dict(mode="sq_oracle", delta=None, +# queries=0, avg_auto_reward=r_or.mean(), # same as total here +# avg_total_reward=r_or.mean())) +# r_or, a_or = run_linear_oracle(data, T, data["true_theta_classification"]) +# rows.append(dict(mode="lr_oracle", delta=None, +# queries=0, avg_auto_reward=r_or.mean(), +# avg_total_reward=r_or.mean())) + + + + +# MixUCB family (lin, mixI, mixII, mixIII) +for expert_type in expert_types: + for mode in ["lin", "mixI", "mixII", "mixIII"]: + # For 'lin' there is no Δ list in the repo – it internally treats Δ as [0] (no query path). + _deltas = [0.0] if mode == "lin" else deltas + for delta in _deltas: + oracle = OnlineLogisticRegressionOracle( + n_features, n_actions, lr, lambda_, beta_lr, rad_sq=beta_sq + ) + r_t, q_t, a_t = run_mixucb( + data=data, + T=T, + n_actions=n_actions, + n_features=n_features, + reward_list_dict=reward_list_dict, + expert_type=expert_type, + delta=delta, + online_reg_oracle=oracle, + mode=mode, + ) # returns reward_per_time, query_per_time, action_per_time + + rows.append(dict( + mode=mode, + delta=float(delta), + queries=int(q_t.sum()), + avg_auto_reward=avg_autonomous_reward(r_t, q_t), + avg_total_reward=r_t.mean(), + )) + + + # PLOT: + query_nums = [int(q_t[:i].sum()) for i in range(len(q_t))] + total_auto_rewards = [avg_autonomous_reward(r_t[:i], q_t[:i]) for i in range(len(q_t))] + feedback_type = mode + expert_type = expert_type + plot_query_reward(query_nums, # cumulative or per-step; set is_cumulative accordingly + total_auto_rewards, # per-step rewards array + feedback_type, + expert_type, + delta, + is_cumulative=True, # flip to False if passing per-step counts + smooth_window=25, # tweak as you like + show_query_markers=False + ) + +df = pd.DataFrame(rows) +print(df) + +# Save a compact summary like your Excel sheet idea +out_path = Path("MixUCB_compare.xlsx") +df.to_excel(out_path, index=False) +print(f"Saved results -> {out_path.resolve()}") + +# (Optional) Tiny sanity plot +try: + import matplotlib.pyplot as plt + for mode in ["lin", "mixI", "mixII", "mixIII"]: + sub = df[df["mode"] == mode] + xs = sub["delta"].fillna(0.0) + plt.plot(xs, sub["avg_total_reward"], marker="o", label=mode) + plt.xlabel("Δ"); plt.ylabel("Avg total reward"); plt.title("Quick comparison") + plt.legend(); plt.tight_layout(); plt.show() +except Exception as e: + print("Plot skipped:", e) + diff --git a/test_NOA_mixUCB_Exp4.py b/test_NOA_mixUCB_Exp4.py new file mode 100644 index 00000000..7344b02c --- /dev/null +++ b/test_NOA_mixUCB_Exp4.py @@ -0,0 +1,355 @@ +# from generate_multilabel_data import generate_synthetic_data + + +# data = generate_synthetic_data(T=10, noise_std=0.2, seed=42) +# print(data) + + +from pathlib import Path +import numpy as np +import pandas as pd +import matplotlib.pyplot as plt + +from generate_multilabel_data import generate_synthetic_data +from run_allucb_NOA_Exp4 import run_mixucb, run_linear_oracle, run_expert # uses the repo’s run functions +from utils.regression_ucb import OnlineLogisticRegressionOracle # regression + UCB online oracle +from matplotlib.collections import LineCollection +from matplotlib.lines import Line2D + + +def plot_query_reward( + query_nums, + rewards, + feedback_type, + expert_type, + delta, + *, + is_cumulative=True, + smooth_window=20, + show_query_markers=True +): + """ + Plot query count (cumulative and per-step) and auto reward (rolling and cumulative average). + + Parameters + ---------- + query_nums : array-like + If is_cumulative=True, this is cumulative queries over time. + If is_cumulative=False, this is per-step query counts. + rewards : array-like + Per-step auto reward (not pre-averaged). + """ + + q = np.asarray(query_nums, dtype=float).ravel() + r = np.asarray(rewards, dtype=float).ravel() + T = min(len(q), len(r)) + q, r = q[:T], r[:T] + + # Convert queries to cumulative and per-step + if is_cumulative: + cum_q = q + per_step_q = np.diff(np.r_[0.0, q]) + else: + per_step_q = q + cum_q = np.cumsum(q) + + per_step_q = np.maximum(per_step_q, 0.0) # avoid tiny negative jitter + + # Rolling mean + w = int(max(1, min(smooth_window, T))) + kernel = np.ones(w) / w + roll_mean = np.convolve(r, kernel, mode="same") + + # Cumulative average + cum_avg = np.cumsum(r) / np.arange(1, T + 1) + x = np.arange(T) + + plt.figure(figsize=(12, 5)) + + # -------- Left: cumulative queries -------- + ax1 = plt.subplot(1, 2, 1) + ax1.plot(x, cum_q, label="Cumulative Queries", color="tab:blue", linewidth=2) + ax1.set_title("Cumulative & Per-Step Queries") + ax1.set_xlabel("Time Step") + ax1.set_ylabel("Cumulative Queries") + ax1.grid(True) + ax1.legend(loc="upper left") + + # -------- Right: reward curves -------- + ax2 = plt.subplot(1, 2, 2) + ax2.plot(x, roll_mean, linewidth=2, label=f"Rolling Mean (w={w})", color="tab:orange") + ax2.plot(x, cum_avg, linewidth=2, linestyle=":", label="Cumulative Average Reward", color="tab:green") + ax2.set_title("Auto Reward") + ax2.set_xlabel("Time Step") + ax2.set_ylabel("Reward") + ax2.grid(True) + ax2.legend(loc="best") + + # optional: vertical lines at query steps + if show_query_markers: + query_idxs = np.where(per_step_q > 0)[0] + for idx in query_idxs: + ax2.axvline(idx, alpha=0.15, color="gray", linestyle="--") + + plt.suptitle(f"Feedback: {feedback_type}, Expert: '{expert_type}', Δ={delta}", fontsize=14) + plt.tight_layout() + plt.show() + + +def plot_query_reward_expertType( + query_nums, + total_rewards, + expert_indices_per_timestep, + feedback_type, + expert_types, + delta, + plot_title="Expert Usage Over Time" +): + """ + Styled to match newer plot_query_reward code. + + Parameters: + - query_nums: list or array, cumulative number of queries + - total_rewards: list or array, total reward at each timestep + - expert_indices_per_timestep: list of ints, index of expert used at each timestep (or -1 for autonomous) + - feedback_type: str, e.g. "I" or "II" + - expert_types: list of str, names of expert types (must align with expert_indices) + - delta: float, the querying threshold + - plot_title: str, plot title prefix + """ + + # Colors + M = len(expert_types) + cmap = plt.get_cmap("tab10") + expert_colors = {i: cmap(i) for i in range(M)} + expert_colors[-1] = "gray" + + # Segment line by expert index + y = np.array(total_rewards) + x = np.arange(len(y)) + points = np.array([x, y]).T.reshape(-1, 1, 2) + segments = np.concatenate([points[:-1], points[1:]], axis=1) + colors = [expert_colors.get(expert_indices_per_timestep[t], "gray") for t in range(len(segments))] + lc = LineCollection(segments, colors=colors, linewidths=2) + + # Plot + plt.figure(figsize=(12, 5)) + + # Subplot 1: cumulative queries + plt.subplot(1, 2, 1) + plt.plot(query_nums) + plt.title("Cumulative Queries") + plt.xlabel("Time Step") + plt.ylabel("Number of Queries") + + # Subplot 2: reward over time (expert-colored) + ax2 = plt.subplot(1, 2, 2) + ax2.add_collection(lc) + ax2.set_xlim(x.min(), x.max()) + ax2.set_ylim(y.min(), y.max()) + ax2.set_title("Total Reward Over Time (Color = Expert)") + ax2.set_xlabel("Time Step") + ax2.set_ylabel("Total Reward") + + # Add legend manually + legend_elements = [Line2D([0], [0], color="gray", lw=2, label="Autonomous (no expert)")] + for i, name in enumerate(expert_types): + legend_elements.append(Line2D([0], [0], color=expert_colors[i], lw=2, label=name)) + + ax2.legend(handles=legend_elements, loc="lower right", fontsize=9) + + # Unified title and layout + plt.suptitle(f"{plot_title} — Feedback: {feedback_type}, Δ={delta}", fontsize=14) + plt.tight_layout() + plt.show() + + + +######################################################################################################## +######################################################################################################## + + +# --- config (edit freely) --- +T = 300 # timesteps to simulate (per run) +seed = 42 # numpy RNG seed +dataset = "synthetic" # "synthetic" | "spanet" | "heart_disease" | "MedNIST" +noise_std = 0.2 # only used for synthetic +deltas = [0.5, 0.75, 1.0] # query thresholds Δ +beta_sq = 1.25 # squared-loss radius (rad_sq) +beta_lr = 2.5 # log-loss radius +lambda_ = 1e-3 # L2 reg +lr = 0.1 # learning rate + +np.random.seed(seed) + +# --- get data dict exactly like the repo expects --- +if dataset == "synthetic": + data = generate_synthetic_data(T=1000, noise_std=noise_std, seed=seed) +elif dataset in ("heart_disease", "MedNIST", "yeast", "iris"): + # You can also generate these through generate_multilabel_data.py, + # but here we keep it simple and just re-use 'synthetic' for a quick demo. + raise ValueError("For non-synthetic datasets, generate a pickle via generate_multilabel_data.py and load it.") +else: + raise ValueError("Unknown dataset") + +# Infer shapes from the data +n_actions = len(data["rounds"][0]["actual_rewards"]) +n_features = data["rounds"][0]["context"].shape[1] + +def avg_autonomous_reward(rewards: np.ndarray, queries: np.ndarray) -> float: + """Average reward on steps where we did NOT query (Z_t = 0).""" + mask_no_query = (queries == 0).astype(int) + if mask_no_query.sum() == 0: + return 0.0 + return (rewards * mask_no_query).sum() / mask_no_query.sum() + + + +############################################################################################### + +#NOA: + + +def phi(x, a, K): + # Feature map + ea = np.zeros(K) + ea[a] = 1 + phi_val = np.kron(x, ea) + return phi_val # / np.linalg.norm(phi_val) # normalize + + +actions_set = list(range(n_actions)) + +# expert_types = ["compare", "demonstrate", "improve", "reward_punish", "off"] +expert_types = ["improve", "reward_punish", "off"] + +reward_list_dict = { + # "compare": lambda rewards, context: ( + # subset := oracle.get_ucb_lcb_subset(context, 2), + # [rewards[a] for a in subset if a in rewards] + # ), + # "demonstrate": lambda rewards, context: ( + # subset := actions_set, + # [rewards[a] for a in subset if a in rewards] + # ), + "improve": lambda rewards, context: ( + subset := oracle.get_ucb_lcb_subset(context, 1) + [max(rewards, key=rewards.get)], + [rewards[a] for a in subset if a in rewards] + ), + "reward_punish": lambda rewards, context: ( + subset := oracle.get_ucb_lcb_subset(context, 1) + [max(rewards, key=rewards.get)], + [-1,1] #-1 for robot, +1 for expert + ), + "off": lambda rewards, context: ( + subset := oracle.get_ucb_lcb_subset(context, 1) + [0], #define external "off" action as: 0 + [rewards[a] for a in subset if a in rewards] + ) +} + + + +M = len(expert_types) +Q_t = np.ones(M) / M + +eta = 0.1 # learning rate +gamma = 0.01 # exploration parameter + +feedback_types = ["mixI", "mixII"] # ["mixI", "mixII", "mixIII"] + + +############################################################################################### + + + + +rows = [] + +# Baselines: perfect/noisy expert + linear oracles +# (shows how to call other helpers without touching the file system) +# perfect expert +# r_exp, a_exp = run_expert(data, T, type="perfect_exp") +# rows.append(dict(mode="perfect_exp", delta=None, +# queries=0, avg_auto_reward=0.0, +# avg_total_reward=r_exp.mean())) +# # noisy expert +# r_exp, a_exp = run_expert(data, T, type="noisy_exp") +# rows.append(dict(mode="noisy_exp", delta=None, +# queries=0, avg_auto_reward=0.0, +# avg_total_reward=r_exp.mean())) +# # squared/logistic “oracle” (uses data['true_theta*']) +# r_or, a_or = run_linear_oracle(data, T, data["true_theta"]) +# rows.append(dict(mode="sq_oracle", delta=None, +# queries=0, avg_auto_reward=r_or.mean(), # same as total here +# avg_total_reward=r_or.mean())) +# r_or, a_or = run_linear_oracle(data, T, data["true_theta_classification"]) +# rows.append(dict(mode="lr_oracle", delta=None, +# queries=0, avg_auto_reward=r_or.mean(), +# avg_total_reward=r_or.mean())) + + + + +# MixUCB family (lin, mixI, mixII, mixIII) +for mode in feedback_types: + # For 'lin' there is no Δ list in the repo – it internally treats Δ as [0] (no query path). + _deltas = [0.0] if mode == "lin" else deltas + for delta in _deltas: + oracle = OnlineLogisticRegressionOracle( + n_features, n_actions, lr, lambda_, beta_lr, rad_sq=beta_sq + ) + r_t, q_t, a_t, expert_indices_per_timestep, total_rewards = run_mixucb( + data=data, + T=T, + n_actions=n_actions, + n_features=n_features, + reward_list_dict=reward_list_dict, + expert_types=expert_types, + delta=delta, + online_reg_oracle=oracle, + Q_t=Q_t, + gamma=gamma, + eta=eta, + mode=mode, + ) # returns reward_per_time, query_per_time, action_per_time + + rows.append(dict( + mode=mode, + delta=float(delta), + queries=int(q_t.sum()), + avg_auto_reward=avg_autonomous_reward(r_t, q_t), + avg_total_reward=r_t.mean(), + )) + + + # PLOT: + query_nums = [int(q_t[:i].sum()) for i in range(len(q_t))] + total_rewards = [avg_autonomous_reward(r_t[:i], q_t[:i]) for i in range(len(q_t))] + plot_query_reward_expertType( + query_nums=query_nums, + total_rewards=total_rewards, + expert_indices_per_timestep=expert_indices_per_timestep, + feedback_type=mode, + expert_types=expert_types, + delta=delta + ) + +df = pd.DataFrame(rows) +print(df) + +# Save a compact summary like your Excel sheet idea +out_path = Path("MixUCB_compare.xlsx") +df.to_excel(out_path, index=False) +print(f"Saved results -> {out_path.resolve()}") + +# (Optional) Tiny sanity plot +try: + import matplotlib.pyplot as plt + for mode in feedback_types: + sub = df[df["mode"] == mode] + xs = sub["delta"].fillna(0.0) + plt.plot(xs, sub["avg_total_reward"], marker="o", label=mode) + plt.xlabel("Δ"); plt.ylabel("Avg total reward"); plt.title("Quick comparison") + plt.legend(); plt.tight_layout(); plt.show() +except Exception as e: + print("Plot skipped:", e) + diff --git a/test_NOA_mixUCB_MetaChoice.py b/test_NOA_mixUCB_MetaChoice.py new file mode 100644 index 00000000..60b72a32 --- /dev/null +++ b/test_NOA_mixUCB_MetaChoice.py @@ -0,0 +1,280 @@ +# from generate_multilabel_data import generate_synthetic_data + + +# data = generate_synthetic_data(T=10, noise_std=0.2, seed=42) +# print(data) + + +from pathlib import Path +import numpy as np +import pandas as pd +import matplotlib.pyplot as plt + +from generate_multilabel_data import generate_synthetic_data +from run_allucb_NOA_mixUCB import run_mixucb, run_linear_oracle, run_expert # uses the repo’s run functions +from utils.regression_ucb import OnlineLogisticRegressionOracle # regression + UCB online oracle + + +def plot_query_reward( + query_nums, + rewards, + feedback_type, + expert_type, + delta, + *, + is_cumulative=True, # set False if query_nums are per-step counts already + smooth_window=20, # rolling mean window for rewards + show_query_markers=True +): + """ + query_nums : array-like + If is_cumulative=True, this is cumulative queries over time. + If is_cumulative=False, this is per-step query counts. + rewards : array-like + Per-step auto reward (not pre-averaged). + """ + + q = np.asarray(query_nums, dtype=float).ravel() + r = np.asarray(rewards, dtype=float).ravel() + T = min(len(q), len(r)) + q, r = q[:T], r[:T] + + # derive cumulative & per-step queries consistently + if is_cumulative: + cum_q = q + per_step_q = np.diff(np.r_[0.0, q]) + else: + per_step_q = q + cum_q = np.cumsum(q) + + # clamp any tiny negative diffs (numerical jitter) to zero + per_step_q = np.maximum(per_step_q, 0.0) + + # rolling mean for rewards + w = int(max(1, min(smooth_window, T))) + kernel = np.ones(w) / w + roll_mean = np.convolve(r, kernel, mode="same") + + # cumulative average reward + cum_avg = np.cumsum(r) / np.arange(1, T + 1) + + x = np.arange(T) + + plt.figure(figsize=(12, 5)) + + # -------- Left: queries -------- + ax1 = plt.subplot(1, 2, 1) + ax1.plot(x, cum_q, label="Cumulative Queries") + ax1.set_title("Cumulative & Per-Step Queries") + ax1.set_xlabel("Time Step") + ax1.set_ylabel("Cumulative") + + # ax1b = ax1.twinx() + # ax1b.plot(x, per_step_q, linestyle="--", beta_sq=0.8, label="Per-Step Queries") + # ax1b.set_ylabel("Per-Step") + + # combine legends from both axes + lines1, labels1 = ax1.get_legend_handles_labels() + # lines2, labels2 = ax1b.get_legend_handles_labels() + ax1.legend(lines1, labels1, loc="upper left") + + # -------- Right: rewards -------- + ax2 = plt.subplot(1, 2, 2) + # ax2.plot(x, r, beta_sq=0.5, label="Reward (per step)") + ax2.plot(x, roll_mean, linewidth=2, label=f"Rolling Mean (w={w})") + ax2.plot(x, cum_avg, linewidth=2, linestyle=":", label="Cumulative Average Auto Reward") + ax2.set_title("Auto Reward") + ax2.set_xlabel("Time Step") + ax2.set_ylabel("Reward") + ax2.legend(loc="best") + + # optional: show vertical markers where a query happened + if show_query_markers: + query_idxs = np.where(per_step_q > 0)[0] + for idx in query_idxs: + ax2.axvline(idx, beta_sq=0.15) + + plt.suptitle(f"Feedback: {feedback_type}, Expert: '{expert_type}', Δ={delta}", fontsize=14) + plt.tight_layout() + plt.show() + + +######################################################################################################## +######################################################################################################## + + +# --- config (edit freely) --- +T = 300 # timesteps to simulate (per run) +seed = 42 # numpy RNG seed +dataset = "synthetic" # "synthetic" | "spanet" | "heart_disease" | "MedNIST" +noise_std = 0.2 # only used for synthetic +deltas = [0.5, 0.75, 1.0] # query thresholds Δ +beta_sq = 1.25 # squared-loss radius (rad_sq) +beta_lr = 2.5 # log-loss radius +lambda_ = 1e-3 # L2 reg +lr = 0.1 # learning rate + +np.random.seed(seed) + +# --- get data dict exactly like the repo expects --- +if dataset == "synthetic": + data = generate_synthetic_data(T=1000, noise_std=noise_std, seed=seed) +elif dataset in ("heart_disease", "MedNIST", "yeast", "iris"): + # You can also generate these through generate_multilabel_data.py, + # but here we keep it simple and just re-use 'synthetic' for a quick demo. + raise ValueError("For non-synthetic datasets, generate a pickle via generate_multilabel_data.py and load it.") +else: + raise ValueError("Unknown dataset") + +# Infer shapes from the data +n_actions = len(data["rounds"][0]["actual_rewards"]) +n_features = data["rounds"][0]["context"].shape[1] + +def avg_autonomous_reward(rewards: np.ndarray, queries: np.ndarray) -> float: + """Average reward on steps where we did NOT query (Z_t = 0).""" + mask_no_query = (queries == 0).astype(int) + if mask_no_query.sum() == 0: + return 0.0 + return (rewards * mask_no_query).sum() / mask_no_query.sum() + + + +############################################################################################### + +#NOA: + + +def phi(x, a, K): + # Feature map + ea = np.zeros(K) + ea[a] = 1 + phi_val = np.kron(x, ea) + return phi_val # / np.linalg.norm(phi_val) # normalize + + +actions_set = list(range(n_actions)) + +# expert_types = ["compare", "demonstrate", "improve", "reward_punish", "off"] +expert_types = ["improve", "reward_punish", "off"] + +reward_list_dict = { + # "compare": lambda rewards, context: ( + # subset := oracle.get_ucb_lcb_subset(context, 2), + # [rewards[a] for a in subset if a in rewards] + # ), + # "demonstrate": lambda rewards, context: ( + # subset := actions_set, + # [rewards[a] for a in subset if a in rewards] + # ), + "improve": lambda rewards, context: ( + subset := oracle.get_ucb_lcb_subset(context, 1) + [max(rewards, key=rewards.get)], + [rewards[a] for a in subset if a in rewards] + ), + "reward_punish": lambda rewards, context: ( + subset := oracle.get_ucb_lcb_subset(context, 1) + [max(rewards, key=rewards.get)], + [-1,1] #-1 for robot, +1 for expert + ), + "off": lambda rewards, context: ( + subset := oracle.get_ucb_lcb_subset(context, 1) + [0], #define external "off" action as: 0 + [rewards[a] for a in subset if a in rewards] + ) +} + + +############################################################################################### + + + + +rows = [] + +# Baselines: perfect/noisy expert + linear oracles +# (shows how to call other helpers without touching the file system) +# perfect expert +# r_exp, a_exp = run_expert(data, T, type="perfect_exp") +# rows.append(dict(mode="perfect_exp", delta=None, +# queries=0, avg_auto_reward=0.0, +# avg_total_reward=r_exp.mean())) +# # noisy expert +# r_exp, a_exp = run_expert(data, T, type="noisy_exp") +# rows.append(dict(mode="noisy_exp", delta=None, +# queries=0, avg_auto_reward=0.0, +# avg_total_reward=r_exp.mean())) +# # squared/logistic “oracle” (uses data['true_theta*']) +# r_or, a_or = run_linear_oracle(data, T, data["true_theta"]) +# rows.append(dict(mode="sq_oracle", delta=None, +# queries=0, avg_auto_reward=r_or.mean(), # same as total here +# avg_total_reward=r_or.mean())) +# r_or, a_or = run_linear_oracle(data, T, data["true_theta_classification"]) +# rows.append(dict(mode="lr_oracle", delta=None, +# queries=0, avg_auto_reward=r_or.mean(), +# avg_total_reward=r_or.mean())) + + + + +# MixUCB family (lin, mixI, mixII, mixIII) +for expert_type in expert_types: + for mode in ["lin", "mixI", "mixII", "mixIII"]: + # For 'lin' there is no Δ list in the repo – it internally treats Δ as [0] (no query path). + _deltas = [0.0] if mode == "lin" else deltas + for delta in _deltas: + oracle = OnlineLogisticRegressionOracle( + n_features, n_actions, lr, lambda_, beta_lr, rad_sq=beta_sq + ) + r_t, q_t, a_t = run_mixucb( + data=data, + T=T, + n_actions=n_actions, + n_features=n_features, + reward_list_dict=reward_list_dict, + expert_type=expert_type, + delta=delta, + online_reg_oracle=oracle, + mode=mode, + ) # returns reward_per_time, query_per_time, action_per_time + + rows.append(dict( + mode=mode, + delta=float(delta), + queries=int(q_t.sum()), + avg_auto_reward=avg_autonomous_reward(r_t, q_t), + avg_total_reward=r_t.mean(), + )) + + + # PLOT: + query_nums = [int(q_t[:i].sum()) for i in range(len(q_t))] + total_auto_rewards = [avg_autonomous_reward(r_t[:i], q_t[:i]) for i in range(len(q_t))] + feedback_type = mode + expert_type = expert_type + plot_query_reward(query_nums, # cumulative or per-step; set is_cumulative accordingly + total_auto_rewards, # per-step rewards array + feedback_type, + expert_type, + delta, + is_cumulative=True, # flip to False if passing per-step counts + smooth_window=25, # tweak as you like + show_query_markers=False + ) + +df = pd.DataFrame(rows) +print(df) + +# Save a compact summary like your Excel sheet idea +out_path = Path("MixUCB_compare.xlsx") +df.to_excel(out_path, index=False) +print(f"Saved results -> {out_path.resolve()}") + +# (Optional) Tiny sanity plot +try: + import matplotlib.pyplot as plt + for mode in ["lin", "mixI", "mixII", "mixIII"]: + sub = df[df["mode"] == mode] + xs = sub["delta"].fillna(0.0) + plt.plot(xs, sub["avg_total_reward"], marker="o", label=mode) + plt.xlabel("Δ"); plt.ylabel("Avg total reward"); plt.title("Quick comparison") + plt.legend(); plt.tight_layout(); plt.show() +except Exception as e: + print("Plot skipped:", e) + diff --git a/utils/regression_ucb.py b/utils/regression_ucb.py index 748f3934..9afff8a9 100644 --- a/utils/regression_ucb.py +++ b/utils/regression_ucb.py @@ -45,6 +45,20 @@ def get_ucb_lcb(self, context): lcb.append(theta_a.dot(context) - sigma_a) return np.array(ucb), np.array(lcb) + def get_ucb_lcb_subset(self, context, subset_size): + context = context.reshape(-1) + ucb_scores = [] + for a in range(self.n_actions): + theta_a = inv(self.A[a]).dot(self.b[a]) + sigma_a = self.alpha * np.sqrt(context.dot(inv(self.A[a]).dot(context))) + ucb = theta_a.dot(context) + sigma_a + ucb_scores.append((a, ucb)) + # Sort actions by UCB (descending), take top-k + sorted_actions = sorted(ucb_scores, key=lambda tup: -tup[1]) + top_k = [a for a, _ in sorted_actions[:subset_size]] + return top_k + + class CombinedLinearModel(BaseEstimator, ClassifierMixin): def __init__(self, input_dim, output_dim, lr=0.01, weight_decay=0.01, epochs=1000, tol=1e-4): @@ -114,6 +128,8 @@ def predict_proba(self, X): outputs = self.model(X_tensor) return torch.softmax(outputs, dim=1).detach().numpy() + + class OnlineLogisticRegressionOracle: def __init__(self, n_features, n_actions, learning_rate, reg_coeff, rad_log, rad_sq=None, max_epochs=1000, tol=1e-4): self.model = CombinedLinearModel(n_features, n_actions, lr=learning_rate, weight_decay=reg_coeff/2, epochs=max_epochs, tol=tol) @@ -176,3 +192,19 @@ def get_ucb_lcb(self, context): ucb.append(theta[a].dot(context) + sigma) lcb.append(theta[a].dot(context) - sigma) return np.array(ucb), np.array(lcb) + + + def get_ucb_lcb_subset(self, context, subset_size): + context = context.reshape(-1) + ucb_scores = [] + theta, X_sum, A_sum = self.get_optimization_parameters() + # TODO also implement separate CI + combined_cov = [X_sum / self.beta_log**2 + A / self.beta_sq**2 for A in A_sum] + for a in range(self.n_actions): + sigma = np.sqrt(context.dot(inv(combined_cov[a]).dot(context))) + ucb = theta[a].dot(context) + sigma + ucb_scores.append((a, ucb)) + # Sort actions by UCB (descending), take top-k + sorted_actions = sorted(ucb_scores, key=lambda tup: -tup[1]) + top_k = [a for a, _ in sorted_actions[:subset_size]] + return top_k \ No newline at end of file From 7769a0c2df1e3ebbc0c1eca723f4b6b00caf14d2 Mon Sep 17 00:00:00 2001 From: noakaplan675 Date: Mon, 18 Aug 2025 22:22:29 -0400 Subject: [PATCH 2/3] added MixUCB with MetaChoice --- MixUCB_compare.xlsx | Bin 5838 -> 5261 bytes run_allucb_NOA_MetaChoice.py | 397 ++++++++++++++++++++++++++++++++++ test_NOA_mixUCB_Exp4.py | 26 +-- test_NOA_mixUCB_MetaChoice.py | 235 +++++++++++++------- 4 files changed, 565 insertions(+), 93 deletions(-) create mode 100644 run_allucb_NOA_MetaChoice.py diff --git a/MixUCB_compare.xlsx b/MixUCB_compare.xlsx index d1838b041fa2a1441605a5666ccaaa89b76aff4f..2da9829bec6c2aa85c3cc2dc63d8173e54057329 100644 GIT binary patch delta 1281 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 KCBEomCg4Bu7D1H& diff --git a/run_allucb_NOA_MetaChoice.py b/run_allucb_NOA_MetaChoice.py new file mode 100644 index 00000000..1d63bbdb --- /dev/null +++ b/run_allucb_NOA_MetaChoice.py @@ -0,0 +1,397 @@ +#!/usr/bin/env python3 +import numpy as np +import pickle +from utils.regression_ucb import MixUCB, OnlineLogisticRegressionOracle +import argparse +from tqdm import tqdm +import logging +import os +import time +from icecream import ic +import argparse + +logging.basicConfig(filename='simulation.log', level=logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s') + + +######################################################################################## +######################################################################################## + +#NOA: + +def get_theta_star(d, K): + theta_star = {a: np.random.randn(d) for a in range(K)} + #normalize: + theta_star = {a: v / np.linalg.norm(v) for a, v in theta_star.items()} + return theta_star + +def f_star_Linear(x, a, theta_star): + # Linear Function Model (for synthetic experiments) + x = x / np.linalg.norm(x) # normalize + return np.dot(x, theta_star[a]) # theta_star is a dict of parameter vectors + +def f_star_Linear_noisy(x, a, theta_star, sigma=0.2, rng=None): + x = np.asarray(x, float) + x /= (np.linalg.norm(x) + 1e-12) # safe normalize + mu = float(np.dot(x, np.asarray(theta_star[a], float))) + if rng is None: rng = np.random.default_rng() + return mu + rng.normal(0.0, sigma) # noisy reward + +def query_expert(x_t, A, f_star, theta_star, feedback_type, reward_list_dict, expert_type, alpha_boltz=0.1, noise_std=0.0): + """ + Query a simulated expert based on MixUCB framework. + """ + # Compute true expected rewards + rewards = {a: f_star(x_t, a, theta_star) for a in A} + + action_set, reward_list = reward_list_dict[expert_type](rewards,x_t) # reward_list_dict[expert_type] is a function that gets the action set and reward list using get_ucb_lcb_subset (that has V_sq) + boltzmann_prob = np.exp(alpha_boltz * np.array(reward_list)) / np.sum(np.exp(alpha_boltz * np.array(reward_list))) + a_tilde = np.random.choice(action_set, p=boltzmann_prob) + if feedback_type == "mixI": + return a_tilde, None + if feedback_type == "mixII": + reward = rewards[a_tilde] + np.random.normal(0, noise_std) + return a_tilde, reward + if feedback_type == "mixIII": + # r_tilde = {a: r + np.random.normal(0, noise_std) for a, r in rewards.items()} + r_tilde = [r + np.random.normal(0, noise_std) for a, r in rewards.items()] + return a_tilde, r_tilde + return None, None + + + +def meta_choose_expert_type(x_t, A, f_star, theta_star, expert_types, reward_list_dict, beta_meta, w_t, delta, expert_indices_per_timestep): + expected_rewards = [] + rewards = {a: f_star(x_t, a, theta_star) for a in A} + for et in expert_types: + _, rewards_list = reward_list_dict[et](rewards,x_t) + if len(rewards_list) == 0: + expected_rewards.append(-np.inf) # avoid division by 0 + else: + expected_rewards.append(np.mean(rewards_list)) # average reward for this expert type + + # Convert to Boltzmann prob: + exp_vals = np.exp(beta_meta * np.array(expected_rewards)) + probs = exp_vals / np.sum(exp_vals) + expert_choice = np.random.choice(expert_types, p=probs) + expert_indices_per_timestep.append(expert_types.index(expert_choice) if w_t >= delta else -1) + return expert_choice, expert_indices_per_timestep + + +############################################################################################ +############################################################################################ + +def run_mixucb(data, T, n_actions, n_features, reward_list_dict, expert_types, delta, online_reg_oracle, gamma, eta, beta_meta, mode=None): + assert mode in ['lin','mixI','mixII','mixIII'] + rationality = 1 + reward_per_time = np.zeros(T) + query_per_time = np.zeros(T) + action_per_time = [] + + data_len = len(data["rounds"]) + permutation = np.arange(data_len, dtype=int) + + theta_star = get_theta_star(n_features,n_actions) + + # init expert type per timestep: + expert_indices_per_timestep = [] + total_rewards = [] + total_reward = 0 + for i in tqdm(range(T)): + logging.info(f'Running UCB {mode} - round: {i}') + + # Compute data index if i > T + # (NOTE: np.random.shuffle is already seeded in the main block.) + if i == 0: + data_ind = i + else: + # if the data length is less than T, we loop over a randomly shuffled permutation of the data. + ind = i % data_len + if ind == 0: + np.random.shuffle(permutation) + data_ind = permutation[ind] + + # # Load pre-generated context and rewards for the current round + # context = data["rounds"][data_ind]["context"] + # # expected vs actual rewards + # expected_rewards = data["rounds"][data_ind]["expected_rewards"] # empty for classification datasets + # actual_rewards = data["rounds"][data_ind]["actual_rewards"] + # # noisy expert choice. + # noisy_expert_choice = data["rounds"][data_ind]["noisy_expert_choice"] + + # NOA: + context = np.random.randn(n_features) + # Calculate UCB and LCB + ucb,lcb = online_reg_oracle.get_ucb_lcb(context) + action_hat = np.argmax(ucb) + + actions_set = list(range(n_actions)) + expected_rewards = [f_star_Linear_noisy(context, a, theta_star) for a in actions_set] + actual_rewards = [f_star_Linear(context, a, theta_star) for a in actions_set] + noisy_expert_choice = 0 + + if mode in ['mixI', 'mixII', 'mixIII']: + # Determine if querying expert or not + width = ucb - lcb + width_Ahat = width[action_hat] + # Print i, action_hat, width_Ahat, delta. + logging.info(f'Round {i}, action_hat: {action_hat}, width_Ahat: {width_Ahat}, delta: {delta}') + + # Meta choice: Sample expert + expert_type, expert_indices_per_timestep = meta_choose_expert_type(context, actions_set, f_star_Linear, theta_star, expert_types, reward_list_dict, beta_meta, width_Ahat, delta, expert_indices_per_timestep) + + if width_Ahat > delta: + # query expert and update online regression + query_per_time[i] = 1 + + if mode == 'mixIII': + if len(expected_rewards) == 0: + expert_action = np.argmax(actual_rewards) + else: + expert_action = np.argmax(expected_rewards) + else: + if len(expected_rewards) == 0: + expert_action = np.argmax(actual_rewards) + else: + # Here we need to insert your action choice based on expert feedback + expert_action, _ = query_expert(context, actions_set, f_star_Linear, theta_star, mode, reward_list_dict, expert_type, alpha_boltz=0.1, noise_std=0.1) + reward = actual_rewards[expert_action] + + if mode == 'mixIII': + if len(expected_rewards) == 0: + online_reg_oracle.update(context,rewards=actual_rewards) + else: + online_reg_oracle.update(context,rewards=expected_rewards) + elif mode == 'mixII': + online_reg_oracle.update(context, action=expert_action) + online_reg_oracle.update(context, action=expert_action, reward=reward) + elif mode == 'mixI': + online_reg_oracle.update(context, action=expert_action) + else: + # take action_hat and update online regression + reward = actual_rewards[action_hat] + online_reg_oracle.update(context, action=action_hat, reward=reward) + + else: + # Print i, action_hat, width_Ahat, delta. + logging.info(f'Round {i}, action_hat: {action_hat}') + reward = actual_rewards[action_hat] + online_reg_oracle.update(context, action=action_hat, reward=reward) + + reward_per_time[i] = reward + + if query_per_time[i]: + action_per_time.append(expert_action) + else: + action_per_time.append(action_hat) + + logging.info(f'{mode} UCB: reward {reward}, query: {query_per_time[i]}, totalq: {np.sum(query_per_time)}') + + total_reward += reward if reward else f_star_Linear(context, action_per_time[i], theta_star) + np.random.normal(0, 0.1) + total_rewards.append(total_reward / (i + 1) if i > 0 else 0) + + return reward_per_time, query_per_time, action_per_time, expert_indices_per_timestep, total_rewards + + +def run_linear_oracle(data, T, theta): + reward_per_time = np.zeros(T) + action_per_time = [] + + data_len = len(data["rounds"]) + permutation = np.arange(data_len, dtype=int) + + for i in tqdm(range(T)): + logging.info(f'Running linear oracle - round: {i}') + + # Compute data index if i > T + # (NOTE: np.random.shuffle is already seeded in the main block.) + if i == 0: + data_ind = i + else: + ind = i % data_len + if ind == 0: + np.random.shuffle(permutation) + data_ind = permutation[ind] + + # Load pre-generated context and rewards for the current round + context = data["rounds"][data_ind]["context"] + + actual_rewards = data["rounds"][data_ind]["actual_rewards"] + + est_rewards = np.dot(theta, context.ravel()) + action = np.argmax(est_rewards) + + reward = actual_rewards[action] + reward_per_time[i] = reward + action_per_time.append(action) + + logging.info(f'oracle: reward {reward}') + + return reward_per_time, action_per_time + + pass + +def run_expert(data, T, type='perfect_exp'): + """ + Runs the expert algorithm for T rounds (either perfect or noisy). + """ + reward_per_time = np.zeros(T) + action_per_time = [] + + data_len = len(data["rounds"]) + permutation = np.arange(data_len, dtype=int) + + for i in tqdm(range(T)): + logging.info(f'Running expert type {type} - round: {i}') + + # Compute data index if i > T + # (NOTE: np.random.shuffle is already seeded in the main block.) + if i == 0: + data_ind = i + else: + ind = i % data_len + if ind == 0: + np.random.shuffle(permutation) + data_ind = permutation[ind] + + # Load pre-generated expected and actual rewards for the current round + expected_rewards = data["rounds"][data_ind]["expected_rewards"] + actual_rewards = data["rounds"][data_ind]["actual_rewards"] + # noisy expert choice. + noisy_expert_choice = data["rounds"][data_ind]["noisy_expert_choice"] + + # Select either the perfect or noisy expert action based on the type. + # Identical to logic in run_mixucb for MixUCB-I/II/III expert logic. + if type == 'perfect_exp': + # Same as MixUCB-III expert logic + if len(expected_rewards) == 0: + expert_action = np.argmax(actual_rewards) + else: + expert_action = np.argmax(expected_rewards) + elif type == 'noisy_exp': + # Same as MixUCB-I/II expert logic. + if len(expected_rewards) == 0: + expert_action = np.argmax(actual_rewards) + else: + expert_action = noisy_expert_choice + + reward = actual_rewards[expert_action] + reward_per_time[i] = reward + action_per_time.append(expert_action) + + logging.info(f'expert: reward {reward}') + + return reward_per_time, action_per_time + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Run UCB Baseline + oracles + experts.') + parser.add_argument('--mode', type=str, default='lin', help='must be: lin, mixI, mixII, mixIII, sq_oracle, lr_oracle, perfect_exp, noisy_exp') + parser.add_argument('--T', type=int, default=0) + parser.add_argument('--delta', nargs='+', type=float, default=[4., 5., 6., 7., 8.]) + parser.add_argument('--lambda_', type=float, default=0.001, help='regularization weight') + parser.add_argument('--pickle_file', type=str, default='simulation_data.pkl', help='Path to the pickle file containing pre-generated data') + parser.add_argument('--seed', type=int, default=42, help='Random seed for reproducibility') + parser.add_argument("--data_name", type=str, default='', help="Name of the dataset to use.") + parser.add_argument('--learning_rate', type=float, default=0.1) + parser.add_argument('--alpha', type=float, default=100, help='squared loss confidence radius') + parser.add_argument('--beta', type=float, default=1000, help='log loss confidence radius') + + args = parser.parse_args() + + # Set random seed for reproducibility + np.random.seed(args.seed) + + # Load pre-generated data from the pickle file + with open(args.pickle_file, 'rb') as f: + data = pickle.load(f) + + # Extract n_actions and n_features from the data + n_actions = len(data["rounds"][0]["actual_rewards"]) + n_features = data["rounds"][0]["context"].shape[1] + # Extract the number of rounds (T) from the data + T = args.T if args.T > 0 else len(data["rounds"]) + + # Initialize parameters + delta_list = args.delta + alpha = args.alpha + beta = args.beta + lambda_ = args.lambda_ + learning_rate = args.learning_rate + data_name = args.data_name + mode = args.mode + seed = args.seed + + if mode in ['sq_oracle', 'lr_oracle']: + results = os.path.join(data_name, f"seed_{seed:02d}", '{}_results'.format(mode)) + os.makedirs(results, exist_ok=True) + print('Makedir {}'.format(results)) + + if mode == 'sq_oracle': + theta = data['true_theta'] + else: + theta = data['true_theta_classification'] + + # Run using the pre-generated data + reward_per_time, action_per_time = run_linear_oracle(data, T, theta) + + print(f"Finished running {mode} for {T} rounds.") + + pkl_name = os.path.join(results, f'{time.strftime("%Y%m%d_%H%M%S")}.pkl') + dict_to_save = { + 'reward_per_time': reward_per_time, + 'action_per_time': action_per_time, + 'delta_list': delta_list + } + with open(pkl_name, 'wb') as f: + pickle.dump(dict_to_save, f) + print('Saved to {}'.format(pkl_name)) + + elif mode in ['perfect_exp', 'noisy_exp']: + results = os.path.join(data_name, f"seed_{seed:02d}", '{}_results'.format(mode)) + os.makedirs(results, exist_ok=True) + print('Makedir {}'.format(results)) + + reward_per_time, action_per_time = run_expert(data, T, type=mode) + + print(f"Finished running {mode} for {T} rounds.") + + pkl_name = os.path.join(results, f'{time.strftime("%Y%m%d_%H%M%S")}.pkl') + dict_to_save = { + 'reward_per_time': reward_per_time, + 'action_per_time': action_per_time, + 'delta_list': delta_list + } + with open(pkl_name, 'wb') as f: + pickle.dump(dict_to_save, f) + print('Saved to {}'.format(pkl_name)) + + else: + if mode == 'lin': + delta_list = [0] + + for delta in delta_list: + results = os.path.join(data_name, f"seed_{seed:02d}", '{}_ucb_results'.format(mode), '{}'.format(delta)) + os.makedirs(results, exist_ok=True) + print('Makedir {}'.format(results)) + + online_reg_oracle = OnlineLogisticRegressionOracle(n_features, n_actions, learning_rate, lambda_, beta, rad_sq=alpha) + + # Run using the pre-generated data + reward_per_time, query_per_time, action_per_time = run_mixucb(data, T, n_actions, n_features, delta, online_reg_oracle, mode=mode) + + print(f"Finished running {mode} UCB for {T} rounds.") + + pkl_name = os.path.join(results, f'{time.strftime("%Y%m%d_%H%M%S")}.pkl') + dict_to_save = { + 'reward_per_time': reward_per_time, + 'query_per_time': query_per_time, + 'action_per_time': action_per_time, + 'alpha': args.alpha, + 'beta': args.beta, + 'lambda_': args.lambda_, + 'delta_list': delta_list + } + with open(pkl_name, 'wb') as f: + pickle.dump(dict_to_save, f) + print('Saved to {}'.format(pkl_name)) diff --git a/test_NOA_mixUCB_Exp4.py b/test_NOA_mixUCB_Exp4.py index 7344b02c..ebcf7931 100644 --- a/test_NOA_mixUCB_Exp4.py +++ b/test_NOA_mixUCB_Exp4.py @@ -11,7 +11,7 @@ import matplotlib.pyplot as plt from generate_multilabel_data import generate_synthetic_data -from run_allucb_NOA_Exp4 import run_mixucb, run_linear_oracle, run_expert # uses the repo’s run functions +from run_allucb_NOA_Exp4 import run_mixucb # uses the repo’s run functions from utils.regression_ucb import OnlineLogisticRegressionOracle # regression + UCB online oracle from matplotlib.collections import LineCollection from matplotlib.lines import Line2D @@ -103,7 +103,7 @@ def plot_query_reward_expertType( feedback_type, expert_types, delta, - plot_title="Expert Usage Over Time" + plot_title="EXP4: Expert Usage Over Time" ): """ Styled to match newer plot_query_reward code. @@ -220,18 +220,18 @@ def phi(x, a, K): actions_set = list(range(n_actions)) -# expert_types = ["compare", "demonstrate", "improve", "reward_punish", "off"] -expert_types = ["improve", "reward_punish", "off"] +expert_types = ["compare", "demonstrate", "improve", "reward_punish", "off"] +# expert_types = ["improve", "reward_punish", "off"] reward_list_dict = { - # "compare": lambda rewards, context: ( - # subset := oracle.get_ucb_lcb_subset(context, 2), - # [rewards[a] for a in subset if a in rewards] - # ), - # "demonstrate": lambda rewards, context: ( - # subset := actions_set, - # [rewards[a] for a in subset if a in rewards] - # ), + "compare": lambda rewards, context: ( + subset := oracle.get_ucb_lcb_subset(context, 2), + [rewards[a] for a in subset if a in rewards] + ), + "demonstrate": lambda rewards, context: ( + subset := actions_set, + [rewards[a] for a in subset if a in rewards] + ), "improve": lambda rewards, context: ( subset := oracle.get_ucb_lcb_subset(context, 1) + [max(rewards, key=rewards.get)], [rewards[a] for a in subset if a in rewards] @@ -249,7 +249,6 @@ def phi(x, a, K): M = len(expert_types) -Q_t = np.ones(M) / M eta = 0.1 # learning rate gamma = 0.01 # exploration parameter @@ -297,6 +296,7 @@ def phi(x, a, K): oracle = OnlineLogisticRegressionOracle( n_features, n_actions, lr, lambda_, beta_lr, rad_sq=beta_sq ) + Q_t = np.ones(M) / M r_t, q_t, a_t, expert_indices_per_timestep, total_rewards = run_mixucb( data=data, T=T, diff --git a/test_NOA_mixUCB_MetaChoice.py b/test_NOA_mixUCB_MetaChoice.py index 60b72a32..f35d33d0 100644 --- a/test_NOA_mixUCB_MetaChoice.py +++ b/test_NOA_mixUCB_MetaChoice.py @@ -11,8 +11,10 @@ import matplotlib.pyplot as plt from generate_multilabel_data import generate_synthetic_data -from run_allucb_NOA_mixUCB import run_mixucb, run_linear_oracle, run_expert # uses the repo’s run functions +from run_allucb_NOA_MetaChoice import run_mixucb # uses the repo’s run functions from utils.regression_ucb import OnlineLogisticRegressionOracle # regression + UCB online oracle +from matplotlib.collections import LineCollection +from matplotlib.lines import Line2D def plot_query_reward( @@ -22,11 +24,15 @@ def plot_query_reward( expert_type, delta, *, - is_cumulative=True, # set False if query_nums are per-step counts already - smooth_window=20, # rolling mean window for rewards + is_cumulative=True, + smooth_window=20, show_query_markers=True ): """ + Plot query count (cumulative and per-step) and auto reward (rolling and cumulative average). + + Parameters + ---------- query_nums : array-like If is_cumulative=True, this is cumulative queries over time. If is_cumulative=False, this is per-step query counts. @@ -39,7 +45,7 @@ def plot_query_reward( T = min(len(q), len(r)) q, r = q[:T], r[:T] - # derive cumulative & per-step queries consistently + # Convert queries to cumulative and per-step if is_cumulative: cum_q = q per_step_q = np.diff(np.r_[0.0, q]) @@ -47,58 +53,118 @@ def plot_query_reward( per_step_q = q cum_q = np.cumsum(q) - # clamp any tiny negative diffs (numerical jitter) to zero - per_step_q = np.maximum(per_step_q, 0.0) + per_step_q = np.maximum(per_step_q, 0.0) # avoid tiny negative jitter - # rolling mean for rewards + # Rolling mean w = int(max(1, min(smooth_window, T))) kernel = np.ones(w) / w roll_mean = np.convolve(r, kernel, mode="same") - # cumulative average reward + # Cumulative average cum_avg = np.cumsum(r) / np.arange(1, T + 1) - x = np.arange(T) plt.figure(figsize=(12, 5)) - # -------- Left: queries -------- + # -------- Left: cumulative queries -------- ax1 = plt.subplot(1, 2, 1) - ax1.plot(x, cum_q, label="Cumulative Queries") + ax1.plot(x, cum_q, label="Cumulative Queries", color="tab:blue", linewidth=2) ax1.set_title("Cumulative & Per-Step Queries") ax1.set_xlabel("Time Step") - ax1.set_ylabel("Cumulative") - - # ax1b = ax1.twinx() - # ax1b.plot(x, per_step_q, linestyle="--", beta_sq=0.8, label="Per-Step Queries") - # ax1b.set_ylabel("Per-Step") + ax1.set_ylabel("Cumulative Queries") + ax1.grid(True) + ax1.legend(loc="upper left") - # combine legends from both axes - lines1, labels1 = ax1.get_legend_handles_labels() - # lines2, labels2 = ax1b.get_legend_handles_labels() - ax1.legend(lines1, labels1, loc="upper left") - - # -------- Right: rewards -------- + # -------- Right: reward curves -------- ax2 = plt.subplot(1, 2, 2) - # ax2.plot(x, r, beta_sq=0.5, label="Reward (per step)") - ax2.plot(x, roll_mean, linewidth=2, label=f"Rolling Mean (w={w})") - ax2.plot(x, cum_avg, linewidth=2, linestyle=":", label="Cumulative Average Auto Reward") + ax2.plot(x, roll_mean, linewidth=2, label=f"Rolling Mean (w={w})", color="tab:orange") + ax2.plot(x, cum_avg, linewidth=2, linestyle=":", label="Cumulative Average Reward", color="tab:green") ax2.set_title("Auto Reward") ax2.set_xlabel("Time Step") ax2.set_ylabel("Reward") + ax2.grid(True) ax2.legend(loc="best") - # optional: show vertical markers where a query happened + # optional: vertical lines at query steps if show_query_markers: query_idxs = np.where(per_step_q > 0)[0] for idx in query_idxs: - ax2.axvline(idx, beta_sq=0.15) + ax2.axvline(idx, alpha=0.15, color="gray", linestyle="--") plt.suptitle(f"Feedback: {feedback_type}, Expert: '{expert_type}', Δ={delta}", fontsize=14) plt.tight_layout() plt.show() +def plot_query_reward_expertType( + query_nums, + total_rewards, + expert_indices_per_timestep, + feedback_type, + expert_types, + delta, + plot_title="MetaChoice: Expert Usage Over Time" +): + """ + Styled to match newer plot_query_reward code. + + Parameters: + - query_nums: list or array, cumulative number of queries + - total_rewards: list or array, total reward at each timestep + - expert_indices_per_timestep: list of ints, index of expert used at each timestep (or -1 for autonomous) + - feedback_type: str, e.g. "I" or "II" + - expert_types: list of str, names of expert types (must align with expert_indices) + - delta: float, the querying threshold + - plot_title: str, plot title prefix + """ + + # Colors + M = len(expert_types) + cmap = plt.get_cmap("tab10") + expert_colors = {i: cmap(i) for i in range(M)} + expert_colors[-1] = "gray" + + # Segment line by expert index + y = np.array(total_rewards) + x = np.arange(len(y)) + points = np.array([x, y]).T.reshape(-1, 1, 2) + segments = np.concatenate([points[:-1], points[1:]], axis=1) + colors = [expert_colors.get(expert_indices_per_timestep[t], "gray") for t in range(len(segments))] + lc = LineCollection(segments, colors=colors, linewidths=2) + + # Plot + plt.figure(figsize=(12, 5)) + + # Subplot 1: cumulative queries + plt.subplot(1, 2, 1) + plt.plot(query_nums) + plt.title("Cumulative Queries") + plt.xlabel("Time Step") + plt.ylabel("Number of Queries") + + # Subplot 2: reward over time (expert-colored) + ax2 = plt.subplot(1, 2, 2) + ax2.add_collection(lc) + ax2.set_xlim(x.min(), x.max()) + ax2.set_ylim(y.min(), y.max()) + ax2.set_title("Total Reward Over Time (Color = Expert)") + ax2.set_xlabel("Time Step") + ax2.set_ylabel("Total Reward") + + # Add legend manually + legend_elements = [Line2D([0], [0], color="gray", lw=2, label="Autonomous (no expert)")] + for i, name in enumerate(expert_types): + legend_elements.append(Line2D([0], [0], color=expert_colors[i], lw=2, label=name)) + + ax2.legend(handles=legend_elements, loc="lower right", fontsize=9) + + # Unified title and layout + plt.suptitle(f"{plot_title} — Feedback: {feedback_type}, Δ={delta}", fontsize=14) + plt.tight_layout() + plt.show() + + + ######################################################################################################## ######################################################################################################## @@ -154,18 +220,18 @@ def phi(x, a, K): actions_set = list(range(n_actions)) -# expert_types = ["compare", "demonstrate", "improve", "reward_punish", "off"] -expert_types = ["improve", "reward_punish", "off"] +expert_types = ["compare", "demonstrate", "improve", "reward_punish", "off"] +# expert_types = ["improve", "reward_punish", "off"] reward_list_dict = { - # "compare": lambda rewards, context: ( - # subset := oracle.get_ucb_lcb_subset(context, 2), - # [rewards[a] for a in subset if a in rewards] - # ), - # "demonstrate": lambda rewards, context: ( - # subset := actions_set, - # [rewards[a] for a in subset if a in rewards] - # ), + "compare": lambda rewards, context: ( + subset := oracle.get_ucb_lcb_subset(context, 2), + [rewards[a] for a in subset if a in rewards] + ), + "demonstrate": lambda rewards, context: ( + subset := actions_set, + [rewards[a] for a in subset if a in rewards] + ), "improve": lambda rewards, context: ( subset := oracle.get_ucb_lcb_subset(context, 1) + [max(rewards, key=rewards.get)], [rewards[a] for a in subset if a in rewards] @@ -181,6 +247,16 @@ def phi(x, a, K): } + +M = len(expert_types) + +eta = 0.1 # learning rate +gamma = 0.01 # exploration parameter +beta_meta = 3.0 # meta-rationality parameter + +feedback_types = ["mixI", "mixII"] # ["mixI", "mixII", "mixIII"] + + ############################################################################################### @@ -214,49 +290,48 @@ def phi(x, a, K): # MixUCB family (lin, mixI, mixII, mixIII) -for expert_type in expert_types: - for mode in ["lin", "mixI", "mixII", "mixIII"]: - # For 'lin' there is no Δ list in the repo – it internally treats Δ as [0] (no query path). - _deltas = [0.0] if mode == "lin" else deltas - for delta in _deltas: - oracle = OnlineLogisticRegressionOracle( - n_features, n_actions, lr, lambda_, beta_lr, rad_sq=beta_sq +for mode in feedback_types: + # For 'lin' there is no Δ list in the repo – it internally treats Δ as [0] (no query path). + _deltas = [0.0] if mode == "lin" else deltas + for delta in _deltas: + oracle = OnlineLogisticRegressionOracle( + n_features, n_actions, lr, lambda_, beta_lr, rad_sq=beta_sq + ) + r_t, q_t, a_t, expert_indices_per_timestep, total_rewards = run_mixucb( + data=data, + T=T, + n_actions=n_actions, + n_features=n_features, + reward_list_dict=reward_list_dict, + expert_types=expert_types, + delta=delta, + online_reg_oracle=oracle, + gamma=gamma, + eta=eta, + beta_meta=beta_meta, + mode=mode, + ) # returns reward_per_time, query_per_time, action_per_time + + rows.append(dict( + mode=mode, + delta=float(delta), + queries=int(q_t.sum()), + avg_auto_reward=avg_autonomous_reward(r_t, q_t), + avg_total_reward=r_t.mean(), + )) + + + # PLOT: + query_nums = [int(q_t[:i].sum()) for i in range(len(q_t))] + total_rewards = [avg_autonomous_reward(r_t[:i], q_t[:i]) for i in range(len(q_t))] + plot_query_reward_expertType( + query_nums=query_nums, + total_rewards=total_rewards, + expert_indices_per_timestep=expert_indices_per_timestep, + feedback_type=mode, + expert_types=expert_types, + delta=delta ) - r_t, q_t, a_t = run_mixucb( - data=data, - T=T, - n_actions=n_actions, - n_features=n_features, - reward_list_dict=reward_list_dict, - expert_type=expert_type, - delta=delta, - online_reg_oracle=oracle, - mode=mode, - ) # returns reward_per_time, query_per_time, action_per_time - - rows.append(dict( - mode=mode, - delta=float(delta), - queries=int(q_t.sum()), - avg_auto_reward=avg_autonomous_reward(r_t, q_t), - avg_total_reward=r_t.mean(), - )) - - - # PLOT: - query_nums = [int(q_t[:i].sum()) for i in range(len(q_t))] - total_auto_rewards = [avg_autonomous_reward(r_t[:i], q_t[:i]) for i in range(len(q_t))] - feedback_type = mode - expert_type = expert_type - plot_query_reward(query_nums, # cumulative or per-step; set is_cumulative accordingly - total_auto_rewards, # per-step rewards array - feedback_type, - expert_type, - delta, - is_cumulative=True, # flip to False if passing per-step counts - smooth_window=25, # tweak as you like - show_query_markers=False - ) df = pd.DataFrame(rows) print(df) @@ -269,7 +344,7 @@ def phi(x, a, K): # (Optional) Tiny sanity plot try: import matplotlib.pyplot as plt - for mode in ["lin", "mixI", "mixII", "mixIII"]: + for mode in feedback_types: sub = df[df["mode"] == mode] xs = sub["delta"].fillna(0.0) plt.plot(xs, sub["avg_total_reward"], marker="o", label=mode) From afc46d8be33f39b51c344fd11b61b789cba536e3 Mon Sep 17 00:00:00 2001 From: noakaplan675 Date: Sat, 23 Aug 2025 20:08:48 -0400 Subject: [PATCH 3/3] added "compare_params_NOA.py" and fixed problems --- MixUCB_compare.xlsx | Bin 5261 -> 73388 bytes MixUCB_compare_21Aug2025.xlsx | Bin 0 -> 73814 bytes MixUCB_compare_EXP4.xlsx | Bin 0 -> 19126 bytes MixUCB_compare_EXP4_21Aug2025.xlsx | Bin 0 -> 19208 bytes MixUCB_compare_MetaChoice.xlsx | Bin 0 -> 18931 bytes MixUCB_compare_MetaChoice_21Aug2025.xlsx | Bin 0 -> 18931 bytes compare_params_NOA.py | 153 +++++++++++++++++++++++ run_allucb_NOA_mixUCB.py | 43 +++++++ test_NOA_mixUCB.py | 64 ++++++---- test_NOA_mixUCB_Exp4.py | 32 ++--- test_NOA_mixUCB_MetaChoice.py | 31 +++-- 11 files changed, 269 insertions(+), 54 deletions(-) create mode 100644 MixUCB_compare_21Aug2025.xlsx create mode 100644 MixUCB_compare_EXP4.xlsx create mode 100644 MixUCB_compare_EXP4_21Aug2025.xlsx create mode 100644 MixUCB_compare_MetaChoice.xlsx create mode 100644 MixUCB_compare_MetaChoice_21Aug2025.xlsx create mode 100644 compare_params_NOA.py diff --git a/MixUCB_compare.xlsx b/MixUCB_compare.xlsx index 2da9829bec6c2aa85c3cc2dc63d8173e54057329..13abc536176789f320c61a67b87230986cfa8e3a 100644 GIT binary patch delta 69950 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 delta 1328 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 X>Pql0%>@7;zwEDH+8l=bFPZ!w1`pXH literal 0 HcmV?d00001 diff --git a/MixUCB_compare_EXP4.xlsx b/MixUCB_compare_EXP4.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..0448ff5d42e0fc8c9369a5133625e0e5f53c0dcf GIT binary patch literal 19126 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

~kbKYz{uz4U4QxN>3= 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 Jr8;|Oe*+86sw)5h literal 0 HcmV?d00001 diff --git a/MixUCB_compare_MetaChoice.xlsx b/MixUCB_compare_MetaChoice.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..4ac56b5d171e55a870a797f950882f847d7ddec3 GIT binary patch literal 18931 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%0D77&{z(>yCv)HT9cNVkftTj>5jI z!D?A1x#bs)5c~wo84Sw27LhlMpj5K|4(q-8@J$^ z600~7YRo4UlB^kg;>hME=Q{q=7!Xs^NZ91#DvTg3xkbY@8i1oST+v(mnwZ)g zcI=F>4D^gDq5d6It%CW1gg7E4h52>?G*9jiuRvQzH56%dqg9@;9*~|hBu`)@3GHl6 zOB}VVEMD!K8A|X3maw&e@L-VB98tp^6Io^wr>WTc8T1ezeZuu_VZhCrSIWmqzbvFD zp6Ggdx_iQ6XpBR8kAis1fqRR=c)yZoO8?x` zpUh2fIW6zXDtOZ`ZFWc6%+t9$ukXrQezyJZfk({bO2Ycqy%QF5tInYj(ATl<=Dzs6 zb>q&?@bV#hg$=l{xBnq2pF7S;aAPWEn|Ek5&oyko#=}%!hnXjMac}3X0Uz5{u+(k0 zj;;=n^6^%h{ye>1q`4C9I|Jcy5OTY9<4`@!h;A#*@Pp_8p zi8JIxh6B7FBwQ!jGLYTn`UHcR(SV&9)qAgA=yn8XH`y@jjQ#nPDy;uTYt3@>y3(;5 zC&7+o?)3e5bEDI&u(a|vK$wdqFXXByZqB>MWl@gvNG^wn7?`^OBj$7P>+x;*F*#9* z??{T&I-vZl1GF?)CqT&@Hj;sd@!Zc-aIQG6NHd9E4yEz#mJ}B^J**01nvMxQce`wa zb)a&?$;6S>7ec}jx$jO3z(7RpWK2hjUzilyNgX@{ZR32=;<*N-!OTo2i0i{N8poEX zuR?;cLA$uD=vVw|T>tIO01dz5nzT(2O%%l1*#X@$%gbxBHN(S-E>BmwlscDlt{rA1 z>EL5oydrpU*g64W8)&^Omp3Dr<;8QUaI!lOA#!QLnWaz$z_uY~c2tw>;!|bJxnyC% zF^hX-D1VyCjSz0j3Alu6{6#lgwLG+_O>jlno1lwPGhImL9EyBhMc~)81g9&v(?hI6 zFS59Px5T(m^e!gau0pI@V_4a>vfWn(h zNIZQZgE%Xxt2-@nEE}-39*VA5J<*D_dDUb)aK0gWDoN4$dd7?56#>#VnK%=2- z5n&11oDI4w>`_B$U+)LCNmCgII1Z_xYer$yR~c;ZQ9h>mD0T_TGxcOSEtJzBT-d$2 zSv2q&5e4`8dZOFik;5duurH6Apl}C76?j(flGHVxm{QvX@@@b)__TIdKI3#<^I5g2 z-5x3fXC*sRe0FOo1DXVCR1>cj;rWg

ZRd_As>jw%jtjkjuM+F~o493|0MT5d(B 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 literal 0 HcmV?d00001 diff --git a/MixUCB_compare_MetaChoice_21Aug2025.xlsx b/MixUCB_compare_MetaChoice_21Aug2025.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..5d7fe6e29cb915acd53c3c14cb2ed6f981f6cc37 GIT binary patch literal 18931 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 {out_path.resolve()}") diff --git a/test_NOA_mixUCB_MetaChoice.py b/test_NOA_mixUCB_MetaChoice.py index f35d33d0..e324632c 100644 --- a/test_NOA_mixUCB_MetaChoice.py +++ b/test_NOA_mixUCB_MetaChoice.py @@ -312,32 +312,37 @@ def phi(x, a, K): mode=mode, ) # returns reward_per_time, query_per_time, action_per_time + cum_queries_per_time = [int(q_t[:i].sum()) for i in range(len(q_t))] + cum_auto_rewards_per_time = [avg_autonomous_reward(r_t[:i], q_t[:i]) for i in range(len(q_t))] rows.append(dict( - mode=mode, + feedback_type=mode, delta=float(delta), + expert_type="MetaChoice", queries=int(q_t.sum()), avg_auto_reward=avg_autonomous_reward(r_t, q_t), avg_total_reward=r_t.mean(), + cum_auto_rewards_per_time=cum_auto_rewards_per_time, + cum_queries_per_time=cum_queries_per_time )) - # PLOT: - query_nums = [int(q_t[:i].sum()) for i in range(len(q_t))] - total_rewards = [avg_autonomous_reward(r_t[:i], q_t[:i]) for i in range(len(q_t))] - plot_query_reward_expertType( - query_nums=query_nums, - total_rewards=total_rewards, - expert_indices_per_timestep=expert_indices_per_timestep, - feedback_type=mode, - expert_types=expert_types, - delta=delta - ) + # # PLOT - query_nums, total_auto_rewards as function of time: + # query_nums = [int(q_t[:i].sum()) for i in range(len(q_t))] + # total_rewards = [avg_autonomous_reward(r_t[:i], q_t[:i]) for i in range(len(q_t))] + # plot_query_reward_expertType( + # query_nums=query_nums, + # total_rewards=total_rewards, + # expert_indices_per_timestep=expert_indices_per_timestep, + # feedback_type=mode, + # expert_types=expert_types, + # delta=delta + # ) df = pd.DataFrame(rows) print(df) # Save a compact summary like your Excel sheet idea -out_path = Path("MixUCB_compare.xlsx") +out_path = Path("MixUCB_compare_MetaChoice.xlsx") df.to_excel(out_path, index=False) print(f"Saved results -> {out_path.resolve()}")