From f48de70377aa07c5ec0e6b5eba31b301f3dccf4f Mon Sep 17 00:00:00 2001 From: Vincent Auriau Date: Thu, 21 Dec 2023 21:33:42 +0100 Subject: [PATCH 001/767] Small modifs on repo initalization (#1) * disable mkdoc * disable ci on push --- .github/workflows/ci.yaml | 2 +- .github/workflows/deploy_docs.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6052675e..0bddb949 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1,6 +1,6 @@ name: CI -on: [push, pull_request] +on: [pull_request] jobs: CI: diff --git a/.github/workflows/deploy_docs.yaml b/.github/workflows/deploy_docs.yaml index d8b7124f..061110ef 100644 --- a/.github/workflows/deploy_docs.yaml +++ b/.github/workflows/deploy_docs.yaml @@ -3,7 +3,7 @@ name: Deploy MkDocs to GitHub Pages on: push: branches: - - main + - master jobs: deploy-docs: From 3744dc02e2ae068648a1b8e3518c44c87b6f8e77 Mon Sep 17 00:00:00 2001 From: Vincent Auriau Date: Thu, 21 Dec 2023 21:34:25 +0100 Subject: [PATCH 002/767] Add base files from rd-assortment repository (#2) * ADD: data files from repo * format choice_dataset * format indexer * format store * add tf_ops * add base_model * add: rumnet * add: condMNL --- lib/data/choice_dataset.py | 897 ++++++++++++++++++++++++++++++++++ lib/data/indexer.py | 304 ++++++++++++ lib/data/store.py | 274 +++++++++++ lib/models/base_model.py | 785 +++++++++++++++++++++++++++++ lib/models/conditional_mnl.py | 884 +++++++++++++++++++++++++++++++++ lib/models/rumnet.py | 816 +++++++++++++++++++++++++++++++ lib/tf_ops.py | 147 ++++++ pyproject.toml | 2 +- 8 files changed, 4108 insertions(+), 1 deletion(-) create mode 100644 lib/data/choice_dataset.py create mode 100644 lib/data/indexer.py create mode 100644 lib/data/store.py create mode 100644 lib/models/base_model.py create mode 100644 lib/models/conditional_mnl.py create mode 100644 lib/models/rumnet.py create mode 100644 lib/tf_ops.py diff --git a/lib/data/choice_dataset.py b/lib/data/choice_dataset.py new file mode 100644 index 00000000..a2fba478 --- /dev/null +++ b/lib/data/choice_dataset.py @@ -0,0 +1,897 @@ +"""Main classes to handle assortment data.""" + +import numpy as np +import pandas as pd +from choice_modeling.data.indexer import ChoiceDatasetIndexer +from choice_modeling.data.store import Store + + +class ChoiceDataset(object): + """ChoiceDataset is the main class to handle assortment data minimizing RAM usage. + + The choices are given as a ragged list of choices + for each session. It is particularly useful if several (a lot) of choices happen + during the same session. For example if we have the same customer buying several + items during the same session, all its choices + can be regrouped under the same session_features. Limits data duplication in such cases. + + The class has same methods/arguments as ChoiceDatset with a slight difference with + self.choices being a ragged list. The returned features in self.__getitem__ are the same + as ChoiceDataset. When calling __getitem__(index) we map index to a session index and a + choice index within the session. + """ + + def __init__( + self, + items_features=None, + sessions_features=None, + sessions_items_features=None, + items_features_names=None, + sessions_features_names=None, + sessions_items_features_names=None, + sessions_items_availabilities=None, + choices=None, # Should not have None as default value ? + batch_size=16, + shuffle=False, + ): + """Builds the ChoiceDataset. + + Parameters + ---------- + items_features : tuple of (array_like, ) + matrix of shape (num_items, num_items_features) containing the features of the items + e.g. item color + sessions_features : tuple of (array_like, ) + matrix of shape (num_sessions, num_sess_features) containing the features of the + sessions e.g. day of week + sessions_items_features : tuple of (array_like, ) + matrix of shape (num_sessions, num_items, num_ses_items_features) containing the item + features varying over sessions, e.g. prices + sessions_items_availabilities : array_like + binary matrix of shape (num_sessions, num_items) containing the availabitilies of + products (1. if present 0. otherwise) over sessions + choices: list of list + for each sessions we have a list of related choices. Main list has same legnth as + session_features and sessions_items_features. + batch_size: int, optional + size of the batches to return in __iter__ method + suffle: bool, optional + whether to shuffle the dataset or not + """ + # --------- [ Handling features type given as tuples or not ] --------- # + # If items_features is not given as tuple, transform it internally as a tuple + # A bit longer because can be None and need to also handle names + if not isinstance(items_features, tuple) and items_features is not None: + items_features = (items_features,) + items_features_names = (items_features_names,) + self._return_items_features_tuple = False + # items_features is already a tuple, names are given, checking consistency + elif items_features is not None and items_features_names is not None: + if ( + len(items_features) != len(items_features_names) + and items_features_names is not None + ): + raise ValueError("items_features shape and items_features_names shape do not match") + self._return_items_features_tuple = True + # In this case names are missing, still transform it as a tuple + elif items_features is not None: + self._return_items_features_tuple = True + items_features_names = (None,) * len(items_features) + + # If sessions_features is not given as tuple, transform it internally as a tuple + # A bit longer because can be None and need to also handle names + if not isinstance(sessions_features, tuple) and sessions_features is not None: + sessions_features = (sessions_features,) + sessions_features_names = (sessions_features_names,) + self._return_sessions_features_tuple = False + # sessions_features is already a tuple, names are given, checking consistency + elif sessions_features is not None and sessions_features_names is not None: + if ( + len(sessions_features) != len(sessions_features_names) + and sessions_features_names is not None + ): + raise ValueError( + "sessions_features shape and sessions_features_names shape \ + do not match" + ) + self._return_sessions_features_tuple = True + # In this case names are missing, still transform it as a tuple + elif sessions_features is not None: + self._return_sessions_features_tuple = True + sessions_features_names = (None,) * len(sessions_features) + + # If sessions_items_features is not given as tuple, transform it internally as a tuple + # A bit longer because can be None and need to also handle names + if not isinstance(sessions_items_features, tuple) and sessions_items_features is not None: + sessions_items_features = (sessions_items_features,) + sessions_items_features_names = (sessions_items_features_names,) + self._return_sessions_items_features_tuple = False + # sessions_items_features is already a tuple, names are given, checking consistency + elif sessions_items_features is not None and sessions_items_features_names is not None: + if ( + len(sessions_items_features) != len(sessions_items_features_names) + and sessions_items_features_names is not None + ): + raise ValueError( + "sessions_items_features shape and \ + sessions_items_features_names shape do not match" + ) + self._return_sessions_items_features_tuple = True + # In this case names are missing, still transform it as a tuple + elif sessions_items_features is not None: + self._return_sessions_items_features_tuple = True + sessions_items_features_names = (None,) * len(sessions_items_features) + + # --------- [Normalizing features types (DataFrame, List, etc...) -> np.ndarray] --------- # + # + # Part of this code is for handling features given as pandas.DataFrame + # Basically it transforms them to be internally stocked as np.ndarray and keep columns + # names as features names + + # Handling items_features + for i, feature in enumerate(items_features): + if isinstance(feature, pd.DataFrame): + # Ordering items by id ? + if "item_id" in feature.columns: + feature = feature.set_index("item_id") + items_features = ( + items_features[:i] + + (feature.loc[np.sort(feature.index)].to_numpy(),) + + items_features[i + 1 :] + ) + items_features_names = ( + items_features_names[:i] + + (feature.columns.tolist(),) + + items_features_names[i + 1 :] + ) + elif isinstance(feature, list): + items_features = items_features[:i] + (np.array(feature),) + items_features[i + 1 :] + + # Handling sessions_features + for i, feature in enumerate(sessions_features): + if isinstance(feature, pd.DataFrame): + # Ordering sessions by id ? + if "session_id" in feature.columns: + feature = feature.set_index("session_id") + sessions_features = ( + sessions_features[:i] + + (feature.loc[np.sort(feature.index)].to_numpy(),) + + sessions_features[i + 1 :] + ) + sessions_features_names = ( + sessions_features_names[:i] + + (feature.columns.tolist(),) + + sessions_features_names[i + 1 :] + ) + elif isinstance(feature, list): + sessions_features = ( + sessions_features[:i] + (np.array(feature),) + sessions_features[i + 1 :] + ) + + # Handling sessions_items_features + for i, feature in enumerate(sessions_items_features): + if isinstance(feature, pd.DataFrame): + # Ordering sessions and items by id ? + if "session_id" not in feature.columns: + feature["session_id"] = feature.index + items_index = np.sort(feature.item_id.unique()) + sessions_index = np.sort(feature.session_id.unique()) + names = [f for f in feature.columns if f != "session_id" and f != "item_id"] + + ( + feature, + sessions_items_availabilities, + ) = self._sessions_items_features_df_to_np( + feature, items_index, sessions_index, feature.columns.tolist() + ) + + sessions_items_features = ( + sessions_items_features[:i] + feature + sessions_items_features[i + 1 :] + ) + + sessions_items_features_names = ( + sessions_items_features_names[:i] + + (names,) + + sessions_items_features_names[i + 1 :] + ) + elif isinstance(feature, list): + sessions_items_features = ( + sessions_items_features[:i] + + (np.array(feature),) + + sessions_items_features[i + 1 :] + ) + + if isinstance(sessions_items_availabilities, list): + sessions_items_availabilities = np.array(sessions_items_availabilities) + + # Handling choices + # Choices must then be given as the name of the chosen item + # Items are sorted by name and attributed an index + # Cannot be a list of choices yet + if isinstance(choices, pd.DataFrame): + # Ordering sessions by id + if "session_id" in choices.columns: + choices = choices.set_index("session_id") + choices = choices.loc[np.sort(choices.index)] + items = np.sort(np.unique(choices.choice)) + # items is the value (str) of the item + choices = [np.where(items == c)[0] for c in choices.choice] + + # Setting attributes of ChoiceDataset + self.items_features = items_features + self.sessions_features = sessions_features + self.sessions_items_features = sessions_items_features + self.sessions_items_availabilities = sessions_items_availabilities + + self.items_features_names = items_features_names + self.sessions_features_names = sessions_features_names + self.sessions_items_features_names = sessions_items_features_names + + self.batch_size = batch_size + self.shuffle = shuffle + + if choices is None: + # Done to keep a logical order of arguments, and has logic: choices have to be specified + raise ValueError("Choices must be specified, got None") + self.ragged_choices = choices + self.indexes, self.choices = self._build_indexes(choices) + self.n_choices = len(self.choices) + + # Different consitency checks to ensure everythin is coherent + self._check_dataset() # Should handle alone if np.arrays are squeezed + self._return_types = self._check_types() + self._check_names() + + # Build .iloc method + self.indexer = ChoiceDatasetIndexer(self) + + def _build_indexes(self, choices): + """Builds the indexes dictionnary from the choices. + + Particularly creates a flatten version of the choices and associates an index so that we can + retrieve from this index the session and the corresponding choice. + + Parameters: + ----------- + choices: list of list + raffed version of the choices + + Returns:: + -------- + indexes: dict + dictionnary of indexes: {index: corresponding_session_index} + choices: np.ndarray + flattened (1D) version of the choices + """ + try: # 1 choice by session + if len(np.squeeze(choices).shape) == 1: + indexes = {i: i for i in range(len(choices))} + flat_choices = np.squeeze(self.ragged_choices) + elif len(np.squeeze(choices).shape) == 0: + indexes = {i: i for i in range(len(choices))} + flat_choices = np.array([np.squeeze(self.ragged_choices)]) + except ValueError: # Ragged sequence of choices + indexes = {} + flat_choices = [] + total_count = 0 + for sess_nb, sess in enumerate(choices): + for choice in sess: + indexes[total_count] = sess_nb + flat_choices.append(choice) + total_count += 1 + return indexes, np.array(flat_choices) + + def _check_dataset(self): + """Verifies that the shapes of the different features are consistent. + + Particularly: + - Over number of items + - Over number of sessions + Verifies that the choices have coherent values + """ + self._check_num_items_shapes() + self._check_num_sessions_shapes() + self._check_choices_coherence() + + def _check_num_items_shapes(self): + """Verifies that the shapes of the different features are consistent over number of items. + + Particularly: + - items_features + - sessions_items_features + - sessions_items_availabilities + Sets the argument base_num_items + """ + if self.items_features is not None: + base_num_items = self.items_features[0].shape[0] + elif self.sessions_items_features is not None: + base_num_items = self.sessions_items_features[0].shape[1] + elif self.sessions_items_availabilities is not None: + base_num_items = self.sessions_items_availabilities.shape[1] + else: + raise ValueError( + "No items features, sessions items features or items availabilities are defined" + ) + self.base_num_items = base_num_items + + if self.items_features is not None: + for items_feature in self.items_features: + if items_feature.shape[0] != base_num_items: + raise ValueError(f"shapes are (f{items_feature.shape[0]}, {base_num_items})") + + if self.sessions_items_features is not None: + for sessions_items_feature in self.sessions_items_features: + if sessions_items_feature.shape[1] != base_num_items: + raise ValueError( + f"shapes are (f{sessions_items_feature.shape[1]}, {base_num_items})" + ) + if self.sessions_items_availabilities is not None: + if self.sessions_items_availabilities.shape[1] != base_num_items: + raise ValueError( + f"shapes are (f{self.sessions_items_availabilities.shape[1]}, \ + {base_num_items})" + ) + + def _check_num_sessions_shapes(self): + """Verifies that the shapes of the different features are consistent over nb of sessions. + + Particularly: + - sessions_features + - sessions_items_features + - sessions_items_availabilities + Sets self.base_num_sessions argument. + """ + base_num_sessions = len(self.ragged_choices) + self.base_num_sessions = base_num_sessions + + if self.sessions_features is not None: + for sessions_feature in self.sessions_features: + if sessions_feature.shape[0] != base_num_sessions: + raise ValueError( + f"shapes are ({sessions_feature.shape[0]}, {base_num_sessions})" + ) + + if self.sessions_items_features is not None: + for sessions_items_feature in self.sessions_items_features: + if sessions_items_feature.shape[0] != base_num_sessions: + raise ValueError( + f"shapes are: ({sessions_items_feature.shape[0]}, \ + {base_num_sessions})" + ) + if self.sessions_items_availabilities is not None: + if self.sessions_items_availabilities.shape[0] != base_num_sessions: + raise ValueError( + f"shapes are: ({self.sessions_items_availabilities.shape[0]}, \ + {base_num_sessions})" + ) + + def _check_choices_coherence(self): + """Verifies that the choices are coherent with the nb of items present in other features. + + Particularly: + - There is no choice index higher than detected number of items + - All items are present at least once in the choices + """ + if np.max(self.choices) > self.base_num_items: + msg = f"Choices values not coherent with number of items given in features. \ + In particular, max value of choices is {np.max(self.choices)} while number of \ + items is {self.base_num_items}" + raise ValueError(msg) + + unique_choices = set(np.unique(self.choices).flatten()) + missing_choices = set(np.arange(start=0, stop=self.base_num_items, step=1)) - unique_choices + if len(missing_choices) > 0: + print(f"Some choices never happen in the dataset: {missing_choices}") + + def _check_types(self): + """Checks types of elements and store it in order to return right types. + + Particularly: + - Either int32 or float32 consistently for features. + float32 is to be preferred unless One-Hot encoding is used. + - float32 for sessions_items_availabilities + - int32 for choices + """ + return_types = [] + + item_types = [] + if self.items_features is not None: + for item_feat in self.items_features: + if np.issubdtype(item_feat[0].dtype, np.integer): + item_types.append(np.int32) + else: + item_types.append(np.float32) + return_types.append(tuple(item_types)) + + session_types = [] + if self.sessions_features is not None: + for sessions_feat in self.sessions_features: + if np.issubdtype(sessions_feat[0].dtype, np.integer): + session_types.append(np.int32) + else: + session_types.append(np.float32) + return_types.append(tuple(session_types)) + + session_item_types = [] + if self.sessions_items_features is not None: + for session_item_feat in self.sessions_items_features: + if np.issubdtype(session_item_feat[0].dtype, np.integer): + session_item_types.append(np.int32) + else: + session_item_types.append(np.float32) + return_types.append(tuple(session_item_types)) + return_types.append(np.float32) + return_types.append(np.int32) + + return return_types + + def _check_names(self): + """Verifies that the names given to features are consistent with the features themselves.""" + if self.items_features_names is not None: + for name, features in zip(self.items_features_names, self.items_features): + if name is not None: + if len(name) != features.shape[1]: + raise ValueError( + f"Specififed items_features_names has \ + length {len(name)} while items_features has {features.shape[1]} elements" + ) + + if self.sessions_features_names is not None: + for name, features in zip(self.sessions_features_names, self.sessions_features): + if name is not None: + if len(name) != features.shape[1]: + raise ValueError( + f"Specified sessions_features_names has \ + length {len(name)} while sessions_features has {features.shape[1]} elements" + ) + + if self.sessions_items_features_names is not None: + for ( + name, + features, + ) in zip(self.sessions_items_features_names, self.sessions_items_features): + if name is not None: + if len(name) != features.shape[1]: + raise ValueError( + f"Specified \ + sessions_items_features_names has length {len(name)} while \ + sessions_items_features has {features.shape[1]} elements" + ) + + def __len__(self): + """Returns length of the dataset e.g. total number of sessions. + + Returns: + ------- + int + total number of sessions + """ + return self.base_num_sessions + + def get_num_items(self): + """Method to access the total number of different items. + + Returns: + ------- + int + total number of different items + """ + return self.base_num_items + + def get_num_sessions(self): + """Method to access the total number of different sessions. + + Redundant with __len__ method. + + Returns: + ------- + int + total number of different sessions + """ + return len(self) + + def get_num_choices(self): + """Method to access the total number of different sessions. + + Returns: + ------- + int + total number of different sessions + """ + return self.n_choices + + @classmethod + def _sessions_items_features_df_to_np( + cls, + df, + items_index, + sessions_index, + features, + items_id_column="item_id", + sessions_id_column="session_id", + ): + """Builds sessions_items_features and sessions_items_availabilities from dataframe. + + Parameters + ---------- + df : pandas.DataFrame + Dataframe containing all the features for each item and sessions + items_index : list + List of items + sessions_index : list + List of sessions + features : list + List of columns of df that represents the items_features (for sessions_items_features) + + Returns: + ------- + np.ndarray of shape (n_sessions, n_items, n_features) + Corresponding sessions_items_features + np.ndarray of shape (n_sessions, n_items) + Corresponding availabilities + """ + try: + features.remove("session_id") + except ValueError: + pass + try: + features.remove("item_id") + except ValueError: + pass + + sessions_items_features = [] + sessions_items_availabilities = [] + for sess in sessions_index: + sess_df = df.loc[df[sessions_id_column] == sess] + + if len(sess_df) == len(items_index): + sess_df = sess_df.T + sess_df.columns = sess_df.loc[items_id_column] + if features is not None: + sessions_items_features.append(sess_df[items_index].loc[features].T.values) + sessions_items_availabilities.append(np.ones(len(items_index))) + else: + sess_feats = [] + sess_av = [] + for item in items_index: + item_df = sess_df.loc[sess_df[items_id_column] == item] + if len(item_df) > 0: + if features is not None: + sess_feats.append(item_df[features].to_numpy()[0]) + sess_av.append(1) + else: + if features is not None: + sess_feats.append(np.zeros(len(features))) + sess_av.append(0) + sessions_items_features.append(sess_feats) + sessions_items_availabilities.append(sess_av) + + if features is not None: + sessions_items_features = (np.array(sessions_items_features),) + else: + sessions_items_features = None + return sessions_items_features, np.array(sessions_items_availabilities) + + @classmethod + def from_single_df( + cls, + df, + items_features_columns, + sessions_features_columns, + sessions_items_features_columns, + items_id_column="item_id", + sessions_id_column="session_id", + choices_column="choice", + choice_mode="items_name", + ): + """Builds numpy arrays for ChoiceDataset from a single dataframe. + + Parameters + ---------- + df : pandas.DataFrame + dataframe in Long format + items_features_columns : list + Columns of the dataframe that are item features + sessions_features_columns : list + Columns of the dataframe that are session features + sessions_items_features_columns : list + Columns of the dataframe that are session-item features + items_id_column: str, optional + Name of the column containing the item ids, default is "items_id" + sessions_id_column: str, optional + Name of the column containing the sessions ids, default is "sessions_id" + choices_column: str, optional + Name of the column containing the choices, default is "choice" + + Returns: + ------- + ChoiceDataset + corresponding ChoiceDataset + """ + # Ordering items and sessions by id + items = np.sort(df[items_id_column].unique()) + sessions = np.sort(df[sessions_id_column].unique()) + + if items_features_columns is not None: + items_features = df[items_features_columns + [items_id_column]].drop_duplicates() + items_features = items_features.set_index(items_id_column) + items_features = (items_features.loc[items].to_numpy(),) + + items_features_columns = (items_features_columns,) + else: + items_features = None + + if sessions_features_columns is not None: + sessions_features = df[ + sessions_features_columns + [sessions_id_column] + ].drop_duplicates() + sessions_features = sessions_features.set_index(sessions_id_column) + sessions_features = (sessions_features.loc[sessions].to_numpy(),) + + sessions_features_columns = (sessions_features_columns,) + else: + sessions_features = None + + ( + sessions_items_features, + sessions_items_availabilities, + ) = cls._sessions_items_features_df_to_np( + df, + items_index=items, + sessions_index=sessions, + features=sessions_items_features_columns, + items_id_column=items_id_column, + sessions_id_column=sessions_id_column, + ) + sessions_items_features_columns = ( + (sessions_items_features_columns,) + if sessions_items_features_columns is not None + else None + ) + + if choice_mode == "item_id": + choices = df[[choices_column, sessions_id_column]].drop_duplicates(sessions_id_column) + choices = choices.set_index(sessions_id_column) + choices = choices.loc[sessions].to_numpy() + # items is the value (str) of the item + choices = [np.where(items == c)[0] for c in choices] + elif choice_mode == "one_zero": + choices = df[[items_id_column, choices_column, sessions_id_column]] + choices = choices.loc[choices[choices_column] == 1] + choices = choices = choices.set_index(sessions_id_column) + choices = ( + choices.loc[sessions][items_id_column] + .map({k: v for v, k in enumerate(items)}) + .to_numpy() + ) + else: + raise ValueError( + f"choice_mode {choice_mode} not recognized. Must be in ['item_id', 'one_zero']" + ) + + return ChoiceDataset( + items_features=items_features, + sessions_features=sessions_features, + sessions_items_features=sessions_items_features, + sessions_items_availabilities=sessions_items_availabilities, + choices=choices, + items_features_names=items_features_columns, + sessions_features_names=sessions_features_columns, + sessions_items_features_names=sessions_items_features_columns, + ) + + def save(self): + """Method to save the dataset.""" + raise NotImplementedError + + def summary(self): + """Method to display a summary of the dataset.""" + raise NotImplementedError + + def get_choice_batch(self, choice_index): + """Method to access data within the ListChoiceDataset from its index. + + One index corresponds to a choice within a session. + + Return order: + - Fixed item features + - Session features + - Session item features + - Items availabilities + - Choice + + Parameters + ---------- + index : int or list of int or slice + indexes of the choices (that will be mapped to choice & session indexes) to return + + """ + if isinstance(choice_index, list): + if self.items_features is None: + items_features = None + else: + items_features = tuple( + items_feature.astype(self._return_types[0][i]) + for i, items_feature in enumerate(self.items_features) + ) + # items_features were not given as a tuple, so we return do not return it as a tuple + if not self._return_items_features_tuple: + items_features = items_features[0] + + # Get the session indexes + sessions_indexes = [self.indexes[i] for i in choice_index] + + if self.sessions_features is None: + sessions_features = None + else: + sessions_features = tuple( + np.stack(sessions_feature[sessions_indexes], axis=0).astype( + self._return_types[1][i] + ) + if not isinstance(sessions_feature, Store) + else sessions_feature.iloc[sessions_indexes] + for i, sessions_feature in enumerate(self.sessions_features) + ) + # sessions_features were not given as a tuple, so we return do not return it + # as a tuple + if not self._return_sessions_features_tuple: + sessions_features = sessions_features[0] + + if self.sessions_items_features is None: + sessions_items_features = None + else: + sessions_items_features = tuple( + np.stack(sessions_items_feature[sessions_indexes], axis=0).astype( + self._return_types[2][i] + ) + if not isinstance(sessions_items_feature, Store) + else sessions_items_feature.iloc[sessions_indexes] + for i, sessions_items_feature in enumerate(self.sessions_items_features) + ) + # sessions_items_features were not given as a tuple, so we return do not return + # it as a tuple + if not self._return_sessions_items_features_tuple: + sessions_items_features = sessions_items_features[0] + + if self.sessions_items_availabilities is None: + sessions_items_availabilities = None + else: + sessions_items_availabilities = self.sessions_items_availabilities[ + sessions_indexes + ].astype(self._return_types[3]) + + choice = self.choices[choice_index].astype(self._return_types[4]) + + return ( + items_features, + sessions_features, + sessions_items_features, + sessions_items_availabilities, + choice, + ) + + if isinstance(choice_index, slice): + return self.get_choice_batch(list(range(*choice_index.indices(self.choices.shape[0])))) + + session_index = self.indexes[choice_index] + choice = self.choices[choice_index] + + if self.items_features is None: + items_features = None + else: + items_features = tuple(items_feature for items_feature in self.items_features) + + if self.sessions_features is None: + sessions_features = None + else: + sessions_features = tuple( + sessions_feature[session_index] for sessions_feature in self.sessions_features + ) + + if self.sessions_items_features is None: + sessions_items_features = None + else: + sessions_items_features = tuple( + sessions_items_feature[session_index] + for sessions_items_feature in self.sessions_items_features + ) + + if self.sessions_items_availabilities is None: + sessions_items_availabilities = None + else: + sessions_items_availabilities = self.sessions_items_availabilities[session_index] + + return ( + items_features, + sessions_features, + sessions_items_features, + sessions_items_availabilities, + choice, + ) + + def __getitem__(self, session_indexes): + """Method to create a sub-ChoiceDataset with only a subset of sessions, from their indexes. + + Parameters + ---------- + indexes : np.ndarray + indexes of the sessions to keep, shape should be (num_sessions,) + + Returns: + ------- + ChoiceDataset + ChoiceDataset with only the sessions indexed by indexes + """ + if isinstance(session_indexes, int): + session_indexes = [session_indexes] + elif isinstance(session_indexes, slice): + return self.__getitem__(list(range(*session_indexes.indices(len(self.ragged_choices))))) + + return ChoiceDataset( + items_features=self.items_features, + sessions_features=tuple( + self.sessions_features[i][session_indexes] + for i in range(len(self.sessions_features)) + ), + sessions_items_features=tuple( + self.sessions_items_features[i][session_indexes] + for i in range(len(self.sessions_items_features)) + ), + sessions_items_availabilities=self.sessions_items_availabilities[session_indexes], + choices=[self.ragged_choices[i] for i in session_indexes], + batch_size=self.batch_size, + items_features_names=self.items_features_names, + sessions_features_names=self.sessions_features_names, + sessions_items_features_names=self.sessions_items_features_names, + ) + + def batch(self, batch_size=None, shuffle=None, sample_weight=None): + """Iterates over dataset return batches of length self.batch_size. + + Parameters + ---------- + batch_size : int + batch size to set + shuffle: bool + Whether or not to shuffle the dataset + sample_weight : Iterable + list of weights to be returned with the right indexing during the shuffling + """ + if batch_size is None: + batch_size = self.batch_size + if shuffle is None: + shuffle = self.shuffle + if batch_size == -1: + batch_size = self.get_num_choices() + + # Get indexes for each choice + num_choices = self.get_num_choices() + indexes = np.arange(num_choices) + # Shuffle indexes + if shuffle and not batch_size == -1: + indexes = np.random.permutation(indexes) + + yielded_size = 0 + while yielded_size < num_choices: + # Return sample_weight if not None, for index matching + if sample_weight is not None: + yield ( + self.get_choice_batch( + indexes[yielded_size : yielded_size + batch_size].tolist() + ), + sample_weight[indexes[yielded_size : yielded_size + batch_size].tolist()], + ) + else: + yield self.get_choice_batch( + indexes[yielded_size : yielded_size + batch_size].tolist() + ) + yielded_size += batch_size + + # Special exit strategy for batch_size = -1 + if batch_size == -1: + yielded_size += 2 * num_choices + + @property + def iloc(self): + """Indexer.""" + return self.indexer diff --git a/lib/data/indexer.py b/lib/data/indexer.py new file mode 100644 index 00000000..0bc2de80 --- /dev/null +++ b/lib/data/indexer.py @@ -0,0 +1,304 @@ +"""Indexer classes for data classes.""" +from abc import abstractmethod + +import numpy as np + + +class Indexer(object): + """Base class for Indexer.""" + + def __init__(self, indexed_object): + """Instanciate an Indexer object. + + Parameters + ---------- + indexed_object : object + object to be indexed. + """ + self.indexed_object = indexed_object + + @abstractmethod + def __getitem__(self, index): + """Main method to be coded for children classes. + + Parameters + ---------- + index : int, slice, list + index(es) of elements of self.indexed_object to be returned. + """ + pass + + +class StoreIndexer(Indexer): + """Class for Ilocing/Batching FeaturesStore.""" + + def __init__(self, store): + """StoreIndexer constructor. + + Parameters + ---------- + store : choice_modeling.data.store.FeaturesStore + Store object to be indexed. + """ + self.store = store + + def __getitem__(self, sequence_index): + """Returns the features appearing at the sequence_index-th position of sequence. + + Parameters + ---------- + sequence_index : (int, list, slice) + index position of the sequence + + Returns: + -------- + array_like + features corresponding to the sequence_index-th position of sequence + """ + if isinstance(sequence_index, list): + return [self.store.store[self.store.sequence[i]] for i in sequence_index] + if isinstance(sequence_index, slice): + return [ + self.store.store[self.store.sequence[i]] + for i in range(*sequence_index.indices(len(self.sequence))) + ] + return self.store.store[self.store.sequence[sequence_index]] + + +class OneHotStoreIndexer(Indexer): + """Class for Ilocing OneHotStore.""" + + def __init__(self, store): + """OneHotStoreIndexer constructor. + + Parameters + ---------- + store : choice_modeling.data.store.OneHotStore + OneHotStore object to be indexed. + """ + self.store = store + + self.shape = (len(self.store.sequence), np.max(list(self.store.store.values())) + 1) + + def __getitem__(self, sequence_index): + """Main method to get an element at sequence_index-th position of self.sequence. + + Parameters + ---------- + sequence_index : (int, list, slice) + index from sequence of element to get + + Returns: + -------- + np.ndarray + OneHot features corresponding to the sequence_index-th position of sequence + """ + if isinstance(sequence_index, list): + # Construction of the OneHot vector from the index of the 1 value + one_hot = np.zeros((len(sequence_index), self.shape[1])) + for i, j in enumerate(sequence_index): + one_hot[i, self.store.store[self.store.sequence[j]]] = 1 + return one_hot.astype(self.store.dtype) + # else: + one_hot = np.zeros(self.shape[1]) + one_hot[self.store.store[self.store.sequence[sequence_index]]] = 1 + return one_hot.astype(self.store.dtype) + + +class ChoiceDatasetIndexer(Indexer): + """Indexing class for ChoiceDataset.""" + + def __init__(self, choice_dataset): + """Instanciate a ChoiceDatasetIndexer object. + + Parameters + ---------- + choice_dataset : choce_modeling.data.dataset.ChoiceDataset + Dataset to be indexed. + """ + self.choice_dataset = choice_dataset + + def _get_items_features(self): + """Method to access items features of the ChoiceDataset. + + Returns: + -------- + tuple of np.ndarray or np.ndarray + items_features of the ChoiceDataset + """ + if self.choice_dataset.items_features is None: + items_features = None + else: + items_features = tuple( + items_feature.astype(self.choice_dataset._return_types[0][i]) + for i, items_feature in enumerate(self.choice_dataset.items_features) + ) + # items_features were not given as a tuple, so we return do not return it as a tuple + if not self.choice_dataset._return_items_features_tuple: + items_features = items_features[0] + + return items_features + + def _get_sessions_features(self, sessions_indexes): + """Method to access sessions features of the ChoiceDataset. + + Parameters + ---------- + sessions_indexes : list of ints or int + indexes of the sessions to return + + Returns: + -------- + tuple of np.ndarray or np.ndarray + items_features of the ChoiceDataset + """ + if self.choice_dataset.sessions_features is None: + sessions_features = None + else: + sessions_features = [] + for i, sessions_feature in enumerate(self.choice_dataset.sessions_features): + if hasattr(sessions_feature, "iloc"): + sessions_features.append( + sessions_feature.iloc[sessions_indexes].astype( + self.choice_dataset._return_types[1][i] + ) + ) + else: + sessions_features.append( + np.stack(sessions_feature[sessions_indexes], axis=0).astype( + self.choice_dataset._return_types[1][i] + ) + ) + # sessions_features were not given as a tuple, so we return do not return it as a tuple + if not self.choice_dataset._return_sessions_features_tuple: + sessions_features = sessions_features[0] + else: + sessions_features = tuple(sessions_features) + return sessions_features + + def _get_sessions_items_features(self, sessions_indexes): + """Method to access sessions items features of the ChoiceDataset. + + Parameters + ---------- + sessions_indexes : list of ints or int + indexes of the sessions to return + + Returns: + -------- + tuple of np.ndarray or np.ndarray + items_features of the ChoiceDataset + """ + if self.choice_dataset.sessions_items_features is None: + return None + sessions_items_features = [] + for i, sessions_items_feature in enumerate(self.choice_dataset.sessions_items_features): + if hasattr(sessions_items_feature, "iloc"): + sessions_items_features.append( + sessions_items_feature.iloc[sessions_indexes].astype(self._return_types[2][i]) + ) + else: + sessions_items_features.append( + np.stack(sessions_items_feature[sessions_indexes], axis=0).astype( + self.choice_dataset._return_types[2][i] + ) + ) + # sessions_items_features were not given as a tuple, thus we do not return it as a tuple + if self.choice_dataset._return_sessions_items_features_tuple: + sessions_items_features = tuple(sessions_items_features) + else: + sessions_items_features = sessions_items_features[0] + return sessions_items_features + + def __getitem__(self, choice_index): + """Method to access data within the ChoiceDataset from its index. + + One index corresponds to a choice within a session. + Return order: + - Fixed item features + - Session features + - Session item features + - Items availabilities + - Choice + + Parameters + ---------- + index : int or list of int or slice + indexes of the choices (that will be mapped to choice & session indexes) to return + + """ + if isinstance(choice_index, list): + items_features = self._get_items_features() + # Get the session indexes + sessions_indexes = [self.choice_dataset.indexes[i] for i in choice_index] + + sessions_features = self._get_sessions_features(sessions_indexes) + sessions_items_features = self._get_sessions_items_features(sessions_indexes) + + if self.choice_dataset.sessions_items_availabilities is None: + sessions_items_availabilities = None + else: + if hasattr(self.choice_dataset.sessions_items_availabilities, "iloc"): + sessions_items_availabilities = ( + self.choice_dataset.sessions_items_availabilities.iloc[ + sessions_indexes + ].astype(self.choice_dataset._return_types[3]) + ) + else: + sessions_items_availabilities = ( + self.choice_dataset.sessions_items_availabilities[sessions_indexes].astype( + self.choice_dataset._return_types[3] + ) + ) + + choice = self.choice_dataset.choices[choice_index].astype( + self.choice_dataset._return_types[4] + ) + + return ( + items_features, + sessions_features, + sessions_items_features, + sessions_items_availabilities, + choice, + ) + + if isinstance(choice_index, slice): + return self.__getitem__(list(range(*choice_index.indices(self.choices.shape[0])))) + + if isinstance(choice_index, int): + items_features = self._get_items_features() + # Get the session indexes + sessions_indexes = self.choice_dataset.indexes[choice_index] + + sessions_features = self._get_sessions_features(sessions_indexes) + sessions_items_features = self._get_sessions_items_features(sessions_indexes) + + if self.choice_dataset.sessions_items_availabilities is None: + sessions_items_availabilities = None + else: + if hasattr(self.choice_dataset.sessions_items_availabilities, "iloc"): + sessions_items_availabilities = ( + self.choice_dataset.sessions_items_availabilities.iloc[ + sessions_indexes + ].astype(self.choice_dataset._return_types[3]) + ) + else: + sessions_items_availabilities = ( + self.choice_dataset.sessions_items_availabilities[sessions_indexes].astype( + self.choice_dataset._return_types[3] + ) + ) + + choice = self.choice_dataset.choices[choice_index].astype( + self.choice_dataset._return_types[4] + ) + + return ( + items_features, + sessions_features, + sessions_items_features, + sessions_items_availabilities, + choice, + ) + raise NotImplementedError diff --git a/lib/data/store.py b/lib/data/store.py new file mode 100644 index 00000000..5680943f --- /dev/null +++ b/lib/data/store.py @@ -0,0 +1,274 @@ +"""Different classes to optimize RAM usage with repeated features over time.""" +import numpy as np +from choice_modeling.data.indexer import OneHotStoreIndexer, StoreIndexer + + +class Store(object): + """Class to keep OneHotStore and FeaturesStore with same parent.""" + + def __init__(self, indexes=None, values=None, sequence=None, name=None, indexer=StoreIndexer): + """Builds the store. + + Parameters + ---------- + indexes : array_like or None + list of indexes of features to store. If None is given, indexes are created from + apparition order of values + values : array_like + list of values of features to store + sequence : array_like + sequence of apparitions of the features + name: string, optional + name of the features store -- not used at the moment + """ + if indexes is None: + indexes = list(range(values)) + self.store = {k: v for (k, v) in zip(indexes, values)} + self.sequence = np.array(sequence) + self.name = name + + if sequence is not None and values is not None: + try: + width = len(values[0]) + except TypeError: + width = 1 + self.shape = (len(sequence), width) + + self.indexer = indexer(self) + + def _get_store_element(self, index): + """Getter method over self.sequence. + + Returns the features stored at index index. Compared to __getitem__, it does take + the index-th element of sequence but the index-th element of the store. + + Parameters + ---------- + index : (int, list, slice) + index argument of the feature + + Returns: + -------- + array_like + features corresponding to the index index in self.store + """ + if isinstance(index, list): + return [self.store[i] for i in index] + # else: + return self.store[index] + + def __len__(self): + """Returns the length of the sequence of apparition of the features.""" + return len(self.sequence) + + @property + def iloc(self): + """Indexing attribute.""" + return self.indexer + + +class FeaturesStore(Store): + """Base class to store features and a sequence of apparitions. + + Mainly useful when features are repeated frequently over the sequence. + An example would be to store the features of a customers (supposing that the same customers come + several times over the work sequence) and to save which customer is concerned for each choice. + + Attributes: + ----------- + store : dict + Dictionary stocking features that can be called from indexes: {index: features} + shape : tuple + shape of the features store: (sequence_length, features_number) + sequence : array_like + List of elements of indexes representing the sequence of apparitions of the features + name: string, optional + name of the features store -- not used at the moment + dtype: type + type of the features + """ + + @classmethod + def from_dict(cls, values_dict, sequence): + """Instantiates the FeaturesStore from a dictionary of values. + + Parameters + ---------- + values_dict : dict + dictionary of values to store, {index: value} + sequence : array_like + sequence of apparitions of the features + + Returns: + -------- + FeaturesStore created from the values in the dictionnary + """ + # Check uniform shape of values + return cls( + indexes=list(values_dict.keys()), values=list(values_dict.values()), sequence=sequence + ) + + @classmethod + def from_list(cls, values_list, sequence): + """Instantiates the FeaturesStore from a list of values. + + Creates indexes for each value + + Parameters + ---------- + values_list : list + List of values to store + sequence : array_like + sequence of apparitions of the features + + Returns: + -------- + FeaturesStore + """ + # Check uniform shape of list + # Useful ? To rethink... + return cls(indexes=list(range(len(values_list))), values=values_list, sequence=sequence) + + def __getitem__(self, sequence_index): + """Subsets self with sequence_index. + + Parameters + ---------- + sequence_index : (int, list, slice) + index position of the sequence + + Returns: + -------- + array_like + features corresponding to the sequence_index-th position of sequence + """ + if isinstance(sequence_index, int): + sequence_index = [sequence_index] + print(sequence_index, type(self.sequence)) + new_sequence = self.sequence[sequence_index] + store = {} + for k, v in self.store.items(): + if k in new_sequence: + store[k] = v + else: + print(f"Key {k} of store with value {v} not in sequence anymore") + + return FeaturesStore.from_dict(store, new_sequence) + + def astype(self, dtype): + """Changes the dtype of the features. + + The type of the features should implement the astype method. + Typically, should work like np.ndarrays. + + Parameters + ---------- + dtype : str or type + type to set the features as + """ + for k, v in self.store.items(): + self.store[k] = v.astype(dtype) + + +class OneHotStore(Store): + """Specific FeaturesStore for one hot features storage. + + Inherits from FeaturesStore. + For example can be used to store a OneHot representation of the days of week. + + Has the same attributes as FeaturesStore, only differs whit some One-Hot optimized methods. + """ + + def __init__( + self, + indexes=None, + values=None, + sequence=None, + name=None, + dtype=np.float32, + ): + """Builds the OneHot features store. + + Parameters + ---------- + indexes : array_like or None + list of indexes of features to store. If None is given, indexes are created from + apparition order of values + values : array_like or None + list of values of features to store that must be One-Hot. If None given they are created + from order of apparition in sequence + sequence : array_like + sequence of apparitions of the features + name: string, optional + name of the features store -- not used at the moment + """ + self.name = name + self.sequence = np.array(sequence) + + if values is None: + self = self.from_sequence(sequence) + else: + self.store = {k: v for (k, v) in zip(indexes, values)} + self.shape = (len(sequence), np.max(values) + 1) + + self.dtype = dtype + self.indexer = OneHotStoreIndexer(self) + + @classmethod + def from_sequence(cls, sequence): + """Creates a OneHotFeatureStore from a sequence of apparition. + + One Hot vector are created from the order of apparition in the sequence: feature vectors + created have a length of the number of different values in the sequence and the 1 is + positioned in order of first appartitions in the sequence. + + Parameters + ---------- + sequence : array-like + Sequence of apparitions of values, or indexes. Will be used to index self.store + + Returns: + -------- + FeatureStore + Created from the sequence. + """ + all_indexes = np.unique(sequence) + values = np.arange(len(all_indexes)) + return cls(indexes=all_indexes, values=values, sequence=sequence) + + def __getitem__(self, sequence_index): + """Main method to get an element at sequence_index-th position of self.sequence. + + Parameters + ---------- + sequence_index : (int, list, slice) + index from sequence of element to get + + Returns: + -------- + np.ndarray + OneHot features corresponding to the sequence_index-th position of sequence + """ + if isinstance(sequence_index, int): + sequence_index = [sequence_index] + new_sequence = self.sequence[sequence_index] + store = {} + for k, v in self.store.items(): + if k in new_sequence: + store[k] = v + else: + print(f"Key {k} of store with value {v} not in sequence anymore") + + return OneHotStore( + indexes=list(store.keys()), values=list(store.values()), sequence=new_sequence + ) + + def astype(self, dtype): + """Method to change (mainly int or float) type of returned OneHot features vectors. + + Parameters + ---------- + dtype : type + Type to set the features as + """ + self.dtype = dtype diff --git a/lib/models/base_model.py b/lib/models/base_model.py new file mode 100644 index 00000000..5b19399b --- /dev/null +++ b/lib/models/base_model.py @@ -0,0 +1,785 @@ +"""Base class for choice models.""" +import json +import os +import time +from abc import abstractmethod +from pathlib import Path + +import numpy as np +import tensorflow as tf +import tqdm +from choice_modeling.tf_ops import ( + CustomCategoricalCrossEntropy, + availability_softmax, + custom_softmax, +) + + +class ChoiceModel(object): + """Base class for choice models.""" + + def __init__( + self, + label_smoothing=0.0, + normalize_non_buy=False, + optimizer="Adam", + callbacks=None, + lr=0.001, + ): + """Instantiates the ChoiceModel. + + Parameters + ---------- + label_smoothing : float, optional + Whether (then is ]O, 1[ value) or not (then can be None or 0) to use label smoothing, + during training, by default 0.0 + by default None. Label smoothing is applied to LogLikelihood loss. + normalize_non_buy : bool, optional + Whether or not to add a normalization (then U=1) with the exit option in probabilites + normalization,by default True + callbacks : list of tf.kera callbacks, optional + List of callbacks to add to model.fit, by default None and only add History + """ + self.is_fitted = False + self.normalize_non_buy = normalize_non_buy + self.label_smoothing = label_smoothing + self.stop_training = False + + # self.loss = tf.keras.losses.CategoricalCrossentropy( + # from_logits=False, label_smoothing=self.label_smoothing + # ) + self.loss = CustomCategoricalCrossEntropy( + from_logits=False, label_smoothing=self.label_smoothing + ) + self.callbacks = tf.keras.callbacks.CallbackList(callbacks, add_history=True, model=None) + self.callbacks.set_model(self) + + # Was originally in BaseMNL, moved here. + if optimizer.lower() == "adam": + self.optimizer = tf.keras.optimizers.Adam(lr) + elif optimizer.lower() == "sgd": + self.optimizer = tf.keras.optimizers.SGD(lr) + elif optimizer.lower() == "adamax": + self.optimizer = tf.keras.optimizers.Adamax(lr) + elif optimizer.lower() == "lbfgs" or optimizer.lower() == "l-bfgs": + print("Using L-BFGS optimizer, setting up .fit() function") + self.fit = self._fit_with_lbfgs + else: + print(f"Optimizer {optimizer} not implemnted, switching for default Adam") + self.optimizer = tf.keras.optimizers.Adam(lr) + + @abstractmethod + def compute_utility( + self, items_batch, sessions_batch, sessions_items_batch, availabilities_batch, choices_batch + ): + """Method that defines how the model computes the utility of a product. + + MUST be implemented in children classe + For simpler use-cases this is the only method to be user-defined. + + Parameters + ---------- + items_batch : tuple of np.ndarray (items_features) + Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products + constant/fixed features. + Shape must be (n_items, n_items_features) + sessions_batch : tuple of np.ndarray (sessions_features) + Time-Features + Shape must be (n_sessions, n_sessions_features) + sessions_items_batch : tuple of np.ndarray (sessions_items_features) + Time-Item-Features + Shape must be (n_sessions, n_sessions_items_features) + availabilities_batch : np.ndarray + Availabilities (sessions_items_availabilities) + Shape must be (n_sessions, n_items) + choices_batch : np.ndarray + Choices + Shape must be (n_sessions, ) + + Returns: + -------- + np.ndarray + Utility of each product for each session. + Shape must be (n_sessions, n_items) + """ + # To be implemented in children classes + # Can be numpy or tensorflow based + return + + @tf.function + def train_step( + self, + items_batch, + sessions_batch, + sessions_items_batch, + availabilities_batch, + choices_batch, + sample_weight=None, + ): + """Function that represents one training step (= one gradient descent step) of the model. + + Parameters + ---------- + items_batch : tuple of np.ndarray (items_features) + Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products + constant/fixed features. + sessions_batch : tuple of np.ndarray (sessions_features) + Time-Features + sessions_items_batch : tuple of np.ndarray (sessions_items_features) + Time-Item-Features + availabilities_batch : np.ndarray + Availabilities (sessions_items_availabilities) + choices_batch : np.ndarray + Choices + sample_weight : np.ndarray, optional + List samples weights to apply during the gradient descent to the batch elements, + by default None + + Returns: + -------- + tf.Tensor + Value of NegativeLogLikelihood loss for the batch + """ + with tf.GradientTape() as tape: + all_u = self.compute_utility( + items_batch, + sessions_batch, + sessions_items_batch, + availabilities_batch, + choices_batch, + ) + """ + all_u = tf.math.exp(all_u) + + # Assortment(t) Utility + norms = tf.reduce_sum(tf.multiply(all_u, ia_batch), axis=1) + if self.normalize_non_buy: + norms += 1 + # Probabilities + final_utilities = tf.divide( + all_u, + tf.repeat(tf.expand_dims(norms, 1), fif_batch[0].shape[0], axis=1), + ) + # Probabilities of selected product + available_utilities = tf.gather_nd(indices=choices_nd, params=final_utilities) + """ + probabilities = availability_softmax(all_u, availabilities_batch, axis=-1) + probabilities = custom_softmax( + all_u, availabilities_batch, normalize_exit=self.normalize_non_buy, axis=-1 + ) + # Negative Log-Likelihood + neg_loglikelihood = self.loss( + y_pred=probabilities, + y_true=tf.one_hot(choices_batch, depth=probabilities.shape[1]), + sample_weight=sample_weight, + ) + """ + if sample_weight is not None: + neg_loglikelihood = -tf.reduce_sum( + tf.math.log(available_utilities + 1e-10) * sample_weight + ) + else: + neg_loglikelihood = -tf.reduce_sum(tf.math.log(available_utilities + 1e-10)) + """ + grads = tape.gradient(neg_loglikelihood, self.weights) + self.optimizer.apply_gradients(zip(grads, self.weights)) + return neg_loglikelihood + + def fit( + self, choice_dataset, n_epochs, batch_size, sample_weight=None, val_dataset=None, verbose=0 + ): + """Method to train the model with a ChoiceDataset. + + Parameters + ---------- + choice_dataset : ChoiceDataset + _description_ + n_epochs : int + Number of epochs + batch_size : int + Batch size + sample_weight : np.ndarray, optional + Sample weights to apply, by default None + val_dataset : ChoiceDataset, optional + Test ChoiceDataset to evaluate performances on test at each epoch, by default None + verbose : int, optional + print level, for debugging, by default 0 + + Returns: + -------- + dict: + Different metrics values over epochs. + """ + losses_history = {"train_loss": []} + t_range = tqdm.trange(n_epochs, position=0) + + self.callbacks.on_train_begin() + + # Iterate of epochs + for epoch_nb in t_range: + self.callbacks.on_epoch_begin(epoch_nb) + t_start = time.time() + train_logs = {"train_loss": []} + val_logs = {"val_loss": []} + epoch_losses = [] + + if sample_weight is not None: + if verbose > 0: + inner_range = tqdm.tqdm( + choice_dataset.batch( + shuffle=True, sample_weight=sample_weight, batch_size=batch_size + ), + total=int(len(choice_dataset) / np.max([1, batch_size])), + position=1, + leave=False, + ) + else: + inner_range = choice_dataset.batch( + shuffle=True, sample_weight=sample_weight, batch_size=batch_size + ) + + for batch_nb, ( + ( + items_batch, + sessions_batch, + sessions_items_batch, + availabilities_batch, + choices_batch, + ), + weight_batch, + ) in enumerate(inner_range): + self.callbacks.on_train_batch_begin(batch_nb) + + neg_loglikelihood = self.train_step( + items_batch, + sessions_batch, + sessions_items_batch, + availabilities_batch, + choices_batch, + sample_weight=weight_batch, + ) + + train_logs["train_loss"].append(neg_loglikelihood) + temps_logs = {k: tf.reduce_mean(v) for k, v in train_logs.items()} + self.callbacks.on_train_batch_end(batch_nb, logs=temps_logs) + + # Optimization Steps + epoch_losses.append(neg_loglikelihood) + + # In this case we do not need to batch the sample_weights + else: + if verbose > 0: + inner_range = tqdm.tqdm( + choice_dataset.batch(shuffle=True, batch_size=batch_size), + total=int(len(choice_dataset) / np.max([batch_size, 1])), + position=1, + leave=False, + ) + else: + inner_range = choice_dataset.batch(shuffle=True, batch_size=batch_size) + for batch_nb, ( + items_batch, + sessions_batch, + sessions_items_batch, + availabilities_batch, + choices_batch, + ) in enumerate(inner_range): + self.callbacks.on_train_batch_begin(batch_nb) + neg_loglikelihood = self.train_step( + items_batch, + sessions_batch, + sessions_items_batch, + availabilities_batch, + choices_batch, + ) + train_logs["train_loss"].append(neg_loglikelihood) + temps_logs = {k: tf.reduce_mean(v) for k, v in train_logs.items()} + self.callbacks.on_train_batch_end(batch_nb, logs=temps_logs) + + # Optimization Steps + epoch_losses.append(neg_loglikelihood) + + # Take into account last batch that may have a differnt length into account for + # the computation of the epoch loss. + if batch_size != -1: + last_batch_size = availabilities_batch.shape[0] + coefficients = tf.concat( + [tf.ones(len(epoch_losses) - 1) * batch_size, [last_batch_size]], axis=0 + ) + epoch_lossses = tf.multiply(epoch_losses, coefficients) + epoch_loss = tf.reduce_sum(epoch_lossses) / len(choice_dataset) + else: + epoch_loss = tf.reduce_mean(epoch_losses) + losses_history["train_loss"].append(epoch_loss) + desc = f"Epoch {epoch_nb} Train Loss {losses_history['train_loss'][-1].numpy()}" + if verbose > 1: + print( + f"Loop {epoch_nb} Time", + time.time() - t_start, + "Loss:", + tf.reduce_sum(epoch_losses).numpy(), + ) + + # Test on val_dataset if provided + if val_dataset is not None: + test_losses = [] + for batch_nb, ( + items_batch, + sessions_batch, + sessions_items_batch, + availabilities_batch, + choices_batch, + ) in enumerate(val_dataset.batch(shuffle=False, batch_size=batch_size)): + self.callbacks.on_batch_begin(batch_nb) + self.callbacks.on_test_batch_begin(batch_nb) + test_losses.append( + self.batch_predict( + items_batch, + sessions_batch, + sessions_items_batch, + availabilities_batch, + choices_batch, + )[0] + ) + val_logs["val_loss"].append(test_losses[-1]) + temps_logs = {k: tf.reduce_mean(v) for k, v in val_logs.items()} + self.callbacks.on_test_batch_end(batch_nb, logs=temps_logs) + test_loss = tf.reduce_mean(test_losses) + if verbose > 1: + print("Test Negative-LogLikelihood:", test_loss.numpy()) + desc += f", Test Loss {test_loss.numpy()}" + losses_history["test_loss"] = losses_history.get("test_loss", []) + [ + test_loss.numpy() + ] + train_logs = {**train_logs, **val_logs} + + temps_logs = {k: tf.reduce_mean(v) for k, v in train_logs.items()} + self.callbacks.on_epoch_end(epoch_nb, logs=temps_logs) + if self.stop_training: + print("Early Stopping taking effect") + break + if verbose > 0: + t_range.set_description(desc) + t_range.refresh() + + temps_logs = {k: tf.reduce_mean(v) for k, v in train_logs.items()} + self.callbacks.on_train_end(logs=temps_logs) + return losses_history + + @tf.function + def batch_predict( + self, + items_batch, + sessions_batch, + sessions_items_batch, + availabilities_batch, + choices_batch, + sample_weight=None, + ): + """Function that represents one prediction (Probas + Loss) for one batch of a ChoiceDataset. + + Parameters + ---------- + items_batch : tuple of np.ndarray (items_features) + Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products + constant features. + sessions_batch : tuple of np.ndarray (sessions_features) + Time-Features + sessions_items_batch : tuple of np.ndarray (sessions_items_features) + Time-Item-Features + availabilities_batch : np.ndarray + Availabilities (sessions_items_availabilities) + choices_batch : np.ndarray + Choices + sample_weight : np.ndarray, optional + List samples weights to apply during the gradient descent to the batch elements, + by default None + + Returns: + -------- + tf.Tensor (1, ) + Value of NegativeLogLikelihood loss for the batch + tf.Tensor (batch_size, n_items) + Probabilities for each product to be chosen for each session + """ + # Compute utilities from features + utilities = self.compute_utility( + items_batch, sessions_batch, sessions_items_batch, availabilities_batch, choices_batch + ) + # Compute probabilities from utilities & availabilties + probabilities = availability_softmax(utilities, availabilities_batch, axis=-1) + probabilities = custom_softmax( + utilities, availabilities_batch, normalize_exit=self.normalize_non_buy, axis=-1 + ) + + # Compute loss from probabilities & actual choices + # batch_loss = self.loss(probabilities, c_batch, sample_weight=sample_weight) + batch_loss = self.loss( + y_pred=probabilities, + y_true=tf.one_hot(choices_batch, depth=probabilities.shape[1]), + sample_weight=sample_weight, + ) + return batch_loss, probabilities + + def save_model(self, path): + """Method to save the different models on disk. + + Parameters + ---------- + path : str + path to the folder where to save the model + """ + if not os.exists(path): + Path(path).mkdir(parents=True) + + for i, weight in enumerate(self.weights): + tf.keras.savedmodel.save(Path(path) / f"weight_{i}") + + # To improve for non-string attributes + params = self.__dict__ + json.dump(Path(path) / "params.json", params) + + # Save optimizer state + + @classmethod + def load_model(cls, path): + """Method to load a ChoiceModel previously saved with save_model(). + + Parameters + ---------- + path : str + path to the folder where the saved model files are + + Returns: + -------- + ChoiceModel + Loaded ChoiceModel + """ + obj = cls() + obj.weights = [] + i = 0 + weight_path = f"weight_{i}" + while weight_path in os.listdir(path): + obj.weights.append(tf.keras.load_model.load(Path(path) / weight_path)) + i += 1 + weight_path = f"weight_{i}" + + # To improve for non string attributes + params = json.load(Path(path) / "params.json") + for k, v in params.items(): + setattr(obj, k, v) + + # Load optimizer step + return cls + + def predict_probas(self, choice_dataset): + """Predicts the choice probabilities for each session and each product of a ChoiceDataset. + + Parameters + ---------- + choice_dataset : ChoiceDataset + Dataset on which to apply to prediction + + Returns: + -------- + np.ndarray (n_sessions, n_items) + Choice probabilties for each session and each product + """ + stacked_probabilities = [] + for ( + items_batch, + sessions_batch, + sessions_items_batch, + availabilities_batch, + choices_batch, + ) in choice_dataset.batch(): + _, probabilities = self.batch_predict( + items_batch, + sessions_batch, + sessions_items_batch, + availabilities_batch, + choices_batch, + ) + stacked_probabilities.append(probabilities) + + return tf.concat(stacked_probabilities, axis=0) + + def evaluate(self, choice_dataset, batch_size=None): + """Evaluates the model for each session and each product of a ChoiceDataset. + + Predicts the probabilities according to the model and computes the Negative-Log-Likelihood + loss from the actual choices. + + Parameters + ---------- + choice_dataset : ChoiceDataset + Dataset on which to apply to prediction + + Returns: + -------- + np.ndarray (n_sessions, n_items) + Choice probabilties for each session and each product + """ + if batch_size is None: + batch_size = choice_dataset.batch_size + batch_losses = [] + for ( + items_batch, + sessions_batch, + sessions_items_batch, + availabilities_batch, + choices_batch, + ) in choice_dataset.batch(batch_size=batch_size): + loss, _ = self.batch_predict( + items_batch, + sessions_batch, + sessions_items_batch, + availabilities_batch, + choices_batch, + ) + batch_losses.append(loss) + if batch_size != -1: + last_batch_size = availabilities_batch.shape[0] + coefficients = tf.concat( + [tf.ones(len(batch_losses) - 1) * batch_size, [last_batch_size]], axis=0 + ) + batch_losses = tf.multiply(batch_losses, coefficients) + batch_loss = tf.reduce_sum(batch_losses) / len(choice_dataset) + else: + batch_loss = tf.reduce_mean(batch_losses) + return batch_loss + + def _lbfgs_train_step(self, dataset): + """A factory to create a function required by tfp.optimizer.lbfgs_minimize. + + Parameters + ---------- + dataset: ChoiceDataset + Dataset on which to estimate the paramters. + + Returns: + -------- + function + with the signature: + loss_value, gradients = f(model_parameters). + """ + # obtain the shapes of all trainable parameters in the model + shapes = tf.shape_n(self.weights) + n_tensors = len(shapes) + + # we'll use tf.dynamic_stitch and tf.dynamic_partition later, so we need to + # prepare required information first + count = 0 + idx = [] # stitch indices + part = [] # partition indices + + for i, shape in enumerate(shapes): + n = np.product(shape) + idx.append(tf.reshape(tf.range(count, count + n, dtype=tf.int32), shape)) + part.extend([i] * n) + count += n + + part = tf.constant(part) + + @tf.function + def assign_new_model_parameters(params_1d): + """A function updating the model's parameters with a 1D tf.Tensor. + + Pararmeters + ----------- + params_1d: tf.Tensor + a 1D tf.Tensor representing the model's trainable parameters. + """ + params = tf.dynamic_partition(params_1d, part, n_tensors) + for i, (shape, param) in enumerate(zip(shapes, params)): + self.weights[i].assign(tf.reshape(param, shape)) + + # now create a function that will be returned by this factory + @tf.function + def f(params_1d): + """A function that can be used by tfp.optimizer.lbfgs_minimize. + + This function is created by function_factory. + + Parameters + ---------- + params_1d: tf.Tensor + a 1D tf.Tensor. + + Returns: + -------- + tf.Tensor + A scalar loss and the gradients w.r.t. the `params_1d`. + tf.Tensor + A 1D tf.Tensor representing the gradients w.r.t. the `params_1d`. + """ + # use GradientTape so that we can calculate the gradient of loss w.r.t. parameters + with tf.GradientTape() as tape: + # update the parameters in the model + assign_new_model_parameters(params_1d) + # calculate the loss + loss_value = self.evaluate(dataset, batch_size=-1) + + # calculate gradients and convert to 1D tf.Tensor + grads = tape.gradient(loss_value, self.weights) + grads = tf.dynamic_stitch(idx, grads) + + # print out iteration & loss + f.iter.assign_add(1) + + # store loss value so we can retrieve later + tf.py_function(f.history.append, inp=[loss_value], Tout=[]) + + return loss_value, grads + + # store these information as members so we can use them outside the scope + f.iter = tf.Variable(0) + f.idx = idx + f.part = part + f.shapes = shapes + f.assign_new_model_parameters = assign_new_model_parameters + f.history = [] + return f + + def _fit_with_lbfgs(self, dataset, n_epochs, tolerance=1e-8): + """Fit function for L-BFGS optimizer. + + Replaces the .fit method when the optimizer is set to L-BFGS. + + Parameters + ---------- + dataset : _type_ + _description_ + n_epochs : _type_ + _description_ + tolerance : _type_, optional + _description_, by default 1e-8 + + Returns: + -------- + dict + Fit history + """ + # Only import tensorflow_probability if LBFGS optimizer is used, avoid unnecessary + # dependency + import tensorflow_probability as tfp + + func = self._lbfgs_train_step(dataset) + + # convert initial model parameters to a 1D tf.Tensor + init_params = tf.dynamic_stitch(func.idx, self.weights) + + # train the model with L-BFGS solver + results = tfp.optimizer.lbfgs_minimize( + value_and_gradients_function=func, + initial_position=init_params, + max_iterations=n_epochs, + tolerance=tolerance, + f_absolute_tolerance=-1, + f_relative_tolerance=-1, + ) + + # after training, the final optimized parameters are still in results.position + # so we have to manually put them back to the model + func.assign_new_model_parameters(results.position) + print("L-BFGS Opimization finished:") + print("---------------------------------------------------------------") + print("Number of iterations:", results[2].numpy()) + print("Algorithm converged before reaching max iterations:", results[0].numpy()) + return func.history + + +class RandomChoiceModel(ChoiceModel): + """Dumb model that randomly attributes utilities to products.""" + + def __init__(self, **kwargs): + """Initialization of the model.""" + super().__init__(**kwargs) + + def compute_utility( + self, items_batch, sessions_batch, sessions_items_batch, availabilities_batch, choices_batch + ): + """Computes the random utility for each product of each session. + + Parameters + ---------- + items_batch : tuple of np.ndarray (items_features) + Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products + constant/fixed features. + sessions_batch : tuple of np.ndarray (sessions_features) + Time-Features + sessions_items_batch : tuple of np.ndarray (sessions_items_features) + Time-Item-Features + availabilities_batch : np.ndarray + Availabilities (sessions_items_availabilities) + choices_batch : np.ndarray + Choices + + Returns: + -------- + tf.Tensor + (n_sessions, n_items) matrix of random utilities + """ + # In order to avoid unused arguments warnings + del items_batch, sessions_batch, availabilities_batch, choices_batch + return np.squeeze(np.random.uniform(shape=(sessions_items_batch.shape), minval=0, maxval=1)) + + def fit(**kwargs): + """Make sure that nothing happens during .fit.""" + del kwargs + return {} + + +class DistribMimickingModel(ChoiceModel): + """Dumb class model that mimicks the probabilities. + + It stores the encountered in the train datasets and always returns them + """ + + def __init__(self, **kwargs): + """Initialization of the model.""" + super().__init__(**kwargs) + self.weights = [] + + def fit(self, choice_dataset, **kwargs): + """Computes the choice frequency of each product and defines it as choice probabilities.""" + del kwargs + choices = choice_dataset.choices + for i in range(choice_dataset.get_num_items()): + self.weights.append(tf.reduce_sum(tf.cast(choices == i, tf.float32))) + self.weights = tf.stack(self.weights) / len(choices) + + def compute_utility( + self, items_batch, sessions_batch, sessions_items_batch, availabilities_batch, choices_batch + ): + """Returns utility that is fixed. U = log(P). + + Parameters + ---------- + items_batch : tuple of np.ndarray (items_features) + Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products + constant/fixed features. + sessions_batch : tuple of np.ndarray (sessions_features) + Time-Features + sessions_items_batch : tuple of np.ndarray (sessions_items_features) + Time-Item-Features + availabilities_batch : np.ndarray + Availabilities (sessions_items_availabilities) + choices_batch : np.ndarray + Choices + + Returns: + -------- + np.ndarray (n_sessions, n_items) + Utilities + + Raises: + ------- + ValueError + If the model has not been fitted cannot evaluate the utility + """ + # In order to avoid unused arguments warnings + del items_batch, sessions_batch, sessions_items_batch, availabilities_batch + if self.weights is None: + raise ValueError("Model not fitted") + return np.stack([np.log(self.weights.numpy())] * len(choices_batch), axis=0) diff --git a/lib/models/conditional_mnl.py b/lib/models/conditional_mnl.py new file mode 100644 index 00000000..9284797e --- /dev/null +++ b/lib/models/conditional_mnl.py @@ -0,0 +1,884 @@ +"""Conditional MNL model.""" + +import tensorflow as tf + +from .base_model import ChoiceModel + + +class ModelSpecification(object): + """Base class to specify the structure of a cMNL.""" + + def __init__(self): + """Instantiate a ModelSpecification object.""" + # User interface + self.coefficients = {} + # Handled by the model + self.feature_to_weight = {} + + def add_coefficients( + self, coefficient_name, feature_name, items_indexes=None, items_names=None + ): + """Adds a coefficient to the model throught the specification of the utility. + + Parameters + ---------- + coefficient_name : str + Name given to the coefficient. + feature_name : str + features name to which the coefficient is associated. It should work with + the names given. + in the ChoiceDataset that will be used for parameters estimation. + items_indexes : list of int, optional + list of items indexes (in the ChoiceDataset) for which we need to add a coefficient, + by default None + items_names : list of str, optional + list of items names (in the ChoiceDataset) for which we need to add a coefficient, + by default None + + Raises: + ------- + ValueError + When names or indexes are both not specified. + """ + if items_indexes is None and items_names is None: + raise ValueError("Either items_indexes or items_names must be specified") + + if isinstance(items_indexes, int): + items_indexes = [items_indexes] + if isinstance(items_names, str): + items_names = [items_names] + self.coefficients[coefficient_name] = { + "feature_name": feature_name, + "items_indexes": items_indexes, + "items_names": items_names, + } + + def add_shared_coefficient( + self, coefficient_name, feature_name, items_indexes=None, items_names=None + ): + """Adds a single, shared coefficient to the model throught the specification of the utility. + + Parameters + ---------- + coefficient_name : str + Name given to the coefficient. + feature_name : str + features name to which the coefficient is associated. It should work with + the names given. + in the ChoiceDataset that will be used for parameters estimation. + items_indexes : list of int, optional + list of items indexes (in the ChoiceDataset) for which the coefficient will be used, + by default None + items_names : list of str, optional + list of items names (in the ChoiceDataset) for which the coefficient will be used, + by default None + + Raises: + ------- + ValueError + When names or indexes are both not specified. + """ + if items_indexes is None and items_names is None: + raise ValueError("Either items_indexes or items_names must be specified") + + if isinstance(items_indexes, int): + print( + "You have added a single index to a shared coefficient. This is not recommended.", + "Returning to standard add_coefficients method.", + ) + self.add_coefficients(coefficient_name, feature_name, items_indexes, items_names) + if isinstance(items_names, str): + print( + "You have added a single name to a shared coefficient. This is not recommended.", + "Returning to standard add_coefficients method.", + ) + self.add_coefficients(coefficient_name, feature_name, items_indexes, items_names) + self.coefficients[coefficient_name] = { + "feature_name": feature_name, + "items_indexes": [items_indexes] if items_indexes is not None else None, + "items_names": items_names if items_names is not None else None, + } + + def get_coefficient(self, coefficient_name): + """Getter of a coefficient specification, from its name. + + Parameters + ---------- + coefficient_name : str + Name of the coefficient to get. + + Returns: + -------- + dict + specification of the coefficient. + """ + return self.coefficients[coefficient_name] + + def add_weight(self, weight_name, weight_index): + """Method used by cMNL class to create the Tensorflow weight corresponding. + + Parameters + ---------- + weight_name : str + Name of the weight to add. + weight_index : int + Index of the weight (in the conditionalMNL) to add. + """ + if weight_name not in self.coefficients.keys(): + raise ValueError(f"Weight {weight_name} not in coefficients") + + self.feature_to_weight[self.coefficients[weight_name]["feature_name"]] = ( + weight_name, + weight_index, + ) + + def list_features_with_weights(self): + """Get a list of the features that have a weight to be estimated. + + Returns: + -------- + dict.keys + List of the features that have a weight to be estimated. + """ + return self.feature_to_weight.keys() + + def get_weight_item_indexes(self, feature_name): + """Get the indexes of the concerned items for a given weight. + + Parameters + ---------- + feature_name : str + Features that is concerned by the weight. + + Returns: + -------- + list + List of indexes of the items concerned by the weight. + int + The index of the weight in the conditionalMNL weights. + """ + weight_name, weight_index = self.feature_to_weight[feature_name] + return self.coefficients[weight_name]["items_indexes"], weight_index + + @property + def coefficients_list(self): + """Returns the list of coefficients. + + Returns: + -------- + dict keys + List of coefficients in the specification. + """ + return list(self.coefficients.keys()) + + +class ConditionalMNL(ChoiceModel): + """Conditional MNL that has a generic structure. It can be parametrized with a dictionnary. + + Arguments: + ---------- + params: dict or ModelSpecification + Specfication of the model to be estimated. + """ + + def __init__( + self, + parameters, + add_exit_choice=False, + optimizer="Adam", + lr=0.001, + **kwargs, + ): + """Initialization of Conditional-MNL. + + Parameters: + ----------- + parameters : dict or ModelSpecification + Dictionnary containing the parametrization of the model. + The dictionnary must have the following structure: + {feature_name_1: mode_1, feature_name_2: mode_2, ...} + mode must be among "constant", "item", "item-full" for now + (same specifications as torch-choice). + add_exit_choice : bool, optional + Whether or not to normalize the probabilities computation with an exit choice + whose utility would be 1, by default True + """ + super().__init__(normalize_non_buy=add_exit_choice, optimizer=optimizer, lr=lr, **kwargs) + self.params = parameters + self.instantiated = False + + def instantiate_from_specifications(self): + """Instantiate the model from ModelSpecification object. + + Returns: + -------- + list of tf.Tensor + List of the weights created coresponding to the specification. + """ + weights = [] + for weight_nb, weight_name in enumerate(self.params.coefficients_list): + num_weights = ( + len(self.params.get_coefficient(weight_name)["items_indexes"]) + if self.params.get_coefficient(weight_name)["items_indexes"] is not None + else len(self.params.get_coefficient(weight_name)["items_names"]) + ) + weight = tf.Variable( + tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(1, num_weights)), + name=weight_name, + ) + weights.append(weight) + """ + feat_to_weight[self.params[weight_name]["feature_name"]] = ( + weight, + self.params[weight_name], + ) + """ + self.params.add_weight(weight_name, weight_nb) + + ## Fill items_indexes here + # Better organize feat_to_weight and specifications + return weights + + def _store_dataset_features_names(self, dataset): + """Registers the name of the features in the dataset. For later use in utility computation. + + Parameters + ---------- + dataset : ChoiceDataset + ChoiceDataset used to fit the model. + """ + self._items_features_names = dataset.items_features_names + self._sessions_features_names = dataset.sessions_features_names + self._sessions_items_features_names = dataset.sessions_items_features_names + + def compute_utility_from_specification( + self, + items_batch, + sessions_batch, + sessions_items_batch, + availabilities_batch, + choices_batch, + verbose=0, + ): + """Computes the utility when the model is constructed from a ModelSpecification object. + + Parameters + ---------- + tems_batch : tuple of np.ndarray (items_features) + Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products + constant/fixed features. + Shape must be (n_items, n_items_features) + sessions_batch : tuple of np.ndarray (sessions_features) + Time-Features + Shape must be (n_sessions, n_sessions_features) + sessions_items_batch : tuple of np.ndarray (sessions_items_features) + Time-Item-Features + Shape must be (n_sessions, n_sessions_items_features) + availabilities_batch : np.ndarray + Availabilities (sessions_items_availabilities) + Shape must be (n_sessions, n_items) + choices_batch : np.ndarray + Choices + Shape must be (n_sessions, ) + verbose : int, optional + Parametrization of the logging outputs, by default 0 + + Returns: + -------- + tf.Tensor + Utilities corresponding of shape (n_sessions, n_items) + """ + del choices_batch, verbose + + num_items = availabilities_batch.shape[1] + num_sessions = availabilities_batch.shape[0] + sessions_items_utilities = [] + # Items features + for i, feat_tuple in enumerate(self._items_features_names): + for j, feat in enumerate(feat_tuple): + if feat in self.params.list_features_with_weights(): + item_index, weight_index = self.params.get_weight_item_indexes(feat) + + s_i_u = tf.zeros((num_items,)) + for q, idx in enumerate(item_index): + if isinstance(idx, list): + for k in idx: + s_i_u = tf.concat( + [ + s_i_u[:k], + tf.multiply( + items_batch[i][k, j], self.weights[weight_index][:, q] + ), + s_i_u[k + 1 :], + ], + axis=0, + ) + else: + s_i_u = tf.concat( + [ + s_i_u[:idx], + tf.multiply( + items_batch[i][idx, j], self.weights[weight_index][:, q] + ), + s_i_u[idx + 1 :], + ], + axis=0, + ) + s_i_u = tf.stack([s_i_u] * num_sessions, axis=0) + + ### Need reshaping here + sessions_items_utilities.append(s_i_u) + else: + print( + f"Feature {feat} is in dataset but has no weight assigned in utility\ + computations" + ) + + # Session features + for i, feat_tuple in enumerate(self._sessions_features_names): + for j, feat in enumerate(feat_tuple): + if feat in self.params.list_features_with_weights(): + item_index, weight_index = self.params.get_weight_item_indexes(feat) + + s_i_u = tf.zeros((num_sessions, num_items)) + + for q, idx in enumerate(item_index): + if isinstance(idx, list): + for k in idx: + s_i_u = tf.concat( + [ + s_i_u[:, :k], + tf.expand_dims( + tf.multiply( + sessions_batch[i][:, j], + self.weights[weight_index][:, q], + ), + axis=-1, + ), + s_i_u[:, k + 1 :], + ], + axis=1, + ) + else: + s_i_u = tf.concat( + [ + s_i_u[:, :idx], + tf.expand_dims( + tf.multiply( + sessions_batch[i][:, j], + self.weights[weight_index][:, q], + ), + axis=-1, + ), + s_i_u[:, idx + 1 :], + ], + axis=1, + ) + + sessions_items_utilities.append(s_i_u) + else: + print( + f"Feature {feat} is in dataset but has no weight assigned in utility\ + computations" + ) + + # Session Items features + for i, feat_tuple in enumerate(self._sessions_items_features_names): + for j, feat in enumerate(feat_tuple): + if feat in self.params.list_features_with_weights(): + item_index, weight_index = self.params.get_weight_item_indexes(feat) + s_i_u = tf.zeros((num_sessions, num_items)) + + for q, idx in enumerate(item_index): + if isinstance(idx, list): + for k in idx: + s_i_u = tf.concat( + [ + s_i_u[:, :k], + tf.expand_dims( + tf.multiply( + sessions_items_batch[i][:, k, j], + self.weights[weight_index][:, q], + ), + axis=-1, + ), + s_i_u[:, k + 1 :], + ], + axis=1, + ) + else: + s_i_u = tf.concat( + [ + s_i_u[:, :idx], + tf.expand_dims( + tf.multiply( + sessions_items_batch[i][:, idx, j], + self.weights[weight_index][:, q], + ), + axis=-1, + ), + s_i_u[:, idx + 1 :], + ], + axis=1, + ) + + sessions_items_utilities.append(s_i_u) + else: + print( + f"Feature {feat} is in dataset but has no weight assigned in utility\ + computations" + ) + + if "intercept" in self.params.list_features_with_weights(): + item_index, weight_index = self.params.get_weight_item_indexes("intercept") + + s_i_u = tf.zeros((num_items,)) + for q, idx in enumerate(item_index): + s_i_u = tf.concat( + [ + s_i_u[:idx], + self.weights[weight_index][:, q], + s_i_u[idx + 1 :], + ], + axis=0, + ) + + s_i_u = tf.stack([s_i_u] * num_sessions, axis=0) + + ### Need reshaping here + + sessions_items_utilities.append(s_i_u) + + return tf.reduce_sum(sessions_items_utilities, axis=0) + + def instantiate_from_dict(self, num_items): + """Instantiation of the model from a dictionnary specification. + + Parameters + ---------- + num_items : int + Number of different items in the assortment. Used to create the right number of weights. + """ + spec = ModelSpecification() + weight_counter = 0 + for feature, mode in self.params.items(): + if mode == "constant": + spec.add_shared_coefficient( + feature + f"_w_{weight_counter}", feature, list(range(num_items)) + ) + elif mode == "item": + spec.add_coefficients( + feature + f"_w_{weight_counter}", feature, list(range(1, num_items)) + ) + elif mode == "item-full": + spec.add_coefficients( + feature + f"_w_{weight_counter}", feature, list(range(num_items)) + ) + + weight_counter += 1 + self.params = spec + self.instantiate_from_specifications() + + def instantiate( + self, + num_items, + items_features_names, + sessions_features_names, + sessions_items_features_names, + ): + """Instantiate the model from self.params and a dataset. + + Model is thus instantiated at .fit() time. + + Parameters + ---------- + num_items : int + Number of different items in the assortment. Used to create the right number of weights. + items_features_names : list of str + Names of the items features in the dataset. + sessions_features_names : list of str + Names of the sessions features in the dataset. + sessions_items_features_names : list of str + Names of the sessions items features in the dataset. + + Raises: + ------- + NotImplementedError + When a mode is wrongly precised. + """ + # Possibility to stack weights to be faster ???? + weights = [] + weights_count = 0 + self._items_features_names = [] + for feat_tuple in items_features_names: + tuple_names = [] + for feat in feat_tuple: + if feat in self.params.keys(): + if self.params[feat] == "constant": + weight = tf.Variable( + tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(1, 1)) + ) + elif self.params[feat] == "item": + weight = tf.Variable( + tf.random_normal_initializer(0.0, 0.02, seed=42)( + shape=(1, num_items - 1) + ) + ) + elif self.params[feat] == "item-full": + weight = tf.Variable( + tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(1, num_items)) + ) + else: + raise NotImplementedError(f"Param {self.params[feat]} not implemented") + weights.append(weight) + tuple_names.append((feat, weights_count)) + weights_count += 1 + + else: + print( + f"Feature {feat} is in dataset but has no weight assigned in utility\ + computations" + ) + if len(tuple_names) > 0: + self._items_features_names.append(tuple_names) + + self._sessions_features_names = [] + for feat_tuple in sessions_features_names: + tuple_names = [] + for feat in feat_tuple: + if feat in self.params.keys(): + if self.params[feat] == "constant": + weight = tf.Variable( + tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(1, 1)), + name=feat, + ) + elif self.params[feat] == "item": + weight = tf.Variable( + tf.random_normal_initializer(0.0, 0.02, seed=42)( + shape=(1, num_items - 1) + ), + name=feat, + ) + elif self.params[feat] == "item-full": + weight = tf.Variable( + tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(1, num_items)), + name=feat, + ) + else: + raise NotImplementedError(f"Param {self.params[feat]} not implemented") + weights.append(weight) + tuple_names.append((feat, weights_count)) + weights_count += 1 + else: + print( + f"Feature {feat} is in dataset but has no weight assigned in utility\ + computations" + ) + if len(tuple_names) > 0: + self._sessions_features_names.append(tuple_names) + + self._sessions_items_features_names = [] + for feat_tuple in sessions_items_features_names: + tuple_names = [] + for feat in feat_tuple: + if feat in self.params.keys(): + if self.params[feat] == "constant": + weight = tf.Variable( + tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(1, 1)), + name=feat, + ) + elif self.params[feat] == "item": + weight = tf.Variable( + tf.random_normal_initializer(0.0, 0.02, seed=42)( + shape=(1, num_items - 1) + ), + name=feat, + ) + elif self.params[feat] == "item-full": + weight = tf.Variable( + tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(1, num_items)), + name=feat, + ) + else: + for i, s_tuple in enumerate(sessions_features_names): + for j, s_feat in enumerate(s_tuple): + if s_feat == self.params[feat]: + # Get num weights with unique values of this feature + # Create a dictionary {value: weight} + # mydict = {} + # for i, j in enumerate( + # np.unique(dataset.sessions_features[i][:, j]) + # ): + # mydict[i] = j + # weight = tf.Variable( + # tf.random_normal_initializer(0.0, 0.02, seed=42)( + # shape=(1, j + 1) + # ), + # name=feat, + # ) + pass + raise NotImplementedError(f"Param {self.params[feat]} not implemented") + weights.append(weight) + tuple_names.append((feat, weights_count)) + weights_count += 1 + else: + print( + f"Feature {feat} is in dataset but has no weight assigned in utility\ + computations" + ) + + if len(tuple_names) > 0: + self._sessions_items_features_names.append(tuple_names) + + if "intercept" in self.params.keys(): + if self.params["intercept"] == "constant": + weight = tf.Variable( + tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(1, 1)), name="intercept" + ) + elif self.params["intercept"] == "item": + weight = tf.Variable( + tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(1, num_items - 1)), + name="intercept", + ) + elif self.params["intercept"] == "item-full": + weight = tf.Variable( + tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(1, num_items)), + name="intercept", + ) + else: + # Is supposed to be in sessions_features_names + raise NotImplementedError(f"Param {self.params['intercept']} not implemented") + weights.append(weight) + else: + print("No Intercept specified... was it forgotten ?") + + if len(weights) > 0: + self.instantiated = True + else: + raise ValueError("No weights instantiated") + return weights + + def compute_utility( + self, items_batch, sessions_batch, sessions_items_batch, availabilities_batch, choices_batch + ): + """Main method to compute the utility of the model. Selects the right method to compute. + + Parameters + ---------- + items_batch : tuple of np.ndarray (items_features) + Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products + constant/fixed features. + Shape must be (n_items, n_items_features) + sessions_batch : tuple of np.ndarray (sessions_features) + Time-Features + Shape must be (n_sessions, n_sessions_features) + sessions_items_batch : tuple of np.ndarray (sessions_items_features) + Time-Item-Features + Shape must be (n_sessions, n_sessions_items_features) + availabilities_batch : np.ndarray + Availabilities (sessions_items_availabilities) + Shape must be (n_sessions, n_items) + choices_batch : np.ndarray + Choices Shape must be (n_sessions, ) + + Returns: + -------- + tf.Tensor + Computed utilities of shape (n_sessions, n_items). + """ + if isinstance(self.params, ModelSpecification): + return self.compute_utility_from_specification( + items_batch, + sessions_batch, + sessions_items_batch, + availabilities_batch, + choices_batch, + ) + return self.compute_utility_from_dict( + items_batch, + sessions_batch, + sessions_items_batch, + availabilities_batch, + choices_batch, + ) + + def compute_utility_from_dict( + self, items_batch, sessions_batch, sessions_items_batch, availabilities_batch, choices_batch + ): + """Computes the utility when the model is constructed from a dictionnary object. + + Parameters + ---------- + tems_batch : tuple of np.ndarray (items_features) + Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products + constant/fixed features. + Shape must be (n_items, n_items_features) + sessions_batch : tuple of np.ndarray (sessions_features) + Time-Features + Shape must be (n_sessions, n_sessions_features) + sessions_items_batch : tuple of np.ndarray (sessions_items_features) + Time-Item-Features + Shape must be (n_sessions, n_sessions_items_features) + availabilities_batch : np.ndarray + Availabilities (sessions_items_availabilities) + Shape must be (n_sessions, n_items) + choices_batch : np.ndarray + Choices + Shape must be (n_sessions, ) + verbose : int, optional + Parametrization of the logging outputs, by default 0 + + Returns: + -------- + tf.Tensor + Utilities corresponding of shape (n_sessions, n_items) + """ + del availabilities_batch, choices_batch + + sessions_items_utilities = [] + num_items = items_batch[0].shape[0] + num_sessions = sessions_batch[0].shape[0] + + # Items features + for i, feat_tuple in enumerate(self._items_features_names): + for j, (feat, k) in enumerate(feat_tuple): + if feat in self.params.keys(): + weight = self.weights[k] + if self.params[feat] == "constant": + s_i_u = tf.concat( + [tf.multiply(items_batch[i][:, j], weight)] * num_sessions, axis=0 + ) + elif self.params[feat] == "item": + weight = tf.concat([tf.constant([[0.0]]), weight], axis=-1) + s_i_u = tf.concat( + [tf.multiply(items_batch[i][:, j], weight)] * num_sessions, axis=0 + ) + elif self.params[feat] == "item-full": + s_i_u = tf.concat( + [tf.multiply(items_batch[i][:, j], weight)] * num_sessions, axis=0 + ) + else: + raise NotImplementedError(f"Param {self.params[feat]} not implemented") + sessions_items_utilities.append(s_i_u) + else: + print( + f"Feature {feat} is in dataset but has no weight assigned in utility \ + computations" + ) + + # Session features + for i, feat_tuple in enumerate(self._sessions_features_names): + for j, (feat, k) in enumerate(feat_tuple): + if feat in self.params.keys(): + weight = self.weights[k] + if self.params[feat] == "constant": + s_i_u = tf.concat( + [tf.multiply(sessions_batch[i][j], weight)] * num_items, axis=-1 + ) + elif self.params[feat] == "item": + weight = tf.concat([tf.constant([[0.0]]), weight], axis=-1) + s_i_u = tf.tensordot(sessions_batch[i][:, j : j + 1], weight, axes=1) + elif self.params[feat] == "item-full": + s_i_u = tf.tensordot(sessions_batch[i][:, j : j + 1], weight, axes=1) + else: + raise NotImplementedError(f"Param {self.params[feat]} not implemented") + sessions_items_utilities.append(s_i_u) + else: + print( + f"Feature {feat} is in dataset but has no weight assigned in utility \ + computations" + ) + + # Session Items features + for i, feat_tuple in enumerate(self._sessions_items_features_names): + for j, (feat, k) in enumerate(feat_tuple): + if feat in self.params.keys(): + weight = self.weights[k] + if self.params[feat] == "constant": + s_i_u = tf.multiply(sessions_items_batch[i][:, :, j], weight) + elif self.params[feat] == "item": + weight = tf.concat([tf.constant([[0.0]]), weight], axis=-1) + s_i_u = tf.multiply(sessions_items_batch[i][:, :, j], weight) + elif self.params[feat] == "item-full": + s_i_u = tf.multiply(sessions_items_batch[i][:, :, j], weight) + else: + raise NotImplementedError(f"Param {self.params[feat]} not implemented") + sessions_items_utilities.append(s_i_u) + else: + print( + f"Feature {feat} is in dataset but has no weight assigned in utility \ + computations" + ) + + if "intercept" in self.params.keys(): + weight = self.weights[-1] + if self.params["intercept"] == "constant": + s_i_u = tf.concat([tf.concat([weight] * num_items, axis=0)] * num_sessions, axis=0) + elif self.params["intercept"] == "item": + weight = tf.concat([tf.constant([[0.0]]), weight], axis=-1) + s_i_u = tf.concat([weight] * num_sessions, axis=0) + elif self.params["intercept"] == "item-full": + s_i_u = tf.concat([weight] * num_sessions, axis=0) + else: + raise NotImplementedError(f"Param {self.params[feat]} not implemented") + sessions_items_utilities.append(s_i_u) + + return tf.reduce_sum(sessions_items_utilities, axis=0) + + def fit(self, choice_dataset, **kwargs): + """Main fit function to estimate the paramters. + + Parameters + ---------- + choice_dataset : ChoiceDataset + Choice dataset to use for the estimation. + + Returns: + -------- + ConditionalMNL + With estimated weights. + """ + if not self.instantiated: + if isinstance(self.params, ModelSpecification): + self.weights = self.instantiate_from_specifications() + self._store_dataset_features_names(choice_dataset) + else: + self.weights = self.instantiate( + num_items=choice_dataset.get_num_items(), + items_features_names=choice_dataset.items_features_names, + sessions_features_names=choice_dataset.sessions_features_names, + sessions_items_features_names=choice_dataset.sessions_items_features_names, + ) + self.instantiated = True + return super().fit(choice_dataset=choice_dataset, **kwargs) + + def _fit_with_lbfgs(self, choice_dataset, n_epochs, tolerance=1e-8): + """Specific fit function to estimate the paramters with LBFGS. + + Parameters + ---------- + choice_dataset : ChoiceDataset + Choice dataset to use for the estimation. + n_epochs : int + Number of epochs to run. + tolerance : float, optional + Tolerance in the research of minimum, by default 1e-8 + + Returns: + -------- + conditionalMNL + self with estimated weights. + """ + if not self.instantiated: + if isinstance(self.params, ModelSpecification): + self.weights = self.instantiate_from_specifications() + self._store_dataset_features_names(choice_dataset) + else: + self.weights = self.instantiate( + num_items=choice_dataset.get_num_items(), + items_features_names=choice_dataset.items_features_names, + sessions_features_names=choice_dataset.sessions_features_names, + sessions_items_features_names=choice_dataset.sessions_items_features_names, + ) + self.instantiated = True + return super()._fit_with_lbfgs(choice_dataset, n_epochs, tolerance) diff --git a/lib/models/rumnet.py b/lib/models/rumnet.py new file mode 100644 index 00000000..2b51837b --- /dev/null +++ b/lib/models/rumnet.py @@ -0,0 +1,816 @@ +"""Implementation of RUMnet for easy use.""" +import tensorflow as tf +from choice_modeling.models.base_model import ChoiceModel + + +class PaperRUMnet(ChoiceModel): + """Re-Implementation of the RUMnet model. + + Re-implemented from the paper: + Representing Random Utility Choice Models with Neural Networks from Ali Aouad and Antoine Désir + https://arxiv.org/abs/2207.12877 + + Inherits from base_model.ChoiceModel + """ + + def __init__( + self, + num_products_features, + num_customer_features, + width_eps_x, + depth_eps_x, + heterogeneity_x, + width_eps_z, + depth_eps_z, + heterogeneity_z, + width_u, + depth_u, + tol, + optimizer, + lr, + normalize_non_buy=True, + logmin=1e-5, + l2_regularization_coef=0.0, + label_smoothing=0.0, + **kwargs, + ): + """Initiation of the RUMnet Model. + + Parameters + ---------- + num_products_features : int + Number of features each product will be described with. + In terms of ChoiceDataset it is the number of + { items_features + sessions_items_features } for one product. + num_customer_features : int + Number of features each customer will be described with. + In terms of ChoiceDataset it is the number of sessions_features. + width_eps_x : int + Number of neurons for each dense layer for the products encoding net. + depth_eps_x : int + Number of dense layers for the products encoding net. + heterogeneity_x : int + Number of nets of products features encoding. + width_eps_z : int + Number of neurons for each dense layer for the customers encoding net. + depth_eps_z : int + Number of dense layers for the customers encoding net. + heterogeneity_z : int + Number of nets of customers features encoding. + width_u : int + Number of neurons for each dense layer for the utility net. + depth_u : int + Number of dense layers for the utility net. + tol : float + # To be Implemented + optimizer : str + String representation of the optimizer to use. By default is Adam if not specified. + Should be within tf.keras.optimizers. + lr : float + Starting learning rate to associate with optimizer. + normalize_non_buy : bool, optional + Whether or not to add exit option with utility 1, by default True + logmin : float, optional + Value to be added within log computation to avoid infinity, by default 1e-5 + l2_regularization_coef : float, optional + Value of dense layers weights regulariation to apply during training, by default 0.0 + label_smoothing : float, optional + Value of smoothing to apply in CrossEntropy loss computation, by default 0.0 + """ + super().__init__(normalize_non_buy=normalize_non_buy, **kwargs) + # Number of features + self.num_products_features = num_products_features + self.num_customer_features = num_customer_features + + # Dimension of encoding nets + self.width_eps_x = width_eps_x + self.depth_eps_x = depth_eps_x + self.heterogeneity_x = heterogeneity_x + + self.width_eps_z = width_eps_z + self.depth_eps_z = depth_eps_z + self.heterogeneity_z = heterogeneity_z + + # Dimension of utility net + self.width_u = width_u + self.depth_u = depth_u + + # Optimization parameters + self.logmin = logmin + self.tol = tol + self.lr = lr + self.normalize_non_buy = normalize_non_buy + self.l2_regularization_coef = l2_regularization_coef + self.label_smoothing = label_smoothing + + if optimizer == "Adam": + self.optimizer = tf.keras.optimizers.Adam(lr) + elif optimizer == "SGD": + self.optimizer = tf.keras.optimizers.SGD(lr) + elif optimizer == "Adamax": + self.optimizer = tf.keras.optimizers.Adamax(lr) + else: + print(f"Optimizer {optimizer} not implemnted, switching for default Adam") + self.optimizer = tf.keras.optimizers.Adam(lr) + + def instantiate(self): + """Instatiation of the RUMnet model. + + Creation of : + - x_model encoding products features, + - z_model encoding customers features, + - u_model computing utilities from product, customer features and their embeddings + """ + # Instatiation of the different nets + self.x_model, self.z_model, self.u_model = recreate_official_nets( + num_products_features=self.num_products_features, + num_customer_features=self.num_customer_features, + x_width=self.width_eps_x, + x_depth=self.depth_eps_x, + x_eps=self.heterogeneity_x, + z_width=self.width_eps_z, + z_depth=self.depth_eps_z, + z_eps=self.heterogeneity_z, + width_u=self.width_u, + depth_u=self.depth_u, + l2_regularization_coeff=self.l2_regularization_coef, + ) + + # Storing weights for back-propagation + self.weights = self.x_model.weights + self.z_model.weights + self.u_model.weights + self.loss = tf.keras.losses.CategoricalCrossentropy( + from_logits=False, label_smoothing=self.label_smoothing + ) + + def compute_utility( + self, + items_features_batch, + session_features_batch, + session_items_features_batch, + availabilities_batch, + choices_batch, + ): + """Compute utility from a batch of ChoiceDataset. + + Here we asssume that: item features = {fixed item features + session item features} + user features = {session features} + + Parameters + ---------- + items_features_batch : tuple of np.ndarray (items_features) + Items-Features: formatting from ChoiceDataset: a matrix representing the + products constant features. + session_features_batch : tuple of np.ndarray (sessions_features) + Time-Features + session_items_features_batch :tuple of np.ndarray (sessions_items_features) + Time-Item-Features + availabilities_batch : np.ndarray + Availabilities (sessions_items_availabilities) + choices_batch : np.ndarray + Choices + + Returns: + -------- + np.ndarray + Utility of each product for each session. + Shape must be (n_sessions, n_items) + """ + del availabilities_batch, choices_batch + ### Restacking of the item features + items_features_batch = tf.concat([*items_features_batch], axis=-1) + session_features_batch = tf.concat([*session_features_batch], axis=-1) + session_items_features_batch = tf.concat([*session_items_features_batch], axis=-1) + + full_item_features = tf.stack( + [items_features_batch] * session_items_features_batch.shape[0], axis=0 + ) + full_item_features = tf.concat([session_items_features_batch, full_item_features], axis=-1) + + ### Computation of utilities + utilities = [] + + # Computation of the customer features embeddings + z_embeddings = self.z_model(session_features_batch) + + # Iterate over items in assortment + for item_i in range(full_item_features.shape[1]): + # Computation of item features embeddings + x_embeddings = self.x_model(full_item_features[:, item_i, :]) + + utilities.append([]) + + # Computation of utilites from embeddings, iteration over heterogeneities + # (eps_x * eps_z) + for _x in x_embeddings: + for _z in z_embeddings: + _u = tf.keras.layers.Concatenate()( + [full_item_features[:, item_i, :], _x, session_features_batch, _z] + ) + utilities[-1].append(self.u_model(_u)) + + ### Reshape utilities: (batch_size, num_items, heterogeneity) + return tf.transpose(tf.squeeze(tf.stack(utilities, axis=0), -1)) + + @tf.function + def train_step( + self, + items_batch, + sessions_batch, + sessions_items_batch, + availabilities_batch, + choices_batch, + sample_weight=None, + ): + """Modified version of train step, as we have to average probabilities over heterogeneities. + + Mayber split into two functions? + One for computing probabilities, one for gradient descent ? + Parameters to be renamed ! + Function that represents one training step (= one gradient descent step) of the model. + + Parameters + ---------- + items_batch : tuple of np.ndarray (items_features) + Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing + the products constant features. + sessions_batch : tuple of np.ndarray (sessions_features) + Time-Features + sessions_items_batch : tuple of np.ndarray (sessions_items_features) + Time-Item-Features + availabilities_batch : np.ndarray + Availabilities (sessions_items_availabilities) + choices_batch : np.ndarray + Choices + sample_weight : np.ndarray, optional + List samples weights to apply during the gradient descent to the batch elements, + by default None + + Returns: + -------- + tf.Tensor + Value of NegativeLogLikelihood loss for the batch + """ + with tf.GradientTape() as tape: + ### Computation of utilities + all_u = self.compute_utility( + items_batch, + sessions_batch, + sessions_items_batch, + availabilities_batch, + choices_batch, + ) + probabilities = [] + + # Iterate over heterogeneities + # for i in range(all_u.shape[2]): + # Assortment(t) Utility + # eps_probabilities = availability_softmax(all_u[:, :, i], ia_batch, axis=2) + eps_probabilities = tf.nn.softmax(all_u, axis=2) + # probabilities.append(eps_probabilities) + + # Average probabilities over heterogeneities + probabilities = tf.reduce_mean(eps_probabilities, axis=1) + """ + # Test with availability normalization + probabilities = tf.multiply(probabilities, ia_batch) + probabilities = tf.divide( + probabilities, tf.reduce_sum(probabilities, axis=1, keepdims=True) + 1e-5 + ) + """ + # Probabilities of selected products + # chosen_probabilities = tf.gather_nd(indices=choices_nd, params=probabilities) + + # Negative Log-Likelihood + nll = self.loss( + y_pred=probabilities, + y_true=tf.one_hot(choices_batch, depth=probabilities.shape[1]), + sample_weight=sample_weight, + ) + # nll = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False)( + # y_pred=probabilities, y_true=c_batch + # ) + # nll = -tf.reduce_sum(tf.math.log(chosen_probabilities + self.logmin)) + + grads = tape.gradient(nll, self.weights) + self.optimizer.apply_gradients(zip(grads, self.weights)) + return nll + + @tf.function + def batch_predict( + self, + items_batch, + sessions_batch, + sessions_items_batch, + availabilities_batch, + choices_batch, + sample_weight=None, + ): + """Function that represents one prediction (Probas + Loss) for one batch of a ChoiceDataset. + + Specific version for RUMnet because it is needed to average probabilities over + heterogeneities. + + Parameters + ---------- + items_batch : tuple of np.ndarray (items_features) + Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products + constant features. + sessions_batch : tuple of np.ndarray (sessions_features) + Time-Features + sessions_items_batch : tuple of np.ndarray (sessions_items_features) + Time-Item-Features + availabilities_batch : np.ndarray + Availabilities (sessions_items_availabilities) + choices_batch : np.ndarray + Choices + sample_weight : np.ndarray, optional + List samples weights to apply during the gradient descent to the batch elements, + by default None + + Returns: + -------- + tf.Tensor (1, ) + Value of NegativeLogLikelihood loss for the batch + tf.Tensor (batch_size, n_items) + Probabilities for each product to be chosen for each session + """ + utilities = self.compute_utility( + items_batch, sessions_batch, sessions_items_batch, availabilities_batch, choices_batch + ) + probabilities = tf.nn.softmax(utilities, axis=2) + probabilities = tf.reduce_mean(probabilities, axis=1) + + # Test with availability normalization + """ + probabilities = tf.multiply(probabilities, ia_batch) + probabilities = tf.divide( + probabilities, tf.reduce_sum(probabilities, axis=1, keepdims=True) + 1e-5 + ) + """ + batch_loss = self.loss( + y_pred=probabilities, + y_true=tf.one_hot(choices_batch, depth=probabilities.shape[1]), + sample_weight=sample_weight, + ) + return batch_loss, probabilities + + +class PaperRUMnet2(PaperRUMnet): + """Other implementation.""" + + def compute_utility( + self, + items_features_batch, + session_features_batch, + session_items_features_batch, + availabilities_batch, + choices_batch, + ): + """Compute utility from a batch of ChoiceDataset. + + Here we asssume that: item features = {fixed item features + session item features} + user features = {session features} + + Parameters + ---------- + items_features_batch : tuple of np.ndarray (items_features) + Items-Features: formatting from ChoiceDataset: a matrix representing + the products constant features. + session_features_batch : tuple of np.ndarray (sessions_features) + Time-Features + session_items_features_batch :tuple of np.ndarray (sessions_items_features) + Time-Item-Features + availabilities_batch : np.ndarray + Availabilities (sessions_items_availabilities) + choices_batch : np.ndarray + Choices + + Returns: + -------- + np.ndarray + Utility of each product for each session. + Shape must be (n_sessions, n_items) + """ + del availabilities_batch, choices_batch + ### Restacking of the item features + items_features_batch = tf.concat([*items_features_batch], axis=-1) + session_features_batch = tf.concat([*session_features_batch], axis=-1) + session_items_features_batch = tf.concat([*session_items_features_batch], axis=-1) + + full_item_features = tf.stack( + [items_features_batch] * session_items_features_batch.shape[0], axis=0 + ) + full_item_features = tf.concat([session_items_features_batch, full_item_features], axis=-1) + + ### Computation of utilities + utilities = [] + + # Computation of the customer features embeddings + z_embeddings = self.z_model(session_features_batch) + + # Iterate over items in + def apply_u(x): + return self.u_model(x) + + for item_i in range(full_item_features.shape[1]): + # Computation of item features embeddings + x_embeddings = self.x_model(full_item_features[:, item_i, :]) + + # utilities.append([]) + + # Computation of utilites from embeddings, iteration over heterogeneities + # (eps_x * eps_z) + _utilities = [] + for _x in x_embeddings: + for _z in z_embeddings: + _u = tf.keras.layers.Concatenate()( + [full_item_features[:, item_i, :], _x, session_features_batch, _z] + ) + _utilities.append(_u) + utilities.append( + tf.map_fn( + fn=apply_u, elems=tf.stack(_utilities, axis=0), fn_output_signature=tf.float32 + ) + ) + ### Reshape utilities: (batch_size, num_items, heterogeneity) + return tf.transpose(tf.squeeze(tf.stack(utilities, axis=0), -1)) + + +class PaperRUMnet3(PaperRUMnet): + """Other Implementation.""" + + def compute_utility( + self, + items_features_batch, + session_features_batch, + session_items_features_batch, + availabilities_batch, + choices_batch, + ): + """Compute utility from a batch of ChoiceDataset. + + Here we asssume that: item features = {fixed item features + session item features} + user features = {session features} + + Parameters + ---------- + items_features_batch : tuple of np.ndarray (items_features) + Items-Features: formatting from ChoiceDataset: a matrix representing the products + constant features. + session_features_batch : tuple of np.ndarray (sessions_features) + Time-Features + session_items_features_batch :tuple of np.ndarray (sessions_items_features) + Time-Item-Features + availabilities_batch : np.ndarray + Availabilities (sessions_items_availabilities) + choices_batch : np.ndarray + Choices + + Returns: + -------- + np.ndarray + Utility of each product for each session. + Shape must be (n_sessions, n_items) + """ + del availabilities_batch, choices_batch + ### Restacking of the item features + items_features_batch = tf.concat([*items_features_batch], axis=-1) + session_features_batch = tf.concat([*session_features_batch], axis=-1) + session_items_features_batch = tf.concat([*session_items_features_batch], axis=-1) + + full_item_features = tf.stack( + [items_features_batch] * session_items_features_batch.shape[0], axis=0 + ) + full_item_features = tf.concat([session_items_features_batch, full_item_features], axis=-1) + + ### Computation of utilities + utilities = [] + + # Computation of the customer features embeddings + z_embeddings = self.z_model(session_features_batch) + + # Iterate over items in assortment + # for item_i in range(full_item_features.shape[1]): + def apply_u(x): + # Computation of item features embeddings + x_embeddings = self.x_model(x) + + utilities = [] + + # Computation of utilites from embeddings, iteration over heterogeneities + # (eps_x * eps_z) + for _x in x_embeddings: + for _z in z_embeddings: + _u = tf.keras.layers.Concatenate()([x, _x, session_features_batch, _z]) + utilities.append(self.u_model(_u)) + return tf.stack(utilities, axis=0) + + utilities = tf.map_fn(fn=apply_u, elems=tf.transpose(full_item_features, perm=[1, 0, 2])) + ### Reshape utilities: (batch_size, num_items, heterogeneity) + return tf.transpose(tf.squeeze(tf.stack(utilities, axis=0), -1)) + + +class PaperRUMnet4(PaperRUMnet): + """Other Implementation.""" + + def compute_utility( + self, + items_features_batch, + session_features_batch, + session_items_features_batch, + availabilities_batch, + choices_batch, + ): + """Compute utility from a batch of ChoiceDataset. + + Here we asssume that: item features = {fixed item features + session item features} + user features = {session features} + + Parameters + ---------- + items_features_batch : tuple of np.ndarray (items_features) + Items-Features: formatting from ChoiceDataset: a matrix representing + the products constant features. + session_features_batch : tuple of np.ndarray (sessions_features) + Time-Features + session_items_features_batch :tuple of np.ndarray (sessions_items_features) + Time-Item-Features + availabilities_batch : np.ndarray + Availabilities (sessions_items_availabilities) + choices_batch : np.ndarray + Choices + + Returns: + -------- + np.ndarray + Utility of each product for each session. + Shape must be (n_sessions, n_items) + """ + del availabilities_batch, choices_batch + ### Restacking of the item features + items_features_batch = tf.concat([*items_features_batch], axis=-1) + session_features_batch = tf.concat([*session_features_batch], axis=-1) + session_items_features_batch = tf.concat([*session_items_features_batch], axis=-1) + + full_item_features = tf.stack( + [items_features_batch] * session_items_features_batch.shape[0], axis=0 + ) + full_item_features = tf.concat([session_items_features_batch, full_item_features], axis=-1) + + ### Computation of utilities + utilities = [] + batch_size = session_features_batch.shape[0] + + # Computation of the customer features embeddings + z_embeddings = self.z_model(session_features_batch) + + # Iterate over items in assortment + for item_i in range(full_item_features.shape[1]): + # Computation of item features embeddings + x_embeddings = self.x_model(full_item_features[:, item_i, :]) + + # utilities.append([]) + _utilities = [] + # Computation of utilites from embeddings, iteration over heterogeneities + # (eps_x * eps_z) + for _x in x_embeddings: + for _z in z_embeddings: + _u = tf.keras.layers.Concatenate()( + [full_item_features[:, item_i, :], _x, session_features_batch, _z] + ) + _utilities.append(_u) + item_utilities = self.u_model(tf.concat(_utilities, axis=0)) + item_utilities = tf.stack( + [ + item_utilities[batch_size * i : batch_size * (i + 1)] + for i in range(len(x_embeddings) * len(z_embeddings)) + ], + axis=1, + ) + utilities.append(item_utilities) + ### Reshape utilities: (batch_size, num_items, heterogeneity) + return tf.squeeze(tf.stack(utilities, axis=1), -1) + + +class PaperRUMnet5(PaperRUMnet): + """Other Implementation.""" + + def compute_utility( + self, + items_features_batch, + session_features_batch, + session_items_features_batch, + availabilities_batch, + choices_batch, + ): + """Compute utility from a batch of ChoiceDataset. + + Here we asssume that: item features = {fixed item features + session item features} + user features = {session features} + + Parameters + ---------- + items_features_batch : tuple of np.ndarray (items_features) + Items-Features: formatting from ChoiceDataset: a matrix representing + the products constant features. + session_features_batch : tuple of np.ndarray (sessions_features) + Time-Features + session_items_features_batch :tuple of np.ndarray (sessions_items_features) + Time-Item-Features + availabilities_batch : np.ndarray + Availabilities (sessions_items_availabilities) + choices_batch : np.ndarray + Choices + + Returns: + -------- + np.ndarray + Utility of each product for each session. + Shape must be (n_sessions, n_items) + """ + del availabilities_batch, choices_batch + ### Restacking of the item features + items_features_batch = tf.concat([*items_features_batch], axis=-1) + session_features_batch = tf.concat([*session_features_batch], axis=-1) + session_items_features_batch = tf.concat([*session_items_features_batch], axis=-1) + + full_item_features = tf.stack( + [items_features_batch] * session_items_features_batch.shape[0], axis=0 + ) + full_item_features = tf.concat([session_items_features_batch, full_item_features], axis=-1) + + ### Computation of utilities + utilities = [] + batch_size = session_features_batch.shape[0] + num_items = full_item_features.shape[1] + + # Computation of the customer features embeddings + z_embeddings = self.z_model(session_features_batch) + + _utilities = [] + # Iterate over items in assortment + for item_i in range(num_items): + # Computation of item features embeddings + x_embeddings = self.x_model(full_item_features[:, item_i, :]) + + # utilities.append([]) + # Computation of utilites from embeddings, iteration over heterogeneities + # (eps_x * eps_z) + for _x in x_embeddings: + for _z in z_embeddings: + _u = tf.keras.layers.Concatenate()( + [full_item_features[:, item_i, :], _x, session_features_batch, _z] + ) + _utilities.append(_u) + utilities = self.u_model(tf.concat(_utilities, axis=0)) + length_one_item = len(x_embeddings) * len(z_embeddings) * batch_size + reshaped_utilities = [] + for item_i in range(num_items): + item_utilities = tf.stack( + [ + utilities[ + item_i * length_one_item + batch_size * i : item_i * length_one_item + + batch_size * (i + 1) + ] + for i in range(len(x_embeddings) * len(z_embeddings)) + ], + axis=1, + ) + print(item_i, "item_u", item_utilities.shape) + reshaped_utilities.append(item_utilities) + ### Reshape utilities: (batch_size, num_items, heterogeneity) + utilities = tf.squeeze(tf.stack(reshaped_utilities, axis=1), -1) + print("u", utilities.shape) + # utilities = tf.stack(utilities, axis=0) + return utilities + + +def create_ff_network(input_shape, depth, width, add_last=False, l2_regularization_coeff=0.0): + """Base function to create a simple fully connected (Dense) network. + + Parameters + ---------- + input_shape : tuple of int + shape of the input of the network. Typically (num_features, ) + depth : int + Number of dense/fully-connected of the network to create. + width : int + Neurons number for all dense layers. + add_last : bool, optional + Whether to add a Dense layer with a single output at the end, by default False + Typically to be used when creating the utility network, that outputs a single number: + the utility. + l2_regularization_coeff : float, optional + Regularization coefficient for Dense layers weights during training, by default 0.0 + + Returns: + -------- + tf.keras.Model + Dense Neural Network with tensorflow backend. + """ + input = tf.keras.layers.Input(shape=input_shape) + regularizer = tf.keras.regularizers.L2(l2_regularization_coeff) + out = input + for _ in range(depth): + out = tf.keras.layers.Dense( + width, activation="elu", kernel_regularizer=regularizer, use_bias=True + )(out) + if add_last: + out = tf.keras.layers.Dense(1, activation="linear", use_bias=False)(out) + return tf.keras.Model(inputs=input, outputs=out) + + +def recreate_official_nets( + num_products_features, + x_width, + x_depth, + x_eps, + num_customer_features, + z_width, + z_depth, + z_eps, + width_u, + depth_u, + l2_regularization_coeff=0.0, +): + """Function to create the three nets used in RUMnet: X_net, Z_net and U_net. + + Parameters + ---------- + num_products_features : int + Number of features each product will be described with. + In terms of ChoiceDataset it is the number of { items_features + sessions_items_features } + for one product. + num_customer_features : int + Number of features each customer will be described with. + In terms of ChoiceDataset it is the number of sessions_features. + width_eps_x : int + Number of neurons for each dense layer for the products encoding net. + depth_eps_x : int + Number of dense layers for the products encoding net. + heterogeneity_x : int + Number of nets of products features encoding. + width_eps_z : int + Number of neurons for each dense layer for the customers encoding net. + depth_eps_z : int + Number of dense layers for the customers encoding net. + heterogeneity_z : int + Number of nets of customers features encoding. + width_u : int + Number of neurons for each dense layer for the utility net. + depth_u : int + Number of dense layers for the utility net. + l2_regularization_coef : float, optional + Value of dense layers weights regulariation to apply during training, by default 0.0 + + Returns: + -------- + tf.keras.Model + Product features encoding network + tf.keras.Model + Customer features encoding network + tf.keras.Model + Features and encoding to utility computation network + """ + # Products and Customers embeddings nets, quiet symmetrical + products_input = tf.keras.layers.Input(shape=(num_products_features)) + customer_input = tf.keras.layers.Input(shape=(num_customer_features)) + x_embeddings = [] + z_embeddings = [] + + # Creating independant nets for each heterogeneity + for _ in range(x_eps): + x_embedding = create_ff_network( + input_shape=num_products_features, + depth=x_depth, + width=x_width, + l2_regularization_coeff=l2_regularization_coeff, + )(products_input) + x_embeddings.append(x_embedding) + + # Creating independant nets for each heterogeneity + for _ in range(z_eps): + z_embedding = create_ff_network( + input_shape=num_customer_features, + depth=z_depth, + width=z_width, + l2_regularization_coeff=l2_regularization_coeff, + )(customer_input) + + z_embeddings.append(z_embedding) + + x_net = tf.keras.Model(inputs=products_input, outputs=x_embeddings, name="X_embedding") + z_net = tf.keras.Model(inputs=customer_input, outputs=z_embeddings, name="Z_embedding") + + # Utility network + u_net = create_ff_network( + input_shape=( + x_width + z_width + num_products_features + num_customer_features + ), # Input shape from previous nets + width=width_u, + depth=depth_u, + add_last=True, # Add last for utility + l2_regularization_coeff=l2_regularization_coeff, + ) + + return x_net, z_net, u_net diff --git a/lib/tf_ops.py b/lib/tf_ops.py new file mode 100644 index 00000000..cf8d617e --- /dev/null +++ b/lib/tf_ops.py @@ -0,0 +1,147 @@ +"""Diverse Tensorflow operations used in the ChoiceLearn library.""" + +import tensorflow as tf + + +def custom_softmax( + sessions_items_logits, sessions_items_availabilities, axis=-1, normalize_exit=False, eps=1e-5 +): + """Function to compute softmax probabilities from utilities. + + Takes into account availabilties (1 if the product is available, 0 otherwise) to set + probabilities to 0 for unavailable products and to renormalize the probabilities of + available products. + + Parameters + ---------- + sessions_items_logits : np.ndarray (n_sessions, n_products) + Utilities / Logits on which to compute the softmax + sessions_items_availabilities : np.ndarray (n_sessions, n_products) + Matrix indicating the availabitily (1) or not (0) of the products + axis : int, optional + Axis of sessions_logits on which to apply the softmax, by default -1 + normalize_exit : bool, optional + Whether to normalize the probabilities of available products with an exit choice of + utility 1, by default False + eps : float, optional + Value to avoid division by 0 when a product with probability almost 1 is unavailable, + by default 1e-5 + + Returns: + -------- + tf.Tensor (n_sessions, n_products) + Probabilities of each product for each session computed from Logits + """ + # Substract max utility to avoid overflow + numerator = tf.exp( + sessions_items_logits - tf.reduce_max(sessions_items_logits, axis=axis, keepdims=True) + ) + # Set unavailable products utility to 0 + numerator = tf.multiply(numerator, sessions_items_availabilities) + # Sum of total available utilities + denominator = tf.reduce_sum(numerator, axis=axis, keepdims=True) + # Add 1 to the denominator to take into account the exit choice + if normalize_exit: + denominator += 1 + # Avoir division by 0 when only unavailable items have highest utilities + elif eps: + denominator += eps + + # Compute softmax + return numerator / denominator + + +class CustomCategoricalCrossEntropy(tf.keras.losses.Loss): + """Custom Categorical Cross Entropy Loss. Handles all options in one place. + + Follows structure of tf.keras.losses.CategoricalCrossentropy and its different possibilities. + + Parameters + ---------- + from_logits : bool, optional + Whether to compute the softmax from logits or probabilities, by default False + sparse : bool, optional + Whether the choice labels are integers(True) or one-hot encoded(False), by default False + label_smoothing : float, optional + Value of smoothing to apply to labels, by default 0.0 + Smoothing applied is 1.0 - label_smoothing for chosen item and + label_smoothing / (num_items - 1)for all other items + axis : int, optional + Axis on which to compute the softmax. Used only if from_logits is True, by default -1 + epsilon : float, optional + Value to apply to avoid computation issues in log, by default 1e-10 + """ + + def __init__( + self, + from_logits=False, + sparse=False, + label_smoothing=0.0, + axis=-1, + epsilon=1e-10, + name="eps_categorical_crossentropy", + reduction=tf.keras.losses.Reduction.AUTO, + ): + """Initialization function. + + Follows structure of tf.keras.losses.CategoricalCrossentropy. + + Parameters + ---------- + from_logits : bool, optional + Whether to compute the softmax from logits or probabilities, by default False + sparse : bool, optional + Whether the choice labels are integers(True) or one-hot encoded(False), by default False + label_smoothing : float, optional + Value of smoothing to apply to labels, by default 0.0 + Smoothing applied is 1.0 - label_smoothing for chosen item and + label_smoothing / (num_items - 1) for all other items + axis : int, optional + Axis on which to compute the softmax. Used only if from_logits is True, by default -1 + epsilon : float, optional + Value to apply to avoid computation issues in log, by default 1e-10 + name: str + Name of the loss function - here to follow tf.keras.losses.Loss signature + reduction: + Reduction function - here to follow tf.keras.losses.Loss signature + """ + super().__init__(reduction=reduction, name=name) + self.label_smoothing = label_smoothing + self.from_logits = from_logits + self.sparse = sparse + self.axis = axis + self.epsilon = epsilon + + def call(self, y_true, y_pred): + """Computes the cross-entropy loss. + + Parameters + ---------- + y_true : np.ndarray | tf.Tenosr + Ground truth labels + y_pred : np.ndarray | tf.Tenosr + Predicted labels + + Returns: + -------- + tf.Tensor + Average Cross-Entropy loss + """ + if self.from_logits: # Apply softmax if utilities are given + y_pred = tf.nn.softmax(y_pred, axis=self.axis) + else: + y_pred = tf.convert_to_tensor(y_pred) + if self.sparse: # Create OneHot labels if sparse labels are given + y_true = tf.one_hot(y_true, depth=tf.shape(y_pred)[self.axis]) + else: + y_true = tf.cast(y_true, y_pred.dtype) + + # Smooth labels + if self.label_smoothing > 0: + label_smoothing = tf.convert_to_tensor(self.label_smoothing, dtype=y_pred.dtype) + num_classes = tf.cast(tf.shape(y_true)[self.axis], y_pred.dtype) + y_true = y_true * (1.0 - label_smoothing) + (label_smoothing / num_classes) + + # Apply label clipping to avoid log(0) and such issues + y_pred = tf.clip_by_value(y_pred, self.epsilon, 1.0 - self.epsilon) + return -tf.reduce_sum(y_true * tf.math.log(y_pred), axis=self.axis) diff --git a/pyproject.toml b/pyproject.toml index 651d0ce9..436216d0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ select = [ "PTH", "PD", ] # See: https://beta.ruff.rs/docs/rules/ -ignore = ["D203", "D213", "ANN101", "ANN102"] +ignore = ["D203", "D213", "ANN101", "ANN102", "ANN204", "ANN001", "ANN202", "ANN201", "ANN206", "ANN003"] line-length = 100 target-version = "py310" exclude = [ From efa9d69a8768e5d5cdc35542539c55b500a118e0 Mon Sep 17 00:00:00 2001 From: Vincent Auriau Date: Fri, 22 Dec 2023 10:36:05 +0100 Subject: [PATCH 003/767] Dev 1st test (#3) * ADD: 1st test * ADD: first working tests organization * FIX: lib renaming -> choice_learn apply changes --- .pre-commit-config.yaml | 2 +- choice_learn/__init__.py | 1 + choice_learn/data/__init__.py | 1 + {lib => choice_learn}/data/choice_dataset.py | 87 +++++++++++++++++-- {lib => choice_learn}/data/indexer.py | 2 +- {lib => choice_learn}/data/store.py | 7 +- choice_learn/models/__init__.py | 1 + {lib => choice_learn}/models/base_model.py | 0 .../models/conditional_mnl.py | 0 {lib => choice_learn}/models/rumnet.py | 3 +- {lib => choice_learn}/tf_ops.py | 0 lib/.gitkeep | 0 pyproject.toml | 7 +- tests/unit_tests/.gitkeep | 0 tests/unit_tests/data/test_store.py | 23 +++++ tests/unit_tests/test_placeholder.py | 6 -- 16 files changed, 121 insertions(+), 19 deletions(-) create mode 100644 choice_learn/__init__.py create mode 100644 choice_learn/data/__init__.py rename {lib => choice_learn}/data/choice_dataset.py (91%) rename {lib => choice_learn}/data/indexer.py (99%) rename {lib => choice_learn}/data/store.py (98%) create mode 100644 choice_learn/models/__init__.py rename {lib => choice_learn}/models/base_model.py (100%) rename {lib => choice_learn}/models/conditional_mnl.py (100%) rename {lib => choice_learn}/models/rumnet.py (99%) rename {lib => choice_learn}/tf_ops.py (100%) delete mode 100644 lib/.gitkeep delete mode 100644 tests/unit_tests/.gitkeep create mode 100644 tests/unit_tests/data/test_store.py delete mode 100644 tests/unit_tests/test_placeholder.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c285e93f..4f8e84c0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -30,7 +30,7 @@ repos: name: Security check (bandit) entry: bandit types: [python] - args: ["--recursive", "lib/"] + args: ["-x", "tests", --recursive, choice_learn] language: system - id: pytest-check name: Tests (pytest) diff --git a/choice_learn/__init__.py b/choice_learn/__init__.py new file mode 100644 index 00000000..0f7eda1f --- /dev/null +++ b/choice_learn/__init__.py @@ -0,0 +1 @@ +"""Choice-Learn library for Python.""" diff --git a/choice_learn/data/__init__.py b/choice_learn/data/__init__.py new file mode 100644 index 00000000..ee23245a --- /dev/null +++ b/choice_learn/data/__init__.py @@ -0,0 +1 @@ +"""Data handling classes and functions.""" diff --git a/lib/data/choice_dataset.py b/choice_learn/data/choice_dataset.py similarity index 91% rename from lib/data/choice_dataset.py rename to choice_learn/data/choice_dataset.py index a2fba478..14716252 100644 --- a/lib/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -2,8 +2,9 @@ import numpy as np import pandas as pd -from choice_modeling.data.indexer import ChoiceDatasetIndexer -from choice_modeling.data.store import Store + +from choice_learn.data.indexer import ChoiceDatasetIndexer +from choice_learn.data.store import Store class ChoiceDataset(object): @@ -686,7 +687,39 @@ def save(self): def summary(self): """Method to display a summary of the dataset.""" - raise NotImplementedError + print("Summary of the dataset:") + print("Number of items:", self.get_num_items()) + print("Number of sessions:", self.get_num_sessions()) + print( + "Number of choices:", + self.get_num_choices(), + "Averaging", + self.get_num_choices() / self.get_num_sessions(), + "choices per session", + ) + if self.items_features is not None: + print(f"Items features: {self.items_features_names}") + if self.items_features is not None: + print(f"{sum([f.shape[1] for f in self.items_features])} items features") + else: + print("No items features registered") + + if self.sessions_features is not None: + print(f"Sessions features: {self.sessions_features_names}") + if self.sessions_features is not None: + print(f"{sum([f.shape[1] for f in self.sessions_features])} session features") + else: + print("No sessions features registered") + + if self.sessions_featuresitems_features is not None: + print(f"Session Items features: {self.sessions_items_features_names}") + if self.sessions_items_features is not None: + print( + f"{sum([f.shape[2] for f in self.sessions_items_features])} sessions \ + items features" + ) + else: + print("No sessions items features registered") def get_choice_batch(self, choice_index): """Method to access data within the ListChoiceDataset from its index. @@ -845,7 +878,7 @@ def __getitem__(self, session_indexes): sessions_items_features_names=self.sessions_items_features_names, ) - def batch(self, batch_size=None, shuffle=None, sample_weight=None): + def old_batch(self, batch_size=None, shuffle=None, sample_weight=None): """Iterates over dataset return batches of length self.batch_size. Parameters @@ -892,6 +925,50 @@ def batch(self, batch_size=None, shuffle=None, sample_weight=None): yielded_size += 2 * num_choices @property - def iloc(self): + def batch(self): """Indexer.""" return self.indexer + + def iter_batch(self, batch_size=None, shuffle=None, sample_weight=None): + """Iterates over dataset return batches of length self.batch_size. + + Newer version. + + Parameters + ---------- + batch_size : int + batch size to set + shuffle: bool + Whether or not to shuffle the dataset + sample_weight : Iterable + list of weights to be returned with the right indexing during the shuffling + """ + if batch_size is None: + batch_size = self.batch_size + if shuffle is None: + shuffle = self.shuffle + if batch_size == -1: + batch_size = self.get_num_choices() + + # Get indexes for each choice + num_choices = self.get_num_choices() + indexes = np.arange(num_choices) + # Shuffle indexes + if shuffle and not batch_size == -1: + indexes = np.random.permutation(indexes) + + yielded_size = 0 + while yielded_size < num_choices: + # Return sample_weight if not None, for index matching + if sample_weight is not None: + yield ( + self.batch[indexes[yielded_size : yielded_size + batch_size].tolist()], + sample_weight[indexes[yielded_size : yielded_size + batch_size].tolist()], + ) + else: + yield self.batch[indexes[yielded_size : yielded_size + batch_size].tolist()] + yielded_size += batch_size + + # Special exit strategy for batch_size = -1 + if batch_size == -1: + yielded_size += 2 * num_choices diff --git a/lib/data/indexer.py b/choice_learn/data/indexer.py similarity index 99% rename from lib/data/indexer.py rename to choice_learn/data/indexer.py index 0bc2de80..f2887581 100644 --- a/lib/data/indexer.py +++ b/choice_learn/data/indexer.py @@ -60,7 +60,7 @@ def __getitem__(self, sequence_index): if isinstance(sequence_index, slice): return [ self.store.store[self.store.sequence[i]] - for i in range(*sequence_index.indices(len(self.sequence))) + for i in range(*sequence_index.indices(len(self.store.sequence))) ] return self.store.store[self.store.sequence[sequence_index]] diff --git a/lib/data/store.py b/choice_learn/data/store.py similarity index 98% rename from lib/data/store.py rename to choice_learn/data/store.py index 5680943f..c0a13b43 100644 --- a/lib/data/store.py +++ b/choice_learn/data/store.py @@ -1,6 +1,7 @@ """Different classes to optimize RAM usage with repeated features over time.""" import numpy as np -from choice_modeling.data.indexer import OneHotStoreIndexer, StoreIndexer + +from choice_learn.data.indexer import OneHotStoreIndexer, StoreIndexer class Store(object): @@ -22,7 +23,7 @@ def __init__(self, indexes=None, values=None, sequence=None, name=None, indexer= name of the features store -- not used at the moment """ if indexes is None: - indexes = list(range(values)) + indexes = list(range(len(values))) self.store = {k: v for (k, v) in zip(indexes, values)} self.sequence = np.array(sequence) self.name = name @@ -62,7 +63,7 @@ def __len__(self): return len(self.sequence) @property - def iloc(self): + def batch(self): """Indexing attribute.""" return self.indexer diff --git a/choice_learn/models/__init__.py b/choice_learn/models/__init__.py new file mode 100644 index 00000000..c5e79129 --- /dev/null +++ b/choice_learn/models/__init__.py @@ -0,0 +1 @@ +"""Models classes and functions.""" diff --git a/lib/models/base_model.py b/choice_learn/models/base_model.py similarity index 100% rename from lib/models/base_model.py rename to choice_learn/models/base_model.py diff --git a/lib/models/conditional_mnl.py b/choice_learn/models/conditional_mnl.py similarity index 100% rename from lib/models/conditional_mnl.py rename to choice_learn/models/conditional_mnl.py diff --git a/lib/models/rumnet.py b/choice_learn/models/rumnet.py similarity index 99% rename from lib/models/rumnet.py rename to choice_learn/models/rumnet.py index 2b51837b..4436b62c 100644 --- a/lib/models/rumnet.py +++ b/choice_learn/models/rumnet.py @@ -1,6 +1,7 @@ """Implementation of RUMnet for easy use.""" import tensorflow as tf -from choice_modeling.models.base_model import ChoiceModel + +from choice_learn.models.base_model import ChoiceModel class PaperRUMnet(ChoiceModel): diff --git a/lib/tf_ops.py b/choice_learn/tf_ops.py similarity index 100% rename from lib/tf_ops.py rename to choice_learn/tf_ops.py diff --git a/lib/.gitkeep b/lib/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/pyproject.toml b/pyproject.toml index 436216d0..cc399e36 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,7 +17,7 @@ requires-python = ">=3.8" "Documentation" = "https://artefactory.github.io/choice-learn-private" [tool.setuptools] -packages = ["lib", "config", "tests"] +packages = ["choice_learn", "config", "tests"] [tool.ruff] select = [ @@ -62,4 +62,7 @@ convention = "google" quote-style = "double" [tool.ruff.isort] -known-first-party = ["lib", "config", "tests"] +known-first-party = ["choice_learn", "config", "tests"] + +[tool.bandit] +exclude_dirs = ["tests/"] diff --git a/tests/unit_tests/.gitkeep b/tests/unit_tests/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/unit_tests/data/test_store.py b/tests/unit_tests/data/test_store.py new file mode 100644 index 00000000..2f57e86e --- /dev/null +++ b/tests/unit_tests/data/test_store.py @@ -0,0 +1,23 @@ +"""Test the store module.""" +from choice_learn.data.store import Store + + +def test_len_store(): + """Test the __len__ method of Store.""" + store = Store(values=[1, 2, 3, 4], sequence=[0, 1, 2, 3, 0, 1, 2, 3]) + assert len(store) == 8 + + +def test_get_store_element(): + """Test the _get_store_element method of Store.""" + store = Store(values=[1, 2, 3, 4], sequence=[0, 1, 2, 3, 0, 1, 2, 3]) + assert store._get_store_element(0) == 1 + assert store._get_store_element([0, 1, 2]) == [1, 2, 3] + + +def test_store_batch(): + """Test the batch method of Store.""" + store = Store(values=[1, 2, 3, 4], sequence=[0, 1, 2, 3, 0, 1, 2, 3]) + assert store.batch[1] == 2 + assert store.batch[2:4] == [3, 4] + assert store.batch[[2, 3, 6, 7]] == [3, 4, 3, 4] diff --git a/tests/unit_tests/test_placeholder.py b/tests/unit_tests/test_placeholder.py deleted file mode 100644 index 338a8e05..00000000 --- a/tests/unit_tests/test_placeholder.py +++ /dev/null @@ -1,6 +0,0 @@ -"""Placeholder test file for unit tests. To be replaced with actual tests.""" - - -def test_placeholder() -> None: - """To be replaced with actual tests.""" - pass From 6357d524dc47b73f202f64972ddca906b352320f Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 22 Dec 2023 11:41:57 +0100 Subject: [PATCH 004/767] FIX: indexer getitem was missing slice as input --- choice_learn/data/indexer.py | 2 ++ choice_learn/data/store.py | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/choice_learn/data/indexer.py b/choice_learn/data/indexer.py index f2887581..a6a09b83 100644 --- a/choice_learn/data/indexer.py +++ b/choice_learn/data/indexer.py @@ -99,6 +99,8 @@ def __getitem__(self, sequence_index): for i, j in enumerate(sequence_index): one_hot[i, self.store.store[self.store.sequence[j]]] = 1 return one_hot.astype(self.store.dtype) + if isinstance(sequence_index, slice): + return self[list(range(*sequence_index.indices(len(self.store.sequence))))] # else: one_hot = np.zeros(self.shape[1]) one_hot[self.store.store[self.store.sequence[sequence_index]]] = 1 diff --git a/choice_learn/data/store.py b/choice_learn/data/store.py index c0a13b43..341aa6e9 100644 --- a/choice_learn/data/store.py +++ b/choice_learn/data/store.py @@ -145,7 +145,6 @@ def __getitem__(self, sequence_index): """ if isinstance(sequence_index, int): sequence_index = [sequence_index] - print(sequence_index, type(self.sequence)) new_sequence = self.sequence[sequence_index] store = {} for k, v in self.store.items(): From 1d26140fb7e655824004b72c912e786bddf78814 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 22 Dec 2023 11:42:16 +0100 Subject: [PATCH 005/767] ADD: store unit tests --- tests/unit_tests/data/test_store.py | 112 +++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 1 deletion(-) diff --git a/tests/unit_tests/data/test_store.py b/tests/unit_tests/data/test_store.py index 2f57e86e..d1fd3df8 100644 --- a/tests/unit_tests/data/test_store.py +++ b/tests/unit_tests/data/test_store.py @@ -1,5 +1,5 @@ """Test the store module.""" -from choice_learn.data.store import Store +from choice_learn.data.store import FeaturesStore, OneHotStore, Store def test_len_store(): @@ -21,3 +21,113 @@ def test_store_batch(): assert store.batch[1] == 2 assert store.batch[2:4] == [3, 4] assert store.batch[[2, 3, 6, 7]] == [3, 4, 3, 4] + + +def test_featuresstore_instantiation(): + """Test the instantiation of FeaturesStore.""" + store = FeaturesStore( + values=[[10, 10], [4, 4], [2, 2], [8, 8]], + sequence=[0, 1, 2, 3, 0, 1, 2, 3], + indexes=[0, 1, 2, 3], + ) + assert store.shape == (8, 2) + assert [store.sequence[i] == [0, 1, 2, 3, 0, 1, 2, 3][i] for i in range(8)] + assert store.store == {0: [10, 10], 1: [4, 4], 2: [2, 2], 3: [8, 8]} + + +def test_featuresstore_instantiation_indexless(): + """Test the instantiation of FeaturesStore.""" + store = FeaturesStore( + values=[[10, 10], [4, 4], [2, 2], [8, 8]], sequence=[0, 1, 2, 3, 0, 1, 2, 3] + ) + assert store.shape == (8, 2) + assert [store.sequence[i] == [0, 1, 2, 3, 0, 1, 2, 3][i] for i in range(8)] + assert store.store == {0: [10, 10], 1: [4, 4], 2: [2, 2], 3: [8, 8]} + + +def test_featuresstore_instantiation_from_list(): + """Test the instantiation of FeaturesStore.""" + store = FeaturesStore.from_list( + values_list=[[10, 10], [4, 4], [2, 2], [8, 8]], sequence=[0, 1, 2, 3, 0, 1, 2, 3] + ) + assert store.shape == (8, 2) + assert [store.sequence[i] == [0, 1, 2, 3, 0, 1, 2, 3][i] for i in range(8)] + assert store.store == {0: [10, 10], 1: [4, 4], 2: [2, 2], 3: [8, 8]} + + +def test_featuresstore_instantiation_fromdict(): + """Test the instantiation of FeaturesStore.""" + store = FeaturesStore.from_dict( + values_dict={0: [10, 10], 1: [4, 4], 2: [2, 2], 3: [8, 8]}, + sequence=[0, 1, 2, 3, 0, 1, 2, 3], + ) + assert store.shape == (8, 2) + assert [store.sequence[i] == [0, 1, 2, 3, 0, 1, 2, 3][i] for i in range(8)] + assert store.store == {0: [10, 10], 1: [4, 4], 2: [2, 2], 3: [8, 8]} + + +def test_featuresstore_getitem(): + """Test the __getitem__ method of FeaturesStore.""" + store = FeaturesStore.from_dict( + values_dict={0: [10, 10], 1: [4, 4], 2: [2, 2], 3: [8, 8]}, + sequence=[0, 1, 2, 3, 0, 1, 2, 3], + ) + sub_store = store[0:3] + assert sub_store.shape == (3, 2) + assert [sub_store.sequence[i] == [0, 1, 2][i] for i in range(3)] + assert sub_store.store == {0: [10, 10], 1: [4, 4], 2: [2, 2]} + + +def test_onehotstore_instantiation(): + """Test the instantiation of OneHotStore.""" + indexes = [0, 1, 2, 4] + values = [0, 1, 2, 3] + sequence = [0, 1, 2, 4, 0, 1, 2, 4] + store = OneHotStore(indexes=indexes, values=values, sequence=sequence) + assert store.shape == (8, 4) + assert [store.sequence[i] == [0, 1, 2, 4, 0, 1, 2, 4][i] for i in range(8)] + assert store.store == {0: 0, 1: 1, 2: 2, 4: 3} + + +def test_onehotstore_instantiation_from_sequence(): + """Test the instantiation; from_sequence of OneHotStore.""" + sequence = [0, 1, 2, 3, 0, 1, 2, 3] + store = OneHotStore.from_sequence(sequence=sequence) + assert store.shape == (8, 4) + assert [store.sequence[i] == [0, 1, 2, 3, 0, 1, 2, 3][i] for i in range(8)] + assert store.store == {0: 0, 1: 1, 2: 2, 3: 3} + + +def test_onehotstore_getitem(): + """Test the getitem of OneHotStore.""" + indexes = [0, 1, 2, 4] + values = [0, 1, 2, 3] + sequence = [0, 1, 2, 4, 0, 1, 2, 4] + store = OneHotStore(indexes=indexes, values=values, sequence=sequence) + sub_store = store[0:3] + assert sub_store.shape == (3, 3) + assert [ + sub_store.sequence[i] == [0, 1, 2, 3, 0, 1, 2, 3][i] for i in range(len(sub_store.sequence)) + ] + assert sub_store.store == { + 0: 0, + 1: 1, + 2: 2, + } + + +def test_onehotstore_batch(): + """Test the getitem of OneHotStore.""" + indexes = [0, 1, 2, 4] + values = [0, 1, 2, 3] + sequence = [0, 1, 2, 4, 0, 1, 2, 4] + store = OneHotStore(indexes=indexes, values=values, sequence=sequence) + + batch = store.batch[0] + assert (batch == [1, 0, 0, 0]).all() + + batch = store.batch[0:4] + assert (batch == [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]).all() + + batch = store.batch[[3, 6, 7]] + assert (batch == [[0, 0, 0, 1], [0, 0, 1, 0], [0, 0, 0, 1]]).all() From 630ac96ae5fa6cad601600c616c110d96e6ec141 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 22 Dec 2023 16:41:11 +0100 Subject: [PATCH 006/767] FIX: small slice fixes --- choice_learn/data/choice_dataset.py | 5 ++--- choice_learn/data/indexer.py | 4 +++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index 14716252..eb512312 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -452,7 +452,7 @@ def _check_names(self): features, ) in zip(self.sessions_items_features_names, self.sessions_items_features): if name is not None: - if len(name) != features.shape[1]: + if len(name) != features.shape[2]: raise ValueError( f"Specified \ sessions_items_features_names has length {len(name)} while \ @@ -669,7 +669,6 @@ def from_single_df( raise ValueError( f"choice_mode {choice_mode} not recognized. Must be in ['item_id', 'one_zero']" ) - return ChoiceDataset( items_features=items_features, sessions_features=sessions_features, @@ -711,7 +710,7 @@ def summary(self): else: print("No sessions features registered") - if self.sessions_featuresitems_features is not None: + if self.sessions_items_features is not None: print(f"Session Items features: {self.sessions_items_features_names}") if self.sessions_items_features is not None: print( diff --git a/choice_learn/data/indexer.py b/choice_learn/data/indexer.py index a6a09b83..5974f59f 100644 --- a/choice_learn/data/indexer.py +++ b/choice_learn/data/indexer.py @@ -266,7 +266,9 @@ def __getitem__(self, choice_index): ) if isinstance(choice_index, slice): - return self.__getitem__(list(range(*choice_index.indices(self.choices.shape[0])))) + return self.__getitem__( + list(range(*choice_index.indices(self.choice_dataset.choices.shape[0]))) + ) if isinstance(choice_index, int): items_features = self._get_items_features() From 9b09618612f1a91f920aff8f06665f02009a5aa0 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 22 Dec 2023 16:45:07 +0100 Subject: [PATCH 007/767] ADD: ChoiceDatset Unit Tests --- tests/unit_tests/data/test_choice_dataset.py | 427 +++++++++++++++++++ 1 file changed, 427 insertions(+) create mode 100644 tests/unit_tests/data/test_choice_dataset.py diff --git a/tests/unit_tests/data/test_choice_dataset.py b/tests/unit_tests/data/test_choice_dataset.py new file mode 100644 index 00000000..6ef06590 --- /dev/null +++ b/tests/unit_tests/data/test_choice_dataset.py @@ -0,0 +1,427 @@ +"""Unit testing for class ChoiceDataset.""" +import pandas as pd +import pytest + +from choice_learn.data.choice_dataset import ChoiceDataset + +items_features = [ + [1, 2], # item 1 [size, weight] + [2, 4], # item 2 [size, weight] + [1.5, 1.5], # item 3 [size, weight] +] + +# We have two customers whose features are +# - Budget +# - Age +# Customer 1 bought item 1 at session 1 and item 2 at session 3 +# Customer 2 bought item 3 at session 2 + +choices = [0, 2, 1] +sessions_items_availabilities = [ + [1, 1, 1], # All items available at session 1 + [1, 1, 1], # All items available at session 2 + [0, 1, 1], # Item 1 not available at session 3 +] + +sessions_features = [ + [100, 20], # session 1, customer 1 [budget, age] + [200, 40], # session 2, customer 2 [budget, age] + [80, 20], # session 3, customer 1 [budget, age] +] + +sessions_items_features = [ + [ + [100, 0], # Session 1, Item 1 [price, promotion] + [140, 0], # Session 1, Item 2 [price, promotion] + [200, 0], # Session 1, Item 2 [price, promotion] + ], + [ + [100, 0], # Session 2 Item 1 [price, promotion] + [120, 1], # Session 2, Item 2 [price, promotion] + [200, 0], # Session 2, Item 2 [price, promotion] + ], + [ + [0, 0], # Session 3, Item 1 [price, promotion], + # values do not really matter, but needs to exist for shapes sake + [120, 1], # Session 3, Item 2 [price, promotion] + [180, 1], # Session 3, Item 2 [price, promotion] + ], +] + + +def test_instantiate_len(): + """Test the __init__ method.""" + choices = [0, 2, 1] + dataset = ChoiceDataset( + items_features=items_features, + sessions_features=sessions_features, + sessions_items_features=sessions_items_features, + sessions_items_availabilities=sessions_items_availabilities, + choices=choices, + ) + assert len(dataset) == 3 + choices = [[0], [1, 2], [2, 1, 1, 1]] + dataset = ChoiceDataset( + items_features=items_features, + sessions_features=sessions_features, + sessions_items_features=sessions_items_features, + sessions_items_availabilities=sessions_items_availabilities, + choices=choices, + ) + assert len(dataset) == 3 + + +def test_fail_instantiate(): + """Tests shapes fail to instantiate.""" + choices = [0, 1] + with pytest.raises(ValueError): + ChoiceDataset( + items_features=items_features, + sessions_features=sessions_features, + sessions_items_features=sessions_items_features, + sessions_items_availabilities=sessions_items_availabilities, + choices=choices, + ) + + +def test_fail_instantiate_2(): + """Tests shapes fail to instantiate.""" + items_features = [ + [1, 2], # item 1 [size, weight] + [2, 4], # item 2 [size, weight] + [1.5], # item 3 [size, weight] + ] + with pytest.raises(ValueError): + ChoiceDataset( + items_features=items_features, + sessions_features=sessions_features, + sessions_items_features=sessions_items_features, + sessions_items_availabilities=sessions_items_availabilities, + choices=choices, + ) + + +def test_fail_instantiate_3(): + """Tests shapes fail to instantiate.""" + items_features = [ + [1, 2], # item 1 [size, weight] + [2, 4], # item 2 [size, weight] + ] + with pytest.raises(ValueError): + ChoiceDataset( + items_features=items_features, + sessions_features=sessions_features, + sessions_items_features=sessions_items_features, + sessions_items_availabilities=sessions_items_availabilities, + choices=choices, + ) + + +def test_fail_instantiate_10(): + """Tests shapes fail to instantiate.""" + sessions_items_availabilities = [ + [1, 1, 1], # All items available at session 1 + [1, 1, 1], # All items available at session 2 + ] + with pytest.raises(ValueError): + ChoiceDataset( + items_features=items_features, + sessions_features=sessions_features, + sessions_items_features=sessions_items_features, + sessions_items_availabilities=sessions_items_availabilities, + choices=choices, + ) + + +def test_fail_instantiate_4(): + """Tests shapes fail to instantiate.""" + sessions_items_availabilities = [ + [1, 1], # All items available at session 1 + [1, 1], # All items available at session 2 + [1, 1], # All items available at session 3 + ] + with pytest.raises(ValueError): + ChoiceDataset( + items_features=items_features, + sessions_features=sessions_features, + sessions_items_features=sessions_items_features, + sessions_items_availabilities=sessions_items_availabilities, + choices=choices, + ) + + +def test_fail_instantiate_5(): + """Tests shapes fail to instantiate.""" + sessions_features = [ + [100, 20], # session 1, customer 1 [budget, age] + [200, 40], # session 2, customer 2 [budget, age] + ] + with pytest.raises(ValueError): + ChoiceDataset( + items_features=items_features, + sessions_features=sessions_features, + sessions_items_features=sessions_items_features, + sessions_items_availabilities=sessions_items_availabilities, + choices=choices, + ) + + +def test_fail_instantiate_6(): + """Tests shapes fail to instantiate.""" + sessions_features = [ + [100], # session 1, customer 1 [budget, age] + [200, 40], # session 2, customer 2 [budget, age] + [80, 20], # session 3, customer 1 [budget, age] + ] + with pytest.raises(ValueError): + ChoiceDataset( + items_features=items_features, + sessions_features=sessions_features, + sessions_items_features=sessions_items_features, + sessions_items_availabilities=sessions_items_availabilities, + choices=choices, + ) + + +def test_fail_instantiate_7(): + """Tests shapes fail to instantiate.""" + sessions_items_features = [ + [ + [100, 0], # Session 1, Item 1 [price, promotion] + [140, 0], # Session 1, Item 2 [price, promotion] + [200, 0], # Session 1, Item 2 [price, promotion] + ], + [ + [100, 0], # Session 2 Item 1 [price, promotion] + [120, 1], # Session 2, Item 2 [price, promotion] + [200, 0], # Session 2, Item 2 [price, promotion] + ], + ] + with pytest.raises(ValueError): + ChoiceDataset( + items_features=items_features, + sessions_features=sessions_features, + sessions_items_features=sessions_items_features, + sessions_items_availabilities=sessions_items_availabilities, + choices=choices, + ) + + +def test_fail_instantiate_8(): + """Tests shapes fail to instantiate.""" + sessions_items_features = [ + [ + [100, 0], # Session 1, Item 1 [price, promotion] + [140, 0], # Session 1, Item 2 [price, promotion] + ], + [ + [100, 0], # Session 2 Item 1 [price, promotion] + [120, 1], # Session 2, Item 2 [price, promotion] + ], + [ + [100, 0], # Session 3, Item 1 [price, promotion], + # values do not really matter, but needs to exist for shapes sake + [120, 1], # Session 3, Item 2 [price, promotion] + ], + ] + with pytest.raises(ValueError): + ChoiceDataset( + items_features=items_features, + sessions_features=sessions_features, + sessions_items_features=sessions_items_features, + sessions_items_availabilities=sessions_items_availabilities, + choices=choices, + ) + + +def test_fail_instantiate_9(): + """Tests shapes fail to instantiate.""" + choices = [0, 4, 2] # choices higher than nb of items + with pytest.raises(ValueError): + ChoiceDataset( + items_features=items_features, + sessions_features=sessions_features, + sessions_items_features=sessions_items_features, + sessions_items_availabilities=sessions_items_availabilities, + choices=choices, + ) + + +def test_shape(): + """Tests get shape methods.""" + dataset = ChoiceDataset( + items_features=items_features, + sessions_features=sessions_features, + sessions_items_features=sessions_items_features, + sessions_items_availabilities=sessions_items_availabilities, + choices=choices, + ) + + assert dataset.get_num_items() == 3 + assert dataset.get_num_sessions() == 3 + assert dataset.get_num_choices() == 3 + + +def test_from_df(): + """Tests from_df method.""" + features_df = pd.DataFrame( + { + "item_id": [0, 1, 2, 0, 1, 2, 1, 2], + "items_feat_1": [1, 2, 1.5, 1, 2, 1.5, 2, 1.5], + "items_feat_2": [2, 4, 1.5, 2, 4, 1.5, 4, 1.5], + "session_id": [0, 0, 0, 1, 1, 1, 2, 2], + "session_feat_1": [100, 100, 100, 200, 200, 200, 80, 80], + "session_feat_2": [20, 20, 20, 40, 40, 40, 20, 20], + "session_item_feat_1": [100, 140, 200, 100, 120, 200, 120, 180], + "session_item_feat_2": [0, 0, 0, 0, 1, 0, 1, 1], + "choice": [0, 0, 0, 2, 2, 2, 1, 1], + } + ) + cd_test = ChoiceDataset.from_single_df( + features_df, + items_features_columns=["items_feat_1", "items_feat_2"], + sessions_features_columns=["session_feat_1", "session_feat_2"], + sessions_items_features_columns=["session_item_feat_1", "session_item_feat_2"], + choice_mode="item_id", + ) + ground_truth_cd = ChoiceDataset( + items_features=items_features, + sessions_features=sessions_features, + sessions_items_features=sessions_items_features, + sessions_items_availabilities=sessions_items_availabilities, + choices=choices, + ) + assert (cd_test.items_features[0] == ground_truth_cd.items_features[0]).all() + assert (cd_test.sessions_features[0] == ground_truth_cd.sessions_features[0]).all() + assert ( + cd_test.sessions_items_features[0].astype("float32") + == ground_truth_cd.sessions_items_features[0].astype("float32") + ).all() + assert ( + cd_test.sessions_items_availabilities == ground_truth_cd.sessions_items_availabilities + ).all() + assert (cd_test.choices == ground_truth_cd.choices).all() + + features_df = pd.DataFrame( + { + "item_id": [0, 1, 2, 0, 1, 2, 1, 2], + "items_feat_1": [1, 2, 1.5, 1, 2, 1.5, 2, 1.5], + "items_feat_2": [2, 4, 1.5, 2, 4, 1.5, 4, 1.5], + "session_id": [0, 0, 0, 1, 1, 1, 2, 2], + "session_feat_1": [100, 100, 100, 200, 200, 200, 80, 80], + "session_feat_2": [20, 20, 20, 40, 40, 40, 20, 20], + "session_item_feat_1": [100, 140, 200, 100, 120, 200, 120, 180], + "session_item_feat_2": [0, 0, 0, 0, 1, 0, 1, 1], + "choice": [1, 0, 0, 0, 0, 1, 1, 0], + } + ) + cd_test = ChoiceDataset.from_single_df( + features_df, + items_features_columns=["items_feat_1", "items_feat_2"], + sessions_features_columns=["session_feat_1", "session_feat_2"], + sessions_items_features_columns=["session_item_feat_1", "session_item_feat_2"], + choice_mode="one_zero", + ) + ground_truth_cd = ChoiceDataset( + items_features=items_features, + sessions_features=sessions_features, + sessions_items_features=sessions_items_features, + sessions_items_availabilities=sessions_items_availabilities, + choices=choices, + ) + assert (cd_test.items_features[0] == ground_truth_cd.items_features[0]).all() + assert (cd_test.sessions_features[0] == ground_truth_cd.sessions_features[0]).all() + assert ( + cd_test.sessions_items_features[0].astype("float32") + == ground_truth_cd.sessions_items_features[0].astype("float32") + ).all() + assert ( + cd_test.sessions_items_availabilities == ground_truth_cd.sessions_items_availabilities + ).all() + assert (cd_test.choices == ground_truth_cd.choices).all() + + +def test_summary(): + """Tests summary method.""" + dataset = ChoiceDataset( + items_features=items_features, + sessions_features=sessions_features, + sessions_items_features=sessions_items_features, + sessions_items_availabilities=sessions_items_availabilities, + choices=choices, + ) + dataset.summary() + assert True + + +def test_getitem(): + """Tests getitem method.""" + dataset = ChoiceDataset( + items_features=items_features, + sessions_features=sessions_features, + sessions_items_features=sessions_items_features, + sessions_items_availabilities=sessions_items_availabilities, + choices=choices, + ) + + sub_dataset = dataset[[0, 1]] + assert (sub_dataset.items_features[0] == dataset.items_features[0]).all() + assert (sub_dataset.sessions_features[0] == dataset.sessions_features[0][[0, 1]]).all() + assert ( + sub_dataset.sessions_items_features[0] == dataset.sessions_items_features[0][[0, 1]] + ).all() + assert ( + sub_dataset.sessions_items_availabilities == dataset.sessions_items_availabilities[[0, 1]] + ).all() + assert (sub_dataset.choices == dataset.choices[[0, 1]]).all() + assert (sub_dataset.choices == [0, 2]).all() + + +def test_batch(): + """Tests the batch method.""" + dataset = ChoiceDataset( + items_features=items_features, + sessions_features=sessions_features, + sessions_items_features=sessions_items_features, + sessions_items_availabilities=sessions_items_availabilities, + choices=choices, + ) + batch = dataset.batch[[0, 1]] + assert (batch[0] == items_features).all() + assert (batch[1] == sessions_features[:2]).all() + assert (batch[2] == sessions_items_features[:2]).all() + assert (batch[3] == sessions_items_availabilities[:2]).all() + assert (batch[4] == choices[:2]).all() + + sliced_batch = dataset.batch[:2] + assert (batch[0] == sliced_batch[0]).all() + assert (batch[1] == sliced_batch[1]).all() + assert (batch[2] == sliced_batch[2]).all() + assert (batch[3] == sliced_batch[3]).all() + assert (batch[4] == sliced_batch[4]).all() + + single_batch = dataset.batch[0] + assert (batch[0] == single_batch[0]).all() + assert (batch[1][0] == single_batch[1]).all() + assert (batch[2][0] == single_batch[2]).all() + assert (batch[3][0] == single_batch[3]).all() + assert (batch[4][0] == single_batch[4]).all() + + +def test_iter_batch(): + """Tests the iter_batch method.""" + dataset = ChoiceDataset( + items_features=items_features, + sessions_features=sessions_features, + sessions_items_features=sessions_items_features, + sessions_items_availabilities=sessions_items_availabilities, + choices=choices, + ) + for batch_nb, batch in enumerate(dataset.iter_batch(batch_size=2)): + assert batch[0].shape[1] == 2 + assert batch[1].shape[1] == 2 + assert batch[2].shape[1] == 3 + assert batch[2].shape[2] == 2 + assert batch[3].shape[1] == 3 + assert batch[4].shape[0] == 2 or batch[4].shape[0] == 1 + assert batch_nb == 1 From 9f426bec477afa08d686c81f83d8cff8cef20cd1 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 2 Jan 2024 12:01:02 +0100 Subject: [PATCH 008/767] FIX: ChoiceDataset when None given --- choice_learn/data/choice_dataset.py | 135 ++++++++++++++-------------- 1 file changed, 70 insertions(+), 65 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index eb512312..d7f78de6 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -130,77 +130,82 @@ def __init__( # names as features names # Handling items_features - for i, feature in enumerate(items_features): - if isinstance(feature, pd.DataFrame): - # Ordering items by id ? - if "item_id" in feature.columns: - feature = feature.set_index("item_id") - items_features = ( - items_features[:i] - + (feature.loc[np.sort(feature.index)].to_numpy(),) - + items_features[i + 1 :] - ) - items_features_names = ( - items_features_names[:i] - + (feature.columns.tolist(),) - + items_features_names[i + 1 :] - ) - elif isinstance(feature, list): - items_features = items_features[:i] + (np.array(feature),) + items_features[i + 1 :] + if items_features is not None: + for i, feature in enumerate(items_features): + if isinstance(feature, pd.DataFrame): + # Ordering items by id ? + if "item_id" in feature.columns: + feature = feature.set_index("item_id") + items_features = ( + items_features[:i] + + (feature.loc[np.sort(feature.index)].to_numpy(),) + + items_features[i + 1 :] + ) + items_features_names = ( + items_features_names[:i] + + (feature.columns.tolist(),) + + items_features_names[i + 1 :] + ) + elif isinstance(feature, list): + items_features = ( + items_features[:i] + (np.array(feature),) + items_features[i + 1 :] + ) # Handling sessions_features - for i, feature in enumerate(sessions_features): - if isinstance(feature, pd.DataFrame): - # Ordering sessions by id ? - if "session_id" in feature.columns: - feature = feature.set_index("session_id") - sessions_features = ( - sessions_features[:i] - + (feature.loc[np.sort(feature.index)].to_numpy(),) - + sessions_features[i + 1 :] - ) - sessions_features_names = ( - sessions_features_names[:i] - + (feature.columns.tolist(),) - + sessions_features_names[i + 1 :] - ) - elif isinstance(feature, list): - sessions_features = ( - sessions_features[:i] + (np.array(feature),) + sessions_features[i + 1 :] - ) + if sessions_features is not None: + for i, feature in enumerate(sessions_features): + if isinstance(feature, pd.DataFrame): + # Ordering sessions by id ? + if "session_id" in feature.columns: + feature = feature.set_index("session_id") + sessions_features = ( + sessions_features[:i] + + (feature.loc[np.sort(feature.index)].to_numpy(),) + + sessions_features[i + 1 :] + ) + sessions_features_names = ( + sessions_features_names[:i] + + (feature.columns.tolist(),) + + sessions_features_names[i + 1 :] + ) + elif isinstance(feature, list): + sessions_features = ( + sessions_features[:i] + (np.array(feature),) + sessions_features[i + 1 :] + ) # Handling sessions_items_features - for i, feature in enumerate(sessions_items_features): - if isinstance(feature, pd.DataFrame): - # Ordering sessions and items by id ? - if "session_id" not in feature.columns: - feature["session_id"] = feature.index - items_index = np.sort(feature.item_id.unique()) - sessions_index = np.sort(feature.session_id.unique()) - names = [f for f in feature.columns if f != "session_id" and f != "item_id"] - - ( - feature, - sessions_items_availabilities, - ) = self._sessions_items_features_df_to_np( - feature, items_index, sessions_index, feature.columns.tolist() - ) + if sessions_items_features is not None: + for i, feature in enumerate(sessions_items_features): + if isinstance(feature, pd.DataFrame): + # Ordering sessions and items by id ? + if "session_id" not in feature.columns: + feature["session_id"] = feature.index + items_index = np.sort(feature.item_id.unique()) + sessions_index = np.sort(feature.session_id.unique()) + names = [f for f in feature.columns if f != "session_id" and f != "item_id"] + + ( + feature, + sessions_items_availabilities, + ) = self._sessions_items_features_df_to_np( + feature, items_index, sessions_index, feature.columns.tolist() + ) - sessions_items_features = ( - sessions_items_features[:i] + feature + sessions_items_features[i + 1 :] - ) + sessions_items_features = ( + sessions_items_features[:i] + feature + sessions_items_features[i + 1 :] + ) - sessions_items_features_names = ( - sessions_items_features_names[:i] - + (names,) - + sessions_items_features_names[i + 1 :] - ) - elif isinstance(feature, list): - sessions_items_features = ( - sessions_items_features[:i] - + (np.array(feature),) - + sessions_items_features[i + 1 :] - ) + sessions_items_features_names = ( + sessions_items_features_names[:i] + + (names,) + + sessions_items_features_names[i + 1 :] + ) + elif isinstance(feature, list): + sessions_items_features = ( + sessions_items_features[:i] + + (np.array(feature),) + + sessions_items_features[i + 1 :] + ) if isinstance(sessions_items_availabilities, list): sessions_items_availabilities = np.array(sessions_items_availabilities) From e7f10098eb04526f2c69e9498e75c64e46f2a6b6 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 2 Jan 2024 13:38:31 +0100 Subject: [PATCH 009/767] ADD: swissmetro loader --- choice_learn/datasets/base.py | 188 +++++++++++++++++++ choice_learn/datasets/data/swissmetro.csv.gz | Bin 0 -> 117429 bytes 2 files changed, 188 insertions(+) create mode 100644 choice_learn/datasets/base.py create mode 100644 choice_learn/datasets/data/swissmetro.csv.gz diff --git a/choice_learn/datasets/base.py b/choice_learn/datasets/base.py new file mode 100644 index 00000000..92289bf3 --- /dev/null +++ b/choice_learn/datasets/base.py @@ -0,0 +1,188 @@ +"""Datasets loader.""" +import csv +import gzip +from importlib import resources + +import numpy as np + +from choice_learn.data.choice_dataset import ChoiceDataset + +DATA_MODULE = "choice_learn.datasets.data" + + +def load_csv(data_file_name, data_module=DATA_MODULE, encoding="utf-8"): + """Base function to load csv files. + + Parameters + ---------- + data_file_name : str + name of the csv file to load + data_module : str, optional + path to directory containing the data file, by default DATA_MODULE + encoding : str, optional + encoding method of file, by default "utf-8" + + Returns: + -------- + list + list of column names + np.ndarray + data contained in the csv file + """ + data_path = resources.files(data_module) + with (data_path / data_file_name).open("r", encoding=encoding) as csv_file: + data_file = csv.reader(csv_file) + names = next(data_file) + data = [] + + for i, ir in enumerate(data_file): + data.append(np.asarray(ir, dtype=np.float64)) + return names, np.stack(data) + + +def load_gzip(data_file_name, data_module=DATA_MODULE, encoding="utf-8"): + """Base function to load zipped .csv.gz files. + + Parameters + ---------- + data_file_name : str + name of the csv.gz file to load + data_module : str, optional + path to directory containing the data file, by default DATA_MODULE + encoding : str, optional + encoding method of file, by default "utf-8" + + Returns: + -------- + list + list of column names + np.ndarray + data contained in the csv file + """ + data_path = resources.files(data_module) + with (data_path / data_file_name).open("rb") as compressed_file: + compressed_file = gzip.open(compressed_file, mode="rt", encoding=encoding) + names = next(compressed_file) + names = names.replace("\n", "") + data = np.loadtxt(compressed_file, delimiter=",", dtype=int) + + return names.split(","), data + + +def slice_from_names(array, slice_names, all_names): + """Slicing on 2nd dimension function for numpy arrays. + + Slices array in the second dimension from column names. + + Parameters + ---------- + array : np.ndarray + array to be sliced + slice_names : list + names of columns to return + all_names : list + names of all columns + + Returns: + -------- + np.ndarray + sliced array + """ + return array[:, [all_names.index(name) for name in slice_names]] + + +def load_swissmetro( + one_hot_cat_data=False, add_items_one_hot=False, as_frame=False, return_desc=False +): + """Load and return the SwissMetro dataset from Bierlaire et al. (2001). + + Parameters + ---------- + one_hot_cat_data : bool, optional + Whether to transform categorical data as OneHot, by default False + add_items_one_hot : bool, optional + Whether to add a OneHot encoding of items as items_features, by default False + as_frame : bool, optional + Whether to return the dataset as pd.DataFrame. If not, returned as ChoiceDataset, + by default False + return_desc : bool, optional + Whether to return the description, by default False + + Returns: + -------- + ChoiceDataset + Loaded SwissMetro dataset + """ + data_file_name = "swissmetro.csv.gz" + names, data = load_gzip(data_file_name) + items = ["TRAIN", "SM", "CAR"] + items_features = [] + session_features = [ + "GROUP", + "PURPOSE", + "FIRST", + "TICKET", + "WHO", + "LUGGAGE", + "AGE", + "MALE", + "INCOME", + "GA", + "ORIGIN", + "DEST", + ] + sessions_items_features = ["TT", "CO", "HE"] + sessions_items_features = [ + [f"{item}_{feature}" for feature in sessions_items_features] for item in items + ] + sessions_items_availabilities = ["TRAIN_AV", "SM_AV", "CAR_AV"] + choice_column = "CHOICE" + + if add_items_one_hot: + items_features = np.eye(len(items), dtype=np.float64) + else: + items_features = None + + # Adding dummy CAR_HE feature as 0 for consistency + names.append("CAR_HE") + data = np.hstack([data, np.zeros((data.shape[0], 1))]) + + session_features = slice_from_names(data, session_features, names) + sessions_items_features = np.stack( + [slice_from_names(data, features, names) for features in sessions_items_features], axis=-1 + ) + sessions_items_availabilities = slice_from_names(data, sessions_items_availabilities, names) + choices = data[:, names.index(choice_column)] + + # Remove no choice + choice_done = np.where(choices > 0)[0] + session_features = session_features[choice_done] + sessions_items_features = sessions_items_features[choice_done] + sessions_items_availabilities = sessions_items_availabilities[choice_done] + choices = choices[choice_done] + + # choices renormalization + choices = choices - 1 + + if return_desc: + # TODO + pass + if one_hot_cat_data: + # TODO + pass + if as_frame: + # TODO + pass + + return ChoiceDataset( + items_features=items_features, + sessions_features=session_features, + sessions_items_features=sessions_items_features, + sessions_items_availabilities=sessions_items_availabilities, + choices=choices, + ) + + +def load_modecanada(): + """_summary_.""" + pass diff --git a/choice_learn/datasets/data/swissmetro.csv.gz b/choice_learn/datasets/data/swissmetro.csv.gz new file mode 100644 index 0000000000000000000000000000000000000000..9b161552da95e0a187ff000addfe57f4514351f3 GIT binary patch literal 117429 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 m41tk8P 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 Date: Tue, 2 Jan 2024 14:13:41 +0100 Subject: [PATCH 010/767] ENH: beautification of repository --- README.md | 18 +++------ notebooks/template.ipynb | 79 ---------------------------------------- 2 files changed, 5 insertions(+), 92 deletions(-) delete mode 100644 notebooks/template.ipynb diff --git a/README.md b/README.md index 9ad5ae03..c9cfd564 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,10 @@ [![Pre-commit](https://img.shields.io/badge/pre--commit-enabled-informational?logo=pre-commit&logoColor=white)](https://github.com/artefactory/choice-learn-private/blob/main/.pre-commit-config.yaml) -TODO: if not done already, check out the [Skaff documentation](https://artefact.roadie.so/catalog/default/component/repo-builder-ds/docs/) for more information about the generated repository. +Choice-Learn is a Python package designed to help you build with ease discrete choice models. +The package provides ready to use datasets and different models from the litterature. It also provides a lower level use if you want to customize any model or create your own from scratch. In particular you will find smart datasets handling to limit RAM usage and different structure commons to any choice model. -choice-learn is a Python package designed to help you build with ease a discrete choice model. +This repository contains a private version of the package. ## Table of Contents @@ -27,22 +28,13 @@ choice-learn is a Python package designed to help you build with ease a discrete To install the required packages in a virtual environment, run the following command: +** pip-install not possible yet, to come soon** ```bash -make install -``` - -TODO: Choose between conda and venv if necessary or let the Makefile as is and copy/paste the [MORE INFO installation section](MORE_INFO.md#eased-installation) to explain how to choose between conda and venv. - -A complete list of available commands can be found using the following command: - -```bash -make help +pip install choice-learn ``` ## Usage -TODO: Add usage instructions here - ## Documentation TODO: Github pages is not enabled by default, you need to enable it in the repository settings: Settings > Pages > Source: "Deploy from a branch" / Branch: "gh-pages" / Folder: "/(root)" diff --git a/notebooks/template.ipynb b/notebooks/template.ipynb deleted file mode 100644 index 298da4cd..00000000 --- a/notebooks/template.ipynb +++ /dev/null @@ -1,79 +0,0 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Imports" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "%load_ext autoreload\n", - "%autoreload 2\n", - "\n", - "import pandas as pd\n", - "pd.set_option('display.max_columns', 500)\n", - "pd.options.plotting.backend = \"plotly\"" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "df = pd.read_csv(\"\")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# EDA" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "venv", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.16" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} From 10e05e2915420352f4aa5ace410252d8c9133280 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 2 Jan 2024 14:22:09 +0100 Subject: [PATCH 011/767] ADD: ModeCanada DataLoader --- choice_learn/datasets/base.py | 79 ++++++++++++++++++- choice_learn/datasets/data/ModeCanada.csv.gz | Bin 0 -> 125485 bytes 2 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 choice_learn/datasets/data/ModeCanada.csv.gz diff --git a/choice_learn/datasets/base.py b/choice_learn/datasets/base.py index 92289bf3..0283f847 100644 --- a/choice_learn/datasets/base.py +++ b/choice_learn/datasets/base.py @@ -4,6 +4,7 @@ from importlib import resources import numpy as np +import pandas as pd from choice_learn.data.choice_dataset import ChoiceDataset @@ -64,7 +65,7 @@ def load_gzip(data_file_name, data_module=DATA_MODULE, encoding="utf-8"): compressed_file = gzip.open(compressed_file, mode="rt", encoding=encoding) names = next(compressed_file) names = names.replace("\n", "") - data = np.loadtxt(compressed_file, delimiter=",", dtype=int) + data = np.loadtxt(compressed_file, delimiter=",", dtype=object) return names.split(","), data @@ -115,6 +116,8 @@ def load_swissmetro( """ data_file_name = "swissmetro.csv.gz" names, data = load_gzip(data_file_name) + data = data.astype(int) + items = ["TRAIN", "SM", "CAR"] items_features = [] session_features = [ @@ -183,6 +186,74 @@ def load_swissmetro( ) -def load_modecanada(): - """_summary_.""" - pass +def load_modecanada(add_items_one_hot=False, as_frame=False, return_desc=False): + """Load and return the ModeCanada dataset from Koppleman et al. (1993). + + Parameters + ---------- + one_hot_cat_data : bool, optional + Whether to transform categorical data as OneHot, by default False + add_items_one_hot : bool, optional + Whether to add a OneHot encoding of items as items_features, by default False + as_frame : bool, optional + Whether to return the dataset as pd.DataFrame. If not, returned as ChoiceDataset, + by default False + return_desc : bool, optional + Whether to return the description, by default False + + Returns: + -------- + ChoiceDataset + Loaded ModeCanada dataset + """ + data_file_name = "ModeCanada.csv.gz" + names, data = load_gzip(data_file_name) + names = [name.replace('"', "") for name in names] + canada_df = pd.DataFrame(data[:, 1:], index=data[:, 0].astype(int), columns=names[1:]) + canada_df["alt"] = canada_df.apply(lambda row: row.alt.replace('"', ""), axis=1) + # Just some typing + canada_df.income = canada_df.income.astype("float32") + + items = ["air", "bus", "car", "train"] + items_features = [] + session_features = ["income"] + sessions_items_features = ["cost", "freq", "ovt", "ivt"] + choice_column = "choice" + + if add_items_one_hot: + canada_df["oh_air"] = canada_df.apply( + lambda row: 1.0 if row.alt == items[0] else 0.0, axis=1 + ) + canada_df["oh_bus"] = canada_df.apply( + lambda row: 1.0 if row.alt == items[1] else 0.0, axis=1 + ) + canada_df["oh_car"] = canada_df.apply( + lambda row: 1.0 if row.alt == items[2] else 0.0, axis=1 + ) + canada_df["oh_train"] = canada_df.apply( + lambda row: 1.0 if row.alt == items[3] else 0.0, axis=1 + ) + items_features = ["oh_air", "oh_bus", "oh_car", "oh_train"] + else: + items_features = None + + if return_desc: + # TODO + pass + if as_frame: + # TODO + pass + + for col in canada_df.columns: + canada_df[col] = pd.to_numeric(canada_df[col], errors="ignore") + + return ChoiceDataset.from_single_df( + df=canada_df, + items_features_columns=items_features, + sessions_features_columns=session_features, + sessions_items_features_columns=sessions_items_features, + items_id_column="alt", + sessions_id_column="case", + choices_column=choice_column, + choice_mode="one_zero", + ) diff --git a/choice_learn/datasets/data/ModeCanada.csv.gz b/choice_learn/datasets/data/ModeCanada.csv.gz new file mode 100644 index 0000000000000000000000000000000000000000..e60d90ab3bf885e99ebf65ae7dc6c829013d200a GIT binary patch literal 125485 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 literal 0 HcmV?d00001 From 61cff51a8ffeae0b8775974e7ed74a4c55185cf4 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 2 Jan 2024 14:25:36 +0100 Subject: [PATCH 012/767] ENH: SM loader now returns ChoiceDataset with features names --- choice_learn/datasets/base.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/choice_learn/datasets/base.py b/choice_learn/datasets/base.py index 0283f847..fcbaf25b 100644 --- a/choice_learn/datasets/base.py +++ b/choice_learn/datasets/base.py @@ -119,8 +119,8 @@ def load_swissmetro( data = data.astype(int) items = ["TRAIN", "SM", "CAR"] - items_features = [] - session_features = [ + items_features_names = [] + session_features_names = [ "GROUP", "PURPOSE", "FIRST", @@ -134,25 +134,28 @@ def load_swissmetro( "ORIGIN", "DEST", ] - sessions_items_features = ["TT", "CO", "HE"] - sessions_items_features = [ - [f"{item}_{feature}" for feature in sessions_items_features] for item in items + sessions_items_features_names = ["TT", "CO", "HE"] + sessions_items_features_names = [ + [f"{item}_{feature}" for feature in sessions_items_features_names] for item in items ] sessions_items_availabilities = ["TRAIN_AV", "SM_AV", "CAR_AV"] choice_column = "CHOICE" if add_items_one_hot: items_features = np.eye(len(items), dtype=np.float64) + items_features_names = [f"oh_{item}" for item in items] else: items_features = None + items_features_names = None # Adding dummy CAR_HE feature as 0 for consistency names.append("CAR_HE") data = np.hstack([data, np.zeros((data.shape[0], 1))]) - session_features = slice_from_names(data, session_features, names) + session_features = slice_from_names(data, session_features_names, names) sessions_items_features = np.stack( - [slice_from_names(data, features, names) for features in sessions_items_features], axis=-1 + [slice_from_names(data, features, names) for features in sessions_items_features_names], + axis=-1, ) sessions_items_availabilities = slice_from_names(data, sessions_items_availabilities, names) choices = data[:, names.index(choice_column)] @@ -183,6 +186,9 @@ def load_swissmetro( sessions_items_features=sessions_items_features, sessions_items_availabilities=sessions_items_availabilities, choices=choices, + items_features_names=items_features_names, + sessions_features_names=session_features_names, + sessions_items_features_names=sessions_items_features_names, ) From 87d2113142aeb67efd7294622222d9d4b8f8830c Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 2 Jan 2024 14:31:32 +0100 Subject: [PATCH 013/767] ADD: as_frame argument now coded --- choice_learn/datasets/base.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/choice_learn/datasets/base.py b/choice_learn/datasets/base.py index fcbaf25b..e31b0782 100644 --- a/choice_learn/datasets/base.py +++ b/choice_learn/datasets/base.py @@ -177,8 +177,7 @@ def load_swissmetro( # TODO pass if as_frame: - # TODO - pass + return pd.DataFrame(data, columns=names) return ChoiceDataset( items_features=items_features, @@ -246,13 +245,13 @@ def load_modecanada(add_items_one_hot=False, as_frame=False, return_desc=False): if return_desc: # TODO pass - if as_frame: - # TODO - pass for col in canada_df.columns: canada_df[col] = pd.to_numeric(canada_df[col], errors="ignore") + if as_frame: + return canada_df + return ChoiceDataset.from_single_df( df=canada_df, items_features_columns=items_features, From 0654e7b3d50f273f25585b575d57573b1ced2831 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 2 Jan 2024 15:01:20 +0100 Subject: [PATCH 014/767] ENH: datasets imported from /datasets level --- choice_learn/datasets/__init__.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 choice_learn/datasets/__init__.py diff --git a/choice_learn/datasets/__init__.py b/choice_learn/datasets/__init__.py new file mode 100644 index 00000000..a16bf199 --- /dev/null +++ b/choice_learn/datasets/__init__.py @@ -0,0 +1,8 @@ +"""Init file for datasets module.""" + +from .base import load_modecanada, load_swissmetro + +__all__ = [ + "load_modecanada", + "load_swissmetro", +] From 28bdd9f7990e1898b54a5b7ca9259cfba72d8e18 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 2 Jan 2024 15:01:49 +0100 Subject: [PATCH 015/767] ADD: data example notebook --- .../choice_learn_introduction_data.ipynb | 586 ++++++++++++++++++ 1 file changed, 586 insertions(+) create mode 100644 notebooks/choice_learn_introduction_data.ipynb diff --git a/notebooks/choice_learn_introduction_data.ipynb b/notebooks/choice_learn_introduction_data.ipynb new file mode 100644 index 00000000..dd06dd4c --- /dev/null +++ b/notebooks/choice_learn_introduction_data.ipynb @@ -0,0 +1,586 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Introduction to choice-learn's data management" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "from pathlib import Path\n", + "\n", + "sys.path.append(\"../\")\n", + "\n", + "import numpy as np\n", + "import pandas as pd" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ChoiceDataset - Getting Started (Fast-track start ??)\n", + "\n", + "choice-learn package aims at being able to handle large datasets. It uses a data structure similar to the one defined in the torch-choice package.\n", + "\n", + "Particularly, it defines 5 type of different data, storing them separatly in order to avoid redundancy in memory:\n", + "\n", + "- items_features: features of considered items that never change (e.g. size, color, etc...)\n", + "- session_features: features that depend on the session (time) of the choice and that are common to all items (e.g. day of week, etc...)\n", + "- session_items_features: features that depend on the item and on the session (e.g. price)\n", + "\n", + "- items_sessions_availabilities: For each session whether the item it present (1.) or not (0.)\n", + "- choices: chosen item among available ones\n", + "\n", + "\n", + "In order to estimate a model using the choice-learn API, you will first need to wrap your dataset within a ChoiceDataset. The easiest way to do it is to use a pandas DataFrame, let's see how to do it !" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from choice_learn.data.choice_dataset import ChoiceDataset\n", + "\n", + "# path to dataset file is:\n", + "filepath = \"choice_learn/datasets/data/ModeCanada.csv.gz\"\n", + "canada_transport_df = pd.read_csv((Path(\"..\") / filepath), index_col=0)\n", + "\n", + "print(\"Let's look at the dataframe:\")\n", + "canada_transport_df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This dataframe is the raw version of the Canada Transport Dataset \\cite. We need to follow some specifications in order to use it as a ChoiceDataset.\n", + "\n", + "The dataset does not contain any items_features (i.e. fixed features for the different items). We will create a One-Hot encoding that will be represent these items_features for the example." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "transport_df = canada_transport_df.copy()\n", + "items = [\"air\", \"bus\", \"car\", \"train\"]\n", + "\n", + "transport_df[\"oh0\"] = transport_df.apply(lambda row: 1. if row.alt == items[0] else 0., axis=1)\n", + "transport_df[\"oh1\"] = transport_df.apply(lambda row: 1. if row.alt == items[1] else 0., axis=1)\n", + "transport_df[\"oh2\"] = transport_df.apply(lambda row: 1. if row.alt == items[2] else 0., axis=1)\n", + "transport_df[\"oh3\"] = transport_df.apply(lambda row: 1. if row.alt == items[3] else 0., axis=1)\n", + "\n", + "# Just some typing\n", + "transport_df.income = transport_df.income.astype(\"float32\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In order to create the ChoiceDataset from the dataframe, we need to specify:\n", + "- the columns representing the items_features\n", + "- the columns representing the sessions_features\n", + "- the columns representing the sessions_items_features\n", + "- the column where the item is identified \n", + "- the column where the session is identified\n", + "- the column in which the choice is given\n", + "\n", + "For our Canada Transport example, here is how it should be done:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset = ChoiceDataset.from_single_df(df=transport_df,\n", + " items_features_columns=[\"oh0\", \"oh1\", \"oh2\", \"oh3\"],\n", + " sessions_features_columns=[\"income\"],\n", + " sessions_items_features_columns=['cost', 'freq', 'ovt', 'ivt'],\n", + " items_id_column=\"alt\",\n", + " sessions_id_column=\"case\",\n", + " choices_column=\"choice\",\n", + " choice_mode=\"one_zero\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In our case, the items_feature are the one-hot values we have created. The column 'income' represents the income of the subject and is shared by all items durint a session. It thus falls in the sessions_features category. On the contrary, 'cost', 'freq', 'ovt' and 'ivt' describe each transportation mode (items) and change for each session (or each case of the survey). They are considered sessions_items_features.\n", + "\n", + "An argument that needs to be precised is choice-mode. It precised how the choice is encoded in the dataframe. Currently two modes are availble:\n", + "\n", + "**one_zero:**\n", + "The choice column contains a 0 when the alternative/item is not chosen in the session and a 1 if it is chosen.\n", + "This is the case here with Canada Transport.\n", + "\n", + "**item_id:**\n", + "The choice column contains the id of the choice during the session. The id corresponds to the values used in the column 'items_id_column'.\n", + "In this case of Canada Transport, the dataframe would need to be:\n", + "\n", + "| | case | alt | choice | dist | cost | ivt | ovt | freq | \tincome | urban | noalt | \n", + "|---|---|---|---|---|---|---|---|---|---|---|---|\n", + "| 1 | 1 | train | car | 83 | 28.25 | 50 | 66 | 4 | 45 | 0 | 2 |\n", + "| 2 | 1 | car | car | 83 | 15.77 | 61 | 0 | 0 | 45 | 0 | 2 |\n", + "| 3 | 2 | train | car | 83 | 28.25 | 50 | 66 | 4 | 25 | 0 | 2 |\n", + "| 4 | 2 | car | car | 83 | 15.77 | 61 | 0 | 0 | 25 | 0 | 2 |\n", + "| 5 | 3 | train | car | 83 | 28.25 | 50 | 66 | 4 | 70 | 0 | 2 |\n", + "\n", + "In the first 5 examples, the chosen transportation is always the car." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset.sessions_features[0].shape, dataset.items_features[0].shape, dataset.sessions_items_features[0].shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ChoiceDataset - Inside the machine\n", + "\n", + "Let's see an example of ChoiceDataset instantiation from numpy arrays:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Let's see an example of ChoiceDataset instantiation\n", + "\n", + "# from choice-learn.data import ChoiceDataset\n", + "\n", + "# Let's consider three items whose features are:\n", + "# - Size\n", + "# - Weight\n", + "# - price\n", + "# - whether is is on promotion or not\n", + "\n", + "items_features = [\n", + " [1, 2], # item 1 [size, weight]\n", + " [2, 4], # item 2 [size, weight]\n", + " [1.5, 1.5], # item 3 [size, weight]\n", + "]\n", + "\n", + "# We have two customers whose features are\n", + "# - Budget\n", + "# - Age\n", + "# Customer 1 bought item 1 at session 1 and item 2 at session 3\n", + "# Customer 2 bought item 3 at session 2\n", + "\n", + "choices = [0, 2, 1]\n", + "sessions_items_availabilities = [\n", + " [1, 1, 1], # All items available at session 1\n", + " [1, 1, 1], # All items available at session 2\n", + " [0, 1, 1], # Item 1 not available at session 3\n", + "]\n", + "\n", + "sessions_features = [\n", + " [100, 20], # session 1, customer 1 [budget, age]\n", + " [200, 40], # session 2, customer 2 [budget, age]\n", + " [80, 20], # session 3, customer 1 [budget, age]\n", + "]\n", + "\n", + "sessions_items_features = [\n", + " [\n", + " [100, 0], # Session 1, Item 1 [price, promotion]\n", + " [140, 0], # Session 1, Item 2 [price, promotion]\n", + " [200, 0], # Session 1, Item 2 [price, promotion]\n", + " ],\n", + " [\n", + " [100, 0], # Session 2 Item 1 [price, promotion]\n", + " [120, 1], # Session 2, Item 2 [price, promotion]\n", + " [200, 0], # Session 2, Item 2 [price, promotion]\n", + " ],\n", + " [\n", + " [100, 0], # Session 3, Item 1 [price, promotion], values do not really matter, but needs to exist for shapes sake\n", + " [120, 1], # Session 3, Item 2 [price, promotion]\n", + " [180, 1], # Session 3, Item 2 [price, promotion]\n", + " ],\n", + "]\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that in items_features and sessions_items_features, the features need to be well ordered:\n", + "- The features are ordered the same for all items\n", + "- The items are ordered the same for items_features and sessions_items_features, and their index is used in choices:\n", + "\n", + "\n", + "**items_features** = [[feature_1_item_A, feature_2_item_A, ...], [features_1_item_B, feature_2_item_B, ...], ...]\n", + "\n", + "**session_items_features** = [[[session_1_feature_1_item_A, ...], [session_1_feature_1_item_B, ...]], [[session_2_feature_1_item_A, ...], [session_2_feature_1_item_B, ...]], ...]\n", + "\n", + "**choices** then represent the index of the item: 0 when item_1 is chose, 1 when item_2, etc..., e.g. [0, 0, 2, 1, ...]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset = ChoiceDataset(\n", + " items_features=items_features,\n", + " sessions_features=sessions_features,\n", + " sessions_items_features=sessions_items_features,\n", + " sessions_items_availabilities=sessions_items_availabilities,\n", + " choices=choices,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset.sessions_items_features[0].shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "ChoiceDataset is indexed by session. You can use [] to subset it.\n", + "It is particularly useful for train/test split:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "train_index = [0, 1]\n", + "test_index = [2]\n", + "train_dataset = dataset[train_index]\n", + "test_dataset = dataset[test_index]\n", + "print(\"Train Dataset length:\", len(train_dataset), \"Test Dataset lenght:\", len(test_dataset))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you want to access the features you can use the .iloc function with sessions indexes \n", + "It returns the features in this order:\n", + "\n", + "- items_features (n_items, n_items_features)\n", + "- sessions_features (n_sessions_indexes, n_sessions_features)\n", + "- sessions_items_features (n_sessions_indexes, n_items, n_sessions_items_features)\n", + "- sessions_items_availabilities (n_sessions_indexes, n_items)\n", + "- choices (n_sessions_indexes,)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "| index | feature | shape | \n", + "|---|---|---|\n", + "| 0 | items_features | (n_items, n_items_features) |\n", + "| 1 | sessions_features | (n_sessions_indexes, n_sessions_features) |\n", + "| 2 | sessions_items_features | (n_sessions_indexes, n_items, n_sessions_items_features) |\n", + "| 3 | sessions_items_availabilities | (n_sessions_indexes, n_items) |\n", + "| 4 | choices | (n_sessions_indexes,) |" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sessions_indexes = [0, 1]\n", + "print(\"Items features:\", train_dataset.batch[sessions_indexes][0])\n", + "print(\"Sessions features:\", train_dataset.batch[sessions_indexes][1])\n", + "print(\"Sessions Items features:\", train_dataset.batch[sessions_indexes][2])\n", + "print(\"Sessions Items Availabilities features:\", train_dataset.batch[sessions_indexes][3])\n", + "print(\"Sessions Choices:\", train_dataset.batch[sessions_indexes][4])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To simplify the iteration over the dataset you can call the .batch method, with the batch_size argument.\n", + "\n", + "Note that batch_size=-1 returns the whole dataset" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# All the features are given for each session, in order to compute utility and NegativeLogLikelihood\n", + "for n_batch, batch in enumerate(dataset.iter_batch(batch_size=1)):\n", + " print(n_batch, batch)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that you will need to use a ChoiceDataset to use the models." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Stacking features**\n", + "If you need to keep a clear distinction between different features, you can use stacking in the ChoiceDataset. For example if we have two kind of items_features and we do not want them to be within the same np.ndarray we can as follow:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "items_features_2 = [\n", + " [11, 12], # item 1 \n", + " [12, 14], # item 2 \n", + " [11.5, 11.5], # item 3 \n", + "]\n", + "dataset = ChoiceDataset(\n", + " items_features=(items_features, items_features_2), # Here items_features specified as a tuple of the two features lists\n", + " sessions_features=sessions_features,\n", + " sessions_items_features=sessions_items_features,\n", + " sessions_items_availabilities=sessions_items_availabilities,\n", + " choices=choices,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When indexing or batching your ChoiceDataset, you will now get items_features as a tuple, with elements corresponding to (items_features, items_features_2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset.batch[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This is possible with:\n", + "- items_features\n", + "- sessions_features\n", + "- sessions_items_features\n", + "As the other should not need any superposition of values." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset = ChoiceDataset(\n", + " items_features=(items_features, items_features_2), # Here items_features specified as a tuple of the two features lists\n", + " sessions_features=(sessions_features, sessions_features),\n", + " sessions_items_features=(sessions_items_features, sessions_items_features),\n", + " sessions_items_availabilities=sessions_items_availabilities,\n", + " choices=choices,\n", + ")\n", + "\n", + "dataset.batch[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## More Advanced use: the FeatureStore & OneHotStore" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The FeaturseStore class is here to stock values that regularly repeat themselves over a sequence.\n", + "Let's take an example where several stores are considered. If we want to model the utility from store features (such as surface, average number of customers, etc...), these features are shared by several choices in our dataset." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# We have three stores, represented by their (surface, average_number_of_customers):\n", + "store_features = [[100, 250], [150, 500], [80, 100]]\n", + "# Now we consider a sequence of choices that happen in [store_1, store_1, store_2, store_3, store_2, store_1, store_3]\n", + "# The usual way to store the features would be:\n", + "usual_store_features = [[100, 250], [100, 250], [150, 500], [80, 100], [150, 500], [100, 250], [80, 100]]\n", + "# There are a lot of repetetitions, which is not very efficient...\n", + "# Let's multiply this with 600 stores represented as one-hot over thousands of sessions, we will have a memory problem !\n", + "# Now the StoreFeatures tries to be more efficient:\n", + "\n", + "store = {1: [100, 250], 2: [150, 500], 3: [80, 100]} # We can use a dictionary to store the features of each store\n", + "sequence = [1, 1, 2, 3, 2, 1, 3] # We can use a sequence of keys to represent the sequence of stores\n", + "\n", + "from choice_learn.data.store import FeaturesStore\n", + "feat_store = FeaturesStore.from_dict(store, sequence)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Now we can access the features of the store appearing at index i in the sequence with the iloc method:\n", + "\n", + "# Let's see the features of the store at index 0\n", + "print(feat_store.batch[0])\n", + "# Now we can also take a whole batch:\n", + "print(feat_store.batch[[0, 1, 5]])\n", + "# Ah ! We selected all the indexes where the store is 1, which is why we always have the same features !" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In order to further optimize RAM usage, you can use the OneHotStore, built specifically for one-hot encoded features. The store will only keep the index of the one of each element and will consitute the one-hot vector only when needed." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from choice_learn.data.store import OneHotStore" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "store = OneHotStore.from_sequence([\"a\", \"a\", \"a\", \"c\", \"b\", \"b\", \"a\"])\n", + "\n", + "# When using from_sequence, the store collects ranked order (lower to higher) of each element as index\n", + "print(\"RAM storage of the OneHotStore:\", store.store, \"with sequence:\", store.sequence)\n", + "# When indexing with iloc, we can access the one-hot encoding of the element at index i in the sequence\n", + "print(\"One-hot vector at index 0:\", store.batch[0])\n", + "print(\"One-hot vector at indexes [0, 1, 3]:\")\n", + "print(store.batch[[0, 1, 3]])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- Add: Example from pandas.DataFrame" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Ready-to-use datasets\n", + "A few well-known open source datasets are directly integrated and the package and can be downloaded in one line:\n", + "- SwissMetro from Bierlaire et al (2001)\n", + "- ModeCanada from Koppleman et al. (1993)\n", + "\n", + "If you feel like another open-source dataset should be included, reach out !" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from choice_learn.datasets import load_swissmetro, load_modecanada\n", + "\n", + "canada_choice_dataset = load_modecanada()\n", + "swissmetro_choice_dataset = load_swissmetro()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The datasets can also be downloaded as dataframes:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "canada_df = load_modecanada(as_frame=True)\n", + "canada_df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "tf_env", + "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.11.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 238073cad9f349eca58a33664f058ab228edc824 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 2 Jan 2024 16:40:33 +0100 Subject: [PATCH 016/767] FIX: CD.batch() -> CD.iter_batch() --- choice_learn/models/base_model.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index 5b19399b..293bae3e 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -8,9 +8,9 @@ import numpy as np import tensorflow as tf import tqdm -from choice_modeling.tf_ops import ( + +from choice_learn.tf_ops import ( CustomCategoricalCrossEntropy, - availability_softmax, custom_softmax, ) @@ -163,7 +163,7 @@ def train_step( # Probabilities of selected product available_utilities = tf.gather_nd(indices=choices_nd, params=final_utilities) """ - probabilities = availability_softmax(all_u, availabilities_batch, axis=-1) + # probabilities = availability_softmax(all_u, availabilities_batch, axis=-1) probabilities = custom_softmax( all_u, availabilities_batch, normalize_exit=self.normalize_non_buy, axis=-1 ) @@ -226,7 +226,7 @@ def fit( if sample_weight is not None: if verbose > 0: inner_range = tqdm.tqdm( - choice_dataset.batch( + choice_dataset.iter_batch( shuffle=True, sample_weight=sample_weight, batch_size=batch_size ), total=int(len(choice_dataset) / np.max([1, batch_size])), @@ -234,7 +234,7 @@ def fit( leave=False, ) else: - inner_range = choice_dataset.batch( + inner_range = choice_dataset.iter_batch( shuffle=True, sample_weight=sample_weight, batch_size=batch_size ) @@ -270,13 +270,13 @@ def fit( else: if verbose > 0: inner_range = tqdm.tqdm( - choice_dataset.batch(shuffle=True, batch_size=batch_size), + choice_dataset.iter_batch(shuffle=True, batch_size=batch_size), total=int(len(choice_dataset) / np.max([batch_size, 1])), position=1, leave=False, ) else: - inner_range = choice_dataset.batch(shuffle=True, batch_size=batch_size) + inner_range = choice_dataset.iter_batch(shuffle=True, batch_size=batch_size) for batch_nb, ( items_batch, sessions_batch, @@ -329,7 +329,7 @@ def fit( sessions_items_batch, availabilities_batch, choices_batch, - ) in enumerate(val_dataset.batch(shuffle=False, batch_size=batch_size)): + ) in enumerate(val_dataset.iter_batch(shuffle=False, batch_size=batch_size)): self.callbacks.on_batch_begin(batch_nb) self.callbacks.on_test_batch_begin(batch_nb) test_losses.append( @@ -407,7 +407,7 @@ def batch_predict( items_batch, sessions_batch, sessions_items_batch, availabilities_batch, choices_batch ) # Compute probabilities from utilities & availabilties - probabilities = availability_softmax(utilities, availabilities_batch, axis=-1) + # probabilities = availability_softmax(utilities, availabilities_batch, axis=-1) probabilities = custom_softmax( utilities, availabilities_batch, normalize_exit=self.normalize_non_buy, axis=-1 ) @@ -492,7 +492,7 @@ def predict_probas(self, choice_dataset): sessions_items_batch, availabilities_batch, choices_batch, - ) in choice_dataset.batch(): + ) in choice_dataset.iter_batch(): _, probabilities = self.batch_predict( items_batch, sessions_batch, @@ -529,7 +529,7 @@ def evaluate(self, choice_dataset, batch_size=None): sessions_items_batch, availabilities_batch, choices_batch, - ) in choice_dataset.batch(batch_size=batch_size): + ) in choice_dataset.iter_batch(batch_size=batch_size): loss, _ = self.batch_predict( items_batch, sessions_batch, From 6f475dbdcb0ebf0da3bbd1971d09af6bdb34b12b Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 2 Jan 2024 17:03:07 +0100 Subject: [PATCH 017/767] ADD: conditional logit example notebook --- .../choice_learn_introduction_clogit.ipynb | 352 ++++++++++++++++++ 1 file changed, 352 insertions(+) create mode 100644 notebooks/choice_learn_introduction_clogit.ipynb diff --git a/notebooks/choice_learn_introduction_clogit.ipynb b/notebooks/choice_learn_introduction_clogit.ipynb new file mode 100644 index 00000000..9293058f --- /dev/null +++ b/notebooks/choice_learn_introduction_clogit.ipynb @@ -0,0 +1,352 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Introduction to choice-learn's modelling" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "from pathlib import Path\n", + "\n", + "sys.path.append(\"../\")\n", + "\n", + "import numpy as np\n", + "import pandas as pd" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ChoiceModel - Getting Started\n", + "\n", + "choice-learn package offers a high level API to conceive and estimate discrete choice models.\n", + "\n", + "We begin this tutorial with the estimation of a Conditional Logit Model on the ModeCanada dataset.\n", + "\n", + "First, we download our data as a ChoiceDataset. See the data management tutorial first if needed." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# TO be transformed to be clearer\n", + "transport_df = pd.read_csv(\"/data/raw_data/ModeCanada.csv\", index_col=0)\n", + "\n", + "# Following torch-Choice guide:\n", + "transport_df = transport_df.loc[transport_df.noalt == 4]\n", + "\n", + "items = [\"air\", \"bus\", \"car\", \"train\"]\n", + "\n", + "transport_df[\"oh_air\"] = transport_df.apply(lambda row: 1. if row.alt == items[0] else 0., axis=1)\n", + "transport_df[\"oh_bus\"] = transport_df.apply(lambda row: 1. if row.alt == items[1] else 0., axis=1)\n", + "transport_df[\"oh_car\"] = transport_df.apply(lambda row: 1. if row.alt == items[2] else 0., axis=1)\n", + "transport_df[\"oh_train\"] = transport_df.apply(lambda row: 1. if row.alt == items[3] else 0., axis=1)\n", + "\n", + "transport_df.income = transport_df.income.astype(\"float32\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from choice_learn.data.choice_dataset import ChoiceDataset\n", + "dataset = ChoiceDataset.from_single_df(df=transport_df,\n", + " items_features_columns=[\"oh_air\", \"oh_bus\", \"oh_car\", \"oh_train\"],\n", + " sessions_features_columns=[\"income\"],\n", + " sessions_items_features_columns=[\"cost\", \"freq\", \"ovt\", \"ivt\"],\n", + " items_id_column=\"alt\",\n", + " sessions_id_column=\"case\",\n", + " choices_column=\"choice\",\n", + " choice_mode=\"one_zero\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we can import the needed modules:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from choice_learn.models.conditional_mnl import ConditionalMNL, ModelSpecification" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The conditional MNL \\ref{Train} specifies a linear utility for each item i during the session s with regards to the features:\n", + "$$\n", + "U(i, s) = \\sum_{features} a(i, s) * feat(i, s)\n", + "$$\n", + "\n", + "We will use a ModelSpecification object to define our model with regards to our ChoiceDataset.\n", + "For each feature in the choice dataset we can specify how it must be specified in the utility.\n", + "\n", + "Let's re-use a common example from \\ref{} on the ModeCanda dataset:\n", + "$$\n", + "U(i, s) = \\beta^{inter}_i + \\beta^{price} \\cdot price(i, s) + \\beta^{freq} \\cdot freq(i, s) + \\beta^{ovt} \\cdot ovt(i, s) + \\beta^{income}_i \\cdot income(s) + \\beta^{ivt}_i \\cdot ivt(i, t) + \\epsilon(i, t)\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that we want to estimate:\n", + "\n", + "- one $\\beta^{price}$, $\\beta^{freq}$ and $\\beta^{ovt}$ coefficient. They are shared by all items.\n", + "- one $\\beta^{ivt}$ coefficient for **each** item.\n", + "- one $\\beta^{inter}$ and $\\beta^{income}$ coefficient for **each** item, with **additional constraint** to be 0 for the first item (air).\n", + "\n", + "We will use a ModelSpecification object to create the right utility function.\n", + "We need to specify for each weight:\n", + "- a unique name\n", + "- the name of the feature it goes with:\n", + " - it must match the feature name in the ChoiceDataset\n", + " - \"intercept\" is the standardized name used for intercept, pay attention not to override it\n", + "- items_indexes: the items concerned, as indexed in the ChoiceDataset" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Instantiation of the specification\n", + "spec = ModelSpecification()\n", + "\n", + "# Creation of the different weights:\n", + "\n", + "\n", + "# add_coefficients adds one coefficient for each specified item_index\n", + "# intercept, and income are added for each item except the first one that needs to be zeroed\n", + "spec.add_coefficients(coefficient_name=\"beta_inter\", feature_name=\"intercept\", items_indexes=[1, 2, 3])\n", + "spec.add_coefficients(coefficient_name=\"beta_income\", feature_name=\"income\", items_indexes=[1, 2, 3])\n", + "\n", + "# ivt is added for each item:\n", + "spec.add_coefficients(coefficient_name=\"beta_ivt\", feature_name=\"ivt\", items_indexes=[0, 1, 2, 3])\n", + "\n", + "# shared_coefficient add one coefficient that is used for all items specified in the items_indexes:\n", + "# Here, cost, freq and ovt coefficients are shared between all items\n", + "spec.add_shared_coefficient(coefficient_name=\"beta_cost\", feature_name=\"cost\", items_indexes=[0, 1, 2, 3])\n", + "spec.add_shared_coefficient(coefficient_name=\"beta_freq\", feature_name=\"freq\", items_indexes=[0, 1, 2, 3])\n", + "spec.add_shared_coefficient(coefficient_name=\"beta_ovt\", feature_name=\"ovt\", items_indexes=[0, 1, 2, 3])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we can instantiate our ConditionalMNL from the specification. We use LBFGS as the estimation method." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cmnl = ConditionalMNL(spec, optimizer=\"lbfgs\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In order to estimate the the coefficients values, use the .fit method with the ChoiceDataset:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "history = cmnl.fit(dataset, n_epochs=1000)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It is possible to see the estimated coefficients with the .weights argument:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cmnl.weights" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The negative loglikelihood can be estimated using .evaluate():" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\"The average neg-loglikelihood is:\", cmnl.evaluate(dataset).numpy())\n", + "print(\"The total neg-loglikelihood is:\", cmnl.evaluate(dataset).numpy()*len(dataset))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can compare the estimated coefficients and the negative log-likelihood obtained in \\ref{} and \\ref{torch-choice}, and it is similar !" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import tensorflow as tf\n", + "\n", + "# Here are the values obtained in the references:\n", + "gt_weights = [\n", + " tf.constant([[0.697311, 1.8437, 3.27381]]),\n", + " tf.constant([[-0.0890796, -0.0279925, -0.038146]]),\n", + " tf.constant([[0.0595089, -0.00678188, -0.00645982, -0.00145029]]),\n", + " tf.constant([[-0.0333421]]),\n", + " tf.constant([[0.0925304]]),\n", + " tf.constant([[-0.0430032]]),\n", + "]\n", + "gt_model = ConditionalMNL(spec, lr=0.01)\n", + "gt_model.fit(dataset, n_epochs=1, batch_size=-1)\n", + "\n", + "# Here we estimate the negative log-likelihood with these coefficients (also, we obtain same value as in those papers):\n", + "gt_model.weights = gt_weights\n", + "gt_model.evaluate(dataset) * len(dataset)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In order to estimate the utilities, use the .predict_utility() method. In order to estimate the probabilities, use the .compute_probabilities() method.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# print(\"Utilities of each item for the first 5 sessions:\", cmnl.predict_utility(dataset)[:5])\n", + "print(\"Purchase probability of each item for the first 5 sessions:\", cmnl.predict_probas(dataset)[:5])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "plt.plot(history)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For very large datasets that do not fit entirely in the memory, the LBFGS method might not be the best choice. Here we can use the power of the Tensorflow library to use stochastic gradient descent optimizers.\n", + "\n", + "In this case, it is possible to obtain the same coefficients estimation, also it is a little tricky to get it quickly. We need to adjust the learning rate over time for the optimization not to be too slow." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cmnl = ConditionalMNL(spec, optimizer=\"Adam\")\n", + "history = cmnl.fit(dataset, n_epochs=2000, batch_size=-1)\n", + "cmnl.optimizer.lr = cmnl.optimizer.lr / 5\n", + "history2 = cmnl.fit(dataset, n_epochs=4000, batch_size=-1)\n", + "cmnl.optimizer.lr = cmnl.optimizer.lr / 10\n", + "history3 = cmnl.fit(dataset, n_epochs=20000, batch_size=-1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cmnl.weights" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cmnl.evaluate(dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "tf_env", + "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.11.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 16d1856c1afd24741c9386fe3c6f201a129093ec Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 2 Jan 2024 17:14:53 +0100 Subject: [PATCH 018/767] ENH: import level for data & models --- choice_learn/data/__init__.py | 4 ++++ choice_learn/models/__init__.py | 5 +++++ notebooks/choice_learn_introduction_clogit.ipynb | 4 ++-- notebooks/choice_learn_introduction_data.ipynb | 6 +++--- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/choice_learn/data/__init__.py b/choice_learn/data/__init__.py index ee23245a..83ca8df0 100644 --- a/choice_learn/data/__init__.py +++ b/choice_learn/data/__init__.py @@ -1 +1,5 @@ """Data handling classes and functions.""" +from .choice_dataset import ChoiceDataset +from .store import FeaturesStore, OneHotStore + +__all__ = ["ChoiceDataset", "FeaturesStore", "OneHotStore"] diff --git a/choice_learn/models/__init__.py b/choice_learn/models/__init__.py index c5e79129..708fec6d 100644 --- a/choice_learn/models/__init__.py +++ b/choice_learn/models/__init__.py @@ -1 +1,6 @@ """Models classes and functions.""" + +from .conditional_mnl import ConditionalMNL, ModelSpecification +from .rumnet import PaperRUMnet as RUMnet + +__all__ = ["ModelSpecification", "ConditionalMNL", "RUMnet"] diff --git a/notebooks/choice_learn_introduction_clogit.ipynb b/notebooks/choice_learn_introduction_clogit.ipynb index 9293058f..df3c6413 100644 --- a/notebooks/choice_learn_introduction_clogit.ipynb +++ b/notebooks/choice_learn_introduction_clogit.ipynb @@ -64,7 +64,7 @@ "metadata": {}, "outputs": [], "source": [ - "from choice_learn.data.choice_dataset import ChoiceDataset\n", + "from choice_learn.data import ChoiceDataset\n", "dataset = ChoiceDataset.from_single_df(df=transport_df,\n", " items_features_columns=[\"oh_air\", \"oh_bus\", \"oh_car\", \"oh_train\"],\n", " sessions_features_columns=[\"income\"],\n", @@ -88,7 +88,7 @@ "metadata": {}, "outputs": [], "source": [ - "from choice_learn.models.conditional_mnl import ConditionalMNL, ModelSpecification" + "from choice_learn.models import ConditionalMNL, ModelSpecification" ] }, { diff --git a/notebooks/choice_learn_introduction_data.ipynb b/notebooks/choice_learn_introduction_data.ipynb index dd06dd4c..61adda62 100644 --- a/notebooks/choice_learn_introduction_data.ipynb +++ b/notebooks/choice_learn_introduction_data.ipynb @@ -50,7 +50,7 @@ "metadata": {}, "outputs": [], "source": [ - "from choice_learn.data.choice_dataset import ChoiceDataset\n", + "from choice_learn.data import ChoiceDataset\n", "\n", "# path to dataset file is:\n", "filepath = \"choice_learn/datasets/data/ModeCanada.csv.gz\"\n", @@ -457,7 +457,7 @@ "store = {1: [100, 250], 2: [150, 500], 3: [80, 100]} # We can use a dictionary to store the features of each store\n", "sequence = [1, 1, 2, 3, 2, 1, 3] # We can use a sequence of keys to represent the sequence of stores\n", "\n", - "from choice_learn.data.store import FeaturesStore\n", + "from choice_learn.data import FeaturesStore\n", "feat_store = FeaturesStore.from_dict(store, sequence)" ] }, @@ -489,7 +489,7 @@ "metadata": {}, "outputs": [], "source": [ - "from choice_learn.data.store import OneHotStore" + "from choice_learn.data import OneHotStore" ] }, { From 6c035ae1f459e95d21734a177755a721c686794c Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Wed, 3 Jan 2024 09:48:33 +0100 Subject: [PATCH 019/767] ENH: ReadMe --- README.md | 35 ++++++++++++++++++---------- docs/choice_learn_official_logo.png | Bin 0 -> 62283 bytes 2 files changed, 23 insertions(+), 12 deletions(-) create mode 100644 docs/choice_learn_official_logo.png diff --git a/README.md b/README.md index c9cfd564..37a90a81 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,11 @@ [![Linting , formatting, imports sorting: ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) [![security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit) [![Pre-commit](https://img.shields.io/badge/pre--commit-enabled-informational?logo=pre-commit&logoColor=white)](https://github.com/artefactory/choice-learn-private/blob/main/.pre-commit-config.yaml) + + + Choice-Learn is a Python package designed to help you build with ease discrete choice models. The package provides ready to use datasets and different models from the litterature. It also provides a lower level use if you want to customize any model or create your own from scratch. In particular you will find smart datasets handling to limit RAM usage and different structure commons to any choice model. @@ -24,8 +27,14 @@ This repository contains a private version of the package. - [Documentation](#documentation) - [Repository Structure](#repository-structure) +## What's in there ? + +## Getting Started - Fast Track + ## Installation +### User installation + To install the required packages in a virtual environment, run the following command: ** pip-install not possible yet, to come soon** @@ -33,6 +42,18 @@ To install the required packages in a virtual environment, run the following com pip install choice-learn ``` +In the mean time you can clone the repository: +```bash +git clone git@github.com:artefactory/choice-learn-private.git +``` + +### Dependencies +Choice-Learn requires the following: +- Python (>=...) +- NumPy (>=...) +- TensorFlow (>=...) +- pandas ? + ## Usage ## Documentation @@ -53,16 +74,6 @@ To build it and deploy it to GitHub pages, run the following command: make deploy_docs ``` -## Repository Structure +## Citation -``` -. -├── .github <- GitHub Actions workflows and PR template -├── bin <- Bash files -├── config <- Configuration files -├── docs <- Documentation files (mkdocs) -├── lib <- Python modules -├── notebooks <- Jupyter notebooks -├── secrets <- Secret files (ignored by git) -└── tests <- Unit tests -``` +### Contributors diff --git a/docs/choice_learn_official_logo.png b/docs/choice_learn_official_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..801c17bcfe85d4ad0c0b67a6c5bb45e75791f3ab GIT binary patch literal 62283 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 literal 0 HcmV?d00001 From 8f5013f9e998f39579dc515b9bf5f97788328256 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Wed, 3 Jan 2024 12:04:27 +0100 Subject: [PATCH 020/767] ADD: 1st version of custom model notebook --- notebooks/custom_model.ipynb | 328 +++++++++++++++++++++++++++++++++++ 1 file changed, 328 insertions(+) create mode 100644 notebooks/custom_model.ipynb diff --git a/notebooks/custom_model.ipynb b/notebooks/custom_model.ipynb new file mode 100644 index 00000000..2da3b10c --- /dev/null +++ b/notebooks/custom_model.ipynb @@ -0,0 +1,328 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Introduction to customized Choice Models" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Choice-Learn package aims at providing structure and helpful functions in order to design any choice model. The main idea is to write the utility function and let the package work its magic.\n", + "It is recommended to read the data tutorial before to understand the ChoiceDataset class.\n", + "\n", + "Let's create again a conditional MNL on the ModeCanada just like the example previous example \\ref{}. Only this time we will write the model ourselves." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "from pathlib import Path\n", + "\n", + "sys.path.append(\"../\")\n", + "\n", + "import numpy as np\n", + "import pandas as pd" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We download the ModeCanada dataset as a ChoiceDataset, see \\ref{} for more details." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from choice_learn.data import ChoiceDataset\n", + "\n", + "# TO be transformed to be clearer\n", + "transport_df = pd.read_csv(\"/data/raw_data/ModeCanada.csv\", index_col=0)\n", + "\n", + "# Following torch-Choice guide:\n", + "transport_df = transport_df.loc[transport_df.noalt == 4]\n", + "\n", + "items = [\"air\", \"bus\", \"car\", \"train\"]\n", + "\n", + "transport_df[\"oh_air\"] = transport_df.apply(lambda row: 1. if row.alt == items[0] else 0., axis=1)\n", + "transport_df[\"oh_bus\"] = transport_df.apply(lambda row: 1. if row.alt == items[1] else 0., axis=1)\n", + "transport_df[\"oh_car\"] = transport_df.apply(lambda row: 1. if row.alt == items[2] else 0., axis=1)\n", + "transport_df[\"oh_train\"] = transport_df.apply(lambda row: 1. if row.alt == items[3] else 0., axis=1)\n", + "\n", + "transport_df.income = transport_df.income.astype(\"float32\")\n", + "\n", + "dataset = ChoiceDataset.from_single_df(df=transport_df,\n", + " items_features_columns=[\"oh_air\",\n", + " \"oh_bus\",\n", + " \"oh_car\",\n", + " \"oh_train\"],\n", + " sessions_features_columns=[\"income\"],\n", + " sessions_items_features_columns=[\"cost\",\n", + " \"freq\",\n", + " \"ovt\",\n", + " \"ivt\"],\n", + " items_id_column=\"alt\",\n", + " sessions_id_column=\"case\",\n", + " choices_column=\"choice\",\n", + " choice_mode=\"one_zero\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will subclass the parent class ChoiceModel that we need to import. It mainly works with TensorFlow as a backend, it is thus recommended to use their operation as much as possible. Most NumPy operations have a TensorFlow equivalent. You can look at the documentation here \\ref{}.\n", + "\n", + "For our custom model to work, we need to specify:\n", + "- Weights initialization in __init__()\n", + "- the utility function in compute_utility()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import tensorflow as tf\n", + "from choice_learn.models.base_model import ChoiceModel" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### *Coefficients Initialization*\n", + "\n", + "Following our utility formula we need four coefficients vectors:\n", + "- $\\beta^{inter}$ has 3 values\n", + "- $\\beta^{price}$, $\\beta^{freq}$, $\\beta^{ovt}$ are regrouped and each has one value, shared by all items\n", + "- $\\beta^{income}$ has 3 values\n", + "- $\\beta^{ivt}$ has 4 values\n", + "\n", + "### *Utility Computation*\n", + "\n", + "In the method compute_utility, we need to define how to estimate each item utility for each session using the features and initialized weights.\n", + "The arguments of the function are each features type of the ChoiceDataset class:\n", + "\n", + "| Order | Argument | shape | Features for ModeCanada| \n", + "|---|---|---|---|\n", + "| 1 | items_features | (n_items, n_items_features) | Items OneHot vectors | \n", + "| 2 | sessions_features | (n_sessions, n_sessions_features) | Customer Income | \n", + "| 3 | sessions_items_features | (n_sessions, n_items, n_sessions_items_features) | Cost, Freq, Ivt, Ovt values of each mode | \n", + "| 4 | sessions_items_availabilities | (n_sessions, n_items) | Not Used | \n", + "| 5 | choices | (n_sessions, ) | Not Used | \n", + "\n", + "The method needs to return the utilities, in the form of a matrix of shape (n_sessions, n_items), reprenting the utility of each item for each session." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class CustomCanadaConditionalMNL(ChoiceModel):\n", + " \"\"\"Conditional MNL following for ModeCanada.\n", + "\n", + " Arguments:\n", + " ----------\n", + " n_item_features : int\n", + " Number of items features\n", + " n_session_item_features : int\n", + " Number of sessions items features\n", + " optimizer : str\n", + " tf.keras.optimizer to use for training, default is Adam\n", + " lr: float\n", + " learning rate for optimizer, default is 1e-3\n", + " \"\"\"\n", + "\n", + " def __init__(\n", + " self,\n", + " **kwargs,\n", + " ):\n", + " \"\"\"Model coefficients instantiation.\"\"\"\n", + " super().__init__(**kwargs)\n", + "\n", + " # Create model weights. Basically is one weight by feature + one for intercept\n", + " beta_inter = tf.Variable(tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(1, 3)),\n", + " name=\"beta_inter\")\n", + " beta_freq_cost_ovt = tf.Variable(tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(1, 3)),\n", + " name=\"beta_freq_cost_ovt\")\n", + " beta_income = tf.Variable(tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(1, 3)),\n", + " name=\"beta_income\")\n", + " beta_ivt = tf.Variable(tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(1, 4)),\n", + " name=\"beta_ivt\")\n", + "\n", + " # Do not forget to add them to the list of weights, it is mandatory !\n", + " self.weights = [beta_inter, beta_freq_cost_ovt, beta_income, beta_ivt]\n", + "\n", + "\n", + " def compute_utility(self, items_batch, sessions_batch, sessions_items_batch, availabilities_batch, choices_batch):\n", + " \"\"\"Method that defines how the model computes the utility of a product.\n", + "\n", + " MNL, here U =\n", + "\n", + " Parameters\n", + " ----------\n", + " items_batch : tuple of np.ndarray (items_features)\n", + " Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products constant features.\n", + " Shape must be (n_items, n_items_features)\n", + " sessions_batch : tuple of np.ndarray (sessions_features)\n", + " Time-Features. Not used as not conditional MNL, means it is the same for all products and is not implicated in utility computation.\n", + " Shape must be (n_sessions, n_sessions_features)\n", + " sessions_items_batch : tuple of np.ndarray (sessions_items_features)\n", + " Time-Item-Features\n", + " Shape must be (n_sessions, n_sessions_items_features)\n", + " availabilities_batch : np.ndarray\n", + " Availabilities (sessions_items_availabilities)\n", + " Shape must be (n_sessions, n_items)\n", + " choices_batch : np.ndarray\n", + " Choices\n", + " Shape must be (n_sessions, )\n", + "\n", + " Returns:\n", + " --------\n", + " np.ndarray\n", + " Utility of each product for each session.\n", + " Shape must be (n_sessions, n_items)\n", + " \"\"\"\n", + " # We use the fact that items_features is OneHot of the item, letting us selecting the right beta when needed (through dot)\n", + " # Utility from items features + intercept\n", + "\n", + " # Concatenation to reach right shape for dot product\n", + " full_beta_inter = tf.concat([tf.constant([[.0]]), self.weights[0]], axis=-1)\n", + " u_intercept = tf.tensordot(tf.concat([*items_batch], axis=-1),\n", + " tf.transpose(full_beta_inter), axes=1) # has shape (n_items, )\n", + "\n", + " sessions_items_ivt = sessions_items_batch[0][:, :, 3]\n", + " sessions_items_cost_freq_ovt = sessions_items_batch[0][:, :, :3]\n", + " u_cost_freq_ovt = tf.squeeze(tf.tensordot(sessions_items_cost_freq_ovt,\n", + " tf.transpose(self.weights[1]), axes=1))\n", + " u_ivt = tf.multiply(sessions_items_ivt, self.weights[3])\n", + "\n", + " # Concatenation to reach right shape for dot product\n", + " full_beta_income = tf.concat([tf.constant([[.0]]), self.weights[2]], axis=-1)\n", + " u_income = tf.tensordot(sessions_batch[0], full_beta_income, axes=1)\n", + "\n", + " # Reshaping the intercept that is constant over all sessions (n_items, ) -> (n_sessions, n_items)\n", + " u_intercept = tf.concat([tf.transpose(u_intercept)] * (u_income.shape[0]), axis=0)\n", + "\n", + " return u_intercept + u_cost_freq_ovt + u_income + u_ivt" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model = CustomCanadaConditionalMNL()\n", + "history = model.fit(dataset, n_epochs=1000, batch_size=-1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Decomposition of the utility operations\n", + "\n", + "#### *Intercept*\n", + "\n", + "- $U_{inter}(air, s) = \\beta^{inter}_{air} = 0$\n", + "- $U_{inter}(bus, s) = \\beta^{inter}_{bus}$\n", + "- $U_{inter}(car, s) = \\beta^{inter}_{car}$\n", + "- $U_{inter}(train, s) = \\beta^{inter}_{train}$\n", + "\n", + "$\\beta^{inter} = \\left(\\begin{array}{c} \n", + "0 \\\\\n", + "\\beta^{inter}_{bus} \\\\\n", + "\\beta^{inter}_{car} \\\\\n", + "\\beta^{inter}_{train} \\\\\n", + "\\end{array}\\right)$\n", + "\n", + "$U_{inter} = \\beta^{inter.T}$\n", + "\n", + "#### *Price, Freq, Ovt*\n", + "- $U_{price, freq, ovt}(air, s) = \\beta^{price} \\cdot price(air, s) + \\beta^{freq} \\cdot freq(air, s) + \\beta^{ovt} \\cdot ovt(air, s)$\n", + "- $U_{price, freq, ovt}(bus, s) = \\beta^{price} \\cdot price(bus, s) + \\beta^{freq} \\cdot freq(bus, s) + \\beta^{ovt} \\cdot ovt(bus, s)$\n", + "- $U_{price, freq, ovt}(car, s) = \\beta^{price} \\cdot price(car, s) + \\beta^{freq} \\cdot freq(car, s) + \\beta^{ovt} \\cdot ovt(car, s)$\n", + "- $U_{price, freq, ovt}(train, s) = \\beta^{price} \\cdot price(train, s) + \\beta^{freq} \\cdot freq(train, s) + \\beta^{ovt} \\cdot ovt(train, s)$\n", + "\n", + "$\\beta^{price, freq, ovt} = \\left(\\begin{array}{c} \n", + "\\beta^{price} \\\\\n", + "\\beta^{freq} \\\\\n", + "\\beta^{ovt} \\\\\n", + "\\end{array}\\right)$ and $sessions\\_items\\_feature[0, :3] = \\left(\\begin{array}{ccc} \n", + "price(air, 0) & freq(air, 0) & ovt(air, 0) \\\\\n", + "price(bus, 0) & freq(bus, 0) & ovt(bus, 0) \\\\\n", + "price(car, 0) & freq(car, 0) & ovt(car, 0) \\\\\n", + "price(train, 0) & freq(train, 0) & ovt(train, 0) \\\\\n", + "\\end{array}\\right)$\n", + "\n", + "$U_{price, freq, ovt} = \\beta^{price, freq, ovt .T} \\cdot sessions\\_items\\_feature[:, :3]$\n", + "\n", + "\n", + "#### *Income*\n", + "- $U_{income}(air, s) = \\beta^{income}_{air} \\cdot income(s)$\n", + "- $U_{income}(bus, s) = \\beta^{income}_{bus} \\cdot income(s)$\n", + "- $U_{income}(car, s) = \\beta^{income}_{car} \\cdot income(s)$\n", + "- $U_{income}(train, s) = \\beta^{income}_{train} \\cdot income(s)$\n", + "\n", + "$\\beta^{income} = \\left(\\begin{array}{c} \n", + "\\beta^{income}_{air} \\\\\n", + "\\beta^{income}_{bus} \\\\\n", + "\\beta^{income}_{car}\\\\\n", + "\\beta^{income}_{train} \\\\\n", + "\\end{array}\\right)$ and $sessions\\_feature = \\left(\\begin{array}{c} \n", + "income(0) \\\\\n", + "income(1) \\\\\n", + "... \\\\\n", + "income(batch\\_size)) \\\\\n", + "\\end{array}\\right)$\n", + "\n", + "$U_{income} = \\beta^{income .T} \\cdot sessions\\_features$" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "tf_env", + "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.11.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 1fe686e375c18248af12dd08fa034179535ff343 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Wed, 3 Jan 2024 14:35:07 +0100 Subject: [PATCH 021/767] ADD: ~finished custom model notebook --- choice_learn/models/base_model.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index 293bae3e..38d4b220 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -648,12 +648,12 @@ def _fit_with_lbfgs(self, dataset, n_epochs, tolerance=1e-8): Parameters ---------- - dataset : _type_ - _description_ - n_epochs : _type_ - _description_ - tolerance : _type_, optional - _description_, by default 1e-8 + dataset : ChoiceDataset + Dataset to be used for coefficients estimations + n_epochs : int + Maximum number of epochs allowed to reach minimum + tolerance : float, optional + Maximum tolerance accepted, by default 1e-8 Returns: -------- From 11f513a0b2b160a3e9a7ca1dd3ca2a2048c274db Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Wed, 3 Jan 2024 14:37:15 +0100 Subject: [PATCH 022/767] ADD: ~finished custom model notebook --- notebooks/custom_model.ipynb | 115 ++++++++++++++++++++++++++++++++--- 1 file changed, 108 insertions(+), 7 deletions(-) diff --git a/notebooks/custom_model.ipynb b/notebooks/custom_model.ipynb index 2da3b10c..78a2dcb9 100644 --- a/notebooks/custom_model.ipynb +++ b/notebooks/custom_model.ipynb @@ -24,6 +24,10 @@ "outputs": [], "source": [ "import os\n", + "\n", + "# Remove GPU use\n", + "os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"\"\n", + "\n", "import sys\n", "from pathlib import Path\n", "\n", @@ -229,8 +233,8 @@ "metadata": {}, "outputs": [], "source": [ - "model = CustomCanadaConditionalMNL()\n", - "history = model.fit(dataset, n_epochs=1000, batch_size=-1)" + "model = CustomCanadaConditionalMNL(optimizer=\"lbfgs\")\n", + "history = model.fit(dataset, n_epochs=400)" ] }, { @@ -239,7 +243,7 @@ "source": [ "### Decomposition of the utility operations\n", "\n", - "#### *Intercept*\n", + "#### > *Intercept*\n", "\n", "- $U_{inter}(air, s) = \\beta^{inter}_{air} = 0$\n", "- $U_{inter}(bus, s) = \\beta^{inter}_{bus}$\n", @@ -255,7 +259,7 @@ "\n", "$U_{inter} = \\beta^{inter.T}$\n", "\n", - "#### *Price, Freq, Ovt*\n", + "#### > *Price, Freq, Ovt*\n", "- $U_{price, freq, ovt}(air, s) = \\beta^{price} \\cdot price(air, s) + \\beta^{freq} \\cdot freq(air, s) + \\beta^{ovt} \\cdot ovt(air, s)$\n", "- $U_{price, freq, ovt}(bus, s) = \\beta^{price} \\cdot price(bus, s) + \\beta^{freq} \\cdot freq(bus, s) + \\beta^{ovt} \\cdot ovt(bus, s)$\n", "- $U_{price, freq, ovt}(car, s) = \\beta^{price} \\cdot price(car, s) + \\beta^{freq} \\cdot freq(car, s) + \\beta^{ovt} \\cdot ovt(car, s)$\n", @@ -274,8 +278,32 @@ "\n", "$U_{price, freq, ovt} = \\beta^{price, freq, ovt .T} \\cdot sessions\\_items\\_feature[:, :3]$\n", "\n", + "Note that in the matrix we couldn't illustrate the sessions dimension, explaining the [0, :3] -> [:, :3].\n", + "sessions_items_features[:, :3] has a shape of (batch_size, 4, 3) and $ \\beta^{price, freq, ovt}$ a shape of (1, 3).\n", + "Resulting $U_{price, freq, ovt} $ has thus shape of (batch_size, 4)\n", + "\n", + "#### > *Ivt*\n", + "- $U_{ivt}(air, s) = \\beta^{ivt}_{air} \\cdot ivt(air, s)$\n", + "- $U_{ivt}(bus, s) = \\beta^{ivt}_{bus} \\cdot ivt(bus, s)$\n", + "- $U_{ivt}(car, s) = \\beta^{ivt}_{car} \\cdot ivt(car, s)$\n", + "- $U_{ivt}(train, s) = \\beta^{ivt}_{train} \\cdot ivt(train, s)$\n", + "\n", + "$\\beta^{ivt} = \\left(\\begin{array}{c} \n", + "\\beta^{ivt}_{air} \\\\\n", + "\\beta^{ivt}_{bus} \\\\\n", + "\\beta^{ivt}_{car}\\\\\n", + "\\beta^{ivt}_{train} \\\\\n", + "\\end{array}\\right)$ and $sessions\\_items\\_features[:, 3] = \\left(\\begin{array}{cccc} \n", + "ivt(0, air) & ivt(0, bus) & ivt(0, car) & ivt(0,train) \\\\\n", + "ivt(1, air) & ivt(1, bus) & ivt(1, car) & ivt(1,train) \\\\\n", + "... & ... & ... & ... \\\\\n", + "ivt(batch_size, air) & ivt(batch_size, bus) & ivt(batch_size, car) & ivt(batch_size,train) \\\\\n", + "\\end{array}\\right)$\n", + "\n", + "\n", + "$U_{ivt} = \\beta^{ivt} * sessions\\_items\\_features[:, 3]$ of shape (batch_size, 4)\n", "\n", - "#### *Income*\n", + "#### > *Income*\n", "- $U_{income}(air, s) = \\beta^{income}_{air} \\cdot income(s)$\n", "- $U_{income}(bus, s) = \\beta^{income}_{bus} \\cdot income(s)$\n", "- $U_{income}(car, s) = \\beta^{income}_{car} \\cdot income(s)$\n", @@ -286,14 +314,87 @@ "\\beta^{income}_{bus} \\\\\n", "\\beta^{income}_{car}\\\\\n", "\\beta^{income}_{train} \\\\\n", - "\\end{array}\\right)$ and $sessions\\_feature = \\left(\\begin{array}{c} \n", + "\\end{array}\\right)$ and $sessions\\_features = \\left(\\begin{array}{c} \n", "income(0) \\\\\n", "income(1) \\\\\n", "... \\\\\n", "income(batch\\_size)) \\\\\n", "\\end{array}\\right)$\n", "\n", - "$U_{income} = \\beta^{income .T} \\cdot sessions\\_features$" + "$U_{income} = \\beta^{income .T} \\cdot sessions\\_features$\n", + "\n", + "By concatenating batch_size times $U_{inter}$ over the sessions we obtain 4 matrixes of shape (batch_size, 4).\n", + "\n", + "The final utility is then:\n", + "$U = U_{inter} + U_{price, freq, ovt} + U_{ivt} + U_{income}$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Results\n", + "We can now test that we o£btain the same results:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(model.weights[0])\n", + "print(model.weights[1])\n", + "print(model.weights[2])\n", + "print(model.weights[3])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The coefficients are organized differently but reach the same values. It is also the case for negative log-lilkelihood:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\"Total Neg LikeliHood;\", model.evaluate(dataset) * len(dataset))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this example we have used a simple linear function for utility computation. We could use any function we would like. Particularly we can use neural networks and activation functions to add non-linearities.\n", + "\n", + "A simple example would be:\n", + "\n", + "```python\n", + "from tensorflow.keras.layers import Dense\n", + "\n", + "class NeuralNetUtility(ChoiceModel):\n", + " def __init__(self, **kwargs):\n", + " super().__init__(**kwargs)\n", + " # First non-linear layer\n", + " self.dense_1 = Dense(units=10, activation=\"elu\")\n", + " # Second linear layer\n", + " self.dense_2 = Dense(units=1, activation=\"linear\")\n", + " # We do not forget to specify self.weights with all coefficients that need to be estimated. Easy with TensorFlow.Layer\n", + " self.weights = self.dense_1.trainable_variables + self.dense_2.trainable_variables\n", + " \n", + " def compute_utility(self, items_batch, sessions_batch, sessions_items_batch, availabilities_batch, choices_batch):\n", + " # We apply the neural network to all sessions_items_features for all the items\n", + " # We then concatenate the utilities of each item of shape (n_sessions, 1) into a single one of shape (n_sessions, n_items)\n", + " u = tf.concat([self.dense_2(self.dense_1(sessions_items_batch[0][:, i])) for i in range(sessions_items_batch[0].shape[1])], axis=1)\n", + " return u\n", + "````\n", + "\n", + "If you want more complex examples, you can look at the following implementations:\n", + "- [RUMnet](../choice_learn/models/rumnet.py)" ] }, { From c7079cfdbc7f29a04b6f21d920feb627bbb4270e Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Wed, 3 Jan 2024 14:45:22 +0100 Subject: [PATCH 023/767] small modifs --- notebooks/custom_model.ipynb | 47 +++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/notebooks/custom_model.ipynb b/notebooks/custom_model.ipynb index 78a2dcb9..11ef8b57 100644 --- a/notebooks/custom_model.ipynb +++ b/notebooks/custom_model.ipynb @@ -119,16 +119,17 @@ "### *Utility Computation*\n", "\n", "In the method compute_utility, we need to define how to estimate each item utility for each session using the features and initialized weights.\n", - "The arguments of the function are each features type of the ChoiceDataset class:\n", + "The arguments of the function are a batch of each features type of the ChoiceDataset class:\n", "\n", "| Order | Argument | shape | Features for ModeCanada| \n", "|---|---|---|---|\n", "| 1 | items_features | (n_items, n_items_features) | Items OneHot vectors | \n", - "| 2 | sessions_features | (n_sessions, n_sessions_features) | Customer Income | \n", - "| 3 | sessions_items_features | (n_sessions, n_items, n_sessions_items_features) | Cost, Freq, Ivt, Ovt values of each mode | \n", - "| 4 | sessions_items_availabilities | (n_sessions, n_items) | Not Used | \n", - "| 5 | choices | (n_sessions, ) | Not Used | \n", + "| 2 | sessions_features | (batch_size, n_sessions_features) | Customer Income | \n", + "| 3 | sessions_items_features | (batch_size, n_items, n_sessions_items_features) | Cost, Freq, Ivt, Ovt values of each mode | \n", + "| 4 | sessions_items_availabilities | (batch_size, n_items) | Not Used | \n", + "| 5 | choices | (batch_size, ) | Not Used | \n", "\n", + "batch_size represents the number of sessions given in the batch.\n", "The method needs to return the utilities, in the form of a matrix of shape (n_sessions, n_items), reprenting the utility of each item for each session." ] }, @@ -163,8 +164,10 @@ " # Create model weights. Basically is one weight by feature + one for intercept\n", " beta_inter = tf.Variable(tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(1, 3)),\n", " name=\"beta_inter\")\n", - " beta_freq_cost_ovt = tf.Variable(tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(1, 3)),\n", - " name=\"beta_freq_cost_ovt\")\n", + " beta_freq_cost_ovt = tf.Variable(\n", + " tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(1, 3)),\n", + " name=\"beta_freq_cost_ovt\"\n", + " )\n", " beta_income = tf.Variable(tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(1, 3)),\n", " name=\"beta_income\")\n", " beta_ivt = tf.Variable(tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(1, 4)),\n", @@ -174,7 +177,12 @@ " self.weights = [beta_inter, beta_freq_cost_ovt, beta_income, beta_ivt]\n", "\n", "\n", - " def compute_utility(self, items_batch, sessions_batch, sessions_items_batch, availabilities_batch, choices_batch):\n", + " def compute_utility(self,\n", + " items_batch,\n", + " sessions_batch,\n", + " sessions_items_batch,\n", + " availabilities_batch,\n", + " choices_batch):\n", " \"\"\"Method that defines how the model computes the utility of a product.\n", "\n", " MNL, here U =\n", @@ -182,10 +190,12 @@ " Parameters\n", " ----------\n", " items_batch : tuple of np.ndarray (items_features)\n", - " Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products constant features.\n", + " Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products\n", + " constant features.\n", " Shape must be (n_items, n_items_features)\n", " sessions_batch : tuple of np.ndarray (sessions_features)\n", - " Time-Features. Not used as not conditional MNL, means it is the same for all products and is not implicated in utility computation.\n", + " Time-Features. Not used as not conditional MNL, means it is the same for all products\n", + " and is not implicated in utility computation.\n", " Shape must be (n_sessions, n_sessions_features)\n", " sessions_items_batch : tuple of np.ndarray (sessions_items_features)\n", " Time-Item-Features\n", @@ -203,7 +213,10 @@ " Utility of each product for each session.\n", " Shape must be (n_sessions, n_items)\n", " \"\"\"\n", - " # We use the fact that items_features is OneHot of the item, letting us selecting the right beta when needed (through dot)\n", + " _ = (availabilities_batch, choices_batch) # Avoid unused variable warning\n", + "\n", + " # We use the fact that items_features is OneHot of the item, letting us selecting the right\n", + " # Beta when needed (through dot)\n", " # Utility from items features + intercept\n", "\n", " # Concatenation to reach right shape for dot product\n", @@ -297,7 +310,7 @@ "ivt(0, air) & ivt(0, bus) & ivt(0, car) & ivt(0,train) \\\\\n", "ivt(1, air) & ivt(1, bus) & ivt(1, car) & ivt(1,train) \\\\\n", "... & ... & ... & ... \\\\\n", - "ivt(batch_size, air) & ivt(batch_size, bus) & ivt(batch_size, car) & ivt(batch_size,train) \\\\\n", + "ivt(batch\\_size, air) & ivt(batch\\_size, bus) & ivt(batch\\_size, car) & ivt(batch\\_size,train) \\\\\n", "\\end{array}\\right)$\n", "\n", "\n", @@ -383,10 +396,16 @@ " self.dense_1 = Dense(units=10, activation=\"elu\")\n", " # Second linear layer\n", " self.dense_2 = Dense(units=1, activation=\"linear\")\n", - " # We do not forget to specify self.weights with all coefficients that need to be estimated. Easy with TensorFlow.Layer\n", + " # We do not forget to specify self.weights with all coefficients that need to be estimated.\n", + " # Easy with TensorFlow.Layer\n", " self.weights = self.dense_1.trainable_variables + self.dense_2.trainable_variables\n", " \n", - " def compute_utility(self, items_batch, sessions_batch, sessions_items_batch, availabilities_batch, choices_batch):\n", + " def compute_utility(self,\n", + " items_batch,\n", + " sessions_batch,\n", + " sessions_items_batch,\n", + " availabilities_batch,\n", + " choices_batch):\n", " # We apply the neural network to all sessions_items_features for all the items\n", " # We then concatenate the utilities of each item of shape (n_sessions, 1) into a single one of shape (n_sessions, n_items)\n", " u = tf.concat([self.dense_2(self.dense_1(sessions_items_batch[0][:, i])) for i in range(sessions_items_batch[0].shape[1])], axis=1)\n", From 00a0dee8efb4b329742a85bc33ce0634b98ca460 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Wed, 3 Jan 2024 14:51:02 +0100 Subject: [PATCH 024/767] enh: add link to notebooks --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 37a90a81..ec8d5293 100644 --- a/README.md +++ b/README.md @@ -22,15 +22,21 @@ This repository contains a private version of the package. - [choice-learn-private](#choice-learn-private) - [Table of Contents](#table-of-contents) + - [What's in there ?](#whats-in-there) - [Installation](#installation) - [Usage](#usage) - [Documentation](#documentation) - - [Repository Structure](#repository-structure) + - [Citation](#citation) ## What's in there ? ## Getting Started - Fast Track +You can find the following notebooks to help you getting started with the package: +- [Introduction to data management](notebooks/choice_learn_introduction_data.ipynb) +- [Introduction to modelling with the conditional logit model on ModeCanada dataaset](notebooks/choice_learn_introduction_clogit.ipynb) +- [Introduction to custom modelling with the ModeCanada dataset](notebooks/custom_model.ipynb) + ## Installation ### User installation From 9d760e5b7f02ab67fbd3dcab061406124b86d4dd Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Wed, 3 Jan 2024 19:07:43 +0100 Subject: [PATCH 025/767] ADD: missing possibility for specification of cmnl --- README.md | 2 + .../choice_learn_introduction_clogit.ipynb | 40 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/README.md b/README.md index ec8d5293..e928999d 100644 --- a/README.md +++ b/README.md @@ -83,3 +83,5 @@ make deploy_docs ## Citation ### Contributors + +## References diff --git a/notebooks/choice_learn_introduction_clogit.ipynb b/notebooks/choice_learn_introduction_clogit.ipynb index df3c6413..f619373f 100644 --- a/notebooks/choice_learn_introduction_clogit.ipynb +++ b/notebooks/choice_learn_introduction_clogit.ipynb @@ -320,6 +320,46 @@ "cmnl.evaluate(dataset)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A faster specification can be done using a dictionnary. It follows torch-choice \\ref{} method to create conditional logit models.\n", + "The parameters dict needs to be as follows:\n", + "- The key is the feature name\n", + "- The value is the mode. Currently three modes are available:\n", + " - constant: the learned coefficient is shared by all items\n", + " - item: one coefficient by item is estimated, the value for the item at index 0 is set to 0\n", + " - item-full: one coefficient by item is estimated\n", + "\n", + "In order to create the same model for the ModeCanada dataset, it looks as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Instantiation of the parameters dictionnary\n", + "params = {\"income\": \"item\",\n", + " \"cost\": \"constant\", \n", + " \"freq\": \"constant\",\n", + " \"ovt\": \"constant\", \n", + " \"ivt\": \"item-full\",\n", + " \"intercept\": \"item\"}\n", + "\n", + "# Instantiation of the model\n", + "cmnl = ConditionalMNL(parameters=params, lr=0.01)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": null, From 228a259598afedb21c7ea60201879df85c92dbc0 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Wed, 3 Jan 2024 22:12:41 +0100 Subject: [PATCH 026/767] =?UTF-8?q?ADD:=20few=20details=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notebooks/choice_learn_introduction_clogit.ipynb | 10 ++++++++-- notebooks/choice_learn_introduction_data.ipynb | 8 ++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/notebooks/choice_learn_introduction_clogit.ipynb b/notebooks/choice_learn_introduction_clogit.ipynb index f619373f..aec7b9f9 100644 --- a/notebooks/choice_learn_introduction_clogit.ipynb +++ b/notebooks/choice_learn_introduction_clogit.ipynb @@ -14,6 +14,9 @@ "outputs": [], "source": [ "import os\n", + "\n", + "os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"\"\n", + "\n", "import sys\n", "from pathlib import Path\n", "\n", @@ -350,7 +353,7 @@ " \"intercept\": \"item\"}\n", "\n", "# Instantiation of the model\n", - "cmnl = ConditionalMNL(parameters=params, lr=0.01)" + "cmnl = ConditionalMNL(parameters=params, optimizer=\"lbfgs\")" ] }, { @@ -358,7 +361,10 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "history = cmnl.fit(dataset, n_epochs=1000)\n", + "print(cmnl.weights)" + ] }, { "cell_type": "code", diff --git a/notebooks/choice_learn_introduction_data.ipynb b/notebooks/choice_learn_introduction_data.ipynb index 61adda62..84755661 100644 --- a/notebooks/choice_learn_introduction_data.ipynb +++ b/notebooks/choice_learn_introduction_data.ipynb @@ -247,8 +247,11 @@ "source": [ "dataset = ChoiceDataset(\n", " items_features=items_features,\n", + " items_features_names=[\"size\", \"weight\"], # You can precise the names of the features if you want\n", " sessions_features=sessions_features,\n", + " sessions_features_names=[\"budget\", \"age\"], # same, not mandatory\n", " sessions_items_features=sessions_items_features,\n", + " sessions_items_features_names=[\"price\", \"promotion\"], # same, not mandatory\n", " sessions_items_availabilities=sessions_items_availabilities,\n", " choices=choices,\n", ")" @@ -556,6 +559,11 @@ "canada_df.head()" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, { "cell_type": "markdown", "metadata": {}, From 1649e309fc1850d8262b38304f8bb4b7f257886c Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Wed, 3 Jan 2024 22:32:54 +0100 Subject: [PATCH 027/767] ADD: filter method --- choice_learn/data/choice_dataset.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index eb512312..4aab5804 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -971,3 +971,16 @@ def iter_batch(self, batch_size=None, shuffle=None, sample_weight=None): # Special exit strategy for batch_size = -1 if batch_size == -1: yielded_size += 2 * num_choices + + def filter(self, bool_list): + """Filter over sessions indexes following bool. + + Parameters + ---------- + bool_list : list of boolean + list of booleans of length self.get_num_sessions() to filter sessions. + True to keep, False to discard. + """ + indexes = list(range(len(bool_list))) + indexes = [i for i, keep in zip(indexes, bool_list) if keep] + return self[indexes] From 3d771458ed4b628a05766c978e2632b173394968 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Wed, 3 Jan 2024 22:33:33 +0100 Subject: [PATCH 028/767] ADD: filter method tests --- tests/unit_tests/data/test_choice_dataset.py | 24 ++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/unit_tests/data/test_choice_dataset.py b/tests/unit_tests/data/test_choice_dataset.py index 6ef06590..0ef46728 100644 --- a/tests/unit_tests/data/test_choice_dataset.py +++ b/tests/unit_tests/data/test_choice_dataset.py @@ -425,3 +425,27 @@ def test_iter_batch(): assert batch[3].shape[1] == 3 assert batch[4].shape[0] == 2 or batch[4].shape[0] == 1 assert batch_nb == 1 + + def test_filter(): + """Tests the filter method.""" + dataset = ChoiceDataset( + items_features=items_features, + sessions_features=sessions_features, + sessions_items_features=sessions_items_features, + sessions_items_availabilities=sessions_items_availabilities, + choices=choices, + ) + filtered_dataset = dataset.filter([True, False, True]) + assert len(filtered_dataset) == 2 + assert (filtered_dataset.items_features[0] == dataset.items_features[0]).all() + assert (filtered_dataset.sessions_features[0] == dataset.sessions_features[0][[0, 2]]).all() + assert ( + filtered_dataset.sessions_items_features[0] + == dataset.sessions_items_features[0][[0, 2]] + ).all() + assert ( + filtered_dataset.sessions_items_availabilities + == dataset.sessions_items_availabilities[[0, 2]] + ).all() + assert (filtered_dataset.choices == dataset.choices[[0, 2]]).all() + assert (filtered_dataset.choices == [0, 1]).all() From 70b4c8f5d1016253ee695381d588ace3ba982270 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 4 Jan 2024 10:24:33 +0100 Subject: [PATCH 029/767] ADD: auto mkdoc on release --- .github/workflows/deploy_docs.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy_docs.yaml b/.github/workflows/deploy_docs.yaml index 061110ef..fb8141e8 100644 --- a/.github/workflows/deploy_docs.yaml +++ b/.github/workflows/deploy_docs.yaml @@ -1,9 +1,8 @@ name: Deploy MkDocs to GitHub Pages on: - push: - branches: - - master + release: + types: [published] jobs: deploy-docs: From 3976c82fb0a235e6e9568a14969b5a0f3971a718 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 4 Jan 2024 10:25:03 +0100 Subject: [PATCH 030/767] ENH: dataframe loading --- notebooks/choice_learn_introduction_clogit.ipynb | 7 ++++--- notebooks/choice_learn_introduction_data.ipynb | 2 +- notebooks/custom_model.ipynb | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/notebooks/choice_learn_introduction_clogit.ipynb b/notebooks/choice_learn_introduction_clogit.ipynb index aec7b9f9..9aea031e 100644 --- a/notebooks/choice_learn_introduction_clogit.ipynb +++ b/notebooks/choice_learn_introduction_clogit.ipynb @@ -45,10 +45,11 @@ "metadata": {}, "outputs": [], "source": [ - "# TO be transformed to be clearer\n", - "transport_df = pd.read_csv(\"/data/raw_data/ModeCanada.csv\", index_col=0)\n", + "from choice_learn.datasets import load_modecanada\n", "\n", - "# Following torch-Choice guide:\n", + "transport_df = load_modecanada(as_frame=True)\n", + "\n", + "# Following torch-choice guide:\n", "transport_df = transport_df.loc[transport_df.noalt == 4]\n", "\n", "items = [\"air\", \"bus\", \"car\", \"train\"]\n", diff --git a/notebooks/choice_learn_introduction_data.ipynb b/notebooks/choice_learn_introduction_data.ipynb index 84755661..6ca00309 100644 --- a/notebooks/choice_learn_introduction_data.ipynb +++ b/notebooks/choice_learn_introduction_data.ipynb @@ -31,7 +31,7 @@ "\n", "choice-learn package aims at being able to handle large datasets. It uses a data structure similar to the one defined in the torch-choice package.\n", "\n", - "Particularly, it defines 5 type of different data, storing them separatly in order to avoid redundancy in memory:\n", + "Particularly, it defines 5 types of different data, storing them separatly in order to avoid redundancy in memory:\n", "\n", "- items_features: features of considered items that never change (e.g. size, color, etc...)\n", "- session_features: features that depend on the session (time) of the choice and that are common to all items (e.g. day of week, etc...)\n", diff --git a/notebooks/custom_model.ipynb b/notebooks/custom_model.ipynb index 11ef8b57..586f1e2a 100644 --- a/notebooks/custom_model.ipynb +++ b/notebooks/custom_model.ipynb @@ -51,9 +51,9 @@ "outputs": [], "source": [ "from choice_learn.data import ChoiceDataset\n", + "from choice_learn.datasets import load_modecanada\n", "\n", - "# TO be transformed to be clearer\n", - "transport_df = pd.read_csv(\"/data/raw_data/ModeCanada.csv\", index_col=0)\n", + "transport_df = load_modecanada(as_frame=True)\n", "\n", "# Following torch-Choice guide:\n", "transport_df = transport_df.loc[transport_df.noalt == 4]\n", From f2575e9b1ed2ba6ad0d8b7974fb0e6d315418caa Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 4 Jan 2024 10:25:15 +0100 Subject: [PATCH 031/767] ENH: small modifs --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e928999d..556f8eb4 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,8 @@ Choice-Learn is a Python package designed to help you build with ease discrete choice models. The package provides ready to use datasets and different models from the litterature. It also provides a lower level use if you want to customize any model or create your own from scratch. In particular you will find smart datasets handling to limit RAM usage and different structure commons to any choice model. +Choice-Learn uses NumPy and pandas as data backend engines and TensorFlow for models. + This repository contains a private version of the package. ## Table of Contents @@ -55,12 +57,16 @@ git clone git@github.com:artefactory/choice-learn-private.git ### Dependencies Choice-Learn requires the following: -- Python (>=...) -- NumPy (>=...) -- TensorFlow (>=...) -- pandas ? +- Python (>=3.8) +- NumPy (>=1.24) +- TensorFlow (>=2.13) +- pandas (>=1.5) ## Usage +```python +from choice_learn.data import ChoiceDataset +from choice_learn.models import ConditionalMNL +``` ## Documentation From 3bc5839c33260f8a4f85e7f6d64699a3a9345ce8 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 4 Jan 2024 12:01:42 +0100 Subject: [PATCH 032/767] ENH: keep some outputs of example notebooks --- choice_learn/models/conditional_mnl.py | 11 +- .../choice_learn_introduction_clogit.ipynb | 146 +++++- .../choice_learn_introduction_data.ipynb | 416 +++++++++++++++++- notebooks/custom_model.ipynb | 37 +- 4 files changed, 567 insertions(+), 43 deletions(-) diff --git a/choice_learn/models/conditional_mnl.py b/choice_learn/models/conditional_mnl.py index 9284797e..f273a09c 100644 --- a/choice_learn/models/conditional_mnl.py +++ b/choice_learn/models/conditional_mnl.py @@ -288,7 +288,7 @@ def compute_utility_from_specification( tf.Tensor Utilities corresponding of shape (n_sessions, n_items) """ - del choices_batch, verbose + _ = choices_batch num_items = availabilities_batch.shape[1] num_sessions = availabilities_batch.shape[0] @@ -329,10 +329,11 @@ def compute_utility_from_specification( ### Need reshaping here sessions_items_utilities.append(s_i_u) else: - print( - f"Feature {feat} is in dataset but has no weight assigned in utility\ - computations" - ) + if verbose > 1: + print( + f"Feature {feat} is in dataset but has no weight assigned in utility\ + computations" + ) # Session features for i, feat_tuple in enumerate(self._sessions_features_names): diff --git a/notebooks/choice_learn_introduction_clogit.ipynb b/notebooks/choice_learn_introduction_clogit.ipynb index 9aea031e..ae12ebd4 100644 --- a/notebooks/choice_learn_introduction_clogit.ipynb +++ b/notebooks/choice_learn_introduction_clogit.ipynb @@ -201,8 +201,28 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ]" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "cmnl.weights" ] @@ -217,8 +237,19 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The average neg-loglikelihood is: 0.674474\n", + "The total neg-loglikelihood is: 1874.3632485866547\n" + ] + } + ], "source": [ "print(\"The average neg-loglikelihood is:\", cmnl.evaluate(dataset).numpy())\n", "print(\"The total neg-loglikelihood is:\", cmnl.evaluate(dataset).numpy()*len(dataset))" @@ -234,8 +265,25 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 1/1 [00:01<00:00, 1.30s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "'Ground Truth' Negative LogLikelihood: tf.Tensor(1874.363, shape=(), dtype=float32)\n" + ] + } + ], "source": [ "import tensorflow as tf\n", "\n", @@ -253,7 +301,7 @@ "\n", "# Here we estimate the negative log-likelihood with these coefficients (also, we obtain same value as in those papers):\n", "gt_model.weights = gt_weights\n", - "gt_model.evaluate(dataset) * len(dataset)" + "print(\"'Ground Truth' Negative LogLikelihood:\", gt_model.evaluate(dataset) * len(dataset))" ] }, { @@ -266,8 +314,23 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Purchase probability of each item for the first 5 sessions: tf.Tensor(\n", + "[[0.19061294 0.00353295 0.40536764 0.40048242]\n", + " [0.34869465 0.00069692 0.36830828 0.28229645]\n", + " [0.14418268 0.00651326 0.4056784 0.4436212 ]\n", + " [0.34869465 0.00069692 0.36830828 0.28229645]\n", + " [0.34869465 0.00069692 0.36830828 0.28229645]], shape=(5, 4), dtype=float32)\n" + ] + } + ], "source": [ "# print(\"Utilities of each item for the first 5 sessions:\", cmnl.predict_utility(dataset)[:5])\n", "print(\"Purchase probability of each item for the first 5 sessions:\", cmnl.predict_probas(dataset)[:5])" @@ -309,8 +372,28 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ]" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "cmnl.weights" ] @@ -318,8 +401,21 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "cmnl.evaluate(dataset)" ] @@ -360,8 +456,28 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Feature oh_air is in dataset but has no weight assigned in utility computations\n", + "Feature oh_bus is in dataset but has no weight assigned in utility computations\n", + "Feature oh_car is in dataset but has no weight assigned in utility computations\n", + "Feature oh_train is in dataset but has no weight assigned in utility computations\n", + "L-BFGS Opimization finished:\n", + "---------------------------------------------------------------\n", + "Number of iterations: 170\n", + "Algorithm converged before reaching max iterations: True\n", + "[, , , , , ]\n" + ] + } + ], "source": [ "history = cmnl.fit(dataset, n_epochs=1000)\n", "print(cmnl.weights)" diff --git a/notebooks/choice_learn_introduction_data.ipynb b/notebooks/choice_learn_introduction_data.ipynb index 6ca00309..55bec28d 100644 --- a/notebooks/choice_learn_introduction_data.ipynb +++ b/notebooks/choice_learn_introduction_data.ipynb @@ -47,8 +47,140 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Let's look at the dataframe:\n" + ] + }, + { + "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", + "
casealtchoicedistcostivtovtfreqincomeurbannoalt
11train08328.25506644502
21car18315.7761004502
32train08328.25506642502
42car18315.7761002502
53train08328.25506647002
\n", + "
" + ], + "text/plain": [ + " case alt choice dist cost ivt ovt freq income urban noalt\n", + "1 1 train 0 83 28.25 50 66 4 45 0 2\n", + "2 1 car 1 83 15.77 61 0 0 45 0 2\n", + "3 2 train 0 83 28.25 50 66 4 25 0 2\n", + "4 2 car 1 83 15.77 61 0 0 25 0 2\n", + "5 3 train 0 83 28.25 50 66 4 70 0 2" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "from choice_learn.data import ChoiceDataset\n", "\n", @@ -260,8 +392,21 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(3, 3, 2)" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "dataset.sessions_items_features[0].shape" ] @@ -277,8 +422,20 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Some choices never happen in the dataset: {1}\n", + "Some choices never happen in the dataset: {0, 2}\n", + "Train Dataset length: 2 Test Dataset lenght: 1\n" + ] + } + ], "source": [ "train_index = [0, 1]\n", "test_index = [2]\n", @@ -317,8 +474,32 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Items features: (array([[1. , 2. ],\n", + " [2. , 4. ],\n", + " [1.5, 1.5]], dtype=float32),)\n", + "Sessions features: (array([[100, 20],\n", + " [200, 40]], dtype=int32),)\n", + "Sessions Items features: (array([[[100, 0],\n", + " [140, 0],\n", + " [200, 0]],\n", + "\n", + " [[100, 0],\n", + " [120, 1],\n", + " [200, 0]]], dtype=int32),)\n", + "Sessions Items Availabilities features: [[1. 1. 1.]\n", + " [1. 1. 1.]]\n", + "Sessions Choices: [0 2]\n" + ] + } + ], "source": [ "sessions_indexes = [0, 1]\n", "print(\"Items features:\", train_dataset.batch[sessions_indexes][0])\n", @@ -340,8 +521,32 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 (array([[1. , 2. ],\n", + " [2. , 4. ],\n", + " [1.5, 1.5]], dtype=float32), array([[100, 20]], dtype=int32), array([[[100, 0],\n", + " [140, 0],\n", + " [200, 0]]], dtype=int32), array([[1., 1., 1.]], dtype=float32), array([0], dtype=int32))\n", + "1 (array([[1. , 2. ],\n", + " [2. , 4. ],\n", + " [1.5, 1.5]], dtype=float32), array([[200, 40]], dtype=int32), array([[[100, 0],\n", + " [120, 1],\n", + " [200, 0]]], dtype=int32), array([[1., 1., 1.]], dtype=float32), array([2], dtype=int32))\n", + "2 (array([[1. , 2. ],\n", + " [2. , 4. ],\n", + " [1.5, 1.5]], dtype=float32), array([[80, 20]], dtype=int32), array([[[100, 0],\n", + " [120, 1],\n", + " [180, 1]]], dtype=int32), array([[0., 1., 1.]], dtype=float32), array([1], dtype=int32))\n" + ] + } + ], "source": [ "# All the features are given for each session, in order to compute utility and NegativeLogLikelihood\n", "for n_batch, batch in enumerate(dataset.iter_batch(batch_size=1)):\n", @@ -393,8 +598,32 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "((array([[1. , 2. ],\n", + " [2. , 4. ],\n", + " [1.5, 1.5]], dtype=float32),\n", + " array([[11. , 12. ],\n", + " [12. , 14. ],\n", + " [11.5, 11.5]], dtype=float32)),\n", + " array([100, 20], dtype=int32),\n", + " array([[100, 0],\n", + " [140, 0],\n", + " [200, 0]], dtype=int32),\n", + " array([1., 1., 1.], dtype=float32),\n", + " 0)" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "dataset.batch[0]" ] @@ -467,8 +696,19 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[100, 250]\n", + "[[100, 250], [100, 250], [100, 250]]\n" + ] + } + ], "source": [ "# Now we can access the features of the store appearing at index i in the sequence with the iloc method:\n", "\n", @@ -498,8 +738,23 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "RAM storage of the OneHotStore: {'a': 0, 'b': 1, 'c': 2} with sequence: ['a' 'a' 'a' 'c' 'b' 'b' 'a']\n", + "One-hot vector at index 0: [1. 0. 0.]\n", + "One-hot vector at indexes [0, 1, 3]:\n", + "[[1. 0. 0.]\n", + " [1. 0. 0.]\n", + " [0. 0. 1.]]\n" + ] + } + ], "source": [ "store = OneHotStore.from_sequence([\"a\", \"a\", \"a\", \"c\", \"b\", \"b\", \"a\"])\n", "\n", @@ -552,8 +807,133 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "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", + "
casealtchoicedistcostivtovtfreqincomeurbannoalt
11train08328.255066445.002
21car18315.77610045.002
32train08328.255066425.002
42car18315.77610025.002
53train08328.255066470.002
\n", + "
" + ], + "text/plain": [ + " case alt choice dist cost ivt ovt freq income urban noalt\n", + "1 1 train 0 83 28.25 50 66 4 45.0 0 2\n", + "2 1 car 1 83 15.77 61 0 0 45.0 0 2\n", + "3 2 train 0 83 28.25 50 66 4 25.0 0 2\n", + "4 2 car 1 83 15.77 61 0 0 25.0 0 2\n", + "5 3 train 0 83 28.25 50 66 4 70.0 0 2" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "canada_df = load_modecanada(as_frame=True)\n", "canada_df.head()" diff --git a/notebooks/custom_model.ipynb b/notebooks/custom_model.ipynb index 586f1e2a..b47e2430 100644 --- a/notebooks/custom_model.ipynb +++ b/notebooks/custom_model.ipynb @@ -20,7 +20,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "import os\n", @@ -353,8 +355,23 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\n", + "\n" + ] + } + ], "source": [ "print(model.weights[0])\n", "print(model.weights[1])\n", @@ -372,8 +389,18 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Total Neg LikeliHood; tf.Tensor(1874.363, shape=(), dtype=float32)\n" + ] + } + ], "source": [ "print(\"Total Neg LikeliHood;\", model.evaluate(dataset) * len(dataset))" ] From 5b957c8e9f14cfcaa6f881eb90010099f1cafa78 Mon Sep 17 00:00:00 2001 From: Emmanuel MALHERBE Date: Fri, 5 Jan 2024 09:58:17 +0100 Subject: [PATCH 033/767] ADD: completely WIP proposal, for a different ChoiceDataset signature (core init) --- choice_learn/data/choice_dataset.py | 287 ++++++++++------------------ 1 file changed, 99 insertions(+), 188 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index fdacbabc..815d1c07 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -24,15 +24,12 @@ class ChoiceDataset(object): def __init__( self, - items_features=None, - sessions_features=None, - sessions_items_features=None, - items_features_names=None, - sessions_features_names=None, - sessions_items_features_names=None, - sessions_items_availabilities=None, - choices=None, # Should not have None as default value ? - batch_size=16, + choices, # Should not have None as default value ? + available_items_features, # MUST INCLUDE item_id column; possible: column "available" binaire + contexts_features=None, # as many context as choices. values or ids (look at key) + features_by_ids=None, # list of FeaturesById --> requires to have df with col "_id" + #choices_features_names=None, # optional way to provide keys + #items_features_names=None, # optional way to provide keys shuffle=False, ): """Builds the ChoiceDataset. @@ -42,86 +39,64 @@ def __init__( items_features : tuple of (array_like, ) matrix of shape (num_items, num_items_features) containing the features of the items e.g. item color - sessions_features : tuple of (array_like, ) - matrix of shape (num_sessions, num_sess_features) containing the features of the - sessions e.g. day of week - sessions_items_features : tuple of (array_like, ) - matrix of shape (num_sessions, num_items, num_ses_items_features) containing the item - features varying over sessions, e.g. prices - sessions_items_availabilities : array_like - binary matrix of shape (num_sessions, num_items) containing the availabitilies of - products (1. if present 0. otherwise) over sessions choices: list of list - for each sessions we have a list of related choices. Main list has same legnth as - session_features and sessions_items_features. - batch_size: int, optional - size of the batches to return in __iter__ method + for each choice we have a list of related choices. Main list has same legnth as + session_features. suffle: bool, optional whether to shuffle the dataset or not """ + + if choices is None: + # Done to keep a logical order of arguments, and has logic: choices have to be specified + raise ValueError("Choices must be specified, got None") + + assert len(choices) == len(available_items) + assert contexts_features is None or len(choices) == len(contexts_features) + # --------- [ Handling features type given as tuples or not ] --------- # # If items_features is not given as tuple, transform it internally as a tuple # A bit longer because can be None and need to also handle names - if not isinstance(items_features, tuple) and items_features is not None: - items_features = (items_features,) - items_features_names = (items_features_names,) - self._return_items_features_tuple = False - # items_features is already a tuple, names are given, checking consistency - elif items_features is not None and items_features_names is not None: - if ( - len(items_features) != len(items_features_names) - and items_features_names is not None - ): - raise ValueError("items_features shape and items_features_names shape do not match") - self._return_items_features_tuple = True - # In this case names are missing, still transform it as a tuple - elif items_features is not None: - self._return_items_features_tuple = True - items_features_names = (None,) * len(items_features) - - # If sessions_features is not given as tuple, transform it internally as a tuple - # A bit longer because can be None and need to also handle names - if not isinstance(sessions_features, tuple) and sessions_features is not None: - sessions_features = (sessions_features,) - sessions_features_names = (sessions_features_names,) - self._return_sessions_features_tuple = False - # sessions_features is already a tuple, names are given, checking consistency - elif sessions_features is not None and sessions_features_names is not None: - if ( - len(sessions_features) != len(sessions_features_names) - and sessions_features_names is not None - ): - raise ValueError( - "sessions_features shape and sessions_features_names shape \ - do not match" - ) - self._return_sessions_features_tuple = True - # In this case names are missing, still transform it as a tuple - elif sessions_features is not None: - self._return_sessions_features_tuple = True - sessions_features_names = (None,) * len(sessions_features) + items_features = None # to pass this part + if items_features is not None: + if not isinstance(items_features, tuple): + items_features = (items_features,) + items_features_names = (items_features_names,) + self._return_items_features_tuple = False + # items_features is already a tuple, names are given, checking consistency + elif items_features_names is not None: + if ( + len(items_features) != len(items_features_names) + and items_features_names is not None + ): + raise ValueError("items_features shape and items_features_names shape do not match") + self._return_items_features_tuple = True + # In this case names are missing, still transform it as a tuple + else: + self._return_items_features_tuple = True + items_features_names = (None,) * len(items_features) - # If sessions_items_features is not given as tuple, transform it internally as a tuple + # If choices_features is not given as tuple, transform it internally as a tuple # A bit longer because can be None and need to also handle names - if not isinstance(sessions_items_features, tuple) and sessions_items_features is not None: - sessions_items_features = (sessions_items_features,) - sessions_items_features_names = (sessions_items_features_names,) - self._return_sessions_items_features_tuple = False - # sessions_items_features is already a tuple, names are given, checking consistency - elif sessions_items_features is not None and sessions_items_features_names is not None: - if ( - len(sessions_items_features) != len(sessions_items_features_names) - and sessions_items_features_names is not None - ): - raise ValueError( - "sessions_items_features shape and \ - sessions_items_features_names shape do not match" - ) - self._return_sessions_items_features_tuple = True - # In this case names are missing, still transform it as a tuple - elif sessions_items_features is not None: - self._return_sessions_items_features_tuple = True - sessions_items_features_names = (None,) * len(sessions_items_features) + if contexts_features is not None: + if not isinstance(contexts_features, tuple): + contexts_features = (contexts_features,) + #choices_features_names = (choices_features_names,) + self._return_choices_features_tuple = False + # choices_features is already a tuple, names are given, checking consistency + elif choices_features_names is not None: + if ( + len(contexts_features) != len(choices_features_names) + and choices_features_names is not None + ): + raise ValueError( + "choices_features shape and choices_features_names shape \ + do not match" + ) + self._return_choices_features_tuple = True + # In this case names are missing, still transform it as a tuple + else: + self._return_choices_features_tuple = True + choices_features_names = (None,) * len(contexts_features) # --------- [Normalizing features types (DataFrame, List, etc...) -> np.ndarray] --------- # # @@ -151,71 +126,37 @@ def __init__( items_features[:i] + (np.array(feature),) + items_features[i + 1 :] ) - # Handling sessions_features - if sessions_features is not None: - for i, feature in enumerate(sessions_features): + # Handling choices_features + if contexts_features is not None: + for i, feature in enumerate(contexts_features): if isinstance(feature, pd.DataFrame): - # Ordering sessions by id ? + # Ordering choices by id ? if "session_id" in feature.columns: feature = feature.set_index("session_id") - sessions_features = ( - sessions_features[:i] + contexts_features = ( + contexts_features[:i] + (feature.loc[np.sort(feature.index)].to_numpy(),) - + sessions_features[i + 1 :] - ) - sessions_features_names = ( - sessions_features_names[:i] - + (feature.columns.tolist(),) - + sessions_features_names[i + 1 :] + + contexts_features[i + 1 :] ) + #choices_features_names = ( + # choices_features_names[:i] + # + (feature.columns.tolist(),) + # + choices_features_names[i + 1 :] + #) elif isinstance(feature, list): - sessions_features = ( - sessions_features[:i] + (np.array(feature),) + sessions_features[i + 1 :] + contexts_features = ( + contexts_features[:i] + (np.array(feature),) + contexts_features[i + 1 :] ) - # Handling sessions_items_features - if sessions_items_features is not None: - for i, feature in enumerate(sessions_items_features): - if isinstance(feature, pd.DataFrame): - # Ordering sessions and items by id ? - if "session_id" not in feature.columns: - feature["session_id"] = feature.index - items_index = np.sort(feature.item_id.unique()) - sessions_index = np.sort(feature.session_id.unique()) - names = [f for f in feature.columns if f != "session_id" and f != "item_id"] - - ( - feature, - sessions_items_availabilities, - ) = self._sessions_items_features_df_to_np( - feature, items_index, sessions_index, feature.columns.tolist() - ) - - sessions_items_features = ( - sessions_items_features[:i] + feature + sessions_items_features[i + 1 :] - ) - - sessions_items_features_names = ( - sessions_items_features_names[:i] - + (names,) - + sessions_items_features_names[i + 1 :] - ) - elif isinstance(feature, list): - sessions_items_features = ( - sessions_items_features[:i] - + (np.array(feature),) - + sessions_items_features[i + 1 :] - ) - - if isinstance(sessions_items_availabilities, list): - sessions_items_availabilities = np.array(sessions_items_availabilities) + if isinstance(available_items, list): + available_items = np.array(available_items, dtype=object) # Handling choices # Choices must then be given as the name of the chosen item # Items are sorted by name and attributed an index # Cannot be a list of choices yet if isinstance(choices, pd.DataFrame): - # Ordering sessions by id + # Ordering choices by id if "session_id" in choices.columns: choices = choices.set_index("session_id") choices = choices.loc[np.sort(choices.index)] @@ -224,29 +165,22 @@ def __init__( choices = [np.where(items == c)[0] for c in choices.choice] # Setting attributes of ChoiceDataset - self.items_features = items_features - self.sessions_features = sessions_features - self.sessions_items_features = sessions_items_features - self.sessions_items_availabilities = sessions_items_availabilities + self.contexts_features = contexts_features + self.available_items = available_items - self.items_features_names = items_features_names - self.sessions_features_names = sessions_features_names - self.sessions_items_features_names = sessions_items_features_names + #self.items_features_names = items_features_names + #self.choices_features_names = choices_features_names - self.batch_size = batch_size self.shuffle = shuffle - if choices is None: - # Done to keep a logical order of arguments, and has logic: choices have to be specified - raise ValueError("Choices must be specified, got None") self.ragged_choices = choices self.indexes, self.choices = self._build_indexes(choices) self.n_choices = len(self.choices) # Different consitency checks to ensure everythin is coherent - self._check_dataset() # Should handle alone if np.arrays are squeezed - self._return_types = self._check_types() - self._check_names() + #self._check_dataset() # Should handle alone if np.arrays are squeezed + #self._return_types = self._check_types() + #self._check_names() # Build .iloc method self.indexer = ChoiceDatasetIndexer(self) @@ -292,7 +226,7 @@ def _check_dataset(self): Particularly: - Over number of items - - Over number of sessions + - Over number of choices Verifies that the choices have coherent values """ self._check_num_items_shapes() @@ -465,14 +399,14 @@ def _check_names(self): ) def __len__(self): - """Returns length of the dataset e.g. total number of sessions. + """Returns length of the dataset e.g. total number of choices. Returns: ------- int - total number of sessions + total number of choices """ - return self.base_num_sessions + return len(self.choices) def get_num_items(self): """Method to access the total number of different items. @@ -484,28 +418,18 @@ def get_num_items(self): """ return self.base_num_items - def get_num_sessions(self): - """Method to access the total number of different sessions. + def get_num_choices(self): + """Method to access the total number of different choices. Redundant with __len__ method. Returns: ------- int - total number of different sessions + total number of different choices """ return len(self) - def get_num_choices(self): - """Method to access the total number of different sessions. - - Returns: - ------- - int - total number of different sessions - """ - return self.n_choices - @classmethod def _sessions_items_features_df_to_np( cls, @@ -725,17 +649,14 @@ def summary(self): else: print("No sessions items features registered") - def get_choice_batch(self, choice_index): + def get_choices_batch(self, choices_indexes, features=None): """Method to access data within the ListChoiceDataset from its index. One index corresponds to a choice within a session. Return order: - - Fixed item features - - Session features - - Session item features - - Items availabilities - - Choice + - df_chosen_item, df of length batch_size + - dfs_available_items, list of lentch batch_size of dfs of length n_available_items Parameters ---------- @@ -838,16 +759,10 @@ def get_choice_batch(self, choice_index): else: sessions_items_availabilities = self.sessions_items_availabilities[session_index] - return ( - items_features, - sessions_features, - sessions_items_features, - sessions_items_availabilities, - choice, - ) + return df_chosen_item, dfs_available_items - def __getitem__(self, session_indexes): - """Method to create a sub-ChoiceDataset with only a subset of sessions, from their indexes. + def __getitem__(self, choices_indexes): + """Method to create a sub-ChoiceDataset with only a subset of choices, from their indexes. Parameters ---------- @@ -876,14 +791,13 @@ def __getitem__(self, session_indexes): ), sessions_items_availabilities=self.sessions_items_availabilities[session_indexes], choices=[self.ragged_choices[i] for i in session_indexes], - batch_size=self.batch_size, items_features_names=self.items_features_names, sessions_features_names=self.sessions_features_names, sessions_items_features_names=self.sessions_items_features_names, ) - def old_batch(self, batch_size=None, shuffle=None, sample_weight=None): - """Iterates over dataset return batches of length self.batch_size. + def old_batch(self, batch_size, shuffle=None, sample_weight=None): + """Iterates over dataset return batches of length batch_size. Parameters ---------- @@ -894,8 +808,7 @@ def old_batch(self, batch_size=None, shuffle=None, sample_weight=None): sample_weight : Iterable list of weights to be returned with the right indexing during the shuffling """ - if batch_size is None: - batch_size = self.batch_size + if shuffle is None: shuffle = self.shuffle if batch_size == -1: @@ -933,8 +846,8 @@ def batch(self): """Indexer.""" return self.indexer - def iter_batch(self, batch_size=None, shuffle=None, sample_weight=None): - """Iterates over dataset return batches of length self.batch_size. + def iter_batch(self, batch_size, shuffle=None, sample_weight=None): + """Iterates over dataset return batches of length batch_size. Newer version. @@ -947,8 +860,7 @@ def iter_batch(self, batch_size=None, shuffle=None, sample_weight=None): sample_weight : Iterable list of weights to be returned with the right indexing during the shuffling """ - if batch_size is None: - batch_size = self.batch_size + if shuffle is None: shuffle = self.shuffle if batch_size == -1: @@ -986,6 +898,5 @@ def filter(self, bool_list): list of booleans of length self.get_num_sessions() to filter sessions. True to keep, False to discard. """ - indexes = list(range(len(bool_list))) - indexes = [i for i, keep in zip(indexes, bool_list) if keep] + indexes = [i for i, keep in enumerate(bool_list) if keep] return self[indexes] From a8a8f9f1c1fd7aa897990d8575072dad0465d87e Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 8 Jan 2024 09:37:50 +0100 Subject: [PATCH 034/767] ADD: base mkdoc --- docs/explanations.md | 0 docs/how-to-guides.md | 0 docs/references.md | 3 +++ docs/tutorials.md | 0 4 files changed, 3 insertions(+) create mode 100644 docs/explanations.md create mode 100644 docs/how-to-guides.md create mode 100644 docs/references.md create mode 100644 docs/tutorials.md diff --git a/docs/explanations.md b/docs/explanations.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/how-to-guides.md b/docs/how-to-guides.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/references.md b/docs/references.md new file mode 100644 index 00000000..c5bb7d8d --- /dev/null +++ b/docs/references.md @@ -0,0 +1,3 @@ +# ChoiceDataset + +:::choice_learn.data.choice_dataset diff --git a/docs/tutorials.md b/docs/tutorials.md new file mode 100644 index 00000000..e69de29b From 7f19b26c02e6dcd35327dd4d0828894143ec4f8b Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 8 Jan 2024 10:16:37 +0100 Subject: [PATCH 035/767] ENH: mkdoc - initialization --- docs/choice_dataset_usage.md | 3 +++ docs/references_base_model.md | 3 +++ docs/references_clogit.md | 3 +++ docs/{references.md => references_data.md} | 0 docs/references_rumnet.md | 3 +++ mkdocs.yaml | 17 +++++++++++++++-- 6 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 docs/choice_dataset_usage.md create mode 100644 docs/references_base_model.md create mode 100644 docs/references_clogit.md rename docs/{references.md => references_data.md} (100%) create mode 100644 docs/references_rumnet.md diff --git a/docs/choice_dataset_usage.md b/docs/choice_dataset_usage.md new file mode 100644 index 00000000..9d717d86 --- /dev/null +++ b/docs/choice_dataset_usage.md @@ -0,0 +1,3 @@ +--8<-- +notebooks/choice_learn_introduction_data.ipynb +--8<-- diff --git a/docs/references_base_model.md b/docs/references_base_model.md new file mode 100644 index 00000000..7eafcdf5 --- /dev/null +++ b/docs/references_base_model.md @@ -0,0 +1,3 @@ +# ChoiceDataset + +:::choice_learn.models.base_model diff --git a/docs/references_clogit.md b/docs/references_clogit.md new file mode 100644 index 00000000..4551842f --- /dev/null +++ b/docs/references_clogit.md @@ -0,0 +1,3 @@ +# ChoiceDataset + +:::choice_learn.models.conditional_mnl diff --git a/docs/references.md b/docs/references_data.md similarity index 100% rename from docs/references.md rename to docs/references_data.md diff --git a/docs/references_rumnet.md b/docs/references_rumnet.md new file mode 100644 index 00000000..19e0ecec --- /dev/null +++ b/docs/references_rumnet.md @@ -0,0 +1,3 @@ +# ChoiceDataset + +:::choice_learn.models.rumnet diff --git a/mkdocs.yaml b/mkdocs.yaml index 8482bf83..903fb298 100644 --- a/mkdocs.yaml +++ b/mkdocs.yaml @@ -23,6 +23,8 @@ theme: - content.tabs.link - content.code.annotation - content.code.copy + logo: choice_learn_official_logo.png + favicon: choice_learn_official_logo.png markdown_extensions: - pymdownx.highlight: @@ -36,7 +38,18 @@ markdown_extensions: plugins: - mkdocstrings - search + - mkdocs-jupyter nav: - - Home: index.md - - Source code: code.md + - HomePage: index.md + - tutorials.md + - How-To Guides: + - Introduction: how-to-guides.md + - ChoiceDataset Usage: choice_dataset_usage.md + - References: + - references_data.md + - Choice Models: + - Base Model: references_base_model.md + - Conditional Logit: references_clogit.md + - RUMnet: references_rumnet.md + - explanations.md From 292f04d7ef66eeff88a28f34a33215dc7a874add Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 8 Jan 2024 16:32:53 +0100 Subject: [PATCH 036/767] ADD: example notebooks --- choice_learn/data/choice_dataset.py | 10 +++++----- docs/choice_dataset_usage.md | 4 +--- mkdocs.yaml | 17 +++++++++++++---- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index fdacbabc..04664b8a 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -55,9 +55,9 @@ def __init__( for each sessions we have a list of related choices. Main list has same legnth as session_features and sessions_items_features. batch_size: int, optional - size of the batches to return in __iter__ method - suffle: bool, optional - whether to shuffle the dataset or not + size of the batches to return in __iter__ method, default is 16 + shuffle: bool, optional + whether to shuffle the dataset or not, default is False """ # --------- [ Handling features type given as tuples or not ] --------- # # If items_features is not given as tuple, transform it internally as a tuple @@ -257,8 +257,8 @@ def _build_indexes(self, choices): Particularly creates a flatten version of the choices and associates an index so that we can retrieve from this index the session and the corresponding choice. - Parameters: - ----------- + Parameters + ---------- choices: list of list raffed version of the choices diff --git a/docs/choice_dataset_usage.md b/docs/choice_dataset_usage.md index 9d717d86..fb058817 100644 --- a/docs/choice_dataset_usage.md +++ b/docs/choice_dataset_usage.md @@ -1,3 +1 @@ ---8<-- -notebooks/choice_learn_introduction_data.ipynb ---8<-- +notebooks/choice_learn_introduction_data.md diff --git a/mkdocs.yaml b/mkdocs.yaml index 903fb298..ba5df33a 100644 --- a/mkdocs.yaml +++ b/mkdocs.yaml @@ -36,16 +36,25 @@ markdown_extensions: - pymdownx.superfences plugins: - - mkdocstrings - - search - - mkdocs-jupyter +- mkdocstrings: + handlers: + python: + options: + docstring_style: numpy + rendering: + show_source: true +- search +- nbconvert: + input_dir: notebooks + recursive: true + output_dir: notebooks nav: - HomePage: index.md - tutorials.md - How-To Guides: - Introduction: how-to-guides.md - - ChoiceDataset Usage: choice_dataset_usage.md + - ChoiceDataset Usage: notebooks/choice_learn_introduction_data.md - References: - references_data.md - Choice Models: From c1fb16666da90123c1da65f6bf3a08bf50f4abc6 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 8 Jan 2024 16:33:53 +0100 Subject: [PATCH 037/767] enh: index --- docs/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/index.md b/docs/index.md index 80134292..cdef8bfb 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,3 +1,3 @@ -# Welcome to the documentation! +# Welcome to the choice-learn documentation! -For more information, make sure to check the [Material for MkDocs documentation](https://squidfunk.github.io/mkdocs-material/getting-started/) +A toolbox for choice-modeling From 1b13fc4f16e47ae46100b39cc3507647b3bc6dfd Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 8 Jan 2024 16:35:09 +0100 Subject: [PATCH 038/767] ADD: easy doc rebuild with GA --- .github/workflows/deploy_docs.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy_docs.yaml b/.github/workflows/deploy_docs.yaml index fb8141e8..a1663645 100644 --- a/.github/workflows/deploy_docs.yaml +++ b/.github/workflows/deploy_docs.yaml @@ -1,8 +1,8 @@ name: Deploy MkDocs to GitHub Pages on: - release: - types: [published] + push: + branch: [main] jobs: deploy-docs: From d1b8face8100a267bc581430d876c37d1dc3b713 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 8 Jan 2024 16:38:36 +0100 Subject: [PATCH 039/767] ADD: nbconvert for mkdocs --- requirements-developer.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements-developer.txt b/requirements-developer.txt index 20cf8a44..4185a5cb 100644 --- a/requirements-developer.txt +++ b/requirements-developer.txt @@ -4,6 +4,7 @@ pre-commit==3.3.3 pytest==7.3.2 mkdocs==1.4.3 mkdocs-material==9.1.15 +mkdocs-nbconvert==0.2.1 mkdocstrings-python==1.1.2 bandit==1.7.5 nbstripout==0.6.1 From 5788fbfb4ed895be08dfb459d62e329ec5477ad8 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 8 Jan 2024 16:48:15 +0100 Subject: [PATCH 040/767] small modifs --- docs/choice_dataset_usage.md | 1 - mkdocs.yaml | 1 - requirements-developer.txt | 6 +++--- 3 files changed, 3 insertions(+), 5 deletions(-) delete mode 100644 docs/choice_dataset_usage.md diff --git a/docs/choice_dataset_usage.md b/docs/choice_dataset_usage.md deleted file mode 100644 index fb058817..00000000 --- a/docs/choice_dataset_usage.md +++ /dev/null @@ -1 +0,0 @@ -notebooks/choice_learn_introduction_data.md diff --git a/mkdocs.yaml b/mkdocs.yaml index ba5df33a..001f9652 100644 --- a/mkdocs.yaml +++ b/mkdocs.yaml @@ -46,7 +46,6 @@ plugins: - search - nbconvert: input_dir: notebooks - recursive: true output_dir: notebooks nav: diff --git a/requirements-developer.txt b/requirements-developer.txt index 4185a5cb..6c8a1784 100644 --- a/requirements-developer.txt +++ b/requirements-developer.txt @@ -2,10 +2,10 @@ ruff==0.1.2 pre-commit==3.3.3 pytest==7.3.2 -mkdocs==1.4.3 -mkdocs-material==9.1.15 +mkdocs==1.5.3 +mkdocs-material==9.5.3 mkdocs-nbconvert==0.2.1 -mkdocstrings-python==1.1.2 +mkdocstrings-python==1.7.5 bandit==1.7.5 nbstripout==0.6.1 ipykernel==6.24.0 From 9fbbb79a3982379ee849dc498cc1b43f31a238af Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 8 Jan 2024 17:01:30 +0100 Subject: [PATCH 041/767] DOC: Reorg --- .../data/references_choice_dataset.md} | 0 docs/references/data/references_dataset.md | 3 +++ docs/references/data/references_store.md | 3 +++ .../models}/references_base_model.md | 2 +- docs/{ => references/models}/references_clogit.md | 2 +- docs/{ => references/models}/references_rumnet.md | 2 +- mkdocs.yaml | 13 +++++++++---- 7 files changed, 18 insertions(+), 7 deletions(-) rename docs/{references_data.md => references/data/references_choice_dataset.md} (100%) create mode 100644 docs/references/data/references_dataset.md create mode 100644 docs/references/data/references_store.md rename docs/{ => references/models}/references_base_model.md (64%) rename docs/{ => references/models}/references_clogit.md (62%) rename docs/{ => references/models}/references_rumnet.md (65%) diff --git a/docs/references_data.md b/docs/references/data/references_choice_dataset.md similarity index 100% rename from docs/references_data.md rename to docs/references/data/references_choice_dataset.md diff --git a/docs/references/data/references_dataset.md b/docs/references/data/references_dataset.md new file mode 100644 index 00000000..48164b63 --- /dev/null +++ b/docs/references/data/references_dataset.md @@ -0,0 +1,3 @@ +# OpenSource datasets Loaders + +:::choice_learn.datasets.base diff --git a/docs/references/data/references_store.md b/docs/references/data/references_store.md new file mode 100644 index 00000000..26e4e5f1 --- /dev/null +++ b/docs/references/data/references_store.md @@ -0,0 +1,3 @@ +# Features Storage + +:::choice_learn.data.store diff --git a/docs/references_base_model.md b/docs/references/models/references_base_model.md similarity index 64% rename from docs/references_base_model.md rename to docs/references/models/references_base_model.md index 7eafcdf5..cda16f5c 100644 --- a/docs/references_base_model.md +++ b/docs/references/models/references_base_model.md @@ -1,3 +1,3 @@ -# ChoiceDataset +# Base model class :::choice_learn.models.base_model diff --git a/docs/references_clogit.md b/docs/references/models/references_clogit.md similarity index 62% rename from docs/references_clogit.md rename to docs/references/models/references_clogit.md index 4551842f..bfd508c5 100644 --- a/docs/references_clogit.md +++ b/docs/references/models/references_clogit.md @@ -1,3 +1,3 @@ -# ChoiceDataset +# Conditional MNL class :::choice_learn.models.conditional_mnl diff --git a/docs/references_rumnet.md b/docs/references/models/references_rumnet.md similarity index 65% rename from docs/references_rumnet.md rename to docs/references/models/references_rumnet.md index 19e0ecec..507e9070 100644 --- a/docs/references_rumnet.md +++ b/docs/references/models/references_rumnet.md @@ -1,3 +1,3 @@ -# ChoiceDataset +# RUMnet class :::choice_learn.models.rumnet diff --git a/mkdocs.yaml b/mkdocs.yaml index 001f9652..b596078d 100644 --- a/mkdocs.yaml +++ b/mkdocs.yaml @@ -54,10 +54,15 @@ nav: - How-To Guides: - Introduction: how-to-guides.md - ChoiceDataset Usage: notebooks/choice_learn_introduction_data.md + - Conditional Logit Estimation: notebooks/choice_learn_introduction_clogit.md + - Custom Choice Model Creation: notebooks/choice_learn_introduction_data.md - References: - - references_data.md + - Data: + - ChoiceDataset: references/data/references_choice_dataset.md + - Features Storage: references/data/references_store.md + - Available Datasets: references/data/references_dataset.md - Choice Models: - - Base Model: references_base_model.md - - Conditional Logit: references_clogit.md - - RUMnet: references_rumnet.md + - Base Model: references/models/references_base_model.md + - Conditional Logit: references/models/references_clogit.md + - RUMnet: references/models/references_rumnet.md - explanations.md From 3f4c3677d9aed83568bff4efe00ba604ce18e36c Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 8 Jan 2024 17:03:39 +0100 Subject: [PATCH 042/767] fix branch mkdocs on push --- .github/workflows/deploy_docs.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy_docs.yaml b/.github/workflows/deploy_docs.yaml index a1663645..1d40dc21 100644 --- a/.github/workflows/deploy_docs.yaml +++ b/.github/workflows/deploy_docs.yaml @@ -2,7 +2,8 @@ name: Deploy MkDocs to GitHub Pages on: push: - branch: [main] + branches: + - main jobs: deploy-docs: From db3c8da0749ede6f9eddeaf9db6b79bac83fd5b5 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 8 Jan 2024 17:05:07 +0100 Subject: [PATCH 043/767] ADD: ci mkdocs on PR --- .github/workflows/deploy_docs.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/deploy_docs.yaml b/.github/workflows/deploy_docs.yaml index 1d40dc21..22500072 100644 --- a/.github/workflows/deploy_docs.yaml +++ b/.github/workflows/deploy_docs.yaml @@ -4,6 +4,9 @@ on: push: branches: - main + pull_request: + branches: + - main jobs: deploy-docs: From f20e0c51db5c29f5edcab78cbf1cf347b73a6030 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 9 Jan 2024 17:20:26 +0100 Subject: [PATCH 044/767] small modifs --- notebooks/choice_learn_introduction_data.ipynb | 4 +++- notebooks/custom_model.ipynb | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/notebooks/choice_learn_introduction_data.ipynb b/notebooks/choice_learn_introduction_data.ipynb index 55bec28d..04d2df1f 100644 --- a/notebooks/choice_learn_introduction_data.ipynb +++ b/notebooks/choice_learn_introduction_data.ipynb @@ -280,7 +280,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "keep_output": true + }, "outputs": [], "source": [ "dataset.sessions_features[0].shape, dataset.items_features[0].shape, dataset.sessions_items_features[0].shape" diff --git a/notebooks/custom_model.ipynb b/notebooks/custom_model.ipynb index b47e2430..2e929611 100644 --- a/notebooks/custom_model.ipynb +++ b/notebooks/custom_model.ipynb @@ -43,7 +43,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We download the ModeCanada dataset as a ChoiceDataset, see \\ref{} for more details." + "We download the ModeCanada dataset as a ChoiceDataset, see [here](./choice_learn_introduction_data.ipynb) for more details." ] }, { From 31c7435a92e88552121a3a4820e2581a88de592e Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 9 Jan 2024 18:33:00 +0100 Subject: [PATCH 045/767] intermediate new signature --- choice_learn/data/choice_dataset.py | 129 +++++++++++++++++++--------- choice_learn/data/storage.py | 74 ++++++++++++++++ 2 files changed, 162 insertions(+), 41 deletions(-) create mode 100644 choice_learn/data/storage.py diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index 815d1c07..a8599bff 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -25,12 +25,14 @@ class ChoiceDataset(object): def __init__( self, choices, # Should not have None as default value ? - available_items_features, # MUST INCLUDE item_id column; possible: column "available" binaire - contexts_features=None, # as many context as choices. values or ids (look at key) - features_by_ids=None, # list of FeaturesById --> requires to have df with col "_id" - #choices_features_names=None, # optional way to provide keys - #items_features_names=None, # optional way to provide keys - shuffle=False, + fixed_items_features=None, + contexts_features=None, # as many context as choices. values or ids (look at key) + contexts_items_features=None, # MUST INCLUDE item_id column; possible: column "available" binary + contexts_items_availabilities=None, + features_by_ids=None, # list of (name, FeaturesStorage) --> requires to have df with col "_id" + fixed_items_features_names=None, + contexts_features_names=None, + contexts_items_features_names=None, ): """Builds the ChoiceDataset. @@ -50,13 +52,11 @@ def __init__( # Done to keep a logical order of arguments, and has logic: choices have to be specified raise ValueError("Choices must be specified, got None") - assert len(choices) == len(available_items) - assert contexts_features is None or len(choices) == len(contexts_features) - # --------- [ Handling features type given as tuples or not ] --------- # # If items_features is not given as tuple, transform it internally as a tuple # A bit longer because can be None and need to also handle names - items_features = None # to pass this part + + items_features = None # to pass this part if items_features is not None: if not isinstance(items_features, tuple): items_features = (items_features,) @@ -68,7 +68,9 @@ def __init__( len(items_features) != len(items_features_names) and items_features_names is not None ): - raise ValueError("items_features shape and items_features_names shape do not match") + raise ValueError( + "items_features shape and items_features_names shape do not match" + ) self._return_items_features_tuple = True # In this case names are missing, still transform it as a tuple else: @@ -80,7 +82,7 @@ def __init__( if contexts_features is not None: if not isinstance(contexts_features, tuple): contexts_features = (contexts_features,) - #choices_features_names = (choices_features_names,) + # choices_features_names = (choices_features_names,) self._return_choices_features_tuple = False # choices_features is already a tuple, names are given, checking consistency elif choices_features_names is not None: @@ -105,28 +107,30 @@ def __init__( # names as features names # Handling items_features - if items_features is not None: - for i, feature in enumerate(items_features): + if fixed_items_features is not None: + for i, feature in enumerate(fixed_items_features): if isinstance(feature, pd.DataFrame): # Ordering items by id ? if "item_id" in feature.columns: feature = feature.set_index("item_id") - items_features = ( - items_features[:i] + fixed_items_features = ( + fixed_items_features[:i] + (feature.loc[np.sort(feature.index)].to_numpy(),) - + items_features[i + 1 :] + + fixed_items_features[i + 1 :] ) - items_features_names = ( - items_features_names[:i] + fixed_items_features_names = ( + fixed_items_features_names[:i] + (feature.columns.tolist(),) - + items_features_names[i + 1 :] + + fixed_items_features_names[i + 1 :] ) elif isinstance(feature, list): - items_features = ( - items_features[:i] + (np.array(feature),) + items_features[i + 1 :] + fixed_items_features = ( + fixed_items_features[:i] + + (np.array(feature),) + + fixed_items_features[i + 1 :] ) - # Handling choices_features + # Handling context features if contexts_features is not None: for i, feature in enumerate(contexts_features): if isinstance(feature, pd.DataFrame): @@ -138,18 +142,61 @@ def __init__( + (feature.loc[np.sort(feature.index)].to_numpy(),) + contexts_features[i + 1 :] ) - #choices_features_names = ( - # choices_features_names[:i] - # + (feature.columns.tolist(),) - # + choices_features_names[i + 1 :] - #) elif isinstance(feature, list): contexts_features = ( contexts_features[:i] + (np.array(feature),) + contexts_features[i + 1 :] ) - - if isinstance(available_items, list): - available_items = np.array(available_items, dtype=object) + # Handling contexts_items_features + if contexts_items_features is not None: + for i, feature in enumerate(contexts_items_features): + if isinstance(feature, pd.DataFrame): + # Ordering choices by id ? + if "session_id" in feature.columns: + if "item_id" in feature.columns: + feature_array = [] + for sess in np.sort(feature.session_id): + sess_df = feature.loc[feature.session_id == sess] + sess_df = sess_df.set_index("item_id") + feature_array.append(sess_df.loc[np.sort(sess_df.index)].to_numpy()) + contexts_items_features = ( + contexts_items_features[:i] + + (np.stack(feature_array, axis=0),) + + contexts_items_features[i + 1 :] + ) + else: + feature = feature.set_index("session_id") + contexts_items_features = ( + contexts_items_features[:i] + + (feature.loc[np.sort(feature.index)].to_numpy(),) + + contexts_items_features[i + 1 :] + ) + elif isinstance(feature, list): + contexts_items_features = ( + contexts_items_features[:i] + + (np.array(feature),) + + contexts_items_features[i + 1 :] + ) + if contexts_items_availabilities is not None: + if isinstance(contexts_items_availabilities, list): + contexts_items_availabilities = np.array( + contexts_items_availabilities, dtype=object + ) + elif isinstance(contexts_items_availabilities, pd.DataFrame): + if "session_id" in contexts_items_availabilities.columns: + if "item_id" in contexts_items_availabilities.columns: + av_array = [] + for sess in np.sort(contexts_items_availabilities.session_id): + sess_df = contexts_items_availabilities.loc[ + contexts_items_availabilities.session_id == sess + ] + sess_df = sess_df.set_index("item_id") + av_array.append(sess_df.loc[np.sort(sess_df.index)].to_numpy()) + contexts_items_availabilities = np.array(av_array) + else: + feature = feature.set_index("session_id") + contexts_items_availabilities = contexts_items_availabilities.loc[ + np.sort(feature.index) + ].to_numpy() # Handling choices # Choices must then be given as the name of the chosen item @@ -165,22 +212,22 @@ def __init__( choices = [np.where(items == c)[0] for c in choices.choice] # Setting attributes of ChoiceDataset + self.fixedf_items_features = fixed_items_features self.contexts_features = contexts_features - self.available_items = available_items - - #self.items_features_names = items_features_names - #self.choices_features_names = choices_features_names + self.contexts_items_features = contexts_items_features + self.context_items_availabilities = contexts_items_availabilities + self.choices = choices - self.shuffle = shuffle + self.fixed_items_features_names = fixed_items_features_names + self.contexts_features_names = contexts_features_names + self.contexts_items_features_names = contexts_items_features_names - self.ragged_choices = choices - self.indexes, self.choices = self._build_indexes(choices) self.n_choices = len(self.choices) # Different consitency checks to ensure everythin is coherent - #self._check_dataset() # Should handle alone if np.arrays are squeezed - #self._return_types = self._check_types() - #self._check_names() + # self._check_dataset() # Should handle alone if np.arrays are squeezed + # self._return_types = self._check_types() + # self._check_names() # Build .iloc method self.indexer = ChoiceDatasetIndexer(self) diff --git a/choice_learn/data/storage.py b/choice_learn/data/storage.py new file mode 100644 index 00000000..e966e369 --- /dev/null +++ b/choice_learn/data/storage.py @@ -0,0 +1,74 @@ +"""Different classes to optimize RAM usage with repeated features over time.""" +import numpy as np +import panda as pd + + +class Storage(object): + """Class to keep OneHotStore and FeaturesStore with same parent.""" + + def __init__(self, ids=None, values=None, values_names=None, name=None): + """Builds the store. + + Parameters + ---------- + indexes : array_like or None + list of indexes of features to store. If None is given, indexes are created from + apparition order of values + values : array_like + list of values of features to store + sequence : array_like + sequence of apparitions of the features + name: string, optional + name of the features store -- not used at the moment + """ + if isinstance(values, dict): + pass + elif isinstance(values, pd.DataFrame): + if values_names is not None: + print("Warning: values_names is ignored when values is a DataFrame") + if "id" in values.columns: + values = values.set_index("id") + values_names = values.columns + storage = {k: v.to_numpy() for (k, v) in values.iterrows()} + elif isinstance(values, list): + pass + elif isinstance(values, np.ndarray): + pass + else: + raise ValueError("values must be a dict, a DataFrame, a list or a numpy array") + + if ids is None: + ids = list(range(len(values))) + + self.storage = {k: v for (k, v) in zip(ids, values)} + self.name = name + + def _get_store_element(self, index): + """Getter method over self.sequence. + + Returns the features stored at index index. Compared to __getitem__, it does take + the index-th element of sequence but the index-th element of the store. + + Parameters + ---------- + index : (int, list, slice) + index argument of the feature + + Returns: + -------- + array_like + features corresponding to the index index in self.store + """ + if isinstance(index, list): + return [self.store[i] for i in index] + # else: + return self.store[index] + + def __len__(self): + """Returns the length of the sequence of apparition of the features.""" + return len(self.sequence) + + @property + def batch(self): + """Indexing attribute.""" + return self.indexer From 2eb992cc3b45f9ba27819f16f8a0e1abfcb5d9fa Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 9 Jan 2024 21:42:03 +0100 Subject: [PATCH 046/767] ADD: new FeaturesStorage --- choice_learn/data/indexer.py | 33 ++++++++++++++++++ choice_learn/data/storage.py | 67 +++++++++++++++++++++++++++++------- 2 files changed, 87 insertions(+), 13 deletions(-) diff --git a/choice_learn/data/indexer.py b/choice_learn/data/indexer.py index 5974f59f..38f05254 100644 --- a/choice_learn/data/indexer.py +++ b/choice_learn/data/indexer.py @@ -1,5 +1,6 @@ """Indexer classes for data classes.""" from abc import abstractmethod +from collections.abc import Iterable import numpy as np @@ -64,6 +65,38 @@ def __getitem__(self, sequence_index): ] return self.store.store[self.store.sequence[sequence_index]] +class StorageIndexer(Indexer): + """Class for Ilocing/Batching FeaturesStorage.""" + + def __init__(self, storage): + """StoreIndexer constructor. + + Parameters + ---------- + store : choice_modeling.data.store.FeaturesStore + Store object to be indexed. + """ + self.storage = storage + + def __getitem__(self, sequence_keys): + """Returns the features appearing at the sequence_index-th position of sequence. + + Parameters + ---------- + sequence_index : (int, list, slice) + index position of the sequence + + Returns: + -------- + array_like + features corresponding to the sequence_index-th position of sequence + """ + if isinstance(sequence_keys, Iterable): + return np.array([self.storage.storage[key] for key in sequence_keys]) + if isinstance(sequence_keys, slice): + raise ValueError("Slicing is not supported for storage") + return np.array(self.storage.storage[sequence_keys]) + class OneHotStoreIndexer(Indexer): """Class for Ilocing OneHotStore.""" diff --git a/choice_learn/data/storage.py b/choice_learn/data/storage.py index e966e369..3d2e2b60 100644 --- a/choice_learn/data/storage.py +++ b/choice_learn/data/storage.py @@ -1,12 +1,34 @@ """Different classes to optimize RAM usage with repeated features over time.""" +from abc import ABC, abstractmethod + import numpy as np -import panda as pd +import pandas as pd +from choice_learn.data.indexer import StorageIndexer -class Storage(object): +class Storage(ABC): """Class to keep OneHotStore and FeaturesStore with same parent.""" - def __init__(self, ids=None, values=None, values_names=None, name=None): + def __init__(self, features_to_store): + self.features_to_store = features_to_store + + @abstractmethod + def __getitem__(self, keys): + pass + + @abstractmethod + def __len__(self): + pass + + @property + def batch(self): + pass + + +class FeaturesStorage(Storage): + """Class to keep OneHotStore and FeaturesStore with same parent.""" + + def __init__(self, ids=None, values=None, values_names=None, name=None, indexer=StorageIndexer): """Builds the store. Parameters @@ -22,7 +44,14 @@ def __init__(self, ids=None, values=None, values_names=None, name=None): name of the features store -- not used at the moment """ if isinstance(values, dict): - pass + storage = values + lengths = [] + for k, v in storage.items(): + assert (isinstance(v, np.ndarray) | isinstance(v, list)) + assert len(np.array(v).shape) == 1 + lengths.append(len(v)) + assert len(set(lengths)) == 1 + elif isinstance(values, pd.DataFrame): if values_names is not None: print("Warning: values_names is ignored when values is a DataFrame") @@ -30,19 +59,20 @@ def __init__(self, ids=None, values=None, values_names=None, name=None): values = values.set_index("id") values_names = values.columns storage = {k: v.to_numpy() for (k, v) in values.iterrows()} - elif isinstance(values, list): - pass - elif isinstance(values, np.ndarray): - pass + elif isinstance(values, list) or isinstance(values, np.ndarray): + if ids is None: + ids = list(range(len(values))) + storage = {k: v for (k, v) in zip(ids, values)} else: raise ValueError("values must be a dict, a DataFrame, a list or a numpy array") - if ids is None: - ids = list(range(len(values))) - - self.storage = {k: v for (k, v) in zip(ids, values)} + self.storage = storage + self.values_names = values_names self.name = name + self.shape = (len(self), len(next(iter(self.storage.values())))) + self.indexer = indexer(self) + def _get_store_element(self, index): """Getter method over self.sequence. @@ -66,7 +96,18 @@ def _get_store_element(self, index): def __len__(self): """Returns the length of the sequence of apparition of the features.""" - return len(self.sequence) + return len(self.storage) + + def __getitem__(self, keys): + """_summary_. + + Parameters + ---------- + keys : _type_ + _description_ + """ + sub_storage = {k: self.storage[k] for k in keys} + return FeaturesStorage(values=sub_storage, values_names=self.values_names, name=self.name) @property def batch(self): From b6289adcd0c52df66e5b256b9314ea837c9d6df1 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 9 Jan 2024 21:42:45 +0100 Subject: [PATCH 047/767] ADD: FeaturesStorage Example --- choice_learn/data/indexer.py | 1 + choice_learn/data/storage.py | 3 +- notebooks/features_storage_example.ipynb | 139 +++++++++++++++++++++++ 3 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 notebooks/features_storage_example.ipynb diff --git a/choice_learn/data/indexer.py b/choice_learn/data/indexer.py index 38f05254..2c8568b1 100644 --- a/choice_learn/data/indexer.py +++ b/choice_learn/data/indexer.py @@ -65,6 +65,7 @@ def __getitem__(self, sequence_index): ] return self.store.store[self.store.sequence[sequence_index]] + class StorageIndexer(Indexer): """Class for Ilocing/Batching FeaturesStorage.""" diff --git a/choice_learn/data/storage.py b/choice_learn/data/storage.py index 3d2e2b60..a96167aa 100644 --- a/choice_learn/data/storage.py +++ b/choice_learn/data/storage.py @@ -6,6 +6,7 @@ from choice_learn.data.indexer import StorageIndexer + class Storage(ABC): """Class to keep OneHotStore and FeaturesStore with same parent.""" @@ -47,7 +48,7 @@ def __init__(self, ids=None, values=None, values_names=None, name=None, indexer= storage = values lengths = [] for k, v in storage.items(): - assert (isinstance(v, np.ndarray) | isinstance(v, list)) + assert isinstance(v, np.ndarray) | isinstance(v, list) assert len(np.array(v).shape) == 1 lengths.append(len(v)) assert len(set(lengths)) == 1 diff --git a/notebooks/features_storage_example.ipynb b/notebooks/features_storage_example.ipynb new file mode 100644 index 00000000..4ed33770 --- /dev/null +++ b/notebooks/features_storage_example.ipynb @@ -0,0 +1,139 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "\n", + "# Remove GPU use\n", + "os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"\"\n", + "\n", + "import sys\n", + "from pathlib import Path\n", + "\n", + "sys.path.append(\"../\")\n", + "\n", + "import numpy as np\n", + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from choice_learn.data.storage import FeaturesStorage" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "features = {\"customerA\": [1, 2, 3], \"customerB\": [4, 5, 6], \"customerC\": [7, 8, 9]}\n", + "\n", + "storage = FeaturesStorage(values=features, values_names=[\"age\", \"income\", \"children_nb\"], name=\"customers\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "storage[[\"customerA\", \"customerC\"]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "storage.batch[[\"customerA\", \"customerC\", \"customerA\", \"customerC\"]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "features = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n", + "ids = [\"customerA\", \"customerB\", \"customerC\"]\n", + "\n", + "storage = FeaturesStorage(ids=ids, values=features, values_names=[\"age\", \"income\", \"children_nb\"], name=\"customers\")\n", + "storage.batch[[\"customerA\", \"customerC\", \"customerA\", \"customerC\"]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "features = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n", + "\n", + "storage = FeaturesStorage(values=features, values_names=[\"age\", \"income\", \"children_nb\"], name=\"customers\")\n", + "storage.batch[[0, 2, 0, 2]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "features = {\"age\": [1, 2, 3], \"income\": [4, 5, 6], \"children_nb\": [7, 8, 9], \"id\": [\"customerA\", \"customerB\", \"customerC\"]}\n", + "features = pd.DataFrame(features)\n", + "storage = FeaturesStorage(values=features, name=\"customers\")\n", + "storage.batch[[\"customerA\", \"customerC\", \"customerA\", \"customerC\"]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "features = {\"age\": [1, 2, 3], \"income\": [4, 5, 6], \"children_nb\": [7, 8, 9]}\n", + "features = pd.DataFrame(features, index=[\"customerA\", \"customerB\", \"customerC\"])\n", + "storage = FeaturesStorage(values=features, name=\"customers\")\n", + "storage.batch[[\"customerA\", \"customerC\", \"customerA\", \"customerC\"]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "tf_env", + "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.11.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From e4b07270a7fd102092c33fe2ef86b2d5f7e34a13 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 9 Jan 2024 23:15:31 +0100 Subject: [PATCH 048/767] ADD: basic CD init running --- choice_learn/data/choice_dataset.py | 175 ++++++++++++++++------------ 1 file changed, 103 insertions(+), 72 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index a8599bff..cbf57729 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -29,7 +29,7 @@ def __init__( contexts_features=None, # as many context as choices. values or ids (look at key) contexts_items_features=None, # MUST INCLUDE item_id column; possible: column "available" binary contexts_items_availabilities=None, - features_by_ids=None, # list of (name, FeaturesStorage) --> requires to have df with col "_id" + features_by_ids=[], # list of (name, FeaturesStorage) --> requires to have df with col "_id" fixed_items_features_names=None, contexts_features_names=None, contexts_items_features_names=None, @@ -56,49 +56,77 @@ def __init__( # If items_features is not given as tuple, transform it internally as a tuple # A bit longer because can be None and need to also handle names - items_features = None # to pass this part - if items_features is not None: - if not isinstance(items_features, tuple): - items_features = (items_features,) - items_features_names = (items_features_names,) + if fixed_items_features is not None: + if not isinstance(fixed_items_features, tuple): + if fixed_items_features_names is not None: + assert len(fixed_items_features) == len(fixed_items_features_names), "Number of features given does not match number of features names given." self._return_items_features_tuple = False - # items_features is already a tuple, names are given, checking consistency - elif items_features_names is not None: - if ( - len(items_features) != len(items_features_names) - and items_features_names is not None - ): - raise ValueError( - "items_features shape and items_features_names shape do not match" - ) - self._return_items_features_tuple = True - # In this case names are missing, still transform it as a tuple + + fixed_items_features = (fixed_items_features,) + fixed_items_features_names = (fixed_items_features_names,) else: self._return_items_features_tuple = True - items_features_names = (None,) * len(items_features) + + # items_features is already a tuple, names are given, checking consistency + if fixed_items_features_names is not None: + for f, name in zip(fixed_items_features, fixed_items_features_names): + if ( + len(f) != len(name) + ): + raise ValueError( + "items_features shape and items_features_names shape do not match" + ) + # In this case names are missing, still transform it as a tuple + else: + fixed_items_features_names = (None,) * len(fixed_items_features) # If choices_features is not given as tuple, transform it internally as a tuple # A bit longer because can be None and need to also handle names if contexts_features is not None: if not isinstance(contexts_features, tuple): - contexts_features = (contexts_features,) - # choices_features_names = (choices_features_names,) self._return_choices_features_tuple = False + if contexts_items_features_names is not None: + assert len(contexts_features) == len(contexts_features_names), "Number of features given does not match number of features names given." + + contexts_features_names = (contexts_features_names,) + contexts_features = (contexts_features,) + # choices_features is already a tuple, names are given, checking consistency - elif choices_features_names is not None: - if ( - len(contexts_features) != len(choices_features_names) - and choices_features_names is not None - ): + else: + self._return_contexts_features_tuple = True + if contexts_features_names is not None: + for f, name in zip(contexts_features, contexts_features_names): + if ( + len(f) != len(name) + ): + raise ValueError( + "contexts_features shape and contexts_features_names shape do not match" + ) + + # In this case names are missing, still transform it as a tuple + else: + choices_features_names = (None,) * len(contexts_features) + + if not isinstance(contexts_items_features, tuple) and contexts_items_features is not None: + self._return_sessions_items_features_tuple = False + if contexts_items_features_names is not None: + assert len(contexts_items_features) == len(contexts_items_features_names), "Number of features given does not match number of features names given for contexts_items." + contexts_items_features = (contexts_items_features,) + contexts_items_features_names = (contexts_items_features_names,) + + # sessions_items_features is already a tuple, names are given, checking consistency + elif contexts_items_features is not None and contexts_items_features_names is not None: + for f, name in zip(contexts_items_features, contexts_items_features_names): + if len(f) != len(name): raise ValueError( - "choices_features shape and choices_features_names shape \ - do not match" + "contexts_items_features shape and \ + contexts_items_features_names shape do not match" ) - self._return_choices_features_tuple = True - # In this case names are missing, still transform it as a tuple - else: - self._return_choices_features_tuple = True - choices_features_names = (None,) * len(contexts_features) + self._return_sessions_items_features_tuple = True + # In this case names are missing, still transform it as a tuple + elif contexts_items_features is not None: + self._return_sessions_items_features_tuple = True + contexts_items_features_names = (None,) * len(contexts_items_features) # --------- [Normalizing features types (DataFrame, List, etc...) -> np.ndarray] --------- # # @@ -201,30 +229,33 @@ def __init__( # Handling choices # Choices must then be given as the name of the chosen item # Items are sorted by name and attributed an index - # Cannot be a list of choices yet if isinstance(choices, pd.DataFrame): # Ordering choices by id - if "session_id" in choices.columns: - choices = choices.set_index("session_id") + if "context_id" in choices.columns: + choices = choices.set_index("context_id") choices = choices.loc[np.sort(choices.index)] items = np.sort(np.unique(choices.choice)) # items is the value (str) of the item choices = [np.where(items == c)[0] for c in choices.choice] # Setting attributes of ChoiceDataset - self.fixedf_items_features = fixed_items_features + self.fixed_items_features = fixed_items_features self.contexts_features = contexts_features self.contexts_items_features = contexts_items_features self.context_items_availabilities = contexts_items_availabilities self.choices = choices + self.features_by_ids = features_by_ids + self.fixed_items_features_names = fixed_items_features_names self.contexts_features_names = contexts_features_names self.contexts_items_features_names = contexts_items_features_names + self._build_features_by_ids() + self.n_choices = len(self.choices) - # Different consitency checks to ensure everythin is coherent + # Different consitency checks to ensure everything is coherent # self._check_dataset() # Should handle alone if np.arrays are squeezed # self._return_types = self._check_types() # self._check_names() @@ -232,41 +263,41 @@ def __init__( # Build .iloc method self.indexer = ChoiceDatasetIndexer(self) - def _build_indexes(self, choices): - """Builds the indexes dictionnary from the choices. - - Particularly creates a flatten version of the choices and associates an index so that we can - retrieve from this index the session and the corresponding choice. - - Parameters: - ----------- - choices: list of list - raffed version of the choices - - Returns:: - -------- - indexes: dict - dictionnary of indexes: {index: corresponding_session_index} - choices: np.ndarray - flattened (1D) version of the choices - """ - try: # 1 choice by session - if len(np.squeeze(choices).shape) == 1: - indexes = {i: i for i in range(len(choices))} - flat_choices = np.squeeze(self.ragged_choices) - elif len(np.squeeze(choices).shape) == 0: - indexes = {i: i for i in range(len(choices))} - flat_choices = np.array([np.squeeze(self.ragged_choices)]) - except ValueError: # Ragged sequence of choices - indexes = {} - flat_choices = [] - total_count = 0 - for sess_nb, sess in enumerate(choices): - for choice in sess: - indexes[total_count] = sess_nb - flat_choices.append(choice) - total_count += 1 - return indexes, np.array(flat_choices) + def _build_features_by_ids(self): + if len(self.features_by_ids) == 0: + print("No features_by_ids given.") + return + + if self.fixed_items_features_names is None and self.contexts_features_names is None and self.contexts_items_features_names is None: + raise ValueError("No features_names given, match with fiven features_by_ids impossible.") + + fixed_items_features_map = [] + contexts_features_map = [] + contexts_items_features_map = [] + + if self.fixed_items_features_names is not None: + for i, feature in self.fixed_items_features_names: + for j, feature_by_id in enumerate(self.features_by_ids): + if feature == feature_by_id.name: + fixed_items_features_map.append((i, feature_by_id.batch)) + + if self.contexts_features_names is not None: + for i, feature in self.contexts_features_names: + for j, feature_by_id in enumerate(self.features_by_ids): + if feature == feature_by_id.name: + contexts_features_map.append((i, feature_by_id.batch)) + + if self.contexts_items_features_names is not None: + for i, feature in self.contexts_items_features_names: + for j, feature_by_id in enumerate(self.features_by_ids): + if feature == feature_by_id.name: + contexts_items_features_map.append((i, feature_by_id.batch)) + + assert len(fixed_items_features_map) + len(contexts_features_map) + len(contexts_items_features_map) == len(self.features_by_ids), "Some features_by_ids were not matched with features_names." + + self.fixed_items_features_map = fixed_items_features_map + self.contexts_features_map = contexts_features_map + self.contexts_items_features_map = contexts_items_features_map def _check_dataset(self): """Verifies that the shapes of the different features are consistent. From 9b533ec07def6460ebed6889d1b12858da1c6369 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 9 Jan 2024 23:15:52 +0100 Subject: [PATCH 049/767] ENH: Ruff --- choice_learn/data/choice_dataset.py | 36 ++++++++++++++++++----------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index cbf57729..7c28d0b5 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -59,7 +59,9 @@ def __init__( if fixed_items_features is not None: if not isinstance(fixed_items_features, tuple): if fixed_items_features_names is not None: - assert len(fixed_items_features) == len(fixed_items_features_names), "Number of features given does not match number of features names given." + assert len(fixed_items_features) == len( + fixed_items_features_names + ), "Number of features given does not match number of features names given." self._return_items_features_tuple = False fixed_items_features = (fixed_items_features,) @@ -70,9 +72,7 @@ def __init__( # items_features is already a tuple, names are given, checking consistency if fixed_items_features_names is not None: for f, name in zip(fixed_items_features, fixed_items_features_names): - if ( - len(f) != len(name) - ): + if len(f) != len(name): raise ValueError( "items_features shape and items_features_names shape do not match" ) @@ -86,7 +86,9 @@ def __init__( if not isinstance(contexts_features, tuple): self._return_choices_features_tuple = False if contexts_items_features_names is not None: - assert len(contexts_features) == len(contexts_features_names), "Number of features given does not match number of features names given." + assert len(contexts_features) == len( + contexts_features_names + ), "Number of features given does not match number of features names given." contexts_features_names = (contexts_features_names,) contexts_features = (contexts_features,) @@ -96,9 +98,7 @@ def __init__( self._return_contexts_features_tuple = True if contexts_features_names is not None: for f, name in zip(contexts_features, contexts_features_names): - if ( - len(f) != len(name) - ): + if len(f) != len(name): raise ValueError( "contexts_features shape and contexts_features_names shape do not match" ) @@ -110,7 +110,9 @@ def __init__( if not isinstance(contexts_items_features, tuple) and contexts_items_features is not None: self._return_sessions_items_features_tuple = False if contexts_items_features_names is not None: - assert len(contexts_items_features) == len(contexts_items_features_names), "Number of features given does not match number of features names given for contexts_items." + assert ( + len(contexts_items_features) == len(contexts_items_features_names) + ), "Number of features given does not match number of features names given for contexts_items." contexts_items_features = (contexts_items_features,) contexts_items_features_names = (contexts_items_features_names,) @@ -267,9 +269,15 @@ def _build_features_by_ids(self): if len(self.features_by_ids) == 0: print("No features_by_ids given.") return - - if self.fixed_items_features_names is None and self.contexts_features_names is None and self.contexts_items_features_names is None: - raise ValueError("No features_names given, match with fiven features_by_ids impossible.") + + if ( + self.fixed_items_features_names is None + and self.contexts_features_names is None + and self.contexts_items_features_names is None + ): + raise ValueError( + "No features_names given, match with fiven features_by_ids impossible." + ) fixed_items_features_map = [] contexts_features_map = [] @@ -293,7 +301,9 @@ def _build_features_by_ids(self): if feature == feature_by_id.name: contexts_items_features_map.append((i, feature_by_id.batch)) - assert len(fixed_items_features_map) + len(contexts_features_map) + len(contexts_items_features_map) == len(self.features_by_ids), "Some features_by_ids were not matched with features_names." + assert len(fixed_items_features_map) + len(contexts_features_map) + len( + contexts_items_features_map + ) == len(self.features_by_ids), "Some features_by_ids were not matched with features_names." self.fixed_items_features_map = fixed_items_features_map self.contexts_features_map = contexts_features_map From fbe8db15ee9f9753866347d4156d7263467684f4 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Wed, 10 Jan 2024 16:23:24 +0100 Subject: [PATCH 050/767] ADD: get_choice_batch ~ok --- choice_learn/data/choice_dataset.py | 280 ++++++++++++++++------------ 1 file changed, 164 insertions(+), 116 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index 7c28d0b5..686e1ddd 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -79,12 +79,14 @@ def __init__( # In this case names are missing, still transform it as a tuple else: fixed_items_features_names = (None,) * len(fixed_items_features) + else: + self._return_items_features_tuple = True # If choices_features is not given as tuple, transform it internally as a tuple # A bit longer because can be None and need to also handle names if contexts_features is not None: if not isinstance(contexts_features, tuple): - self._return_choices_features_tuple = False + self._return_contexts_features_tuple = False if contexts_items_features_names is not None: assert len(contexts_features) == len( contexts_features_names @@ -105,10 +107,12 @@ def __init__( # In this case names are missing, still transform it as a tuple else: - choices_features_names = (None,) * len(contexts_features) + contexts_features_names = (None,) * len(contexts_features) + else: + self._return_contexts_features_tuple = True if not isinstance(contexts_items_features, tuple) and contexts_items_features is not None: - self._return_sessions_items_features_tuple = False + self._return_contexts_items_features_tuple = False if contexts_items_features_names is not None: assert ( len(contexts_items_features) == len(contexts_items_features_names) @@ -124,12 +128,15 @@ def __init__( "contexts_items_features shape and \ contexts_items_features_names shape do not match" ) - self._return_sessions_items_features_tuple = True + self._return_contexts_items_features_tuple = True # In this case names are missing, still transform it as a tuple elif contexts_items_features is not None: - self._return_sessions_items_features_tuple = True + self._return_contexts_items_features_tuple = True contexts_items_features_names = (None,) * len(contexts_items_features) + else: + self._return_contexts_items_features_tuple = True + # --------- [Normalizing features types (DataFrame, List, etc...) -> np.ndarray] --------- # # # Part of this code is for handling features given as pandas.DataFrame @@ -172,6 +179,11 @@ def __init__( + (feature.loc[np.sort(feature.index)].to_numpy(),) + contexts_features[i + 1 :] ) + contexts_features_names = ( + contexts_features_names[:i] + + (feature.columns,) + + contexts_features_names[i + 1 :] + ) elif isinstance(feature, list): contexts_features = ( contexts_features[:i] + (np.array(feature),) + contexts_features[i + 1 :] @@ -244,7 +256,7 @@ def __init__( self.fixed_items_features = fixed_items_features self.contexts_features = contexts_features self.contexts_items_features = contexts_items_features - self.context_items_availabilities = contexts_items_availabilities + self.contexts_items_availabilities = contexts_items_availabilities self.choices = choices self.features_by_ids = features_by_ids @@ -258,8 +270,8 @@ def __init__( self.n_choices = len(self.choices) # Different consitency checks to ensure everything is coherent - # self._check_dataset() # Should handle alone if np.arrays are squeezed - # self._return_types = self._check_types() + self._check_dataset() # Should handle alone if np.arrays are squeezed + self._return_types = self._check_types() # self._check_names() # Build .iloc method @@ -284,22 +296,28 @@ def _build_features_by_ids(self): contexts_items_features_map = [] if self.fixed_items_features_names is not None: - for i, feature in self.fixed_items_features_names: - for j, feature_by_id in enumerate(self.features_by_ids): - if feature == feature_by_id.name: - fixed_items_features_map.append((i, feature_by_id.batch)) + for i, feature in enumerate(self.fixed_items_features_names): + if feature is not None: + for j, column_name in enumerate(feature): + for feature_by_id in self.features_by_ids: + if column_name == feature_by_id.name: + fixed_items_features_map.append(((i, j), feature_by_id.batch)) if self.contexts_features_names is not None: - for i, feature in self.contexts_features_names: - for j, feature_by_id in enumerate(self.features_by_ids): - if feature == feature_by_id.name: - contexts_features_map.append((i, feature_by_id.batch)) + for i, feature in enumerate(self.contexts_features_names): + if feature is not None: + for j, column_name in enumerate(feature): + for feature_by_id in self.features_by_ids: + if column_name == feature_by_id.name: + contexts_features_map.append(((i, j), feature_by_id.batch)) if self.contexts_items_features_names is not None: - for i, feature in self.contexts_items_features_names: - for j, feature_by_id in enumerate(self.features_by_ids): - if feature == feature_by_id.name: - contexts_items_features_map.append((i, feature_by_id.batch)) + for i, feature in enumerate(self.contexts_items_features_names): + if feature is not None: + for k, column_name in enumerate(feature): + for feature_by_id in self.features_by_ids: + if column_name == feature_by_id.name: + contexts_items_features_map.append(((i, j), feature_by_id.batch)) assert len(fixed_items_features_map) + len(contexts_features_map) + len( contexts_items_features_map @@ -330,33 +348,33 @@ def _check_num_items_shapes(self): - sessions_items_availabilities Sets the argument base_num_items """ - if self.items_features is not None: - base_num_items = self.items_features[0].shape[0] - elif self.sessions_items_features is not None: - base_num_items = self.sessions_items_features[0].shape[1] - elif self.sessions_items_availabilities is not None: - base_num_items = self.sessions_items_availabilities.shape[1] + if self.fixed_items_features is not None: + base_num_items = self.fixed_items_features[0].shape[0] + elif self.contexts_items_features is not None: + base_num_items = self.contexts_items_features[0].shape[1] + elif self.contexts_items_availabilities is not None: + base_num_items = self.contexts_items_availabilities.shape[1] else: raise ValueError( "No items features, sessions items features or items availabilities are defined" ) self.base_num_items = base_num_items - if self.items_features is not None: - for items_feature in self.items_features: + if self.fixed_items_features is not None: + for items_feature in self.fixed_items_features: if items_feature.shape[0] != base_num_items: raise ValueError(f"shapes are (f{items_feature.shape[0]}, {base_num_items})") - if self.sessions_items_features is not None: - for sessions_items_feature in self.sessions_items_features: + if self.contexts_items_features is not None: + for sessions_items_feature in self.contexts_items_features: if sessions_items_feature.shape[1] != base_num_items: raise ValueError( f"shapes are (f{sessions_items_feature.shape[1]}, {base_num_items})" ) - if self.sessions_items_availabilities is not None: - if self.sessions_items_availabilities.shape[1] != base_num_items: + if self.contexts_items_availabilities is not None: + if self.contexts_items_availabilities.shape[1] != base_num_items: raise ValueError( - f"shapes are (f{self.sessions_items_availabilities.shape[1]}, \ + f"shapes are (f{self.contexts_items_availabilities.shape[1]}, \ {base_num_items})" ) @@ -369,27 +387,27 @@ def _check_num_sessions_shapes(self): - sessions_items_availabilities Sets self.base_num_sessions argument. """ - base_num_sessions = len(self.ragged_choices) + base_num_sessions = len(self.choices) self.base_num_sessions = base_num_sessions - if self.sessions_features is not None: - for sessions_feature in self.sessions_features: + if self.contexts_features is not None: + for sessions_feature in self.contexts_features: if sessions_feature.shape[0] != base_num_sessions: raise ValueError( f"shapes are ({sessions_feature.shape[0]}, {base_num_sessions})" ) - if self.sessions_items_features is not None: - for sessions_items_feature in self.sessions_items_features: + if self.contexts_items_features is not None: + for sessions_items_feature in self.contexts_items_features: if sessions_items_feature.shape[0] != base_num_sessions: raise ValueError( f"shapes are: ({sessions_items_feature.shape[0]}, \ {base_num_sessions})" ) - if self.sessions_items_availabilities is not None: - if self.sessions_items_availabilities.shape[0] != base_num_sessions: + if self.contexts_items_availabilities is not None: + if self.contexts_items_availabilities.shape[0] != base_num_sessions: raise ValueError( - f"shapes are: ({self.sessions_items_availabilities.shape[0]}, \ + f"shapes are: ({self.contexts_items_availabilities.shape[0]}, \ {base_num_sessions})" ) @@ -423,8 +441,8 @@ def _check_types(self): return_types = [] item_types = [] - if self.items_features is not None: - for item_feat in self.items_features: + if self.fixed_items_features is not None: + for item_feat in self.fixed_items_features: if np.issubdtype(item_feat[0].dtype, np.integer): item_types.append(np.int32) else: @@ -432,8 +450,8 @@ def _check_types(self): return_types.append(tuple(item_types)) session_types = [] - if self.sessions_features is not None: - for sessions_feat in self.sessions_features: + if self.contexts_features is not None: + for sessions_feat in self.contexts_features: if np.issubdtype(sessions_feat[0].dtype, np.integer): session_types.append(np.int32) else: @@ -441,8 +459,8 @@ def _check_types(self): return_types.append(tuple(session_types)) session_item_types = [] - if self.sessions_items_features is not None: - for session_item_feat in self.sessions_items_features: + if self.contexts_items_features is not None: + for session_item_feat in self.contexts_items_features: if np.issubdtype(session_item_feat[0].dtype, np.integer): session_item_types.append(np.int32) else: @@ -752,102 +770,132 @@ def get_choices_batch(self, choices_indexes, features=None): indexes of the choices (that will be mapped to choice & session indexes) to return """ - if isinstance(choice_index, list): - if self.items_features is None: - items_features = None + if isinstance(choices_indexes, list): + print(choices_indexes) + if self.fixed_items_features is None: + fixed_items_features = None else: - items_features = tuple( - items_feature.astype(self._return_types[0][i]) - for i, items_feature in enumerate(self.items_features) + fixed_items_features = tuple( + items_feature + # .astype(self._return_types[0][i]) + for i, items_feature in enumerate(self.fixed_items_features) ) - # items_features were not given as a tuple, so we return do not return it as a tuple - if not self._return_items_features_tuple: - items_features = items_features[0] - - # Get the session indexes - sessions_indexes = [self.indexes[i] for i in choice_index] - if self.sessions_features is None: - sessions_features = None + if self.contexts_features is None: + contexts_features = None else: - sessions_features = tuple( - np.stack(sessions_feature[sessions_indexes], axis=0).astype( - self._return_types[1][i] - ) - if not isinstance(sessions_feature, Store) - else sessions_feature.iloc[sessions_indexes] - for i, sessions_feature in enumerate(self.sessions_features) + contexts_features = tuple( + contexts_features[choices_indexes] + # .astype(self._return_types[1][i]) + for i, contexts_features in enumerate(self.contexts_features) ) # sessions_features were not given as a tuple, so we return do not return it # as a tuple - if not self._return_sessions_features_tuple: - sessions_features = sessions_features[0] - if self.sessions_items_features is None: - sessions_items_features = None + if self.contexts_items_features is None: + contexts_items_features = None else: - sessions_items_features = tuple( - np.stack(sessions_items_feature[sessions_indexes], axis=0).astype( - self._return_types[2][i] - ) - if not isinstance(sessions_items_feature, Store) - else sessions_items_feature.iloc[sessions_indexes] - for i, sessions_items_feature in enumerate(self.sessions_items_features) + contexts_items_features = tuple( + contexts_items_feature[choices_indexes] + # .astype(self._return_types[2][i]) + for i, contexts_items_feature in enumerate(self.contexts_items_features) ) - # sessions_items_features were not given as a tuple, so we return do not return - # it as a tuple - if not self._return_sessions_items_features_tuple: - sessions_items_features = sessions_items_features[0] - if self.sessions_items_availabilities is None: - sessions_items_availabilities = None + if self.contexts_items_availabilities is None: + contexts_items_availabilities = np.ones((len(choices_indexes), self.base_num_items)) else: - sessions_items_availabilities = self.sessions_items_availabilities[ - sessions_indexes - ].astype(self._return_types[3]) - - choice = self.choices[choice_index].astype(self._return_types[4]) + contexts_items_availabilities = self.contexts_items_availabilities[choices_indexes] + # .astype(self._return_types[3]) + + choices = self.choices[choices_indexes].astype(self._return_types[4]) + + for indexes, func in self.fixed_items_features_map: + fixed_items_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = func[ + fixed_items_features[indexes[0]][:, indexes[1]] + ] + for indexes, func in self.contexts_features_map: + contexts_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = func[ + contexts_features[indexes[0]][:, indexes[1]] + ] + for indexes, func in self.contexts_items_features_map: + contexts_items_features[indexes[0]][:, :, indexes[1] : indexes[1] + 1] = func[ + contexts_items_features[indexes[0]][:, :, indexes[1]] + ] + + # items_features were not given as a tuple, so we return do not return it as a tuple + if not self._return_items_features_tuple: + fixed_items_features = fixed_items_features[0] + if not self._return_contexts_features_tuple: + contexts_features = contexts_features[0] + # sessions_items_features were not given as a tuple, so we return do not return + # it as a tuple + if not self._return_contexts_items_features_tuple: + contexts_items_features = contexts_items_features[0] return ( - items_features, - sessions_features, - sessions_items_features, - sessions_items_availabilities, - choice, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, ) - if isinstance(choice_index, slice): - return self.get_choice_batch(list(range(*choice_index.indices(self.choices.shape[0])))) + if isinstance(choices_indexes, slice): + return self.get_choice_batch( + list(range(*choices_indexes.indices(self.choices.shape[0]))) + ) - session_index = self.indexes[choice_index] - choice = self.choices[choice_index] + ### New + choice = self.choices[choices_indexes] - if self.items_features is None: - items_features = None + # fif = self.fif ? + if self.fixed_items_features is None: + fixed_items_features = None else: - items_features = tuple(items_feature for items_feature in self.items_features) + fixed_items_features = tuple( + items_feature for items_feature in self.fixed_items_features + ) - if self.sessions_features is None: - sessions_features = None + if self.contexts_features is None: + contexts_features = None else: - sessions_features = tuple( - sessions_feature[session_index] for sessions_feature in self.sessions_features + contexts_features = tuple( + contexts_feature[choices_indexes] for contexts_feature in self.contexts_features ) - if self.sessions_items_features is None: - sessions_items_features = None + if self.contexts_items_features is None: + contexts_items_features = None else: - sessions_items_features = tuple( - sessions_items_feature[session_index] - for sessions_items_feature in self.sessions_items_features + contexts_items_features = tuple( + contexts_items_feature[choices_indexes] + for contexts_items_feature in self.contexts_items_features ) - if self.sessions_items_availabilities is None: - sessions_items_availabilities = None + if self.contexts_items_availabilities is None: + contexts_items_availabilities = np.ones((self.base_num_items)) else: - sessions_items_availabilities = self.sessions_items_availabilities[session_index] - - return df_chosen_item, dfs_available_items + contexts_items_availabilities = self.contexts_items_availabilities[choices_indexes] + + for indexes, func in self.fixed_items_features_map: + fixed_items_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = func[ + fixed_items_features[indexes[0]][:, indexes[1]] + ] + for indexes, func in self.contexts_features_map: + contexts_features[indexes[0]][indexes[1] : indexes[1] + 1] = func[ + contexts_features[indexes[0]][indexes[1]] + ] + for indexes, func in self.contexts_items_features_map: + contexts_items_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = func[ + contexts_items_features[indexes[0]][:, indexes[1]] + ] + + return ( + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choice, + ) def __getitem__(self, choices_indexes): """Method to create a sub-ChoiceDataset with only a subset of choices, from their indexes. From 101e402c4b2637bd01b72b617e28d1ee2e6e9c9d Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 11 Jan 2024 12:19:40 +0100 Subject: [PATCH 051/767] enhancing readme --- README.md | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 556f8eb4..4ab1d6e2 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ -Choice-Learn is a Python package designed to help you build with ease discrete choice models. +Choice-Learn is a Python package designed to help you build discrete choice models. The package provides ready to use datasets and different models from the litterature. It also provides a lower level use if you want to customize any model or create your own from scratch. In particular you will find smart datasets handling to limit RAM usage and different structure commons to any choice model. Choice-Learn uses NumPy and pandas as data backend engines and TensorFlow for models. @@ -32,11 +32,34 @@ This repository contains a private version of the package. ## What's in there ? +### Data +- Generic dataset handling with the ChoiceDataset class +- Ready-To-Use datasets: + - SwissMetro from Bierlaire et al. (2001) + - ModeCanada from Koppelman et al. (1993) + +### Models +- Ready to use models: + - Conditional MultiNomialLogit, Train, K.; McFadden, D.; Ben-Akiva, M. (1987) + - RUMnet, Aouad A.; Désir A. (2022) +- Ready to use models to be implemented: + - Nested MultiNomialLogit + - MultiNomialLogit with latent variables (MixedLogit) + - TasteNet + - SHOPPER + - Others ... +- Custom modelling is made easy by subclassing the ChoiceModel class + +### Different tools (to come) +- Standardization of evaluation protocols +- Assortment optimization from model +- Interfaces + ## Getting Started - Fast Track You can find the following notebooks to help you getting started with the package: - [Introduction to data management](notebooks/choice_learn_introduction_data.ipynb) -- [Introduction to modelling with the conditional logit model on ModeCanada dataaset](notebooks/choice_learn_introduction_clogit.ipynb) +- [Introduction to modelling with the conditional logit model on ModeCanada dataset](notebooks/choice_learn_introduction_clogit.ipynb) - [Introduction to custom modelling with the ModeCanada dataset](notebooks/custom_model.ipynb) ## Installation @@ -70,22 +93,8 @@ from choice_learn.models import ConditionalMNL ## Documentation -TODO: Github pages is not enabled by default, you need to enable it in the repository settings: Settings > Pages > Source: "Deploy from a branch" / Branch: "gh-pages" / Folder: "/(root)" - A detailed documentation of this project is available [here](https://artefactory.github.io/choice-learn-private/) -To serve the documentation locally, run the following command: - -```bash -mkdocs serve -``` - -To build it and deploy it to GitHub pages, run the following command: - -```bash -make deploy_docs -``` - ## Citation ### Contributors From 3155b13a80d435790d0d5129fd13cd9b4f336888 Mon Sep 17 00:00:00 2001 From: Vincent Auriau Date: Thu, 11 Jan 2024 15:12:59 +0100 Subject: [PATCH 052/767] Update README.md --- README.md | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 556f8eb4..8a614595 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ -Choice-Learn is a Python package designed to help you build with ease discrete choice models. +Choice-Learn is a Python package designed to help you build discrete choice models. The package provides ready to use datasets and different models from the litterature. It also provides a lower level use if you want to customize any model or create your own from scratch. In particular you will find smart datasets handling to limit RAM usage and different structure commons to any choice model. Choice-Learn uses NumPy and pandas as data backend engines and TensorFlow for models. @@ -32,11 +32,34 @@ This repository contains a private version of the package. ## What's in there ? +### Data +- Generic dataset handling with the ChoiceDataset class +- Ready-To-Use datasets: + - SwissMetro from Bierlaire et al. (2001) + - ModeCanada from Koppelman et al. (1993) + +### Models +- Ready to use models: + - Conditional MultiNomialLogit, Train, K.; McFadden, D.; Ben-Akiva, M. (1987) + - RUMnet, Aouad A.; Désir A. (2022) +- Ready to use models to be implemented: + - Nested MultiNomialLogit + - MultiNomialLogit with latent variables (MixedLogit) + - TasteNet + - SHOPPER + - Others ... +- Custom modelling is made easy by subclassing the ChoiceModel class + +### Different tools (to come) +- Standardization of evaluation protocols +- Assortment optimization from model +- Interfaces + ## Getting Started - Fast Track You can find the following notebooks to help you getting started with the package: - [Introduction to data management](notebooks/choice_learn_introduction_data.ipynb) -- [Introduction to modelling with the conditional logit model on ModeCanada dataaset](notebooks/choice_learn_introduction_clogit.ipynb) +- [Introduction to modelling with the conditional logit model on ModeCanada dataset](notebooks/choice_learn_introduction_clogit.ipynb) - [Introduction to custom modelling with the ModeCanada dataset](notebooks/custom_model.ipynb) ## Installation @@ -65,27 +88,13 @@ Choice-Learn requires the following: ## Usage ```python from choice_learn.data import ChoiceDataset -from choice_learn.models import ConditionalMNL +from choice_learn.models import ConditionalMNL, RUMnet ``` ## Documentation -TODO: Github pages is not enabled by default, you need to enable it in the repository settings: Settings > Pages > Source: "Deploy from a branch" / Branch: "gh-pages" / Folder: "/(root)" - A detailed documentation of this project is available [here](https://artefactory.github.io/choice-learn-private/) -To serve the documentation locally, run the following command: - -```bash -mkdocs serve -``` - -To build it and deploy it to GitHub pages, run the following command: - -```bash -make deploy_docs -``` - ## Citation ### Contributors From fb4e1ba2425801ce88b5ed41a5cfcd4b2d222732 Mon Sep 17 00:00:00 2001 From: Vincent Auriau Date: Thu, 11 Jan 2024 15:19:43 +0100 Subject: [PATCH 053/767] Update mkdocs.yaml --- mkdocs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yaml b/mkdocs.yaml index b596078d..7e6371ac 100644 --- a/mkdocs.yaml +++ b/mkdocs.yaml @@ -55,7 +55,7 @@ nav: - Introduction: how-to-guides.md - ChoiceDataset Usage: notebooks/choice_learn_introduction_data.md - Conditional Logit Estimation: notebooks/choice_learn_introduction_clogit.md - - Custom Choice Model Creation: notebooks/choice_learn_introduction_data.md + - Custom Choice Model Creation: notebooks/custom_model.md - References: - Data: - ChoiceDataset: references/data/references_choice_dataset.md From 29630ab1c5b37866c659c4dd3a259aa8d8863858 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 12 Jan 2024 14:27:19 +0100 Subject: [PATCH 054/767] ENH some doc --- README.md | 2 +- mkdocs.yaml | 3 +++ requirements-developer.txt | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4ab1d6e2..8a614595 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ Choice-Learn requires the following: ## Usage ```python from choice_learn.data import ChoiceDataset -from choice_learn.models import ConditionalMNL +from choice_learn.models import ConditionalMNL, RUMnet ``` ## Documentation diff --git a/mkdocs.yaml b/mkdocs.yaml index 8482bf83..305ba7ae 100644 --- a/mkdocs.yaml +++ b/mkdocs.yaml @@ -32,10 +32,13 @@ markdown_extensions: - pymdownx.inlinehilite - pymdownx.snippets - pymdownx.superfences + - mdx_math plugins: - mkdocstrings - search +extra_javascript: + - https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js?config=TeX-AMS-MML_HTMLorMML nav: - Home: index.md diff --git a/requirements-developer.txt b/requirements-developer.txt index 20cf8a44..1937e301 100644 --- a/requirements-developer.txt +++ b/requirements-developer.txt @@ -5,6 +5,7 @@ pytest==7.3.2 mkdocs==1.4.3 mkdocs-material==9.1.15 mkdocstrings-python==1.1.2 +python-markdown-math bandit==1.7.5 nbstripout==0.6.1 ipykernel==6.24.0 From 238773956ff6c556c87b8df7c69f541a189f4eb6 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 12 Jan 2024 18:33:21 +0100 Subject: [PATCH 055/767] FIX: detailed features with pd.DataFrame --- choice_learn/data/choice_dataset.py | 31 ++++++++++++++++++----------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index 686e1ddd..50a492f9 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -88,7 +88,7 @@ def __init__( if not isinstance(contexts_features, tuple): self._return_contexts_features_tuple = False if contexts_items_features_names is not None: - assert len(contexts_features) == len( + assert len(contexts_features[0]) == len( contexts_features_names ), "Number of features given does not match number of features names given." @@ -115,7 +115,7 @@ def __init__( self._return_contexts_items_features_tuple = False if contexts_items_features_names is not None: assert ( - len(contexts_items_features) == len(contexts_items_features_names) + len(contexts_items_features[0][0]) == len(contexts_items_features_names) ), "Number of features given does not match number of features names given for contexts_items." contexts_items_features = (contexts_items_features,) contexts_items_features_names = (contexts_items_features_names,) @@ -196,9 +196,11 @@ def __init__( if "session_id" in feature.columns: if "item_id" in feature.columns: feature_array = [] - for sess in np.sort(feature.session_id): + for sess in np.sort(feature.session_id.unique()): sess_df = feature.loc[feature.session_id == sess] - sess_df = sess_df.set_index("item_id") + sess_df = sess_df[ + sess_df.columns.difference(["sess_id"]) + ].set_index("item_id") feature_array.append(sess_df.loc[np.sort(sess_df.index)].to_numpy()) contexts_items_features = ( contexts_items_features[:i] @@ -212,12 +214,16 @@ def __init__( + (feature.loc[np.sort(feature.index)].to_numpy(),) + contexts_items_features[i + 1 :] ) + else: + raise ValueError("session_id column not found in contexts_items_features") elif isinstance(feature, list): contexts_items_features = ( contexts_items_features[:i] + (np.array(feature),) + contexts_items_features[i + 1 :] ) + print(contexts_items_features) + print(contexts_items_features[0].shape) if contexts_items_availabilities is not None: if isinstance(contexts_items_availabilities, list): contexts_items_availabilities = np.array( @@ -265,6 +271,7 @@ def __init__( self.contexts_features_names = contexts_features_names self.contexts_items_features_names = contexts_items_features_names + # What about typing ? should builf after check to change it ? self._build_features_by_ids() self.n_choices = len(self.choices) @@ -272,7 +279,7 @@ def __init__( # Different consitency checks to ensure everything is coherent self._check_dataset() # Should handle alone if np.arrays are squeezed self._return_types = self._check_types() - # self._check_names() + self._check_names() # Build .iloc method self.indexer = ChoiceDatasetIndexer(self) @@ -473,8 +480,8 @@ def _check_types(self): def _check_names(self): """Verifies that the names given to features are consistent with the features themselves.""" - if self.items_features_names is not None: - for name, features in zip(self.items_features_names, self.items_features): + if self.fixed_items_features_names is not None: + for name, features in zip(self.fixed_items_features_names, self.fixed_items_features): if name is not None: if len(name) != features.shape[1]: raise ValueError( @@ -482,8 +489,8 @@ def _check_names(self): length {len(name)} while items_features has {features.shape[1]} elements" ) - if self.sessions_features_names is not None: - for name, features in zip(self.sessions_features_names, self.sessions_features): + if self.contexts_features_names is not None: + for name, features in zip(self.contexts_features_names, self.contexts_features): if name is not None: if len(name) != features.shape[1]: raise ValueError( @@ -491,17 +498,17 @@ def _check_names(self): length {len(name)} while sessions_features has {features.shape[1]} elements" ) - if self.sessions_items_features_names is not None: + if self.contexts_items_features_names is not None: for ( name, features, - ) in zip(self.sessions_items_features_names, self.sessions_items_features): + ) in zip(self.contexts_items_features_names, self.contexts_items_features): if name is not None: if len(name) != features.shape[2]: raise ValueError( f"Specified \ sessions_items_features_names has length {len(name)} while \ - sessions_items_features has {features.shape[1]} elements" + sessions_items_features has {features.shape[2]} elements" ) def __len__(self): From 290de081ecbdd07720b6bf8c8c0c7e5b4cae027c Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 12 Jan 2024 18:49:23 +0100 Subject: [PATCH 056/767] FIX: summary df --- choice_learn/data/choice_dataset.py | 54 ++++++++++++++++++----------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index 50a492f9..cd5bb341 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -199,7 +199,7 @@ def __init__( for sess in np.sort(feature.session_id.unique()): sess_df = feature.loc[feature.session_id == sess] sess_df = sess_df[ - sess_df.columns.difference(["sess_id"]) + sess_df.columns.difference(["session_id"]) ].set_index("item_id") feature_array.append(sess_df.loc[np.sort(sess_df.index)].to_numpy()) contexts_items_features = ( @@ -207,6 +207,11 @@ def __init__( + (np.stack(feature_array, axis=0),) + contexts_items_features[i + 1 :] ) + contexts_items_features_names = ( + contexts_items_features_names[:i] + + (sess_df.columns,) + + contexts_items_features_names[i + 1 :] + ) else: feature = feature.set_index("session_id") contexts_items_features = ( @@ -214,6 +219,11 @@ def __init__( + (feature.loc[np.sort(feature.index)].to_numpy(),) + contexts_items_features[i + 1 :] ) + contexts_items_features_names = ( + contexts_items_features_names[:i] + + (feature.columns,) + + contexts_items_features_names[i + 1 :] + ) else: raise ValueError("session_id column not found in contexts_items_features") elif isinstance(feature, list): @@ -222,8 +232,6 @@ def __init__( + (np.array(feature),) + contexts_items_features[i + 1 :] ) - print(contexts_items_features) - print(contexts_items_features[0].shape) if contexts_items_availabilities is not None: if isinstance(contexts_items_availabilities, list): contexts_items_availabilities = np.array( @@ -728,39 +736,43 @@ def save(self): def summary(self): """Method to display a summary of the dataset.""" - print("Summary of the dataset:") + print("%=====================================================================%") + print("%%% Summary of the dataset:") + print("%=====================================================================%") print("Number of items:", self.get_num_items()) - print("Number of sessions:", self.get_num_sessions()) print( "Number of choices:", - self.get_num_choices(), - "Averaging", - self.get_num_choices() / self.get_num_sessions(), - "choices per session", + len(self), ) - if self.items_features is not None: - print(f"Items features: {self.items_features_names}") - if self.items_features is not None: - print(f"{sum([f.shape[1] for f in self.items_features])} items features") + if self.fixed_items_features is not None: + print(f"Fixed Items Features:") + print(f"{sum([f.shape[1] for f in self.fixed_items_features])} items features") + if self.fixed_items_features_names is not None: + print(f"with names: {self.fixed_items_features_names}") else: print("No items features registered") + print("\n") - if self.sessions_features is not None: - print(f"Sessions features: {self.sessions_features_names}") - if self.sessions_features is not None: - print(f"{sum([f.shape[1] for f in self.sessions_features])} session features") + if self.contexts_features is not None: + print(f"Sessions features:") + print(f"{sum([f.shape[1] for f in self.contexts_features])} session features") + if self.contexts_features_names is not None: + print(f"with names: {self.contexts_features_names}") else: print("No sessions features registered") + print("\n") - if self.sessions_items_features is not None: - print(f"Session Items features: {self.sessions_items_features_names}") - if self.sessions_items_features is not None: + if self.contexts_items_features is not None: + print(f"Session Items features:") print( - f"{sum([f.shape[2] for f in self.sessions_items_features])} sessions \ + f"{sum([f.shape[2] for f in self.contexts_items_features])} sessions \ items features" ) + if self.contexts_items_features_names is not None: + print(f"with names: {self.contexts_items_features_names}") else: print("No sessions items features registered") + print("%=====================================================================%") def get_choices_batch(self, choices_indexes, features=None): """Method to access data within the ListChoiceDataset from its index. From 7c2a0679528062de01c44b5f7e0aee9ce68b9654 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Sat, 13 Jan 2024 00:20:33 +0100 Subject: [PATCH 057/767] ADD: working indexer --- choice_learn/data/choice_dataset.py | 257 +++++++++++++--------------- choice_learn/data/indexer.py | 192 +++++++++++++-------- 2 files changed, 236 insertions(+), 213 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index cd5bb341..8e2660e2 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -100,7 +100,7 @@ def __init__( self._return_contexts_features_tuple = True if contexts_features_names is not None: for f, name in zip(contexts_features, contexts_features_names): - if len(f) != len(name): + if len(f[0]) != len(name): raise ValueError( "contexts_features shape and contexts_features_names shape do not match" ) @@ -123,10 +123,9 @@ def __init__( # sessions_items_features is already a tuple, names are given, checking consistency elif contexts_items_features is not None and contexts_items_features_names is not None: for f, name in zip(contexts_items_features, contexts_items_features_names): - if len(f) != len(name): + if len(f[0][0]) != len(name): raise ValueError( - "contexts_items_features shape and \ - contexts_items_features_names shape do not match" + "contexts_items_features shape and contexts_items_features_names shape do not match" ) self._return_contexts_items_features_tuple = True # In this case names are missing, still transform it as a tuple @@ -280,7 +279,11 @@ def __init__( self.contexts_items_features_names = contexts_items_features_names # What about typing ? should builf after check to change it ? - self._build_features_by_ids() + ( + self.fixed_items_features_map, + self.contexts_features_map, + self.contexts_items_features_map, + ) = self._build_features_by_ids() self.n_choices = len(self.choices) @@ -295,7 +298,7 @@ def __init__( def _build_features_by_ids(self): if len(self.features_by_ids) == 0: print("No features_by_ids given.") - return + return [], [], [] if ( self.fixed_items_features_names is None @@ -338,9 +341,7 @@ def _build_features_by_ids(self): contexts_items_features_map ) == len(self.features_by_ids), "Some features_by_ids were not matched with features_names." - self.fixed_items_features_map = fixed_items_features_map - self.contexts_features_map = contexts_features_map - self.contexts_items_features_map = contexts_items_features_map + return fixed_items_features_map, contexts_features_map, contexts_items_features_map def _check_dataset(self): """Verifies that the shapes of the different features are consistent. @@ -552,14 +553,14 @@ def get_num_choices(self): return len(self) @classmethod - def _sessions_items_features_df_to_np( + def _contexts_items_features_df_to_np( cls, df, items_index, - sessions_index, + contexts_index, features, items_id_column="item_id", - sessions_id_column="session_id", + contexts_id_column="session_id", ): """Builds sessions_items_features and sessions_items_availabilities from dataframe. @@ -590,17 +591,17 @@ def _sessions_items_features_df_to_np( except ValueError: pass - sessions_items_features = [] - sessions_items_availabilities = [] - for sess in sessions_index: - sess_df = df.loc[df[sessions_id_column] == sess] + contexts_items_features = [] + contexts_items_availabilities = [] + for sess in contexts_index: + sess_df = df.loc[df[contexts_id_column] == sess] if len(sess_df) == len(items_index): sess_df = sess_df.T sess_df.columns = sess_df.loc[items_id_column] if features is not None: - sessions_items_features.append(sess_df[items_index].loc[features].T.values) - sessions_items_availabilities.append(np.ones(len(items_index))) + contexts_items_features.append(sess_df[items_index].loc[features].T.values) + contexts_items_availabilities.append(np.ones(len(items_index))) else: sess_feats = [] sess_av = [] @@ -614,24 +615,24 @@ def _sessions_items_features_df_to_np( if features is not None: sess_feats.append(np.zeros(len(features))) sess_av.append(0) - sessions_items_features.append(sess_feats) - sessions_items_availabilities.append(sess_av) + contexts_items_features.append(sess_feats) + contexts_items_availabilities.append(sess_av) if features is not None: - sessions_items_features = (np.array(sessions_items_features),) + sessions_items_features = (np.array(contexts_items_features),) else: sessions_items_features = None - return sessions_items_features, np.array(sessions_items_availabilities) + return sessions_items_features, np.array(contexts_items_availabilities) @classmethod def from_single_df( cls, df, - items_features_columns, - sessions_features_columns, - sessions_items_features_columns, + fixed_items_features_columns, + contexts_features_columns, + contexts_items_features_columns, items_id_column="item_id", - sessions_id_column="session_id", + contexts_id_column="context_id", choices_column="choice", choice_mode="items_name", ): @@ -661,55 +662,55 @@ def from_single_df( """ # Ordering items and sessions by id items = np.sort(df[items_id_column].unique()) - sessions = np.sort(df[sessions_id_column].unique()) + sessions = np.sort(df[contexts_id_column].unique()) - if items_features_columns is not None: - items_features = df[items_features_columns + [items_id_column]].drop_duplicates() + if fixed_items_features_columns is not None: + items_features = df[fixed_items_features_columns + [items_id_column]].drop_duplicates() items_features = items_features.set_index(items_id_column) items_features = (items_features.loc[items].to_numpy(),) - items_features_columns = (items_features_columns,) + items_features_columns = (fixed_items_features_columns,) else: items_features = None - if sessions_features_columns is not None: - sessions_features = df[ - sessions_features_columns + [sessions_id_column] + if contexts_features_columns is not None: + contexts_features = df[ + contexts_features_columns + [contexts_id_column] ].drop_duplicates() - sessions_features = sessions_features.set_index(sessions_id_column) - sessions_features = (sessions_features.loc[sessions].to_numpy(),) + contexts_features = contexts_features.set_index(contexts_id_column) + contexts_features = (contexts_features.loc[sessions].to_numpy(),) - sessions_features_columns = (sessions_features_columns,) + contexts_features_columns = (contexts_features_columns,) else: - sessions_features = None + contexts_features = None ( - sessions_items_features, - sessions_items_availabilities, - ) = cls._sessions_items_features_df_to_np( + contexts_items_features, + contexts_items_availabilities, + ) = cls._contexts_items_features_df_to_np( df, items_index=items, - sessions_index=sessions, - features=sessions_items_features_columns, + contexts_index=sessions, + features=contexts_items_features_columns, items_id_column=items_id_column, - sessions_id_column=sessions_id_column, + contexts_id_column=contexts_id_column, ) - sessions_items_features_columns = ( - (sessions_items_features_columns,) - if sessions_items_features_columns is not None + contexts_items_features_columns = ( + (contexts_items_features_columns,) + if contexts_items_features_columns is not None else None ) if choice_mode == "item_id": - choices = df[[choices_column, sessions_id_column]].drop_duplicates(sessions_id_column) - choices = choices.set_index(sessions_id_column) + choices = df[[choices_column, contexts_id_column]].drop_duplicates(contexts_id_column) + choices = choices.set_index(contexts_id_column) choices = choices.loc[sessions].to_numpy() # items is the value (str) of the item choices = [np.where(items == c)[0] for c in choices] elif choice_mode == "one_zero": - choices = df[[items_id_column, choices_column, sessions_id_column]] + choices = df[[items_id_column, choices_column, contexts_id_column]] choices = choices.loc[choices[choices_column] == 1] - choices = choices = choices.set_index(sessions_id_column) + choices = choices = choices.set_index(contexts_id_column) choices = ( choices.loc[sessions][items_id_column] .map({k: v for v, k in enumerate(items)}) @@ -720,14 +721,14 @@ def from_single_df( f"choice_mode {choice_mode} not recognized. Must be in ['item_id', 'one_zero']" ) return ChoiceDataset( - items_features=items_features, - sessions_features=sessions_features, - sessions_items_features=sessions_items_features, - sessions_items_availabilities=sessions_items_availabilities, + fixed_items_features=items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, choices=choices, - items_features_names=items_features_columns, - sessions_features_names=sessions_features_columns, - sessions_items_features_names=sessions_items_features_columns, + fixed_items_features_names=items_features_columns, + contexts_features_names=contexts_features_columns, + contexts_items_features_names=contexts_items_features_columns, ) def save(self): @@ -745,7 +746,7 @@ def summary(self): len(self), ) if self.fixed_items_features is not None: - print(f"Fixed Items Features:") + print("Fixed Items Features:") print(f"{sum([f.shape[1] for f in self.fixed_items_features])} items features") if self.fixed_items_features_names is not None: print(f"with names: {self.fixed_items_features_names}") @@ -754,7 +755,7 @@ def summary(self): print("\n") if self.contexts_features is not None: - print(f"Sessions features:") + print("Sessions features:") print(f"{sum([f.shape[1] for f in self.contexts_features])} session features") if self.contexts_features_names is not None: print(f"with names: {self.contexts_features_names}") @@ -763,7 +764,7 @@ def summary(self): print("\n") if self.contexts_items_features is not None: - print(f"Session Items features:") + print("Session Items features:") print( f"{sum([f.shape[2] for f in self.contexts_items_features])} sessions \ items features" @@ -790,11 +791,10 @@ def get_choices_batch(self, choices_indexes, features=None): """ if isinstance(choices_indexes, list): - print(choices_indexes) if self.fixed_items_features is None: fixed_items_features = None else: - fixed_items_features = tuple( + fixed_items_features = list( items_feature # .astype(self._return_types[0][i]) for i, items_feature in enumerate(self.fixed_items_features) @@ -803,7 +803,7 @@ def get_choices_batch(self, choices_indexes, features=None): if self.contexts_features is None: contexts_features = None else: - contexts_features = tuple( + contexts_features = list( contexts_features[choices_indexes] # .astype(self._return_types[1][i]) for i, contexts_features in enumerate(self.contexts_features) @@ -814,7 +814,7 @@ def get_choices_batch(self, choices_indexes, features=None): if self.contexts_items_features is None: contexts_items_features = None else: - contexts_items_features = tuple( + contexts_items_features = list( contexts_items_feature[choices_indexes] # .astype(self._return_types[2][i]) for i, contexts_items_feature in enumerate(self.contexts_items_features) @@ -829,26 +829,53 @@ def get_choices_batch(self, choices_indexes, features=None): choices = self.choices[choices_indexes].astype(self._return_types[4]) for indexes, func in self.fixed_items_features_map: - fixed_items_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = func[ - fixed_items_features[indexes[0]][:, indexes[1]] - ] + fixed_items_features[indexes[0]] = np.concatenate( + [ + fixed_items_features[indexes[0]][:, : indexes[1]], + func[fixed_items_features[indexes[0]][:, indexes[1]]], + fixed_items_features[indexes[0]][:, indexes[1] + 1 :], + ], + axis=1, + ) for indexes, func in self.contexts_features_map: - contexts_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = func[ - contexts_features[indexes[0]][:, indexes[1]] - ] + contexts_features[indexes[0]] = np.concatenate( + [ + contexts_features[indexes[0]][:, : indexes[1]], + func[contexts_features[indexes[0]][:, indexes[1]]], + contexts_features[indexes[0]][:, indexes[1] + 1 :], + ], + axis=1, + ) for indexes, func in self.contexts_items_features_map: contexts_items_features[indexes[0]][:, :, indexes[1] : indexes[1] + 1] = func[ contexts_items_features[indexes[0]][:, :, indexes[1]] ] + contexts_items_features[indexes[0]] = np.concatenate( + [ + contexts_items_features[indexes[0]][:, :, : indexes[1]], + func[contexts_items_features[indexes[0]][:, :, indexes[1]]], + contexts_items_features[indexes[0]][:, :, indexes[1] + 1 :], + ], + axis=2, + ) # items_features were not given as a tuple, so we return do not return it as a tuple - if not self._return_items_features_tuple: + if self._return_items_features_tuple and self.fixed_items_features is not None: + fixed_items_features = tuple(fixed_items_features) + elif self.fixed_items_features is not None: fixed_items_features = fixed_items_features[0] - if not self._return_contexts_features_tuple: + if self._return_contexts_features_tuple and self.contexts_features is not None: + contexts_features = tuple(contexts_features) + elif self.contexts_features is not None: contexts_features = contexts_features[0] # sessions_items_features were not given as a tuple, so we return do not return # it as a tuple - if not self._return_contexts_items_features_tuple: + if ( + self._return_contexts_items_features_tuple + and self.contexts_items_features is not None + ): + contexts_items_features = tuple(contexts_items_features) + elif self.contexts_items_features is not None: contexts_items_features = contexts_items_features[0] return ( @@ -929,73 +956,29 @@ def __getitem__(self, choices_indexes): ChoiceDataset ChoiceDataset with only the sessions indexed by indexes """ - if isinstance(session_indexes, int): - session_indexes = [session_indexes] - elif isinstance(session_indexes, slice): - return self.__getitem__(list(range(*session_indexes.indices(len(self.ragged_choices))))) + if isinstance(choices_indexes, int): + choices_indexes = [choices_indexes] + elif isinstance(choices_indexes, slice): + return self.__getitem__(list(range(*choices_indexes.indices(len(self.choices))))) return ChoiceDataset( - items_features=self.items_features, - sessions_features=tuple( - self.sessions_features[i][session_indexes] - for i in range(len(self.sessions_features)) + fixed_items_features=self.fixed_items_features, + contexts_features=tuple( + self.contexts_features[i][choices_indexes] + for i in range(len(self.contexts_features)) ), - sessions_items_features=tuple( - self.sessions_items_features[i][session_indexes] - for i in range(len(self.sessions_items_features)) + contexts_items_features=tuple( + self.contexts_items_features[i][choices_indexes] + for i in range(len(self.contexts_items_features)) ), - sessions_items_availabilities=self.sessions_items_availabilities[session_indexes], - choices=[self.ragged_choices[i] for i in session_indexes], - items_features_names=self.items_features_names, - sessions_features_names=self.sessions_features_names, - sessions_items_features_names=self.sessions_items_features_names, + contexts_items_availabilities=self.contexts_items_availabilities[choices_indexes], + choices=[self.choices[i] for i in choices_indexes], + fixed_items_features_names=self.fixed_items_features_names, + contexts_features_names=self.contexts_features_names, + contexts_items_features_names=self.contexts_items_features_names, + features_by_ids=self.features_by_ids, ) - def old_batch(self, batch_size, shuffle=None, sample_weight=None): - """Iterates over dataset return batches of length batch_size. - - Parameters - ---------- - batch_size : int - batch size to set - shuffle: bool - Whether or not to shuffle the dataset - sample_weight : Iterable - list of weights to be returned with the right indexing during the shuffling - """ - - if shuffle is None: - shuffle = self.shuffle - if batch_size == -1: - batch_size = self.get_num_choices() - - # Get indexes for each choice - num_choices = self.get_num_choices() - indexes = np.arange(num_choices) - # Shuffle indexes - if shuffle and not batch_size == -1: - indexes = np.random.permutation(indexes) - - yielded_size = 0 - while yielded_size < num_choices: - # Return sample_weight if not None, for index matching - if sample_weight is not None: - yield ( - self.get_choice_batch( - indexes[yielded_size : yielded_size + batch_size].tolist() - ), - sample_weight[indexes[yielded_size : yielded_size + batch_size].tolist()], - ) - else: - yield self.get_choice_batch( - indexes[yielded_size : yielded_size + batch_size].tolist() - ) - yielded_size += batch_size - - # Special exit strategy for batch_size = -1 - if batch_size == -1: - yielded_size += 2 * num_choices - @property def batch(self): """Indexer.""" @@ -1015,14 +998,12 @@ def iter_batch(self, batch_size, shuffle=None, sample_weight=None): sample_weight : Iterable list of weights to be returned with the right indexing during the shuffling """ - if shuffle is None: shuffle = self.shuffle if batch_size == -1: - batch_size = self.get_num_choices() - + batch_size = len(self) # Get indexes for each choice - num_choices = self.get_num_choices() + num_choices = len(self) indexes = np.arange(num_choices) # Shuffle indexes if shuffle and not batch_size == -1: diff --git a/choice_learn/data/indexer.py b/choice_learn/data/indexer.py index 2c8568b1..723ec7d0 100644 --- a/choice_learn/data/indexer.py +++ b/choice_learn/data/indexer.py @@ -154,7 +154,7 @@ def __init__(self, choice_dataset): """ self.choice_dataset = choice_dataset - def _get_items_features(self): + def _get_fixed_items_features(self): """Method to access items features of the ChoiceDataset. Returns: @@ -162,20 +162,20 @@ def _get_items_features(self): tuple of np.ndarray or np.ndarray items_features of the ChoiceDataset """ - if self.choice_dataset.items_features is None: + if self.choice_dataset.fixed_items_features is None: items_features = None else: items_features = tuple( items_feature.astype(self.choice_dataset._return_types[0][i]) - for i, items_feature in enumerate(self.choice_dataset.items_features) + for i, items_feature in enumerate(self.choice_dataset.fixed_items_features) ) # items_features were not given as a tuple, so we return do not return it as a tuple - if not self.choice_dataset._return_items_features_tuple: - items_features = items_features[0] + # if not self.choice_dataset._return_items_features_tuple: + # items_features = items_features[0] return items_features - def _get_sessions_features(self, sessions_indexes): + def _get_contexts_features(self, contexts_indexes): """Method to access sessions features of the ChoiceDataset. Parameters @@ -188,31 +188,31 @@ def _get_sessions_features(self, sessions_indexes): tuple of np.ndarray or np.ndarray items_features of the ChoiceDataset """ - if self.choice_dataset.sessions_features is None: - sessions_features = None + if self.choice_dataset.contexts_features is None: + contexts_features = None else: - sessions_features = [] - for i, sessions_feature in enumerate(self.choice_dataset.sessions_features): - if hasattr(sessions_feature, "iloc"): - sessions_features.append( - sessions_feature.iloc[sessions_indexes].astype( + contexts_features = [] + for i, contexts_feature in enumerate(self.choice_dataset.contexts_features): + if hasattr(contexts_feature, "batch"): + contexts_features.append( + contexts_feature.batch[contexts_indexes].astype( self.choice_dataset._return_types[1][i] ) ) else: - sessions_features.append( - np.stack(sessions_feature[sessions_indexes], axis=0).astype( + contexts_features.append( + np.stack(contexts_feature[contexts_indexes], axis=0).astype( self.choice_dataset._return_types[1][i] ) ) # sessions_features were not given as a tuple, so we return do not return it as a tuple - if not self.choice_dataset._return_sessions_features_tuple: - sessions_features = sessions_features[0] - else: - sessions_features = tuple(sessions_features) - return sessions_features + # if not self.choice_dataset._return_contexts_features_tuple: + # contexts_features = contexts_feature[0] + # else: + # contexts_features = tuple(contexts_features) + return contexts_features - def _get_sessions_items_features(self, sessions_indexes): + def _get_contexts_items_features(self, contexts_indexes): """Method to access sessions items features of the ChoiceDataset. Parameters @@ -225,28 +225,28 @@ def _get_sessions_items_features(self, sessions_indexes): tuple of np.ndarray or np.ndarray items_features of the ChoiceDataset """ - if self.choice_dataset.sessions_items_features is None: + if self.choice_dataset.contexts_items_features is None: return None - sessions_items_features = [] - for i, sessions_items_feature in enumerate(self.choice_dataset.sessions_items_features): - if hasattr(sessions_items_feature, "iloc"): - sessions_items_features.append( - sessions_items_feature.iloc[sessions_indexes].astype(self._return_types[2][i]) + contexts_items_features = [] + for i, contexts_items_feature in enumerate(self.choice_dataset.contexts_items_features): + if hasattr(contexts_items_feature, "iloc"): + contexts_items_features.append( + contexts_items_feature.iloc[contexts_indexes].astype(self._return_types[2][i]) ) else: - sessions_items_features.append( - np.stack(sessions_items_feature[sessions_indexes], axis=0).astype( + contexts_items_features.append( + np.stack(contexts_items_feature[contexts_indexes], axis=0).astype( self.choice_dataset._return_types[2][i] ) ) # sessions_items_features were not given as a tuple, thus we do not return it as a tuple - if self.choice_dataset._return_sessions_items_features_tuple: - sessions_items_features = tuple(sessions_items_features) - else: - sessions_items_features = sessions_items_features[0] - return sessions_items_features + # if self.choice_dataset._return_contexts_items_features_tuple: + # contexts_items_features = tuple(contexts_items_features) + # else: + # contexts_items_features = contexts_items_features[0] + return contexts_items_features - def __getitem__(self, choice_index): + def __getitem__(self, choices_indexes): """Method to access data within the ChoiceDataset from its index. One index corresponds to a choice within a session. @@ -263,80 +263,122 @@ def __getitem__(self, choice_index): indexes of the choices (that will be mapped to choice & session indexes) to return """ - if isinstance(choice_index, list): - items_features = self._get_items_features() - # Get the session indexes - sessions_indexes = [self.choice_dataset.indexes[i] for i in choice_index] + if isinstance(choices_indexes, list): + fixed_items_features = self._get_fixed_items_features() - sessions_features = self._get_sessions_features(sessions_indexes) - sessions_items_features = self._get_sessions_items_features(sessions_indexes) + # Get the session indexes + contexts_features = self._get_contexts_features(choices_indexes) + contexts_items_features = self._get_contexts_items_features(choices_indexes) - if self.choice_dataset.sessions_items_availabilities is None: - sessions_items_availabilities = None + if self.choice_dataset.contexts_items_availabilities is None: + contexts_items_availabilities = None else: - if hasattr(self.choice_dataset.sessions_items_availabilities, "iloc"): - sessions_items_availabilities = ( - self.choice_dataset.sessions_items_availabilities.iloc[ - sessions_indexes + if hasattr(self.choice_dataset.contexts_items_availabilities, "batch"): + contexts_items_availabilities = ( + self.choice_dataset.contexts_items_availabilities.batch[ + choices_indexes ].astype(self.choice_dataset._return_types[3]) ) else: - sessions_items_availabilities = ( - self.choice_dataset.sessions_items_availabilities[sessions_indexes].astype( + contexts_items_availabilities = ( + self.choice_dataset.contexts_items_availabilities[choices_indexes].astype( self.choice_dataset._return_types[3] ) ) - choice = self.choice_dataset.choices[choice_index].astype( + for indexes, func in self.choice_dataset.fixed_items_features_map: + fixed_items_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = func[ + fixed_items_features[indexes[0]][:, indexes[1]] + ] + for indexes, func in self.choice_dataset.contexts_features_map: + contexts_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = func[ + contexts_features[indexes[0]][:, indexes[1]] + ] + for indexes, func in self.choice_dataset.contexts_items_features_map: + contexts_items_features[indexes[0]][:, :, indexes[1] : indexes[1] + 1] = func[ + contexts_items_features[indexes[0]][:, :, indexes[1]] + ] + # items_features were not given as a tuple, so we return do not return it as a tuple + if not self.choice_dataset._return_items_features_tuple: + fixed_items_features = fixed_items_features[0] + if not self.choice_dataset._return_contexts_features_tuple: + contexts_features = contexts_features[0] + # sessions_items_features were not given as a tuple, so we return do not return + # it as a tuple + if not self.choice_dataset._return_contexts_items_features_tuple: + contexts_items_features = contexts_items_features[0] + + choices = self.choice_dataset.choices[choices_indexes].astype( self.choice_dataset._return_types[4] ) return ( - items_features, - sessions_features, - sessions_items_features, - sessions_items_availabilities, - choice, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, ) - if isinstance(choice_index, slice): + if isinstance(choices_indexes, slice): return self.__getitem__( - list(range(*choice_index.indices(self.choice_dataset.choices.shape[0]))) + list(range(*choices_indexes.indices(self.choice_dataset.choices.shape[0]))) ) - if isinstance(choice_index, int): - items_features = self._get_items_features() + if isinstance(choices_indexes, int): + fixed_items_features = self._get_fixed_items_features() # Get the session indexes - sessions_indexes = self.choice_dataset.indexes[choice_index] - sessions_features = self._get_sessions_features(sessions_indexes) - sessions_items_features = self._get_sessions_items_features(sessions_indexes) + contexts_features = self._get_contexts_features(choices_indexes) + contexts_items_features = self._get_contexts_items_features(choices_indexes) - if self.choice_dataset.sessions_items_availabilities is None: - sessions_items_availabilities = None + if self.choice_dataset.contexts_items_availabilities is None: + contexts_items_availabilities = None else: - if hasattr(self.choice_dataset.sessions_items_availabilities, "iloc"): - sessions_items_availabilities = ( - self.choice_dataset.sessions_items_availabilities.iloc[ - sessions_indexes + if hasattr(self.choice_dataset.contexts_items_availabilities, "batch"): + contexts_items_availabilities = ( + self.choice_dataset.contexts_items_availabilities.iloc[ + choices_indexes ].astype(self.choice_dataset._return_types[3]) ) else: - sessions_items_availabilities = ( - self.choice_dataset.sessions_items_availabilities[sessions_indexes].astype( + contexts_items_availabilities = ( + self.choice_dataset.contexts_items_availabilities[choices_indexes].astype( self.choice_dataset._return_types[3] ) ) + for indexes, func in self.choice_dataset.fixed_items_features_map: + fixed_items_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = func[ + fixed_items_features[indexes[0]][:, indexes[1]] + ] + for indexes, func in self.choice_dataset.contexts_features_map: + contexts_features[indexes[0]][indexes[1] : indexes[1] + 1] = func[ + contexts_features[indexes[0]][indexes[1]] + ] + for indexes, func in self.choice_dataset.contexts_items_features_map: + contexts_items_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = func[ + contexts_items_features[indexes[0]][:, indexes[1]] + ] - choice = self.choice_dataset.choices[choice_index].astype( + # items_features were not given as a tuple, so we return do not return it as a tuple + if not self.choice_dataset._return_items_features_tuple: + fixed_items_features = fixed_items_features[0] + if not self.choice_dataset._return_contexts_features_tuple: + contexts_features = contexts_features[0] + # sessions_items_features were not given as a tuple, so we return do not return + # it as a tuple + if not self.choice_dataset._return_contexts_items_features_tuple: + contexts_items_features = contexts_items_features[0] + + choice = self.choice_dataset.choices[choices_indexes].astype( self.choice_dataset._return_types[4] ) return ( - items_features, - sessions_features, - sessions_items_features, - sessions_items_availabilities, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, choice, ) raise NotImplementedError From ab508b37148d321b500e3f3971d827b8c998f649 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Sat, 13 Jan 2024 19:57:31 +0100 Subject: [PATCH 058/767] ADD: fully functional new signature --- choice_learn/data/choice_dataset.py | 95 +++++++++++++++---------- choice_learn/data/indexer.py | 103 +++++++++++++++++++--------- choice_learn/data/storage.py | 23 +++++-- 3 files changed, 145 insertions(+), 76 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index 8e2660e2..a98577b6 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -4,7 +4,6 @@ import pandas as pd from choice_learn.data.indexer import ChoiceDatasetIndexer -from choice_learn.data.store import Store class ChoiceDataset(object): @@ -319,7 +318,7 @@ def _build_features_by_ids(self): for j, column_name in enumerate(feature): for feature_by_id in self.features_by_ids: if column_name == feature_by_id.name: - fixed_items_features_map.append(((i, j), feature_by_id.batch)) + fixed_items_features_map.append(((i, j), feature_by_id)) if self.contexts_features_names is not None: for i, feature in enumerate(self.contexts_features_names): @@ -327,7 +326,7 @@ def _build_features_by_ids(self): for j, column_name in enumerate(feature): for feature_by_id in self.features_by_ids: if column_name == feature_by_id.name: - contexts_features_map.append(((i, j), feature_by_id.batch)) + contexts_features_map.append(((i, j), feature_by_id)) if self.contexts_items_features_names is not None: for i, feature in enumerate(self.contexts_items_features_names): @@ -335,7 +334,7 @@ def _build_features_by_ids(self): for k, column_name in enumerate(feature): for feature_by_id in self.features_by_ids: if column_name == feature_by_id.name: - contexts_items_features_map.append(((i, j), feature_by_id.batch)) + contexts_items_features_map.append(((i, j), feature_by_id)) assert len(fixed_items_features_map) + len(contexts_features_map) + len( contexts_items_features_map @@ -463,6 +462,10 @@ def _check_types(self): item_types.append(np.int32) else: item_types.append(np.float32) + + for indexes, f_by_id in self.fixed_items_features_map: + sample_dtype = f_by_id.get_storage_types() + item_types[indexes[0]] = sample_dtype return_types.append(tuple(item_types)) session_types = [] @@ -472,6 +475,9 @@ def _check_types(self): session_types.append(np.int32) else: session_types.append(np.float32) + for indexes, f_by_id in self.contexts_features_map: + sample_dtype = f_by_id.get_storage_type() + session_types[indexes[0]] = sample_dtype return_types.append(tuple(session_types)) session_item_types = [] @@ -481,6 +487,9 @@ def _check_types(self): session_item_types.append(np.int32) else: session_item_types.append(np.float32) + for indexes, f_by_id in self.contexts_items_features_map: + sample_dtype = f_by_id.get_storage_types() + session_item_types[indexes[0]] = sample_dtype return_types.append(tuple(session_item_types)) return_types.append(np.float32) return_types.append(np.int32) @@ -828,55 +837,67 @@ def get_choices_batch(self, choices_indexes, features=None): choices = self.choices[choices_indexes].astype(self._return_types[4]) - for indexes, func in self.fixed_items_features_map: + for indexes, f_by_id in self.fixed_items_features_map: fixed_items_features[indexes[0]] = np.concatenate( [ fixed_items_features[indexes[0]][:, : indexes[1]], - func[fixed_items_features[indexes[0]][:, indexes[1]]], + f_by_id.batch[fixed_items_features[indexes[0]][:, indexes[1]]], fixed_items_features[indexes[0]][:, indexes[1] + 1 :], ], axis=1, ) - for indexes, func in self.contexts_features_map: + for indexes, f_by_id in self.contexts_features_map: contexts_features[indexes[0]] = np.concatenate( [ contexts_features[indexes[0]][:, : indexes[1]], - func[contexts_features[indexes[0]][:, indexes[1]]], + f_by_id.batch[contexts_features[indexes[0]][:, indexes[1]]], contexts_features[indexes[0]][:, indexes[1] + 1 :], ], axis=1, ) - for indexes, func in self.contexts_items_features_map: - contexts_items_features[indexes[0]][:, :, indexes[1] : indexes[1] + 1] = func[ - contexts_items_features[indexes[0]][:, :, indexes[1]] - ] + for indexes, f_by_id in self.contexts_items_features_map: + contexts_items_features[indexes[0]][ + :, :, indexes[1] : indexes[1] + 1 + ] = f_by_id.batch[contexts_items_features[indexes[0]][:, :, indexes[1]]] contexts_items_features[indexes[0]] = np.concatenate( [ contexts_items_features[indexes[0]][:, :, : indexes[1]], - func[contexts_items_features[indexes[0]][:, :, indexes[1]]], + f_by_id.batch[contexts_items_features[indexes[0]][:, :, indexes[1]]], contexts_items_features[indexes[0]][:, :, indexes[1] + 1 :], ], axis=2, ) - # items_features were not given as a tuple, so we return do not return it as a tuple - if self._return_items_features_tuple and self.fixed_items_features is not None: - fixed_items_features = tuple(fixed_items_features) - elif self.fixed_items_features is not None: - fixed_items_features = fixed_items_features[0] - if self._return_contexts_features_tuple and self.contexts_features is not None: - contexts_features = tuple(contexts_features) - elif self.contexts_features is not None: - contexts_features = contexts_features[0] - # sessions_items_features were not given as a tuple, so we return do not return - # it as a tuple - if ( - self._return_contexts_items_features_tuple - and self.contexts_items_features is not None - ): - contexts_items_features = tuple(contexts_items_features) - elif self.contexts_items_features is not None: - contexts_items_features = contexts_items_features[0] + if fixed_items_features is not None: + for i in range(len(fixed_items_features)): + fixed_items_features[i] = fixed_items_features[i].astype( + self._return_types[0][i] + ) + # items_features were not given as a tuple, so we return do not return it as a tuple + if not self._return_items_features_tuple: + fixed_items_features = fixed_items_features[0] + else: + fixed_items_features = tuple(fixed_items_features) + + if contexts_features is not None: + for i in range(len(contexts_features)): + contexts_features[i] = contexts_features[i].astype(self._return_types[1][i]) + if not self._return_contexts_features_tuple: + contexts_features = contexts_features[0] + else: + contexts_features = tuple(contexts_features) + + if contexts_items_features is not None: + for i in range(len(contexts_items_features)): + contexts_items_features[i] = contexts_items_features[i].astype( + self._return_types[2][i] + ) + # sessions_items_features were not given as a tuple, so we return do not return + # it as a tuple + if not self._return_contexts_items_features_tuple: + contexts_items_features = contexts_items_features[0] + else: + contexts_items_features = tuple(contexts_items_features) return ( fixed_items_features, @@ -922,16 +943,16 @@ def get_choices_batch(self, choices_indexes, features=None): else: contexts_items_availabilities = self.contexts_items_availabilities[choices_indexes] - for indexes, func in self.fixed_items_features_map: - fixed_items_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = func[ + for indexes, f_by_id in self.fixed_items_features_map: + fixed_items_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = f_by_id.batch[ fixed_items_features[indexes[0]][:, indexes[1]] ] - for indexes, func in self.contexts_features_map: - contexts_features[indexes[0]][indexes[1] : indexes[1] + 1] = func[ + for indexes, f_by_id in self.contexts_features_map: + contexts_features[indexes[0]][indexes[1] : indexes[1] + 1] = f_by_id.batch[ contexts_features[indexes[0]][indexes[1]] ] - for indexes, func in self.contexts_items_features_map: - contexts_items_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = func[ + for indexes, f_by_id in self.contexts_items_features_map: + contexts_items_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = f_by_id.batch[ contexts_items_features[indexes[0]][:, indexes[1]] ] diff --git a/choice_learn/data/indexer.py b/choice_learn/data/indexer.py index 723ec7d0..8a1cca28 100644 --- a/choice_learn/data/indexer.py +++ b/choice_learn/data/indexer.py @@ -165,7 +165,7 @@ def _get_fixed_items_features(self): if self.choice_dataset.fixed_items_features is None: items_features = None else: - items_features = tuple( + items_features = list( items_feature.astype(self.choice_dataset._return_types[0][i]) for i, items_feature in enumerate(self.choice_dataset.fixed_items_features) ) @@ -200,11 +200,7 @@ def _get_contexts_features(self, contexts_indexes): ) ) else: - contexts_features.append( - np.stack(contexts_feature[contexts_indexes], axis=0).astype( - self.choice_dataset._return_types[1][i] - ) - ) + contexts_features.append(np.stack(contexts_feature[contexts_indexes], axis=0)) # sessions_features were not given as a tuple, so we return do not return it as a tuple # if not self.choice_dataset._return_contexts_features_tuple: # contexts_features = contexts_feature[0] @@ -286,27 +282,68 @@ def __getitem__(self, choices_indexes): ) ) - for indexes, func in self.choice_dataset.fixed_items_features_map: - fixed_items_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = func[ - fixed_items_features[indexes[0]][:, indexes[1]] - ] - for indexes, func in self.choice_dataset.contexts_features_map: - contexts_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = func[ - contexts_features[indexes[0]][:, indexes[1]] - ] - for indexes, func in self.choice_dataset.contexts_items_features_map: - contexts_items_features[indexes[0]][:, :, indexes[1] : indexes[1] + 1] = func[ - contexts_items_features[indexes[0]][:, :, indexes[1]] - ] - # items_features were not given as a tuple, so we return do not return it as a tuple - if not self.choice_dataset._return_items_features_tuple: - fixed_items_features = fixed_items_features[0] - if not self.choice_dataset._return_contexts_features_tuple: - contexts_features = contexts_features[0] - # sessions_items_features were not given as a tuple, so we return do not return - # it as a tuple - if not self.choice_dataset._return_contexts_items_features_tuple: - contexts_items_features = contexts_items_features[0] + for indexes, f_by_id in self.choice_dataset.fixed_items_features_map: + fixed_items_features[indexes[0]] = np.concatenate( + [ + fixed_items_features[indexes[0]][:, : indexes[1]], + f_by_id.batch[fixed_items_features[indexes[0]][:, indexes[1]]], + fixed_items_features[indexes[0]][:, indexes[1] + 1 :], + ], + axis=1, + ) + for indexes, f_by_id in self.choice_dataset.contexts_features_map: + contexts_features[indexes[0]] = np.concatenate( + [ + contexts_features[indexes[0]][:, : indexes[1]], + f_by_id.batch[contexts_features[indexes[0]][:, indexes[1]]], + contexts_features[indexes[0]][:, indexes[1] + 1 :], + ], + axis=1, + ) + for indexes, f_by_id in self.choice_dataset.contexts_items_features_map: + contexts_items_features[indexes[0]][ + :, :, indexes[1] : indexes[1] + 1 + ] = f_by_id.batch[contexts_items_features[indexes[0]][:, :, indexes[1]]] + contexts_items_features[indexes[0]] = np.concatenate( + [ + contexts_items_features[indexes[0]][:, :, : indexes[1]], + f_by_id.batch[contexts_items_features[indexes[0]][:, :, indexes[1]]], + contexts_items_features[indexes[0]][:, :, indexes[1] + 1 :], + ], + axis=2, + ) + if fixed_items_features is not None: + for i in range(len(fixed_items_features)): + fixed_items_features[i] = fixed_items_features[i].astype( + self.choice_dataset._return_types[0][i] + ) + # items_features were not given as a tuple, so we return do not return it as a tuple + if not self.choice_dataset._return_items_features_tuple: + fixed_items_features = fixed_items_features[0] + else: + fixed_items_features = tuple(fixed_items_features) + + if contexts_features is not None: + for i in range(len(contexts_features)): + contexts_features[i] = contexts_features[i].astype( + self.choice_dataset._return_types[1][i] + ) + if not self.choice_dataset._return_contexts_features_tuple: + contexts_features = contexts_features[0] + else: + contexts_features = tuple(contexts_features) + + if contexts_items_features is not None: + for i in range(len(contexts_items_features)): + contexts_items_features[i] = contexts_items_features[i].astype( + self.choice_dataset._return_types[2][i] + ) + # sessions_items_features were not given as a tuple, so we return do not return + # it as a tuple + if not self.choice_dataset._return_contexts_items_features_tuple: + contexts_items_features = contexts_items_features[0] + else: + contexts_items_features = tuple(contexts_items_features) choices = self.choice_dataset.choices[choices_indexes].astype( self.choice_dataset._return_types[4] @@ -347,16 +384,16 @@ def __getitem__(self, choices_indexes): self.choice_dataset._return_types[3] ) ) - for indexes, func in self.choice_dataset.fixed_items_features_map: - fixed_items_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = func[ + for indexes, f_by_id in self.choice_dataset.fixed_items_features_map: + fixed_items_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = f_by_id.batch[ fixed_items_features[indexes[0]][:, indexes[1]] ] - for indexes, func in self.choice_dataset.contexts_features_map: - contexts_features[indexes[0]][indexes[1] : indexes[1] + 1] = func[ + for indexes, f_by_id in self.choice_dataset.contexts_features_map: + contexts_features[indexes[0]][indexes[1] : indexes[1] + 1] = f_by_id.batch[ contexts_features[indexes[0]][indexes[1]] ] - for indexes, func in self.choice_dataset.contexts_items_features_map: - contexts_items_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = func[ + for indexes, f_by_id in self.choice_dataset.contexts_items_features_map: + contexts_items_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = f_by_id.batch[ contexts_items_features[indexes[0]][:, indexes[1]] ] diff --git a/choice_learn/data/storage.py b/choice_learn/data/storage.py index a96167aa..992a3e62 100644 --- a/choice_learn/data/storage.py +++ b/choice_learn/data/storage.py @@ -51,6 +51,8 @@ def __init__(self, ids=None, values=None, values_names=None, name=None, indexer= assert isinstance(v, np.ndarray) | isinstance(v, list) assert len(np.array(v).shape) == 1 lengths.append(len(v)) + if isinstance(v, list): + storage[k] = np.array(v) assert len(set(lengths)) == 1 elif isinstance(values, pd.DataFrame): @@ -63,7 +65,7 @@ def __init__(self, ids=None, values=None, values_names=None, name=None, indexer= elif isinstance(values, list) or isinstance(values, np.ndarray): if ids is None: ids = list(range(len(values))) - storage = {k: v for (k, v) in zip(ids, values)} + storage = {k: np.array(v) for (k, v) in zip(ids, values)} else: raise ValueError("values must be a dict, a DataFrame, a list or a numpy array") @@ -74,7 +76,7 @@ def __init__(self, ids=None, values=None, values_names=None, name=None, indexer= self.shape = (len(self), len(next(iter(self.storage.values())))) self.indexer = indexer(self) - def _get_store_element(self, index): + def get_element_from_index(self, index): """Getter method over self.sequence. Returns the features stored at index index. Compared to __getitem__, it does take @@ -90,10 +92,8 @@ def _get_store_element(self, index): array_like features corresponding to the index index in self.store """ - if isinstance(index, list): - return [self.store[i] for i in index] - # else: - return self.store[index] + keys = list(self.storage.keys())[index] + return self.storage[keys] def __len__(self): """Returns the length of the sequence of apparition of the features.""" @@ -110,6 +110,17 @@ def __getitem__(self, keys): sub_storage = {k: self.storage[k] for k in keys} return FeaturesStorage(values=sub_storage, values_names=self.values_names, name=self.name) + def get_storage_type(self): + """Functions to access stored elements dtypes. + + Returns: + -------- + tuple + tuple of dtypes of the stored elements, as returned by np.dtype + """ + element = self.get_element_from_index(0) + return element.dtype + @property def batch(self): """Indexing attribute.""" From 4a233983d0a4f663e03a7856fe382a0090bb2e01 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Sat, 13 Jan 2024 21:48:28 +0100 Subject: [PATCH 059/767] DOC: redocumented --- choice_learn/data/choice_dataset.py | 152 +++++++++++++++------- choice_learn/data/indexer.py | 112 ++++++++++------ choice_learn/data/storage.py | 193 +++++++++++++++++++++++++--- 3 files changed, 356 insertions(+), 101 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index a98577b6..a261103a 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -26,9 +26,9 @@ def __init__( choices, # Should not have None as default value ? fixed_items_features=None, contexts_features=None, # as many context as choices. values or ids (look at key) - contexts_items_features=None, # MUST INCLUDE item_id column; possible: column "available" binary + contexts_items_features=None, contexts_items_availabilities=None, - features_by_ids=[], # list of (name, FeaturesStorage) --> requires to have df with col "_id" + features_by_ids=[], # list of (name, FeaturesStorage) fixed_items_features_names=None, contexts_features_names=None, contexts_items_features_names=None, @@ -37,16 +37,33 @@ def __init__( Parameters ---------- - items_features : tuple of (array_like, ) + choices: list or np.ndarray + list of chosen items indexes + fixed_items_features : tuple of (array_like, ) matrix of shape (num_items, num_items_features) containing the features of the items - e.g. item color - choices: list of list - for each choice we have a list of related choices. Main list has same legnth as - session_features. - suffle: bool, optional - whether to shuffle the dataset or not + that never change, e.g. item color, default is None + contexts_features : tuple of (array_like, ) + matrix of shape (num_choices, num_contexts_features) containing the features of the + different contexts that are common to all items (e.g. store features, + customer features, etc...) + contexts_items_features : tuple of (array_like, ), default is None + matrix of shape (num_choices, num_items, num_contexts_items_features) + containing the features + of the items that change over time (e.g. price, promotion, etc...), default is None + contexts_items_availabilities : array_like + matrix of shape (num_choices, num_items) containing the availabilities of the items + over the different choices, default is None + features_by_ids : list of (name, FeaturesStorage) + List of Storage objects. Their name must correspond to a feature name + among fixed_items, contexts, + contexts_items and their ids must match to those features values. Default is [] + fixed_items_features_names : tuple of (array_like, ) + list of names of the fixed_items_features, default is None + contexts_features_names : tuple of (array_like, ) + list of names of the contexts_features, default is None + contexts_items_features_names : tuple of (array_like, ) + list of names of the contexts_items_features, default is None """ - if choices is None: # Done to keep a logical order of arguments, and has logic: choices have to be specified raise ValueError("Choices must be specified, got None") @@ -58,9 +75,11 @@ def __init__( if fixed_items_features is not None: if not isinstance(fixed_items_features, tuple): if fixed_items_features_names is not None: - assert len(fixed_items_features) == len( - fixed_items_features_names - ), "Number of features given does not match number of features names given." + if len(fixed_items_features) == len(fixed_items_features_names): + raise ValueError( + """Number of features given does not match number + of features names given.""" + ) self._return_items_features_tuple = False fixed_items_features = (fixed_items_features,) @@ -87,9 +106,11 @@ def __init__( if not isinstance(contexts_features, tuple): self._return_contexts_features_tuple = False if contexts_items_features_names is not None: - assert len(contexts_features[0]) == len( - contexts_features_names - ), "Number of features given does not match number of features names given." + if len(contexts_features[0]) == len(contexts_features_names): + raise ValueError( + """Number of features given does not match + number of features names given.""" + ) contexts_features_names = (contexts_features_names,) contexts_features = (contexts_features,) @@ -101,7 +122,8 @@ def __init__( for f, name in zip(contexts_features, contexts_features_names): if len(f[0]) != len(name): raise ValueError( - "contexts_features shape and contexts_features_names shape do not match" + """contexts_features shape and contexts_features_names + shape do not match""" ) # In this case names are missing, still transform it as a tuple @@ -113,9 +135,11 @@ def __init__( if not isinstance(contexts_items_features, tuple) and contexts_items_features is not None: self._return_contexts_items_features_tuple = False if contexts_items_features_names is not None: - assert ( - len(contexts_items_features[0][0]) == len(contexts_items_features_names) - ), "Number of features given does not match number of features names given for contexts_items." + if len(contexts_items_features[0][0]) != len(contexts_items_features_names): + raise ValueError( + """Number of features given does not match + number of features names given for contexts_items.""" + ) contexts_items_features = (contexts_items_features,) contexts_items_features_names = (contexts_items_features_names,) @@ -124,7 +148,8 @@ def __init__( for f, name in zip(contexts_items_features, contexts_items_features_names): if len(f[0][0]) != len(name): raise ValueError( - "contexts_items_features shape and contexts_items_features_names shape do not match" + """contexts_items_features shape and + contexts_items_features_names shape do not match""" ) self._return_contexts_items_features_tuple = True # In this case names are missing, still transform it as a tuple @@ -295,6 +320,20 @@ def __init__( self.indexer = ChoiceDatasetIndexer(self) def _build_features_by_ids(self): + """Builds mapping function. + + Those mapping functions are so that at indexing, + the features are rebuilt with the features by id. + + Returns: + -------- + tuple + indexes and features_by_id of fixed_items_features + tuple + indexes and features_by_id of contexts_features + tuple + indexes and features_by_id of contexts_items_features + """ if len(self.features_by_ids) == 0: print("No features_by_ids given.") return [], [], [] @@ -336,9 +375,10 @@ def _build_features_by_ids(self): if column_name == feature_by_id.name: contexts_items_features_map.append(((i, j), feature_by_id)) - assert len(fixed_items_features_map) + len(contexts_features_map) + len( + if len(fixed_items_features_map) + len(contexts_features_map) + len( contexts_items_features_map - ) == len(self.features_by_ids), "Some features_by_ids were not matched with features_names." + ) == len(self.features_by_ids): + raise ValueError("Some features_by_ids were not matched with features_names.") return fixed_items_features_map, contexts_features_map, contexts_items_features_map @@ -569,9 +609,9 @@ def _contexts_items_features_df_to_np( contexts_index, features, items_id_column="item_id", - contexts_id_column="session_id", + contexts_id_column="contexts_id", ): - """Builds sessions_items_features and sessions_items_availabilities from dataframe. + """Builds contexts_items_features and contexts_items_availabilities from dataframe. Parameters ---------- @@ -579,20 +619,24 @@ def _contexts_items_features_df_to_np( Dataframe containing all the features for each item and sessions items_index : list List of items - sessions_index : list + contexts_index : list List of sessions features : list List of columns of df that represents the items_features (for sessions_items_features) + items_id_column: str, optional + Name of the column containing the item ids, default is "items_id" + contexts_id_column: str, optional + Name of the column containing the sessions ids, default is "contexts_id" Returns: ------- - np.ndarray of shape (n_sessions, n_items, n_features) - Corresponding sessions_items_features - np.ndarray of shape (n_sessions, n_items) + np.ndarray of shape (n_choices, n_items, n_features) + Corresponding contexts_items_features + np.ndarray of shape (n_choices, n_items) Corresponding availabilities """ try: - features.remove("session_id") + features.remove("context_id") except ValueError: pass try: @@ -637,9 +681,9 @@ def _contexts_items_features_df_to_np( def from_single_df( cls, df, - fixed_items_features_columns, - contexts_features_columns, - contexts_items_features_columns, + fixed_items_features_columns=None, + contexts_features_columns=None, + contexts_items_features_columns=None, items_id_column="item_id", contexts_id_column="context_id", choices_column="choice", @@ -651,18 +695,21 @@ def from_single_df( ---------- df : pandas.DataFrame dataframe in Long format - items_features_columns : list - Columns of the dataframe that are item features - sessions_features_columns : list - Columns of the dataframe that are session features - sessions_items_features_columns : list - Columns of the dataframe that are session-item features + fixed_items_features_columns : list + Columns of the dataframe that are item features, default is None + contexts_features_columns : list + Columns of the dataframe that are contexts features, default is None + contexts_items_features_columns : list + Columns of the dataframe that are context-item features, default is None items_id_column: str, optional Name of the column containing the item ids, default is "items_id" - sessions_id_column: str, optional - Name of the column containing the sessions ids, default is "sessions_id" + contexts_id_column: str, optional + Name of the column containing the sessions ids, default is "contexts_id" choices_column: str, optional Name of the column containing the choices, default is "choice" + choice_mode: str, optional + How choice is indicated in df, either "items_name" or "one_zero", + default is "items_name" Returns: ------- @@ -795,10 +842,25 @@ def get_choices_batch(self, choices_indexes, features=None): Parameters ---------- - index : int or list of int or slice + choices_indexes : int or list of int or slice indexes of the choices (that will be mapped to choice & session indexes) to return + features : list of str, optional + list of features to return. None returns all of them, default is None. + Returns: + -------- + tuple of (array_like, ) + tuple of arrays containing the features of the different items + tuple of (array_like, ) + tuple of arrays containing the features of the different contexts + tuple of (array_like, ) + tuple of arrays containing the features of the different contexts_items + array_like + array containing the availabilities of the different items + array_like + array containing the choices (indexes of chosen items) """ + _ = features if isinstance(choices_indexes, list): if self.fixed_items_features is None: fixed_items_features = None @@ -969,8 +1031,8 @@ def __getitem__(self, choices_indexes): Parameters ---------- - indexes : np.ndarray - indexes of the sessions to keep, shape should be (num_sessions,) + choices_indexes : np.ndarray + indexes of the contexts / choices to keep, shape should be (num_choices,) Returns: ------- @@ -1002,7 +1064,7 @@ def __getitem__(self, choices_indexes): @property def batch(self): - """Indexer.""" + """Indexer. Corresponds to get_choice_batch, but with [] logic.""" return self.indexer def iter_batch(self, batch_size, shuffle=None, sample_weight=None): diff --git a/choice_learn/data/indexer.py b/choice_learn/data/indexer.py index 8a1cca28..6c9137dc 100644 --- a/choice_learn/data/indexer.py +++ b/choice_learn/data/indexer.py @@ -74,8 +74,8 @@ def __init__(self, storage): Parameters ---------- - store : choice_modeling.data.store.FeaturesStore - Store object to be indexed. + storage : choice_modeling.data.store.FeaturesStorage + Storage object to be indexed. """ self.storage = storage @@ -84,13 +84,13 @@ def __getitem__(self, sequence_keys): Parameters ---------- - sequence_index : (int, list, slice) - index position of the sequence + sequence_keys : (int, list, slice) + keys of values to be retrieved Returns: -------- array_like - features corresponding to the sequence_index-th position of sequence + features corresponding to the sequence_keys """ if isinstance(sequence_keys, Iterable): return np.array([self.storage.storage[key] for key in sequence_keys]) @@ -99,6 +99,48 @@ def __getitem__(self, sequence_keys): return np.array(self.storage.storage[sequence_keys]) +class OneHotStorageIndexer(Indexer): + """Class for Ilocing OneHotStorage.""" + + def __init__(self, storage): + """OneHotStorageIndexer constructor. + + Parameters + ---------- + storage : choice_modeling.data.store.OneHotStorage + OneHotStorage object to be indexed. + """ + self.storage = storage + self.shape = storage.shape + self.dtype = storage.dtype + + def __getitem__(self, sequence_keys): + """Get the 1 indexes corresponding to the sequence_keys and builds the OneHot matrix. + + Parameters + ---------- + sequence_keys : (int, list, slice) + keys of values to be retrieved + + Returns: + -------- + np.ndarray + OneHot reconstructed vectors corresponding to sequence_keys + """ + if isinstance(sequence_keys, list): + # Construction of the OneHot vector from the index of the 1 value + one_hot = np.zeros((len(sequence_keys), self.shape[1])) + for i, j in enumerate(sequence_keys): + one_hot[i, self.storage.storage[j]] = 1 + return one_hot.astype(self.dtype) + if isinstance(sequence_keys, slice): + return self[list(range(*sequence_keys.indices(len(self.shape[0]))))] + # else: + one_hot = np.zeros(self.shape[1]) + one_hot[self.storage.storage[sequence_keys]] = 1 + return one_hot.astype(self.dtype) + + class OneHotStoreIndexer(Indexer): """Class for Ilocing OneHotStore.""" @@ -169,24 +211,20 @@ def _get_fixed_items_features(self): items_feature.astype(self.choice_dataset._return_types[0][i]) for i, items_feature in enumerate(self.choice_dataset.fixed_items_features) ) - # items_features were not given as a tuple, so we return do not return it as a tuple - # if not self.choice_dataset._return_items_features_tuple: - # items_features = items_features[0] - return items_features - def _get_contexts_features(self, contexts_indexes): + def _get_contexts_features(self, choices_indexes): """Method to access sessions features of the ChoiceDataset. Parameters ---------- - sessions_indexes : list of ints or int - indexes of the sessions to return + choices_indexes : list of ints or int + choices indexes of the contexts features to return Returns: -------- tuple of np.ndarray or np.ndarray - items_features of the ChoiceDataset + right indexed contexts_features of the ChoiceDataset """ if self.choice_dataset.contexts_features is None: contexts_features = None @@ -195,31 +233,26 @@ def _get_contexts_features(self, contexts_indexes): for i, contexts_feature in enumerate(self.choice_dataset.contexts_features): if hasattr(contexts_feature, "batch"): contexts_features.append( - contexts_feature.batch[contexts_indexes].astype( + contexts_feature.batch[choices_indexes].astype( self.choice_dataset._return_types[1][i] ) ) else: - contexts_features.append(np.stack(contexts_feature[contexts_indexes], axis=0)) - # sessions_features were not given as a tuple, so we return do not return it as a tuple - # if not self.choice_dataset._return_contexts_features_tuple: - # contexts_features = contexts_feature[0] - # else: - # contexts_features = tuple(contexts_features) + contexts_features.append(np.stack(contexts_feature[choices_indexes], axis=0)) return contexts_features - def _get_contexts_items_features(self, contexts_indexes): + def _get_contexts_items_features(self, choices_indexes): """Method to access sessions items features of the ChoiceDataset. Parameters ---------- - sessions_indexes : list of ints or int - indexes of the sessions to return + choices_indexes : list of ints or int + indexes of the choices for which we want the contexts items features Returns: -------- tuple of np.ndarray or np.ndarray - items_features of the ChoiceDataset + right indexes contexts_items_features of the ChoiceDataset """ if self.choice_dataset.contexts_items_features is None: return None @@ -227,19 +260,14 @@ def _get_contexts_items_features(self, contexts_indexes): for i, contexts_items_feature in enumerate(self.choice_dataset.contexts_items_features): if hasattr(contexts_items_feature, "iloc"): contexts_items_features.append( - contexts_items_feature.iloc[contexts_indexes].astype(self._return_types[2][i]) + contexts_items_feature.iloc[choices_indexes].astype(self._return_types[2][i]) ) else: contexts_items_features.append( - np.stack(contexts_items_feature[contexts_indexes], axis=0).astype( + np.stack(contexts_items_feature[choices_indexes], axis=0).astype( self.choice_dataset._return_types[2][i] ) ) - # sessions_items_features were not given as a tuple, thus we do not return it as a tuple - # if self.choice_dataset._return_contexts_items_features_tuple: - # contexts_items_features = tuple(contexts_items_features) - # else: - # contexts_items_features = contexts_items_features[0] return contexts_items_features def __getitem__(self, choices_indexes): @@ -248,24 +276,24 @@ def __getitem__(self, choices_indexes): One index corresponds to a choice within a session. Return order: - Fixed item features - - Session features - - Session item features + - Contexts features + - Contexts item features - Items availabilities - - Choice + - Choices Parameters ---------- - index : int or list of int or slice + choices_indexes : int or list of int or slice indexes of the choices (that will be mapped to choice & session indexes) to return """ if isinstance(choices_indexes, list): + # Get the features fixed_items_features = self._get_fixed_items_features() - - # Get the session indexes contexts_features = self._get_contexts_features(choices_indexes) contexts_items_features = self._get_contexts_items_features(choices_indexes) + # Get availabilities if self.choice_dataset.contexts_items_availabilities is None: contexts_items_availabilities = None else: @@ -281,7 +309,7 @@ def __getitem__(self, choices_indexes): self.choice_dataset._return_types[3] ) ) - + # Get choices for indexes, f_by_id in self.choice_dataset.fixed_items_features_map: fixed_items_features[indexes[0]] = np.concatenate( [ @@ -291,6 +319,7 @@ def __getitem__(self, choices_indexes): ], axis=1, ) + # Features by ID mapping for indexes, f_by_id in self.choice_dataset.contexts_features_map: contexts_features[indexes[0]] = np.concatenate( [ @@ -312,6 +341,7 @@ def __getitem__(self, choices_indexes): ], axis=2, ) + # Shaping and typing if fixed_items_features is not None: for i in range(len(fixed_items_features)): fixed_items_features[i] = fixed_items_features[i].astype( @@ -363,12 +393,12 @@ def __getitem__(self, choices_indexes): ) if isinstance(choices_indexes, int): + # Get the features fixed_items_features = self._get_fixed_items_features() - # Get the session indexes - contexts_features = self._get_contexts_features(choices_indexes) contexts_items_features = self._get_contexts_items_features(choices_indexes) + # Get availabilities if self.choice_dataset.contexts_items_availabilities is None: contexts_items_availabilities = None else: @@ -384,6 +414,7 @@ def __getitem__(self, choices_indexes): self.choice_dataset._return_types[3] ) ) + # Features by ID mapping for indexes, f_by_id in self.choice_dataset.fixed_items_features_map: fixed_items_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = f_by_id.batch[ fixed_items_features[indexes[0]][:, indexes[1]] @@ -397,6 +428,7 @@ def __getitem__(self, choices_indexes): contexts_items_features[indexes[0]][:, indexes[1]] ] + # Shaping and typing # items_features were not given as a tuple, so we return do not return it as a tuple if not self.choice_dataset._return_items_features_tuple: fixed_items_features = fixed_items_features[0] diff --git a/choice_learn/data/storage.py b/choice_learn/data/storage.py index 992a3e62..365f84de 100644 --- a/choice_learn/data/storage.py +++ b/choice_learn/data/storage.py @@ -4,56 +4,79 @@ import numpy as np import pandas as pd -from choice_learn.data.indexer import StorageIndexer +from choice_learn.data.indexer import OneHotStorageIndexer, StorageIndexer class Storage(ABC): - """Class to keep OneHotStore and FeaturesStore with same parent.""" + """Parent Class to have OneHotStorage and FeaturesStorage with same parent.""" def __init__(self, features_to_store): + """Instantiation. + + Parameters + ---------- + features_to_store : object + Object to store + """ self.features_to_store = features_to_store @abstractmethod def __getitem__(self, keys): + """Base function to access an element. To be implemented in children classes. + + Parameters + ---------- + keys : float, int, str or list of + values among indexes of the stiage + """ pass @abstractmethod def __len__(self): + """Returns the length of the sequence of apparition of the features.""" pass @property def batch(self): + """Indexing method.""" pass class FeaturesStorage(Storage): - """Class to keep OneHotStore and FeaturesStore with same parent.""" + """Function to store features with ids.""" def __init__(self, ids=None, values=None, values_names=None, name=None, indexer=StorageIndexer): """Builds the store. Parameters ---------- - indexes : array_like or None - list of indexes of features to store. If None is given, indexes are created from + ids : array_like or None + list of ids of features to store. If None is given, ids are created from apparition order of values values : array_like list of values of features to store - sequence : array_like - sequence of apparitions of the features + values_names : array_like + Iterable of str indicating the name of the features. Must be same length as values. name: string, optional - name of the features store -- not used at the moment + name of the features store """ if isinstance(values, dict): storage = values lengths = [] for k, v in storage.items(): - assert isinstance(v, np.ndarray) | isinstance(v, list) - assert len(np.array(v).shape) == 1 + if not isinstance(v, np.ndarray) | isinstance(v, list): + raise ValueError("values must be a dict of np.ndarray or list") + if not len(np.array(v).shape) == 1: + raise ValueError( + "values (features) must be a dict of np.ndarray or list of 1D arrays" + ) lengths.append(len(v)) if isinstance(v, list): storage[k] = np.array(v) - assert len(set(lengths)) == 1 + if not len(set(lengths)) == 1: + raise ValueError("values (dict values) must all have same length") + if ids is not None: + print("Warning: ids is ignored when values is a dict") elif isinstance(values, pd.DataFrame): if values_names is not None: @@ -99,15 +122,20 @@ def __len__(self): """Returns the length of the sequence of apparition of the features.""" return len(self.storage) - def __getitem__(self, keys): - """_summary_. + def __getitem__(self, id_keys): + """Subset FeaturesStorage, keeping only features which id is in keys. Parameters ---------- - keys : _type_ - _description_ + id_keys : Iterable + List of ids to keep. + + Returns: + -------- + FeaturesStorage + Subset of the FeaturesStorage, with only the features whose id is in id_keys """ - sub_storage = {k: self.storage[k] for k in keys} + sub_storage = {k: self.storage[k] for k in id_keys} return FeaturesStorage(values=sub_storage, values_names=self.values_names, name=self.name) def get_storage_type(self): @@ -125,3 +153,136 @@ def get_storage_type(self): def batch(self): """Indexing attribute.""" return self.indexer + + +class OneHotStorage(Storage): + """Specific Storage for one hot features storage. + + Inherits from Storage. + For example can be used to store a OneHot representation of the days of week. + + Has the same attributes as FeaturesStoage, only differs whit some One-Hot optimized methods. + It only stores the indexes of the features, and creates the OneHot matrix + when needed, using .batch[]. + """ + + def __init__( + self, ids=None, values=None, name=None, dtype=np.uint8, indexer=OneHotStorageIndexer + ): + """Builds the store. + + Parameters + ---------- + ids : array_like or None + list of ids of features to store. If None is given, ids are created from + apparition order of values + values : array_like + list of values of features to store + dtype: type + type for One Hot representation, usually int or float, default is np.uint8 + name: string, optional + name of the features store + """ + if isinstance(values, dict): + storage = values + for k, v in storage.items(): + if not isinstance(v, int): + raise ValueError( + """values of values dict must be int as + they are indexes of the one hot vector ones.""" + ) + length = np.max(list(storage.values())) + 1 + if ids is not None: + print("Warning: ids is ignored when values is a dict") + + elif isinstance(values, list) or isinstance(values, np.ndarray): + if ids is None: + ids = list(range(len(values))) + storage = {k: int(v) for (k, v) in zip(ids, values)} + length = np.max(values) + 1 + + elif values is None: + if ids is None: + raise ValueError("ids or values must be given, both are None") + value = 0 + storage = {} + for id in ids: + storage[id] = value + value += 1 + length = value + else: + raise ValueError("values must be a dict, a DataFrame, a list or a numpy array") + + self.storage = storage + self.name = name + + self.shape = (len(self), length) + self.dtype = dtype + self.indexer = indexer(self) + + def __len__(self): + """Returns the length of the sequence of apparition of the features.""" + return len(self.storage) + + def __getitem__(self, id_keys): + """Subset FeaturesStorage, keeping only features which id is in keys. + + Parameters + ---------- + id_keys : Iterable + List of ids to keep. + + Returns: + -------- + OneHotStorage + Subset of the OneHotStorage, with only the features whose id is in id_keys + """ + if isinstance(id_keys, int): + id_keys = [id_keys] + sub_storage = {k: self.storage[k] for k in id_keys} + + return OneHotStorage(values=sub_storage, name=self.name, dtype=self.dtype) + + def astype(self, dtype): + """Method to change (mainly int or float) type of returned OneHot features vectors. + + Parameters + ---------- + dtype : type + Type to set the features as + """ + self.dtype = dtype + + def get_element_from_index(self, index): + """Getter method over self.sequence. + + Returns the features stored at index index. Compared to __getitem__, it does take + the index-th element of sequence but the index-th element of the store. + + Parameters + ---------- + index : (int, list, slice) + index argument of the feature + + Returns: + -------- + array_like + features corresponding to the index index in self.store + """ + keys = list(self.storage.keys())[index] + return self.storage[keys] + + def get_storage_type(self): + """Functions to access stored elements dtypes. + + Returns: + -------- + type + tuple of dtypes of the stored elements, as returned by np.dtype + """ + return self.dtype + + @property + def batch(self): + """Indexing attribute.""" + return self.indexer From dc6b719874a54282b79f3067691d3d751240fc5e Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 15 Jan 2024 10:01:35 +0100 Subject: [PATCH 060/767] ENH: ConditionalMNL creates ModelSpecification on its own --- choice_learn/models/base_model.py | 10 +- choice_learn/models/conditional_mnl.py | 270 ++++++++++++++++--------- 2 files changed, 176 insertions(+), 104 deletions(-) diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index 38d4b220..a5560f93 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -472,13 +472,15 @@ def load_model(cls, path): # Load optimizer step return cls - def predict_probas(self, choice_dataset): + def predict_probas(self, choice_dataset, batch_size=-1): """Predicts the choice probabilities for each session and each product of a ChoiceDataset. Parameters ---------- choice_dataset : ChoiceDataset Dataset on which to apply to prediction + batch_size : int, optional + Batch size to use for the prediction, by default -1 Returns: -------- @@ -492,7 +494,7 @@ def predict_probas(self, choice_dataset): sessions_items_batch, availabilities_batch, choices_batch, - ) in choice_dataset.iter_batch(): + ) in choice_dataset.iter_batch(batch_size=batch_size): _, probabilities = self.batch_predict( items_batch, sessions_batch, @@ -504,7 +506,7 @@ def predict_probas(self, choice_dataset): return tf.concat(stacked_probabilities, axis=0) - def evaluate(self, choice_dataset, batch_size=None): + def evaluate(self, choice_dataset, batch_size=-1): """Evaluates the model for each session and each product of a ChoiceDataset. Predicts the probabilities according to the model and computes the Negative-Log-Likelihood @@ -520,8 +522,6 @@ def evaluate(self, choice_dataset, batch_size=None): np.ndarray (n_sessions, n_items) Choice probabilties for each session and each product """ - if batch_size is None: - batch_size = choice_dataset.batch_size batch_losses = [] for ( items_batch, diff --git a/choice_learn/models/conditional_mnl.py b/choice_learn/models/conditional_mnl.py index 9284797e..2e47451a 100644 --- a/choice_learn/models/conditional_mnl.py +++ b/choice_learn/models/conditional_mnl.py @@ -183,7 +183,7 @@ class ConditionalMNL(ChoiceModel): def __init__( self, - parameters, + parameters=None, add_exit_choice=False, optimizer="Adam", lr=0.001, @@ -207,6 +207,78 @@ def __init__( self.params = parameters self.instantiated = False + def add_coefficients( + self, coefficient_name, feature_name, items_indexes=None, items_names=None + ): + """Adds a coefficient to the model throught the specification of the utility. + + Parameters + ---------- + coefficient_name : str + Name given to the coefficient. + feature_name : str + features name to which the coefficient is associated. It should work with + the names given. + in the ChoiceDataset that will be used for parameters estimation. + items_indexes : list of int, optional + list of items indexes (in the ChoiceDataset) for which we need to add a coefficient, + by default None + items_names : list of str, optional + list of items names (in the ChoiceDataset) for which we need to add a coefficient, + by default None + + Raises: + ------- + ValueError + When names or indexes are both not specified. + """ + if self.params is None: + self.params = ModelSpecification() + elif not isinstance(self.params, ModelSpecification): + raise ValueError("Cannot add coefficient on top of a dict instantiation.") + self.params.add_coefficients( + coefficient_name=coefficient_name, + feature_name=feature_name, + items_indexes=items_indexes, + items_names=items_names, + ) + + def add_shared_coefficient( + self, coefficient_name, feature_name, items_indexes=None, items_names=None + ): + """Adds a single, shared coefficient to the model throught the specification of the utility. + + Parameters + ---------- + coefficient_name : str + Name given to the coefficient. + feature_name : str + features name to which the coefficient is associated. It should work with + the names given. + in the ChoiceDataset that will be used for parameters estimation. + items_indexes : list of int, optional + list of items indexes (in the ChoiceDataset) for which the coefficient will be used, + by default None + items_names : list of str, optional + list of items names (in the ChoiceDataset) for which the coefficient will be used, + by default None + + Raises: + ------- + ValueError + When names or indexes are both not specified. + """ + if self.params is None: + self.params = ModelSpecification() + elif not isinstance(self.params, ModelSpecification): + raise ValueError("Cannot add shared coefficient on top of a dict instantiation.") + self.params.add_shared_coefficient( + coefficient_name=coefficient_name, + feature_name=feature_name, + items_indexes=items_indexes, + items_names=items_names, + ) + def instantiate_from_specifications(self): """Instantiate the model from ModelSpecification object. @@ -247,15 +319,15 @@ def _store_dataset_features_names(self, dataset): dataset : ChoiceDataset ChoiceDataset used to fit the model. """ - self._items_features_names = dataset.items_features_names - self._sessions_features_names = dataset.sessions_features_names - self._sessions_items_features_names = dataset.sessions_items_features_names + self._items_features_names = dataset.fixed_items_features_names + self._contexts_features_names = dataset.contexts_features_names + self._contexts_items_features_names = dataset.contexts_items_features_names def compute_utility_from_specification( self, items_batch, - sessions_batch, - sessions_items_batch, + contexts_batch, + contexts_items_batch, availabilities_batch, choices_batch, verbose=0, @@ -268,31 +340,31 @@ def compute_utility_from_specification( Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products constant/fixed features. Shape must be (n_items, n_items_features) - sessions_batch : tuple of np.ndarray (sessions_features) + contexts_batch : tuple of np.ndarray (contexts_features) Time-Features - Shape must be (n_sessions, n_sessions_features) - sessions_items_batch : tuple of np.ndarray (sessions_items_features) + Shape must be (n_choices, n_contexts_features) + contexts_items_batch : tuple of np.ndarray (contexts_items_features) Time-Item-Features - Shape must be (n_sessions, n_sessions_items_features) + Shape must be (n_choices, n_contexts_items_features) availabilities_batch : np.ndarray - Availabilities (sessions_items_availabilities) - Shape must be (n_sessions, n_items) + Availabilities (contexts_items_availabilities) + Shape must be (n_choices, n_items) choices_batch : np.ndarray Choices - Shape must be (n_sessions, ) + Shape must be (n_choices, ) verbose : int, optional Parametrization of the logging outputs, by default 0 Returns: -------- tf.Tensor - Utilities corresponding of shape (n_sessions, n_items) + Utilities corresponding of shape (n_choices, n_items) """ del choices_batch, verbose num_items = availabilities_batch.shape[1] - num_sessions = availabilities_batch.shape[0] - sessions_items_utilities = [] + num_choices = availabilities_batch.shape[0] + contexts_items_utilities = [] # Items features for i, feat_tuple in enumerate(self._items_features_names): for j, feat in enumerate(feat_tuple): @@ -324,23 +396,23 @@ def compute_utility_from_specification( ], axis=0, ) - s_i_u = tf.stack([s_i_u] * num_sessions, axis=0) + s_i_u = tf.stack([s_i_u] * num_choices, axis=0) ### Need reshaping here - sessions_items_utilities.append(s_i_u) + contexts_items_utilities.append(s_i_u) else: print( f"Feature {feat} is in dataset but has no weight assigned in utility\ computations" ) - # Session features - for i, feat_tuple in enumerate(self._sessions_features_names): + # Context features + for i, feat_tuple in enumerate(self._contexts_features_names): for j, feat in enumerate(feat_tuple): if feat in self.params.list_features_with_weights(): item_index, weight_index = self.params.get_weight_item_indexes(feat) - s_i_u = tf.zeros((num_sessions, num_items)) + s_i_u = tf.zeros((num_choices, num_items)) for q, idx in enumerate(item_index): if isinstance(idx, list): @@ -350,7 +422,7 @@ def compute_utility_from_specification( s_i_u[:, :k], tf.expand_dims( tf.multiply( - sessions_batch[i][:, j], + contexts_batch[i][:, j], self.weights[weight_index][:, q], ), axis=-1, @@ -365,7 +437,7 @@ def compute_utility_from_specification( s_i_u[:, :idx], tf.expand_dims( tf.multiply( - sessions_batch[i][:, j], + contexts_batch[i][:, j], self.weights[weight_index][:, q], ), axis=-1, @@ -375,19 +447,19 @@ def compute_utility_from_specification( axis=1, ) - sessions_items_utilities.append(s_i_u) + contexts_items_utilities.append(s_i_u) else: print( f"Feature {feat} is in dataset but has no weight assigned in utility\ computations" ) - # Session Items features - for i, feat_tuple in enumerate(self._sessions_items_features_names): + # context Items features + for i, feat_tuple in enumerate(self._contexts_items_features_names): for j, feat in enumerate(feat_tuple): if feat in self.params.list_features_with_weights(): item_index, weight_index = self.params.get_weight_item_indexes(feat) - s_i_u = tf.zeros((num_sessions, num_items)) + s_i_u = tf.zeros((num_choices, num_items)) for q, idx in enumerate(item_index): if isinstance(idx, list): @@ -397,7 +469,7 @@ def compute_utility_from_specification( s_i_u[:, :k], tf.expand_dims( tf.multiply( - sessions_items_batch[i][:, k, j], + contexts_items_batch[i][:, k, j], self.weights[weight_index][:, q], ), axis=-1, @@ -412,7 +484,7 @@ def compute_utility_from_specification( s_i_u[:, :idx], tf.expand_dims( tf.multiply( - sessions_items_batch[i][:, idx, j], + contexts_items_batch[i][:, idx, j], self.weights[weight_index][:, q], ), axis=-1, @@ -422,7 +494,7 @@ def compute_utility_from_specification( axis=1, ) - sessions_items_utilities.append(s_i_u) + contexts_items_utilities.append(s_i_u) else: print( f"Feature {feat} is in dataset but has no weight assigned in utility\ @@ -443,13 +515,13 @@ def compute_utility_from_specification( axis=0, ) - s_i_u = tf.stack([s_i_u] * num_sessions, axis=0) + s_i_u = tf.stack([s_i_u] * num_choices, axis=0) ### Need reshaping here - sessions_items_utilities.append(s_i_u) + contexts_items_utilities.append(s_i_u) - return tf.reduce_sum(sessions_items_utilities, axis=0) + return tf.reduce_sum(contexts_items_utilities, axis=0) def instantiate_from_dict(self, num_items): """Instantiation of the model from a dictionnary specification. @@ -483,8 +555,8 @@ def instantiate( self, num_items, items_features_names, - sessions_features_names, - sessions_items_features_names, + contexts_features_names, + contexts_items_features_names, ): """Instantiate the model from self.params and a dataset. @@ -496,10 +568,10 @@ def instantiate( Number of different items in the assortment. Used to create the right number of weights. items_features_names : list of str Names of the items features in the dataset. - sessions_features_names : list of str - Names of the sessions features in the dataset. - sessions_items_features_names : list of str - Names of the sessions items features in the dataset. + contexts_features_names : list of str + Names of the contexts features in the dataset. + contexts_items_features_names : list of str + Names of the contexts items features in the dataset. Raises: ------- @@ -542,8 +614,8 @@ def instantiate( if len(tuple_names) > 0: self._items_features_names.append(tuple_names) - self._sessions_features_names = [] - for feat_tuple in sessions_features_names: + self._contexts_features_names = [] + for feat_tuple in contexts_features_names: tuple_names = [] for feat in feat_tuple: if feat in self.params.keys(): @@ -575,10 +647,10 @@ def instantiate( computations" ) if len(tuple_names) > 0: - self._sessions_features_names.append(tuple_names) + self._contexts_features_names.append(tuple_names) - self._sessions_items_features_names = [] - for feat_tuple in sessions_items_features_names: + self._contexts_items_features_names = [] + for feat_tuple in contexts_items_features_names: tuple_names = [] for feat in feat_tuple: if feat in self.params.keys(): @@ -600,7 +672,7 @@ def instantiate( name=feat, ) else: - for i, s_tuple in enumerate(sessions_features_names): + for i, s_tuple in enumerate(contexts_features_names): for j, s_feat in enumerate(s_tuple): if s_feat == self.params[feat]: # Get num weights with unique values of this feature @@ -628,7 +700,7 @@ def instantiate( ) if len(tuple_names) > 0: - self._sessions_items_features_names.append(tuple_names) + self._contexts_items_features_names.append(tuple_names) if "intercept" in self.params.keys(): if self.params["intercept"] == "constant": @@ -646,7 +718,7 @@ def instantiate( name="intercept", ) else: - # Is supposed to be in sessions_features_names + # Is supposed to be in contexts_features_names raise NotImplementedError(f"Param {self.params['intercept']} not implemented") weights.append(weight) else: @@ -659,7 +731,7 @@ def instantiate( return weights def compute_utility( - self, items_batch, sessions_batch, sessions_items_batch, availabilities_batch, choices_batch + self, items_batch, contexts_batch, contexts_items_batch, availabilities_batch, choices_batch ): """Main method to compute the utility of the model. Selects the right method to compute. @@ -669,75 +741,75 @@ def compute_utility( Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products constant/fixed features. Shape must be (n_items, n_items_features) - sessions_batch : tuple of np.ndarray (sessions_features) + contexts_batch : tuple of np.ndarray (contexts_features) Time-Features - Shape must be (n_sessions, n_sessions_features) - sessions_items_batch : tuple of np.ndarray (sessions_items_features) + Shape must be (n_choices, n_contexts_features) + contexts_items_batch : tuple of np.ndarray (contexts_items_features) Time-Item-Features - Shape must be (n_sessions, n_sessions_items_features) + Shape must be (n_choices, n_contexts_items_features) availabilities_batch : np.ndarray - Availabilities (sessions_items_availabilities) - Shape must be (n_sessions, n_items) + Availabilities (contexts_items_availabilities) + Shape must be (n_choices, n_items) choices_batch : np.ndarray - Choices Shape must be (n_sessions, ) + Choices Shape must be (n_choices, ) Returns: -------- tf.Tensor - Computed utilities of shape (n_sessions, n_items). + Computed utilities of shape (n_choices, n_items). """ if isinstance(self.params, ModelSpecification): return self.compute_utility_from_specification( items_batch, - sessions_batch, - sessions_items_batch, + contexts_batch, + contexts_items_batch, availabilities_batch, choices_batch, ) return self.compute_utility_from_dict( items_batch, - sessions_batch, - sessions_items_batch, + contexts_batch, + contexts_items_batch, availabilities_batch, choices_batch, ) def compute_utility_from_dict( - self, items_batch, sessions_batch, sessions_items_batch, availabilities_batch, choices_batch + self, items_batch, contexts_batch, contexts_items_batch, availabilities_batch, choices_batch ): """Computes the utility when the model is constructed from a dictionnary object. Parameters ---------- - tems_batch : tuple of np.ndarray (items_features) + items_batch : tuple of np.ndarray (items_features) Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products constant/fixed features. Shape must be (n_items, n_items_features) - sessions_batch : tuple of np.ndarray (sessions_features) + contexts_batch : tuple of np.ndarray (contexts_features) Time-Features - Shape must be (n_sessions, n_sessions_features) - sessions_items_batch : tuple of np.ndarray (sessions_items_features) + Shape must be (n_choices, n_contexts_features) + contexts_items_batch : tuple of np.ndarray (contexts_items_features) Time-Item-Features - Shape must be (n_sessions, n_sessions_items_features) + Shape must be (n_choices, n_contexts_items_features) availabilities_batch : np.ndarray - Availabilities (sessions_items_availabilities) - Shape must be (n_sessions, n_items) + Availabilities (contexts_items_availabilities) + Shape must be (n_choices, n_items) choices_batch : np.ndarray Choices - Shape must be (n_sessions, ) + Shape must be (n_choices, ) verbose : int, optional Parametrization of the logging outputs, by default 0 Returns: -------- tf.Tensor - Utilities corresponding of shape (n_sessions, n_items) + Utilities corresponding of shape (n_choices, n_items) """ del availabilities_batch, choices_batch - sessions_items_utilities = [] + contexts_items_utilities = [] num_items = items_batch[0].shape[0] - num_sessions = sessions_batch[0].shape[0] + num_choices = contexts_batch[0].shape[0] # Items features for i, feat_tuple in enumerate(self._items_features_names): @@ -746,64 +818,64 @@ def compute_utility_from_dict( weight = self.weights[k] if self.params[feat] == "constant": s_i_u = tf.concat( - [tf.multiply(items_batch[i][:, j], weight)] * num_sessions, axis=0 + [tf.multiply(items_batch[i][:, j], weight)] * num_choices, axis=0 ) elif self.params[feat] == "item": weight = tf.concat([tf.constant([[0.0]]), weight], axis=-1) s_i_u = tf.concat( - [tf.multiply(items_batch[i][:, j], weight)] * num_sessions, axis=0 + [tf.multiply(items_batch[i][:, j], weight)] * num_choices, axis=0 ) elif self.params[feat] == "item-full": s_i_u = tf.concat( - [tf.multiply(items_batch[i][:, j], weight)] * num_sessions, axis=0 + [tf.multiply(items_batch[i][:, j], weight)] * num_choices, axis=0 ) else: raise NotImplementedError(f"Param {self.params[feat]} not implemented") - sessions_items_utilities.append(s_i_u) + contexts_items_utilities.append(s_i_u) else: print( f"Feature {feat} is in dataset but has no weight assigned in utility \ computations" ) - # Session features - for i, feat_tuple in enumerate(self._sessions_features_names): + # context features + for i, feat_tuple in enumerate(self._contexts_features_names): for j, (feat, k) in enumerate(feat_tuple): if feat in self.params.keys(): weight = self.weights[k] if self.params[feat] == "constant": s_i_u = tf.concat( - [tf.multiply(sessions_batch[i][j], weight)] * num_items, axis=-1 + [tf.multiply(contexts_batch[i][j], weight)] * num_items, axis=-1 ) elif self.params[feat] == "item": weight = tf.concat([tf.constant([[0.0]]), weight], axis=-1) - s_i_u = tf.tensordot(sessions_batch[i][:, j : j + 1], weight, axes=1) + s_i_u = tf.tensordot(contexts_batch[i][:, j : j + 1], weight, axes=1) elif self.params[feat] == "item-full": - s_i_u = tf.tensordot(sessions_batch[i][:, j : j + 1], weight, axes=1) + s_i_u = tf.tensordot(contexts_batch[i][:, j : j + 1], weight, axes=1) else: raise NotImplementedError(f"Param {self.params[feat]} not implemented") - sessions_items_utilities.append(s_i_u) + contexts_items_utilities.append(s_i_u) else: print( f"Feature {feat} is in dataset but has no weight assigned in utility \ computations" ) - # Session Items features - for i, feat_tuple in enumerate(self._sessions_items_features_names): + # context Items features + for i, feat_tuple in enumerate(self._contexts_items_features_names): for j, (feat, k) in enumerate(feat_tuple): if feat in self.params.keys(): weight = self.weights[k] if self.params[feat] == "constant": - s_i_u = tf.multiply(sessions_items_batch[i][:, :, j], weight) + s_i_u = tf.multiply(contexts_items_batch[i][:, :, j], weight) elif self.params[feat] == "item": weight = tf.concat([tf.constant([[0.0]]), weight], axis=-1) - s_i_u = tf.multiply(sessions_items_batch[i][:, :, j], weight) + s_i_u = tf.multiply(contexts_items_batch[i][:, :, j], weight) elif self.params[feat] == "item-full": - s_i_u = tf.multiply(sessions_items_batch[i][:, :, j], weight) + s_i_u = tf.multiply(contexts_items_batch[i][:, :, j], weight) else: raise NotImplementedError(f"Param {self.params[feat]} not implemented") - sessions_items_utilities.append(s_i_u) + contexts_items_utilities.append(s_i_u) else: print( f"Feature {feat} is in dataset but has no weight assigned in utility \ @@ -813,17 +885,17 @@ def compute_utility_from_dict( if "intercept" in self.params.keys(): weight = self.weights[-1] if self.params["intercept"] == "constant": - s_i_u = tf.concat([tf.concat([weight] * num_items, axis=0)] * num_sessions, axis=0) + s_i_u = tf.concat([tf.concat([weight] * num_items, axis=0)] * num_choices, axis=0) elif self.params["intercept"] == "item": weight = tf.concat([tf.constant([[0.0]]), weight], axis=-1) - s_i_u = tf.concat([weight] * num_sessions, axis=0) + s_i_u = tf.concat([weight] * num_choices, axis=0) elif self.params["intercept"] == "item-full": - s_i_u = tf.concat([weight] * num_sessions, axis=0) + s_i_u = tf.concat([weight] * num_choices, axis=0) else: raise NotImplementedError(f"Param {self.params[feat]} not implemented") - sessions_items_utilities.append(s_i_u) + contexts_items_utilities.append(s_i_u) - return tf.reduce_sum(sessions_items_utilities, axis=0) + return tf.reduce_sum(contexts_items_utilities, axis=0) def fit(self, choice_dataset, **kwargs): """Main fit function to estimate the paramters. @@ -845,9 +917,9 @@ def fit(self, choice_dataset, **kwargs): else: self.weights = self.instantiate( num_items=choice_dataset.get_num_items(), - items_features_names=choice_dataset.items_features_names, - sessions_features_names=choice_dataset.sessions_features_names, - sessions_items_features_names=choice_dataset.sessions_items_features_names, + items_features_names=choice_dataset.fixed_items_features_names, + contexts_features_names=choice_dataset.contexts_features_names, + contexts_items_features_names=choice_dataset.contexts_items_features_names, ) self.instantiated = True return super().fit(choice_dataset=choice_dataset, **kwargs) @@ -876,9 +948,9 @@ def _fit_with_lbfgs(self, choice_dataset, n_epochs, tolerance=1e-8): else: self.weights = self.instantiate( num_items=choice_dataset.get_num_items(), - items_features_names=choice_dataset.items_features_names, - sessions_features_names=choice_dataset.sessions_features_names, - sessions_items_features_names=choice_dataset.sessions_items_features_names, + items_features_names=choice_dataset.fixed_items_features_names, + contexts_features_names=choice_dataset.contexts_features_names, + contexts_items_features_names=choice_dataset.contexts_items_features_names, ) self.instantiated = True return super()._fit_with_lbfgs(choice_dataset, n_epochs, tolerance) From 0a9a7679088e50d1d9520ad0771a58e0dc0c8567 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 15 Jan 2024 14:15:39 +0100 Subject: [PATCH 061/767] FIX: from_df --- choice_learn/data/choice_dataset.py | 54 +++++++++++++++-------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index a261103a..2a341de4 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -90,7 +90,7 @@ def __init__( # items_features is already a tuple, names are given, checking consistency if fixed_items_features_names is not None: for f, name in zip(fixed_items_features, fixed_items_features_names): - if len(f) != len(name): + if len(f[0]) != len(name): raise ValueError( "items_features shape and items_features_names shape do not match" ) @@ -106,10 +106,12 @@ def __init__( if not isinstance(contexts_features, tuple): self._return_contexts_features_tuple = False if contexts_items_features_names is not None: - if len(contexts_features[0]) == len(contexts_features_names): + if len(contexts_features[0]) != len(contexts_features_names): raise ValueError( - """Number of features given does not match - number of features names given.""" + f"""Number of features given does not match + number of features names given: + {len(contexts_features[0])} and + {len(contexts_features_names)}""" ) contexts_features_names = (contexts_features_names,) @@ -137,8 +139,10 @@ def __init__( if contexts_items_features_names is not None: if len(contexts_items_features[0][0]) != len(contexts_items_features_names): raise ValueError( - """Number of features given does not match - number of features names given for contexts_items.""" + f"""Number of features given does not match + number of features names given for contexts_items: + {len(contexts_items_features[0][0])} and + {len(contexts_items_features_names)}""" ) contexts_items_features = (contexts_items_features,) contexts_items_features_names = (contexts_items_features_names,) @@ -195,8 +199,8 @@ def __init__( for i, feature in enumerate(contexts_features): if isinstance(feature, pd.DataFrame): # Ordering choices by id ? - if "session_id" in feature.columns: - feature = feature.set_index("session_id") + if "context_id" in feature.columns: + feature = feature.set_index("context_id") contexts_features = ( contexts_features[:i] + (feature.loc[np.sort(feature.index)].to_numpy(),) @@ -216,13 +220,13 @@ def __init__( for i, feature in enumerate(contexts_items_features): if isinstance(feature, pd.DataFrame): # Ordering choices by id ? - if "session_id" in feature.columns: + if "context_id" in feature.columns: if "item_id" in feature.columns: feature_array = [] - for sess in np.sort(feature.session_id.unique()): - sess_df = feature.loc[feature.session_id == sess] + for sess in np.sort(feature.context_id.unique()): + sess_df = feature.loc[feature.context_id == sess] sess_df = sess_df[ - sess_df.columns.difference(["session_id"]) + sess_df.columns.difference(["context_id"]) ].set_index("item_id") feature_array.append(sess_df.loc[np.sort(sess_df.index)].to_numpy()) contexts_items_features = ( @@ -236,7 +240,7 @@ def __init__( + contexts_items_features_names[i + 1 :] ) else: - feature = feature.set_index("session_id") + feature = feature.set_index("context_id") contexts_items_features = ( contexts_items_features[:i] + (feature.loc[np.sort(feature.index)].to_numpy(),) @@ -248,7 +252,7 @@ def __init__( + contexts_items_features_names[i + 1 :] ) else: - raise ValueError("session_id column not found in contexts_items_features") + raise ValueError("context_id column not found in contexts_items_features") elif isinstance(feature, list): contexts_items_features = ( contexts_items_features[:i] @@ -261,18 +265,18 @@ def __init__( contexts_items_availabilities, dtype=object ) elif isinstance(contexts_items_availabilities, pd.DataFrame): - if "session_id" in contexts_items_availabilities.columns: + if "context_id" in contexts_items_availabilities.columns: if "item_id" in contexts_items_availabilities.columns: av_array = [] - for sess in np.sort(contexts_items_availabilities.session_id): + for sess in np.sort(contexts_items_availabilities.context_id): sess_df = contexts_items_availabilities.loc[ - contexts_items_availabilities.session_id == sess + contexts_items_availabilities.context__id == sess ] sess_df = sess_df.set_index("item_id") av_array.append(sess_df.loc[np.sort(sess_df.index)].to_numpy()) contexts_items_availabilities = np.array(av_array) else: - feature = feature.set_index("session_id") + feature = feature.set_index("context_id") contexts_items_availabilities = contexts_items_availabilities.loc[ np.sort(feature.index) ].to_numpy() @@ -687,7 +691,7 @@ def from_single_df( items_id_column="item_id", contexts_id_column="context_id", choices_column="choice", - choice_mode="items_name", + choice_mode="items_id", ): """Builds numpy arrays for ChoiceDataset from a single dataframe. @@ -709,7 +713,7 @@ def from_single_df( Name of the column containing the choices, default is "choice" choice_mode: str, optional How choice is indicated in df, either "items_name" or "one_zero", - default is "items_name" + default is "items_id" Returns: ------- @@ -757,7 +761,7 @@ def from_single_df( else None ) - if choice_mode == "item_id": + if choice_mode == "items_id": choices = df[[choices_column, contexts_id_column]].drop_duplicates(contexts_id_column) choices = choices.set_index(contexts_id_column) choices = choices.loc[sessions].to_numpy() @@ -766,7 +770,7 @@ def from_single_df( elif choice_mode == "one_zero": choices = df[[items_id_column, choices_column, contexts_id_column]] choices = choices.loc[choices[choices_column] == 1] - choices = choices = choices.set_index(contexts_id_column) + choices = choices.set_index(contexts_id_column) choices = ( choices.loc[sessions][items_id_column] .map({k: v for v, k in enumerate(items)}) @@ -774,7 +778,7 @@ def from_single_df( ) else: raise ValueError( - f"choice_mode {choice_mode} not recognized. Must be in ['item_id', 'one_zero']" + f"choice_mode {choice_mode} not recognized. Must be in ['items_id', 'one_zero']" ) return ChoiceDataset( fixed_items_features=items_features, @@ -1067,7 +1071,7 @@ def batch(self): """Indexer. Corresponds to get_choice_batch, but with [] logic.""" return self.indexer - def iter_batch(self, batch_size, shuffle=None, sample_weight=None): + def iter_batch(self, batch_size, shuffle=False, sample_weight=None): """Iterates over dataset return batches of length batch_size. Newer version. @@ -1081,8 +1085,6 @@ def iter_batch(self, batch_size, shuffle=None, sample_weight=None): sample_weight : Iterable list of weights to be returned with the right indexing during the shuffling """ - if shuffle is None: - shuffle = self.shuffle if batch_size == -1: batch_size = len(self) # Get indexes for each choice From dd4697c0e1b756654a3b0488e179f41cea5329b8 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 15 Jan 2024 14:16:08 +0100 Subject: [PATCH 062/767] ADD: notebook with all different instantiation possibilities --- notebooks/dataset_creation.ipynb | 256 +++++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 notebooks/dataset_creation.ipynb diff --git a/notebooks/dataset_creation.ipynb b/notebooks/dataset_creation.ipynb new file mode 100644 index 00000000..9fb255a1 --- /dev/null +++ b/notebooks/dataset_creation.ipynb @@ -0,0 +1,256 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## All possible ways to create a ChoiceDataset\n", + "\n", + "Listed below ! " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "from pathlib import Path\n", + "\n", + "sys.path.append(\"../\")\n", + "\n", + "import numpy as np\n", + "import pandas as pd\n", + "\n", + "from choice_learn.data import ChoiceDataset\n", + "from choice_learn.data.storage import FeaturesStorage" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will use the CanadaMode dataset for this example. We can download it directly:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from choice_learn.datasets import load_modecanada, load_swissmetro\n", + "\n", + "canada_transport_df = load_modecanada(as_frame=True)\n", + "print(canada_transport_df.head())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's create a column indicating whether the considered transport alternative is individual or not transport." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "canada_transport_df[\"is_individual\"] = canada_transport_df.apply(lambda row: 1 if row.alt ==\"car\" else 0,\n", + " axis=1)\n", + "print(canada_transport_df.head())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### From a single dataframe" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset = ChoiceDataset.from_single_df(df=canada_transport_df,\n", + " fixed_items_features_columns=[\"is_individual\"],\n", + " contexts_features_columns=[\"income\"],\n", + " contexts_items_features_columns=[\"dist\", \"cost\", \"ivt\", \"ovt\"],\n", + " items_id_column=\"alt\",\n", + " contexts_id_column=\"case\",\n", + " choices_column=\"choice\",\n", + " choice_mode=\"one_zero\", # the choice columns indicates if the item is chosen (1) or not (0)\n", + " )\n", + "print(dataset.summary())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Another mode is possible, if the dataframe indicates the name of the chosen item instead of ones and zeros:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "id_df = canada_transport_df.copy(deep=True)\n", + "one_hot_choice = [0] * len(id_df)\n", + "for n_row, row in id_df.iterrows():\n", + " if row.choice == 0:\n", + " sub_df = id_df[id_df.case == row.case]\n", + " choice = sub_df.loc[sub_df.choice == 1].alt.to_numpy()[0]\n", + " one_hot_choice[n_row-1] = choice\n", + "\n", + "for n_row, row in id_df.iterrows():\n", + " if row.choice == 1:\n", + " one_hot_choice[n_row-1] = row.alt\n", + "\n", + "id_df[\"one_hot_choice\"] = one_hot_choice\n", + "\n", + "print(id_df.head())\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset = ChoiceDataset.from_single_df(df=id_df,\n", + " fixed_items_features_columns=[\"is_individual\"],\n", + " contexts_features_columns=[\"income\"],\n", + " contexts_items_features_columns=[\"dist\", \"cost\", \"ivt\", \"ovt\"],\n", + " items_id_column=\"alt\",\n", + " contexts_id_column=\"case\",\n", + " choices_column=\"one_hot_choice\",\n", + " choice_mode=\"items_id\", # the choice columns indicates if the item is chosen (1) or not (0)\n", + " )\n", + "print(dataset.summary())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let's say that you have your data split into several files:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "canada_transport_df.alt.unique()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fixed_items_features = pd.DataFrame({\"item_id\": [\"car\", \"train\", \"bus\", \"air\"],\n", + " \"is_individual\": [1, 0, 0, 0]})\n", + "# The item_id column is necessery, otherwise it will keep the order\n", + "# however it is less safe with pd.DataFrame" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "contexts_features = canada_transport_df[[\"case\", \"income\"]].drop_duplicates()\n", + "contexts_features = contexts_features.rename(columns={\"case\": \"context_id\"})\n", + "# If the context_id column does not exist, the index is used" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "contexts_items_features = canada_transport_df[[\"case\", \"alt\", \"dist\", \"cost\", \"ivt\", \"ovt\"]]\n", + "contexts_items_features = contexts_items_features.rename(columns={\"case\": \"context_id\", \"alt\": \"item_id\"})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "canada_transport_df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "choices = canada_transport_df.loc[canada_transport_df.choice==1][[\"case\", \"alt\"]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset = ChoiceDataset(fixed_items_features=fixed_items_features,\n", + " contexts_features=contexts_features,\n", + " contexts_items_features=contexts_items_features,\n", + " choices=choices)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "tf_env", + "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.11.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 36bfd6972e3b891db18d8dbe8754986a72cda00b Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 15 Jan 2024 14:16:59 +0100 Subject: [PATCH 063/767] small changes --- .../choice_learn_introduction_clogit.ipynb | 127 ++++++++---------- notebooks/features_storage_example.ipynb | 64 ++++++++- 2 files changed, 122 insertions(+), 69 deletions(-) diff --git a/notebooks/choice_learn_introduction_clogit.ipynb b/notebooks/choice_learn_introduction_clogit.ipynb index 9aea031e..85c345f8 100644 --- a/notebooks/choice_learn_introduction_clogit.ipynb +++ b/notebooks/choice_learn_introduction_clogit.ipynb @@ -70,11 +70,11 @@ "source": [ "from choice_learn.data import ChoiceDataset\n", "dataset = ChoiceDataset.from_single_df(df=transport_df,\n", - " items_features_columns=[\"oh_air\", \"oh_bus\", \"oh_car\", \"oh_train\"],\n", - " sessions_features_columns=[\"income\"],\n", - " sessions_items_features_columns=[\"cost\", \"freq\", \"ovt\", \"ivt\"],\n", + " fixed_items_features_columns=[\"oh_air\", \"oh_bus\", \"oh_car\", \"oh_train\"],\n", + " contexts_features_columns=[\"income\"],\n", + " contexts_items_features_columns=[\"cost\", \"freq\", \"ovt\", \"ivt\"],\n", " items_id_column=\"alt\",\n", - " sessions_id_column=\"case\",\n", + " contexts_id_column=\"case\",\n", " choices_column=\"choice\",\n", " choice_mode=\"one_zero\")" ] @@ -92,7 +92,7 @@ "metadata": {}, "outputs": [], "source": [ - "from choice_learn.models import ConditionalMNL, ModelSpecification" + "from choice_learn.models import ConditionalMNL" ] }, { @@ -138,25 +138,25 @@ "metadata": {}, "outputs": [], "source": [ - "# Instantiation of the specification\n", - "spec = ModelSpecification()\n", + "# Initialization of the model\n", + "model = ConditionalMNL(optimizer=\"lbfgs\")\n", "\n", "# Creation of the different weights:\n", "\n", "\n", "# add_coefficients adds one coefficient for each specified item_index\n", "# intercept, and income are added for each item except the first one that needs to be zeroed\n", - "spec.add_coefficients(coefficient_name=\"beta_inter\", feature_name=\"intercept\", items_indexes=[1, 2, 3])\n", - "spec.add_coefficients(coefficient_name=\"beta_income\", feature_name=\"income\", items_indexes=[1, 2, 3])\n", + "model.add_coefficients(coefficient_name=\"beta_inter\", feature_name=\"intercept\", items_indexes=[1, 2, 3])\n", + "model.add_coefficients(coefficient_name=\"beta_income\", feature_name=\"income\", items_indexes=[1, 2, 3])\n", "\n", "# ivt is added for each item:\n", - "spec.add_coefficients(coefficient_name=\"beta_ivt\", feature_name=\"ivt\", items_indexes=[0, 1, 2, 3])\n", + "model.add_coefficients(coefficient_name=\"beta_ivt\", feature_name=\"ivt\", items_indexes=[0, 1, 2, 3])\n", "\n", "# shared_coefficient add one coefficient that is used for all items specified in the items_indexes:\n", "# Here, cost, freq and ovt coefficients are shared between all items\n", - "spec.add_shared_coefficient(coefficient_name=\"beta_cost\", feature_name=\"cost\", items_indexes=[0, 1, 2, 3])\n", - "spec.add_shared_coefficient(coefficient_name=\"beta_freq\", feature_name=\"freq\", items_indexes=[0, 1, 2, 3])\n", - "spec.add_shared_coefficient(coefficient_name=\"beta_ovt\", feature_name=\"ovt\", items_indexes=[0, 1, 2, 3])" + "model.add_shared_coefficient(coefficient_name=\"beta_cost\", feature_name=\"cost\", items_indexes=[0, 1, 2, 3])\n", + "model.add_shared_coefficient(coefficient_name=\"beta_freq\", feature_name=\"freq\", items_indexes=[0, 1, 2, 3])\n", + "model.add_shared_coefficient(coefficient_name=\"beta_ovt\", feature_name=\"ovt\", items_indexes=[0, 1, 2, 3])" ] }, { @@ -166,20 +166,27 @@ "Now, we can instantiate our ConditionalMNL from the specification. We use LBFGS as the estimation method." ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In order to estimate the the coefficients values, use the .fit method with the ChoiceDataset:" + ] + }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "cmnl = ConditionalMNL(spec, optimizer=\"lbfgs\")" + "history = model.fit(dataset, n_epochs=1000)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "In order to estimate the the coefficients values, use the .fit method with the ChoiceDataset:" + "It is possible to see the estimated coefficients with the .weights argument:" ] }, { @@ -188,14 +195,14 @@ "metadata": {}, "outputs": [], "source": [ - "history = cmnl.fit(dataset, n_epochs=1000)" + "model.weights" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "It is possible to see the estimated coefficients with the .weights argument:" + "The negative loglikelihood can be estimated using .evaluate():" ] }, { @@ -204,14 +211,23 @@ "metadata": {}, "outputs": [], "source": [ - "cmnl.weights" + "print(\"The average neg-loglikelihood is:\", model.evaluate(dataset).numpy())\n", + "print(\"The total neg-loglikelihood is:\", model.evaluate(dataset).numpy()*len(dataset))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The negative loglikelihood can be estimated using .evaluate():" + "A faster specification can be done using a dictionnary. It follows torch-choice \\ref{} method to create conditional logit models.\n", + "The parameters dict needs to be as follows:\n", + "- The key is the feature name\n", + "- The value is the mode. Currently three modes are available:\n", + " - constant: the learned coefficient is shared by all items\n", + " - item: one coefficient by item is estimated, the value for the item at index 0 is set to 0\n", + " - item-full: one coefficient by item is estimated\n", + "\n", + "In order to create the same model for the ModeCanada dataset, it looks as follows:" ] }, { @@ -220,8 +236,26 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"The average neg-loglikelihood is:\", cmnl.evaluate(dataset).numpy())\n", - "print(\"The total neg-loglikelihood is:\", cmnl.evaluate(dataset).numpy()*len(dataset))" + "# Instantiation of the parameters dictionnary\n", + "params = {\"income\": \"item\",\n", + " \"cost\": \"constant\", \n", + " \"freq\": \"constant\",\n", + " \"ovt\": \"constant\", \n", + " \"ivt\": \"item-full\",\n", + " \"intercept\": \"item\"}\n", + "\n", + "# Instantiation of the model\n", + "cmnl = ConditionalMNL(parameters=params, optimizer=\"lbfgs\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "history = cmnl.fit(dataset, n_epochs=1000)\n", + "print(cmnl.weights)" ] }, { @@ -241,14 +275,14 @@ "\n", "# Here are the values obtained in the references:\n", "gt_weights = [\n", - " tf.constant([[0.697311, 1.8437, 3.27381]]),\n", " tf.constant([[-0.0890796, -0.0279925, -0.038146]]),\n", - " tf.constant([[0.0595089, -0.00678188, -0.00645982, -0.00145029]]),\n", " tf.constant([[-0.0333421]]),\n", " tf.constant([[0.0925304]]),\n", " tf.constant([[-0.0430032]]),\n", + " tf.constant([[0.0595089, -0.00678188, -0.00645982, -0.00145029]]),\n", + " tf.constant([[0.697311, 1.8437, 3.27381]]),\n", "]\n", - "gt_model = ConditionalMNL(spec, lr=0.01)\n", + "gt_model = ConditionalMNL(parameters=params, lr=0.01)\n", "gt_model.fit(dataset, n_epochs=1, batch_size=-1)\n", "\n", "# Here we estimate the negative log-likelihood with these coefficients (also, we obtain same value as in those papers):\n", @@ -298,7 +332,7 @@ "metadata": {}, "outputs": [], "source": [ - "cmnl = ConditionalMNL(spec, optimizer=\"Adam\")\n", + "cmnl = ConditionalMNL(parameters=params, optimizer=\"Adam\")\n", "history = cmnl.fit(dataset, n_epochs=2000, batch_size=-1)\n", "cmnl.optimizer.lr = cmnl.optimizer.lr / 5\n", "history2 = cmnl.fit(dataset, n_epochs=4000, batch_size=-1)\n", @@ -324,49 +358,6 @@ "cmnl.evaluate(dataset)" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A faster specification can be done using a dictionnary. It follows torch-choice \\ref{} method to create conditional logit models.\n", - "The parameters dict needs to be as follows:\n", - "- The key is the feature name\n", - "- The value is the mode. Currently three modes are available:\n", - " - constant: the learned coefficient is shared by all items\n", - " - item: one coefficient by item is estimated, the value for the item at index 0 is set to 0\n", - " - item-full: one coefficient by item is estimated\n", - "\n", - "In order to create the same model for the ModeCanada dataset, it looks as follows:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Instantiation of the parameters dictionnary\n", - "params = {\"income\": \"item\",\n", - " \"cost\": \"constant\", \n", - " \"freq\": \"constant\",\n", - " \"ovt\": \"constant\", \n", - " \"ivt\": \"item-full\",\n", - " \"intercept\": \"item\"}\n", - "\n", - "# Instantiation of the model\n", - "cmnl = ConditionalMNL(parameters=params, optimizer=\"lbfgs\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "history = cmnl.fit(dataset, n_epochs=1000)\n", - "print(cmnl.weights)" - ] - }, { "cell_type": "code", "execution_count": null, diff --git a/notebooks/features_storage_example.ipynb b/notebooks/features_storage_example.ipynb index 4ed33770..43200b9b 100644 --- a/notebooks/features_storage_example.ipynb +++ b/notebooks/features_storage_example.ipynb @@ -26,7 +26,7 @@ "metadata": {}, "outputs": [], "source": [ - "from choice_learn.data.storage import FeaturesStorage" + "from choice_learn.data.storage import FeaturesStorage, OneHotStorage" ] }, { @@ -107,6 +107,68 @@ "storage.batch[[\"customerA\", \"customerC\", \"customerA\", \"customerC\"]]" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ids = [0, 1, 2, 3, 4]\n", + "values = [4, 3, 2, 1, 0]\n", + "\n", + "oh_storage = OneHotStorage(ids=ids, values=values, name=\"OneHotTest\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "oh_storage.batch[[0, 2, 4]], oh_storage.get_element_from_index(0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "oh_storage = OneHotStorage(values=values, name=\"OneHotTest\")\n", + "oh_storage.batch[[0, 2, 4]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "oh_storage = OneHotStorage(ids=ids, name=\"OneHotTest\")\n", + "oh_storage.batch[[0, 2, 4]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "values_dict = {k:v for k, v in zip(ids, values)}\n", + "oh_storage = OneHotStorage(values=values_dict, name=\"OneHotTest\")\n", + "oh_storage.batch[[0, 2, 4]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "oh_storage = OneHotStorage(ids=ids, values=values_dict, name=\"OneHotTest\")\n", + "oh_storage = OneHotStorage(name=\"OneHotTest\")" + ] + }, { "cell_type": "code", "execution_count": null, From 6b23a071c458ee8d5054f1da45d67d1802696260 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 15 Jan 2024 14:24:00 +0100 Subject: [PATCH 064/767] test bandit config --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index cc399e36..f4693f3b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,5 +64,5 @@ quote-style = "double" [tool.ruff.isort] known-first-party = ["choice_learn", "config", "tests"] -[tool.bandit] +[tool.bandit.assert_used] exclude_dirs = ["tests/"] From 2ab676b6b005158171c5d5dc71b0bdbdf6652a1c Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 15 Jan 2024 15:52:00 +0100 Subject: [PATCH 065/767] FIX: few important fixes --- choice_learn/data/choice_dataset.py | 45 ++++++++++++++++++++++------- choice_learn/data/indexer.py | 3 +- choice_learn/data/storage.py | 8 +++-- 3 files changed, 42 insertions(+), 14 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index 2a341de4..b03b17c4 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -67,6 +67,7 @@ def __init__( if choices is None: # Done to keep a logical order of arguments, and has logic: choices have to be specified raise ValueError("Choices must be specified, got None") + choices = np.array(choices) # --------- [ Handling features type given as tuples or not ] --------- # # If items_features is not given as tuple, transform it internally as a tuple @@ -766,7 +767,7 @@ def from_single_df( choices = choices.set_index(contexts_id_column) choices = choices.loc[sessions].to_numpy() # items is the value (str) of the item - choices = [np.where(items == c)[0] for c in choices] + choices = np.squeeze([np.where(items == c)[0] for c in choices]) elif choice_mode == "one_zero": choices = df[[items_id_column, choices_column, contexts_id_column]] choices = choices.loc[choices[choices_column] == 1] @@ -1048,21 +1049,45 @@ def __getitem__(self, choices_indexes): elif isinstance(choices_indexes, slice): return self.__getitem__(list(range(*choices_indexes.indices(len(self.choices))))) - return ChoiceDataset( - fixed_items_features=self.fixed_items_features, - contexts_features=tuple( + if self.fixed_items_features[0] is None: + fixed_items_features = None + else: + fixed_items_features = self.fixed_items_features + if self.contexts_features[0] is None: + contexts_features = None + else: + contexts_features = tuple( self.contexts_features[i][choices_indexes] for i in range(len(self.contexts_features)) - ), - contexts_items_features=tuple( + ) + if self.contexts_items_features[0] is None: + contexts_items_features = None + else: + contexts_items_features = tuple( self.contexts_items_features[i][choices_indexes] for i in range(len(self.contexts_items_features)) - ), + ) + if self.fixed_items_features_names[0] is None: + fixed_items_features_names = None + else: + fixed_items_features_names = self.fixed_items_features_names + if self.contexts_features_names[0] is None: + contexts_features_names = None + else: + contexts_features_names = self.contexts_features_names + if self.contexts_items_features_names[0] is None: + contexts_items_features_names = None + else: + contexts_items_features_names = self.contexts_items_features_names + return ChoiceDataset( + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, contexts_items_availabilities=self.contexts_items_availabilities[choices_indexes], choices=[self.choices[i] for i in choices_indexes], - fixed_items_features_names=self.fixed_items_features_names, - contexts_features_names=self.contexts_features_names, - contexts_items_features_names=self.contexts_items_features_names, + fixed_items_features_names=fixed_items_features_names, + contexts_features_names=contexts_features_names, + contexts_items_features_names=contexts_items_features_names, features_by_ids=self.features_by_ids, ) diff --git a/choice_learn/data/indexer.py b/choice_learn/data/indexer.py index 6c9137dc..d070ee09 100644 --- a/choice_learn/data/indexer.py +++ b/choice_learn/data/indexer.py @@ -1,6 +1,5 @@ """Indexer classes for data classes.""" from abc import abstractmethod -from collections.abc import Iterable import numpy as np @@ -92,7 +91,7 @@ def __getitem__(self, sequence_keys): array_like features corresponding to the sequence_keys """ - if isinstance(sequence_keys, Iterable): + if isinstance(sequence_keys, list) or isinstance(sequence_keys, np.ndarray): return np.array([self.storage.storage[key] for key in sequence_keys]) if isinstance(sequence_keys, slice): raise ValueError("Slicing is not supported for storage") diff --git a/choice_learn/data/storage.py b/choice_learn/data/storage.py index 365f84de..d38ef03e 100644 --- a/choice_learn/data/storage.py +++ b/choice_learn/data/storage.py @@ -115,8 +115,10 @@ def get_element_from_index(self, index): array_like features corresponding to the index index in self.store """ - keys = list(self.storage.keys())[index] - return self.storage[keys] + if isinstance(index, int): + index = [index] + keys = [list(self.storage.keys())[i] for i in index] + return self.batch[keys] def __len__(self): """Returns the length of the sequence of apparition of the features.""" @@ -135,6 +137,8 @@ def __getitem__(self, id_keys): FeaturesStorage Subset of the FeaturesStorage, with only the features whose id is in id_keys """ + if not isinstance(id_keys, list): + id_keys = [id_keys] sub_storage = {k: self.storage[k] for k in id_keys} return FeaturesStorage(values=sub_storage, values_names=self.values_names, name=self.name) From a5109917559ec2d7e6e458206490eda434b52052 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 15 Jan 2024 15:53:54 +0100 Subject: [PATCH 066/767] ADD: tests with new signature --- notebooks/features_storage_example.ipynb | 1 - tests/unit_tests/data/test_choice_dataset.py | 226 +++++++++--------- tests/unit_tests/data/test_store.py | 237 ++++++++++++------- 3 files changed, 263 insertions(+), 201 deletions(-) diff --git a/notebooks/features_storage_example.ipynb b/notebooks/features_storage_example.ipynb index 43200b9b..5e8df68a 100644 --- a/notebooks/features_storage_example.ipynb +++ b/notebooks/features_storage_example.ipynb @@ -36,7 +36,6 @@ "outputs": [], "source": [ "features = {\"customerA\": [1, 2, 3], \"customerB\": [4, 5, 6], \"customerC\": [7, 8, 9]}\n", - "\n", "storage = FeaturesStorage(values=features, values_names=[\"age\", \"income\", \"children_nb\"], name=\"customers\")" ] }, diff --git a/tests/unit_tests/data/test_choice_dataset.py b/tests/unit_tests/data/test_choice_dataset.py index 0ef46728..b288cde3 100644 --- a/tests/unit_tests/data/test_choice_dataset.py +++ b/tests/unit_tests/data/test_choice_dataset.py @@ -4,7 +4,7 @@ from choice_learn.data.choice_dataset import ChoiceDataset -items_features = [ +fixed_items_features = [ [1, 2], # item 1 [size, weight] [2, 4], # item 2 [size, weight] [1.5, 1.5], # item 3 [size, weight] @@ -17,19 +17,19 @@ # Customer 2 bought item 3 at session 2 choices = [0, 2, 1] -sessions_items_availabilities = [ +contexts_items_availabilities = [ [1, 1, 1], # All items available at session 1 [1, 1, 1], # All items available at session 2 [0, 1, 1], # Item 1 not available at session 3 ] -sessions_features = [ +contexts_features = [ [100, 20], # session 1, customer 1 [budget, age] [200, 40], # session 2, customer 2 [budget, age] [80, 20], # session 3, customer 1 [budget, age] ] -sessions_items_features = [ +contexts_items_features = [ [ [100, 0], # Session 1, Item 1 [price, promotion] [140, 0], # Session 1, Item 2 [price, promotion] @@ -53,19 +53,10 @@ def test_instantiate_len(): """Test the __init__ method.""" choices = [0, 2, 1] dataset = ChoiceDataset( - items_features=items_features, - sessions_features=sessions_features, - sessions_items_features=sessions_items_features, - sessions_items_availabilities=sessions_items_availabilities, - choices=choices, - ) - assert len(dataset) == 3 - choices = [[0], [1, 2], [2, 1, 1, 1]] - dataset = ChoiceDataset( - items_features=items_features, - sessions_features=sessions_features, - sessions_items_features=sessions_items_features, - sessions_items_availabilities=sessions_items_availabilities, + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) assert len(dataset) == 3 @@ -76,10 +67,10 @@ def test_fail_instantiate(): choices = [0, 1] with pytest.raises(ValueError): ChoiceDataset( - items_features=items_features, - sessions_features=sessions_features, - sessions_items_features=sessions_items_features, - sessions_items_availabilities=sessions_items_availabilities, + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) @@ -93,10 +84,10 @@ def test_fail_instantiate_2(): ] with pytest.raises(ValueError): ChoiceDataset( - items_features=items_features, - sessions_features=sessions_features, - sessions_items_features=sessions_items_features, - sessions_items_availabilities=sessions_items_availabilities, + fixed_items_features=items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) @@ -109,10 +100,10 @@ def test_fail_instantiate_3(): ] with pytest.raises(ValueError): ChoiceDataset( - items_features=items_features, - sessions_features=sessions_features, - sessions_items_features=sessions_items_features, - sessions_items_availabilities=sessions_items_availabilities, + fixed_items_features=items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) @@ -125,10 +116,10 @@ def test_fail_instantiate_10(): ] with pytest.raises(ValueError): ChoiceDataset( - items_features=items_features, - sessions_features=sessions_features, - sessions_items_features=sessions_items_features, - sessions_items_availabilities=sessions_items_availabilities, + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=sessions_items_availabilities, choices=choices, ) @@ -142,10 +133,10 @@ def test_fail_instantiate_4(): ] with pytest.raises(ValueError): ChoiceDataset( - items_features=items_features, - sessions_features=sessions_features, - sessions_items_features=sessions_items_features, - sessions_items_availabilities=sessions_items_availabilities, + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=sessions_items_availabilities, choices=choices, ) @@ -158,10 +149,10 @@ def test_fail_instantiate_5(): ] with pytest.raises(ValueError): ChoiceDataset( - items_features=items_features, - sessions_features=sessions_features, - sessions_items_features=sessions_items_features, - sessions_items_availabilities=sessions_items_availabilities, + fixed_items_features=fixed_items_features, + contexts_features=sessions_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) @@ -175,10 +166,10 @@ def test_fail_instantiate_6(): ] with pytest.raises(ValueError): ChoiceDataset( - items_features=items_features, - sessions_features=sessions_features, - sessions_items_features=sessions_items_features, - sessions_items_availabilities=sessions_items_availabilities, + fixed_items_features=fixed_items_features, + contexts_features=sessions_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) @@ -199,10 +190,10 @@ def test_fail_instantiate_7(): ] with pytest.raises(ValueError): ChoiceDataset( - items_features=items_features, - sessions_features=sessions_features, - sessions_items_features=sessions_items_features, - sessions_items_availabilities=sessions_items_availabilities, + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=sessions_items_features, + contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) @@ -226,10 +217,10 @@ def test_fail_instantiate_8(): ] with pytest.raises(ValueError): ChoiceDataset( - items_features=items_features, - sessions_features=sessions_features, - sessions_items_features=sessions_items_features, - sessions_items_availabilities=sessions_items_availabilities, + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=sessions_items_features, + contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) @@ -239,10 +230,10 @@ def test_fail_instantiate_9(): choices = [0, 4, 2] # choices higher than nb of items with pytest.raises(ValueError): ChoiceDataset( - items_features=items_features, - sessions_features=sessions_features, - sessions_items_features=sessions_items_features, - sessions_items_availabilities=sessions_items_availabilities, + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) @@ -250,15 +241,14 @@ def test_fail_instantiate_9(): def test_shape(): """Tests get shape methods.""" dataset = ChoiceDataset( - items_features=items_features, - sessions_features=sessions_features, - sessions_items_features=sessions_items_features, - sessions_items_availabilities=sessions_items_availabilities, + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) assert dataset.get_num_items() == 3 - assert dataset.get_num_sessions() == 3 assert dataset.get_num_choices() == 3 @@ -269,7 +259,7 @@ def test_from_df(): "item_id": [0, 1, 2, 0, 1, 2, 1, 2], "items_feat_1": [1, 2, 1.5, 1, 2, 1.5, 2, 1.5], "items_feat_2": [2, 4, 1.5, 2, 4, 1.5, 4, 1.5], - "session_id": [0, 0, 0, 1, 1, 1, 2, 2], + "context_id": [0, 0, 0, 1, 1, 1, 2, 2], "session_feat_1": [100, 100, 100, 200, 200, 200, 80, 80], "session_feat_2": [20, 20, 20, 40, 40, 40, 20, 20], "session_item_feat_1": [100, 140, 200, 100, 120, 200, 120, 180], @@ -279,27 +269,29 @@ def test_from_df(): ) cd_test = ChoiceDataset.from_single_df( features_df, - items_features_columns=["items_feat_1", "items_feat_2"], - sessions_features_columns=["session_feat_1", "session_feat_2"], - sessions_items_features_columns=["session_item_feat_1", "session_item_feat_2"], - choice_mode="item_id", + fixed_items_features_columns=["items_feat_1", "items_feat_2"], + contexts_features_columns=["session_feat_1", "session_feat_2"], + contexts_items_features_columns=["session_item_feat_1", "session_item_feat_2"], + choice_mode="items_id", ) ground_truth_cd = ChoiceDataset( - items_features=items_features, - sessions_features=sessions_features, - sessions_items_features=sessions_items_features, - sessions_items_availabilities=sessions_items_availabilities, + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) - assert (cd_test.items_features[0] == ground_truth_cd.items_features[0]).all() - assert (cd_test.sessions_features[0] == ground_truth_cd.sessions_features[0]).all() + assert (cd_test.fixed_items_features[0] == ground_truth_cd.fixed_items_features[0]).all() + assert (cd_test.contexts_features[0] == ground_truth_cd.contexts_features[0]).all() assert ( - cd_test.sessions_items_features[0].astype("float32") - == ground_truth_cd.sessions_items_features[0].astype("float32") + cd_test.contexts_items_features[0].astype("float32") + == ground_truth_cd.contexts_items_features[0].astype("float32") ).all() assert ( - cd_test.sessions_items_availabilities == ground_truth_cd.sessions_items_availabilities + cd_test.contexts_items_availabilities == ground_truth_cd.contexts_items_availabilities ).all() + print(cd_test.choices) + print(cd_test.fixed_items_features) assert (cd_test.choices == ground_truth_cd.choices).all() features_df = pd.DataFrame( @@ -307,7 +299,7 @@ def test_from_df(): "item_id": [0, 1, 2, 0, 1, 2, 1, 2], "items_feat_1": [1, 2, 1.5, 1, 2, 1.5, 2, 1.5], "items_feat_2": [2, 4, 1.5, 2, 4, 1.5, 4, 1.5], - "session_id": [0, 0, 0, 1, 1, 1, 2, 2], + "context_id": [0, 0, 0, 1, 1, 1, 2, 2], "session_feat_1": [100, 100, 100, 200, 200, 200, 80, 80], "session_feat_2": [20, 20, 20, 40, 40, 40, 20, 20], "session_item_feat_1": [100, 140, 200, 100, 120, 200, 120, 180], @@ -317,26 +309,26 @@ def test_from_df(): ) cd_test = ChoiceDataset.from_single_df( features_df, - items_features_columns=["items_feat_1", "items_feat_2"], - sessions_features_columns=["session_feat_1", "session_feat_2"], - sessions_items_features_columns=["session_item_feat_1", "session_item_feat_2"], + fixed_items_features_columns=["items_feat_1", "items_feat_2"], + contexts_features_columns=["session_feat_1", "session_feat_2"], + contexts_items_features_columns=["session_item_feat_1", "session_item_feat_2"], choice_mode="one_zero", ) ground_truth_cd = ChoiceDataset( - items_features=items_features, - sessions_features=sessions_features, - sessions_items_features=sessions_items_features, - sessions_items_availabilities=sessions_items_availabilities, + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) - assert (cd_test.items_features[0] == ground_truth_cd.items_features[0]).all() - assert (cd_test.sessions_features[0] == ground_truth_cd.sessions_features[0]).all() + assert (cd_test.fixed_items_features[0] == ground_truth_cd.fixed_items_features[0]).all() + assert (cd_test.contexts_features[0] == ground_truth_cd.contexts_features[0]).all() assert ( - cd_test.sessions_items_features[0].astype("float32") - == ground_truth_cd.sessions_items_features[0].astype("float32") + cd_test.contexts_items_features[0].astype("float32") + == ground_truth_cd.contexts_items_features[0].astype("float32") ).all() assert ( - cd_test.sessions_items_availabilities == ground_truth_cd.sessions_items_availabilities + cd_test.contexts_items_availabilities == ground_truth_cd.contexts_items_availabilities ).all() assert (cd_test.choices == ground_truth_cd.choices).all() @@ -344,10 +336,10 @@ def test_from_df(): def test_summary(): """Tests summary method.""" dataset = ChoiceDataset( - items_features=items_features, - sessions_features=sessions_features, - sessions_items_features=sessions_items_features, - sessions_items_availabilities=sessions_items_availabilities, + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) dataset.summary() @@ -357,21 +349,21 @@ def test_summary(): def test_getitem(): """Tests getitem method.""" dataset = ChoiceDataset( - items_features=items_features, - sessions_features=sessions_features, - sessions_items_features=sessions_items_features, - sessions_items_availabilities=sessions_items_availabilities, + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) sub_dataset = dataset[[0, 1]] - assert (sub_dataset.items_features[0] == dataset.items_features[0]).all() - assert (sub_dataset.sessions_features[0] == dataset.sessions_features[0][[0, 1]]).all() + assert (sub_dataset.fixed_items_features[0] == dataset.fixed_items_features[0]).all() + assert (sub_dataset.contexts_features[0] == dataset.contexts_features[0][[0, 1]]).all() assert ( - sub_dataset.sessions_items_features[0] == dataset.sessions_items_features[0][[0, 1]] + sub_dataset.contexts_items_features[0] == dataset.contexts_items_features[0][[0, 1]] ).all() assert ( - sub_dataset.sessions_items_availabilities == dataset.sessions_items_availabilities[[0, 1]] + sub_dataset.contexts_items_availabilities == dataset.contexts_items_availabilities[[0, 1]] ).all() assert (sub_dataset.choices == dataset.choices[[0, 1]]).all() assert (sub_dataset.choices == [0, 2]).all() @@ -380,17 +372,17 @@ def test_getitem(): def test_batch(): """Tests the batch method.""" dataset = ChoiceDataset( - items_features=items_features, - sessions_features=sessions_features, - sessions_items_features=sessions_items_features, - sessions_items_availabilities=sessions_items_availabilities, + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) batch = dataset.batch[[0, 1]] - assert (batch[0] == items_features).all() - assert (batch[1] == sessions_features[:2]).all() - assert (batch[2] == sessions_items_features[:2]).all() - assert (batch[3] == sessions_items_availabilities[:2]).all() + assert (batch[0] == fixed_items_features).all() + assert (batch[1] == contexts_features[:2]).all() + assert (batch[2] == contexts_items_features[:2]).all() + assert (batch[3] == contexts_items_availabilities[:2]).all() assert (batch[4] == choices[:2]).all() sliced_batch = dataset.batch[:2] @@ -411,10 +403,10 @@ def test_batch(): def test_iter_batch(): """Tests the iter_batch method.""" dataset = ChoiceDataset( - items_features=items_features, - sessions_features=sessions_features, - sessions_items_features=sessions_items_features, - sessions_items_availabilities=sessions_items_availabilities, + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) for batch_nb, batch in enumerate(dataset.iter_batch(batch_size=2)): @@ -429,10 +421,10 @@ def test_iter_batch(): def test_filter(): """Tests the filter method.""" dataset = ChoiceDataset( - items_features=items_features, - sessions_features=sessions_features, - sessions_items_features=sessions_items_features, - sessions_items_availabilities=sessions_items_availabilities, + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) filtered_dataset = dataset.filter([True, False, True]) diff --git a/tests/unit_tests/data/test_store.py b/tests/unit_tests/data/test_store.py index d1fd3df8..9fdd1767 100644 --- a/tests/unit_tests/data/test_store.py +++ b/tests/unit_tests/data/test_store.py @@ -1,133 +1,204 @@ """Test the store module.""" -from choice_learn.data.store import FeaturesStore, OneHotStore, Store +import numpy as np +import pandas as pd + +from choice_learn.data.storage import FeaturesStorage, OneHotStorage def test_len_store(): - """Test the __len__ method of Store.""" - store = Store(values=[1, 2, 3, 4], sequence=[0, 1, 2, 3, 0, 1, 2, 3]) - assert len(store) == 8 + """Test the __len__ method of Storage.""" + features = {"customerA": [1, 2], "customerB": [4, 5], "customerC": [7, 8]} + storage = FeaturesStorage( + values=features, values_names=["age", "income", "children_nb"], name="customers" + ) + assert len(storage) == 3 + assert storage.shape == (3, 2) def test_get_store_element(): """Test the _get_store_element method of Store.""" - store = Store(values=[1, 2, 3, 4], sequence=[0, 1, 2, 3, 0, 1, 2, 3]) - assert store._get_store_element(0) == 1 - assert store._get_store_element([0, 1, 2]) == [1, 2, 3] + features = {"customerA": [1, 2], "customerB": [4, 5], "customerC": [7, 8]} + storage = FeaturesStorage( + values=features, values_names=["age", "income", "children_nb"], name="customers" + ) + assert (storage.get_element_from_index(0) == np.array([1, 2])).all() + assert (storage.get_element_from_index([0, 1, 2]) == np.array([[1, 2], [4, 5], [7, 8]])).all() def test_store_batch(): """Test the batch method of Store.""" - store = Store(values=[1, 2, 3, 4], sequence=[0, 1, 2, 3, 0, 1, 2, 3]) - assert store.batch[1] == 2 - assert store.batch[2:4] == [3, 4] - assert store.batch[[2, 3, 6, 7]] == [3, 4, 3, 4] + features = {"customerA": [1, 2], "customerB": [4, 5], "customerC": [7, 8]} + storage = FeaturesStorage( + values=features, values_names=["age", "income", "children_nb"], name="customers" + ) + assert (storage.batch["customerA"] == np.array([1, 2])).all() + assert ( + storage.batch[["customerA", "customerC", "customerA", "customerC"]] + == np.array([[1, 2], [7, 8], [1, 2], [7, 8]]) + ).all() def test_featuresstore_instantiation(): """Test the instantiation of FeaturesStore.""" - store = FeaturesStore( - values=[[10, 10], [4, 4], [2, 2], [8, 8]], - sequence=[0, 1, 2, 3, 0, 1, 2, 3], - indexes=[0, 1, 2, 3], + features = {"customerA": [1, 2], "customerB": [4, 5], "customerC": [7, 8]} + storage = FeaturesStorage( + values=features, values_names=["age", "income", "children_nb"], name="customers" ) - assert store.shape == (8, 2) - assert [store.sequence[i] == [0, 1, 2, 3, 0, 1, 2, 3][i] for i in range(8)] - assert store.store == {0: [10, 10], 1: [4, 4], 2: [2, 2], 3: [8, 8]} + + for k, v in storage.storage.items(): + assert ( + v + == { + "customerA": np.array([1, 2]), + "customerB": np.array([4, 5]), + "customerC": np.array([7, 8]), + }[k] + ).all() def test_featuresstore_instantiation_indexless(): """Test the instantiation of FeaturesStore.""" - store = FeaturesStore( - values=[[10, 10], [4, 4], [2, 2], [8, 8]], sequence=[0, 1, 2, 3, 0, 1, 2, 3] + features = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] + ids = ["customerA", "customerB", "customerC"] + + storage = FeaturesStorage( + ids=ids, values=features, values_names=["age", "income", "children_nb"], name="customers" ) - assert store.shape == (8, 2) - assert [store.sequence[i] == [0, 1, 2, 3, 0, 1, 2, 3][i] for i in range(8)] - assert store.store == {0: [10, 10], 1: [4, 4], 2: [2, 2], 3: [8, 8]} + assert storage.shape == (3, 3) + for k, v in storage.storage.items(): + assert ( + v + == { + "customerA": np.array([1, 2, 3]), + "customerB": np.array([4, 5, 6]), + "customerC": np.array([7, 8, 9]), + }[k] + ).all() def test_featuresstore_instantiation_from_list(): """Test the instantiation of FeaturesStore.""" - store = FeaturesStore.from_list( - values_list=[[10, 10], [4, 4], [2, 2], [8, 8]], sequence=[0, 1, 2, 3, 0, 1, 2, 3] + features = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] + + storage = FeaturesStorage( + values=features, values_names=["age", "income", "children_nb"], name="customers" ) - assert store.shape == (8, 2) - assert [store.sequence[i] == [0, 1, 2, 3, 0, 1, 2, 3][i] for i in range(8)] - assert store.store == {0: [10, 10], 1: [4, 4], 2: [2, 2], 3: [8, 8]} + storage.batch[[0, 2, 0, 2]] + assert storage.shape == (3, 3) + for k, v in storage.storage.items(): + assert ( + v == {0: np.array([1, 2, 3]), 1: np.array([4, 5, 6]), 2: np.array([7, 8, 9])}[k] + ).all() def test_featuresstore_instantiation_fromdict(): """Test the instantiation of FeaturesStore.""" - store = FeaturesStore.from_dict( - values_dict={0: [10, 10], 1: [4, 4], 2: [2, 2], 3: [8, 8]}, - sequence=[0, 1, 2, 3, 0, 1, 2, 3], - ) - assert store.shape == (8, 2) - assert [store.sequence[i] == [0, 1, 2, 3, 0, 1, 2, 3][i] for i in range(8)] - assert store.store == {0: [10, 10], 1: [4, 4], 2: [2, 2], 3: [8, 8]} + features = { + "age": [1, 4, 7], + "income": [2, 5, 8], + "children_nb": [3, 6, 9], + "id": ["customerA", "customerB", "customerC"], + } + features = pd.DataFrame(features) + storage = FeaturesStorage(values=features, name="customers") + assert storage.shape == (3, 3) + for k, v in storage.storage.items(): + assert ( + v + == { + "customerA": np.array([1, 2, 3]), + "customerB": np.array([4, 5, 6]), + "customerC": np.array([7, 8, 9]), + }[k] + ).all() + + +def test_featuresstore_instantiation_fromdf(): + """Test the instantiation of FeaturesStore.""" + features = {"age": [1, 4, 7], "income": [2, 5, 8], "children_nb": [3, 6, 9]} + features = pd.DataFrame(features, index=["customerA", "customerB", "customerC"]) + storage = FeaturesStorage(values=features, name="customers") + assert storage.shape == (3, 3) + for k, v in storage.storage.items(): + assert ( + v + == { + "customerA": np.array([1, 2, 3]), + "customerB": np.array([4, 5, 6]), + "customerC": np.array([7, 8, 9]), + }[k] + ).all() def test_featuresstore_getitem(): """Test the __getitem__ method of FeaturesStore.""" - store = FeaturesStore.from_dict( - values_dict={0: [10, 10], 1: [4, 4], 2: [2, 2], 3: [8, 8]}, - sequence=[0, 1, 2, 3, 0, 1, 2, 3], + features = {"customerA": [1, 2], "customerB": [4, 5], "customerC": [7, 8]} + storage = FeaturesStorage( + values=features, values_names=["age", "income", "children_nb"], name="customers" ) - sub_store = store[0:3] - assert sub_store.shape == (3, 2) - assert [sub_store.sequence[i] == [0, 1, 2][i] for i in range(3)] - assert sub_store.store == {0: [10, 10], 1: [4, 4], 2: [2, 2]} + sub_storage = storage[["customerA", "customerC"]] + assert sub_storage.shape == (2, 2) + for k, v in {"customerA": np.array([1, 2]), "customerC": np.array([7, 8])}.items(): + print(v, sub_storage.storage[k]) + assert (v == sub_storage.storage[k]).all() def test_onehotstore_instantiation(): """Test the instantiation of OneHotStore.""" - indexes = [0, 1, 2, 4] - values = [0, 1, 2, 3] - sequence = [0, 1, 2, 4, 0, 1, 2, 4] - store = OneHotStore(indexes=indexes, values=values, sequence=sequence) - assert store.shape == (8, 4) - assert [store.sequence[i] == [0, 1, 2, 4, 0, 1, 2, 4][i] for i in range(8)] - assert store.store == {0: 0, 1: 1, 2: 2, 4: 3} + ids = [0, 1, 2, 3, 4] + values = [4, 3, 2, 1, 0] + storage = OneHotStorage(ids=ids, values=values, name="OneHotTest") + assert storage.shape == (5, 5) + assert storage.storage == {0: 4, 1: 3, 2: 2, 3: 1, 4: 0} def test_onehotstore_instantiation_from_sequence(): """Test the instantiation; from_sequence of OneHotStore.""" - sequence = [0, 1, 2, 3, 0, 1, 2, 3] - store = OneHotStore.from_sequence(sequence=sequence) - assert store.shape == (8, 4) - assert [store.sequence[i] == [0, 1, 2, 3, 0, 1, 2, 3][i] for i in range(8)] - assert store.store == {0: 0, 1: 1, 2: 2, 3: 3} + values = [4, 3, 2, 1, 0] + storage = OneHotStorage(values=values, name="OneHotTest") + assert ( + storage.batch[[0, 2, 4]] == np.array([[0, 0, 0, 0, 1], [0, 0, 1, 0, 0], [1, 0, 0, 0, 0]]) + ).all() + assert storage.storage == {4: 0, 3: 1, 2: 2, 1: 3, 0: 4} -def test_onehotstore_getitem(): - """Test the getitem of OneHotStore.""" - indexes = [0, 1, 2, 4] - values = [0, 1, 2, 3] - sequence = [0, 1, 2, 4, 0, 1, 2, 4] - store = OneHotStore(indexes=indexes, values=values, sequence=sequence) - sub_store = store[0:3] - assert sub_store.shape == (3, 3) - assert [ - sub_store.sequence[i] == [0, 1, 2, 3, 0, 1, 2, 3][i] for i in range(len(sub_store.sequence)) - ] - assert sub_store.store == { - 0: 0, - 1: 1, - 2: 2, - } +def test_onehotstore_instantiation_from_ids(): + """Test the instantiation; from_sequence of OneHotStore.""" + ids = [0, 1, 2, 3, 4] + storage = OneHotStorage(ids=ids, name="OneHotTest") + assert ( + storage.batch[[0, 2, 4]] == np.array([[1, 0, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 0, 1]]) + ).all() + assert storage.storage == {0: 0, 1: 1, 2: 2, 3: 3, 4: 4} -def test_onehotstore_batch(): - """Test the getitem of OneHotStore.""" - indexes = [0, 1, 2, 4] - values = [0, 1, 2, 3] - sequence = [0, 1, 2, 4, 0, 1, 2, 4] - store = OneHotStore(indexes=indexes, values=values, sequence=sequence) - - batch = store.batch[0] - assert (batch == [1, 0, 0, 0]).all() +def test_onehotstore_instantiation_from_dict(): + """Test the instantiation; from_sequence of OneHotStore.""" + ids = [0, 1, 2, 3, 4] + values = [4, 3, 2, 1, 0] + values_dict = {k: v for k, v in zip(ids, values)} + storage = OneHotStorage(values=values_dict, name="OneHotTest") + assert ( + storage.batch[[0, 2, 4]] == np.array([[0, 0, 0, 0, 1], [0, 0, 1, 0, 0], [1, 0, 0, 0, 0]]) + ).all() + assert storage.storage == {4: 0, 3: 1, 2: 2, 1: 3, 0: 4} - batch = store.batch[0:4] - assert (batch == [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]).all() - batch = store.batch[[3, 6, 7]] - assert (batch == [[0, 0, 0, 1], [0, 0, 1, 0], [0, 0, 0, 1]]).all() +def test_onehotstore_getitem(): + """Test the getitem of OneHotStore.""" + ids = [0, 1, 2, 3, 4] + values = [4, 3, 2, 1, 0] + storage = OneHotStorage(ids=ids, values=values, name="OneHotTest") + assert ( + storage.batch[[0, 2, 4]] == np.array([[0, 0, 0, 0, 1], [0, 0, 1, 0, 0], [1, 0, 0, 0, 0]]) + ).all() + assert storage.get_element_from_index(0) == 4 + + +def test_fail_instantiation(): + """Testing failed instantiation.""" + try: + _ = OneHotStorage(name="OneHotTest") + assert False + except ValueError: + assert True From dc6fdf3a397f21756386d61c09bd1b263bebde34 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 15 Jan 2024 15:59:06 +0100 Subject: [PATCH 067/767] FIX: mkdocs after wrong merge --- mkdocs.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mkdocs.yaml b/mkdocs.yaml index b9054fe2..93d3cd97 100644 --- a/mkdocs.yaml +++ b/mkdocs.yaml @@ -36,9 +36,10 @@ markdown_extensions: - pymdownx.superfences - mdx_math -plugins: -- extra_javascript: +extra_javascript: - https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js?config=TeX-AMS-MML_HTMLorMML + +plugins: - mkdocstrings: handlers: python: From 66e9b8c0d1307408de8204c706e71489105a30d3 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 16 Jan 2024 15:24:00 +0100 Subject: [PATCH 068/767] ENH: now availabilities can be computed from split DF --- choice_learn/data/choice_dataset.py | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index b03b17c4..2dc62582 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -67,7 +67,6 @@ def __init__( if choices is None: # Done to keep a logical order of arguments, and has logic: choices have to be specified raise ValueError("Choices must be specified, got None") - choices = np.array(choices) # --------- [ Handling features type given as tuples or not ] --------- # # If items_features is not given as tuple, transform it internally as a tuple @@ -223,13 +222,25 @@ def __init__( # Ordering choices by id ? if "context_id" in feature.columns: if "item_id" in feature.columns: + all_items = np.sort(feature.item_id.unique()) feature_array = [] + temp_availabilities = [] for sess in np.sort(feature.context_id.unique()): sess_df = feature.loc[feature.context_id == sess] sess_df = sess_df[ sess_df.columns.difference(["context_id"]) ].set_index("item_id") - feature_array.append(sess_df.loc[np.sort(sess_df.index)].to_numpy()) + sess_feature = [] + sessions_availabilities = [] + for item in all_items: + if item in sess_df.index: + sess_feature.append(sess_df.loc[item].to_numpy()) + sessions_availabilities.append(1) + else: + sess_feature.append(np.zeros(len(sess_df.columns))) + sessions_availabilities.append(0) + feature_array.append(sess_feature) + temp_availabilities.append(sessions_availabilities) contexts_items_features = ( contexts_items_features[:i] + (np.stack(feature_array, axis=0),) @@ -240,6 +251,11 @@ def __init__( + (sess_df.columns,) + contexts_items_features_names[i + 1 :] ) + if ( + contexts_items_availabilities is None + and len(np.unique(temp_availabilities)) > 1 + ): + contexts_items_availabilities = np.array(temp_availabilities) else: feature = feature.set_index("context_id") contexts_items_features = ( @@ -271,7 +287,7 @@ def __init__( av_array = [] for sess in np.sort(contexts_items_availabilities.context_id): sess_df = contexts_items_availabilities.loc[ - contexts_items_availabilities.context__id == sess + contexts_items_availabilities.context_id == sess ] sess_df = sess_df.set_index("item_id") av_array.append(sess_df.loc[np.sort(sess_df.index)].to_numpy()) @@ -293,6 +309,9 @@ def __init__( items = np.sort(np.unique(choices.choice)) # items is the value (str) of the item choices = [np.where(items == c)[0] for c in choices.choice] + choices = np.squeeze(choices) + elif isinstance(choices, list): + choices = np.array(choices) # Setting attributes of ChoiceDataset self.fixed_items_features = fixed_items_features @@ -835,6 +854,7 @@ def summary(self): else: print("No sessions items features registered") print("%=====================================================================%") + return "" def get_choices_batch(self, choices_indexes, features=None): """Method to access data within the ListChoiceDataset from its index. From 3ac4a31efadaf7ccbe26a695f27efea250054486 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 16 Jan 2024 15:24:48 +0100 Subject: [PATCH 069/767] ADD: several loading mode for modeCanada so that the example is prettier and can always use it --- choice_learn/datasets/base.py | 111 ++++++++++++++++++++++++++++++++-- 1 file changed, 107 insertions(+), 4 deletions(-) diff --git a/choice_learn/datasets/base.py b/choice_learn/datasets/base.py index e31b0782..fbd42e7d 100644 --- a/choice_learn/datasets/base.py +++ b/choice_learn/datasets/base.py @@ -191,26 +191,44 @@ def load_swissmetro( ) -def load_modecanada(add_items_one_hot=False, as_frame=False, return_desc=False): +def load_modecanada( + add_items_one_hot=False, + add_is_public=False, + as_frame=False, + return_desc=False, + choice_mode="one_zero", + split_features=False, + to_wide=False, +): """Load and return the ModeCanada dataset from Koppleman et al. (1993). Parameters ---------- one_hot_cat_data : bool, optional - Whether to transform categorical data as OneHot, by default False + Whether to transform categorical data as OneHot, by default False. + add_is_public : bool, optional + Whether to add the is_public feature, by default False. add_items_one_hot : bool, optional Whether to add a OneHot encoding of items as items_features, by default False as_frame : bool, optional Whether to return the dataset as pd.DataFrame. If not, returned as ChoiceDataset, - by default False + by default False. return_desc : bool, optional - Whether to return the description, by default False + Whether to return the description, by default False. + choice_mode : str, optional, among ["one_zero", "items_id"] + mode indicating how the choice is encoded, by default "one_zero". + split_features : bool, optional + Whether to split features by type in different dataframes, by default False. + to_wide : bool, optional + Whether to return the dataset in wide format, + by default False (an thus retuned in long format). Returns: -------- ChoiceDataset Loaded ModeCanada dataset """ + _ = to_wide data_file_name = "ModeCanada.csv.gz" names, data = load_gzip(data_file_name) names = [name.replace('"', "") for name in names] @@ -242,6 +260,11 @@ def load_modecanada(add_items_one_hot=False, as_frame=False, return_desc=False): else: items_features = None + if add_is_public: + canada_df["is_public"] = canada_df.apply( + lambda row: 0.0 if row.alt == "car" else 1.0, axis=1 + ) + if return_desc: # TODO pass @@ -249,9 +272,89 @@ def load_modecanada(add_items_one_hot=False, as_frame=False, return_desc=False): for col in canada_df.columns: canada_df[col] = pd.to_numeric(canada_df[col], errors="ignore") + if choice_mode == "items_id": + # We need to transform how the choice is encoded to add the chosen item id + named_choice = [0] * len(canada_df) + for n_row, row in canada_df.iterrows(): + if row.choice == 0: + sub_df = canada_df[canada_df.case == row.case] + choice = sub_df.loc[sub_df.choice == 1].alt.to_numpy()[0] + named_choice[n_row - 1] = choice + + for n_row, row in canada_df.iterrows(): + if row.choice == 1: + named_choice[n_row - 1] = row.alt + + canada_df["choice"] = named_choice + if as_frame: + if split_features: + if add_is_public: + fixed_items_features = pd.DataFrame( + {"item_id": ["car", "train", "bus", "air"], "is_public": [0, 1, 1, 1]} + ) + else: + fixed_items_features = None + contexts_features = canada_df[["case", "income", "dist", "urban"]].drop_duplicates() + contexts_features = contexts_features.rename(columns={"case": "context_id"}) + + contexts_items_features = canada_df[["case", "alt", "freq", "cost", "ivt", "ovt"]] + contexts_items_features = contexts_items_features.rename( + columns={"case": "context_id", "alt": "item_id"} + ) + + choices = canada_df.loc[canada_df.choice == 1][["case", "alt"]] + choices = choices.rename(columns={"case": "context_id", "alt": "choice"}) + + return fixed_items_features, contexts_features, contexts_items_features, choices return canada_df + if split_features: + # Order of item_id is alphabetical: air, bus, car, train + if add_is_public: + fixed_items_features = np.array([[1.0], [1.0], [0.0], [1.0]]) + else: + fixed_items_features = None + contexts_features = ( + canada_df[["case", "income", "dist", "urban"]] + .drop_duplicates()[["income", "dist", "urban"]] + .to_numpy() + ) + + cif = [] + ci_av = [] + for context in canada_df.case.unique(): + context_df = canada_df.loc[canada_df.case == context] + # Order of item_id is alphabetical: air, bus, car, train + cf = [] + cav = [] + for item in ["air", "bus", "car", "train"]: + if item in context_df.alt.unique(): + cf.append( + context_df.loc[context_df.alt == item][ + ["freq", "cost", "ivt", "ovt"] + ].to_numpy()[0] + ) + cav.append(1) + else: + cf.append([0.0, 0.0, 0.0, 0.0]) + cav.append(0) + cif.append(cf) + ci_av.append(cav) + contexts_items_features = np.array(cif) + contexts_items_availabilities = np.array(ci_av) + + choices = np.squeeze(canada_df.loc[canada_df.choice == 1]["alt"].to_numpy()) + choices = np.array([["air", "bus", "car", "train"].index(c) for c in choices]) + + return ( + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, + ) + return ChoiceDataset.from_single_df( df=canada_df, items_features_columns=items_features, From 996b4055ad56c76dbfa9ace80e450e52a1c23060 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 16 Jan 2024 15:25:21 +0100 Subject: [PATCH 070/767] ENH: re updaed all methods for CD creation --- notebooks/dataset_creation.ipynb | 196 ++++++++++++++++++++++--------- 1 file changed, 139 insertions(+), 57 deletions(-) diff --git a/notebooks/dataset_creation.ipynb b/notebooks/dataset_creation.ipynb index 9fb255a1..efc5581b 100644 --- a/notebooks/dataset_creation.ipynb +++ b/notebooks/dataset_creation.ipynb @@ -19,6 +19,7 @@ "import sys\n", "from pathlib import Path\n", "\n", + "\n", "sys.path.append(\"../\")\n", "\n", "import numpy as np\n", @@ -43,8 +44,8 @@ "source": [ "from choice_learn.datasets import load_modecanada, load_swissmetro\n", "\n", - "canada_transport_df = load_modecanada(as_frame=True)\n", - "print(canada_transport_df.head())" + "canada_df = load_modecanada(as_frame=True, add_is_public=True)\n", + "canada_df.head()" ] }, { @@ -54,17 +55,6 @@ "Let's create a column indicating whether the considered transport alternative is individual or not transport." ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "canada_transport_df[\"is_individual\"] = canada_transport_df.apply(lambda row: 1 if row.alt ==\"car\" else 0,\n", - " axis=1)\n", - "print(canada_transport_df.head())" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -78,14 +68,15 @@ "metadata": {}, "outputs": [], "source": [ - "dataset = ChoiceDataset.from_single_df(df=canada_transport_df,\n", - " fixed_items_features_columns=[\"is_individual\"],\n", - " contexts_features_columns=[\"income\"],\n", - " contexts_items_features_columns=[\"dist\", \"cost\", \"ivt\", \"ovt\"],\n", + "dataset = ChoiceDataset.from_single_df(df=canada_df,\n", + " fixed_items_features_columns=[\"is_public\"],\n", + " contexts_features_columns=[\"dist\", \"income\", \"urban\"],\n", + " contexts_items_features_columns=[\"freq\", \"cost\", \"ivt\", \"ovt\"],\n", " items_id_column=\"alt\",\n", " contexts_id_column=\"case\",\n", " choices_column=\"choice\",\n", - " choice_mode=\"one_zero\", # the choice columns indicates if the item is chosen (1) or not (0)\n", + " # the choice columns indicates if the item is chosen (1) or not (0)\n", + " choice_mode=\"one_zero\",\n", " )\n", "print(dataset.summary())" ] @@ -103,21 +94,16 @@ "metadata": {}, "outputs": [], "source": [ - "id_df = canada_transport_df.copy(deep=True)\n", - "one_hot_choice = [0] * len(id_df)\n", - "for n_row, row in id_df.iterrows():\n", - " if row.choice == 0:\n", - " sub_df = id_df[id_df.case == row.case]\n", - " choice = sub_df.loc[sub_df.choice == 1].alt.to_numpy()[0]\n", - " one_hot_choice[n_row-1] = choice\n", - "\n", - "for n_row, row in id_df.iterrows():\n", - " if row.choice == 1:\n", - " one_hot_choice[n_row-1] = row.alt\n", - "\n", - "id_df[\"one_hot_choice\"] = one_hot_choice\n", - "\n", - "print(id_df.head())\n" + "canada_df = load_modecanada(as_frame=True, add_is_public=True, choice_mode=\"items_id\")\n", + "canada_df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This time, the choice is not given by ones and zeros but actually names for each context which alternative (item) has been chosen.\n", + "The ChoiceDataset handles this case easily, by specifying 'choice_mode=\"items_id\"'." ] }, { @@ -126,14 +112,15 @@ "metadata": {}, "outputs": [], "source": [ - "dataset = ChoiceDataset.from_single_df(df=id_df,\n", - " fixed_items_features_columns=[\"is_individual\"],\n", - " contexts_features_columns=[\"income\"],\n", - " contexts_items_features_columns=[\"dist\", \"cost\", \"ivt\", \"ovt\"],\n", + "dataset = ChoiceDataset.from_single_df(df=canada_df,\n", + " fixed_items_features_columns=[\"is_public\"],\n", + " contexts_features_columns=[\"dist\", \"income\", \"urban\"],\n", + " contexts_items_features_columns=[\"freq\", \"cost\", \"ivt\", \"ovt\"],\n", " items_id_column=\"alt\",\n", " contexts_id_column=\"case\",\n", - " choices_column=\"one_hot_choice\",\n", - " choice_mode=\"items_id\", # the choice columns indicates if the item is chosen (1) or not (0)\n", + " choices_column=\"choice\",\n", + " # the choice columns indicates the id of the chosen item\n", + " choice_mode=\"items_id\",\n", " )\n", "print(dataset.summary())" ] @@ -142,16 +129,15 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now, let's say that you have your data split into several files:" + "### From several DataFrames" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "canada_transport_df.alt.unique()" + "Now, let's say that you have your data split into several files. It can happen if you store the different type of features in different SQL Tables for example.\n", + "You will only need to follow some restrictions:" ] }, { @@ -160,10 +146,15 @@ "metadata": {}, "outputs": [], "source": [ - "fixed_items_features = pd.DataFrame({\"item_id\": [\"car\", \"train\", \"bus\", \"air\"],\n", - " \"is_individual\": [1, 0, 0, 0]})\n", - "# The item_id column is necessery, otherwise it will keep the order\n", - "# however it is less safe with pd.DataFrame" + "fixed_items_features, contexts_features, contexts_items_features, choices =\\\n", + "load_modecanada(as_frame=True, split_features=True, add_is_public=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "fixed_items_features need to have a column named \"item_id\" referencing the item. Others columns are free to be any feature." ] }, { @@ -172,9 +163,14 @@ "metadata": {}, "outputs": [], "source": [ - "contexts_features = canada_transport_df[[\"case\", \"income\"]].drop_duplicates()\n", - "contexts_features = contexts_features.rename(columns={\"case\": \"context_id\"})\n", - "# If the context_id column does not exist, the index is used" + "fixed_items_features.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "contexts_features need to have a \"context_id\" column (otherwise index is used). Other columns are free to be any feature." ] }, { @@ -183,8 +179,15 @@ "metadata": {}, "outputs": [], "source": [ - "contexts_items_features = canada_transport_df[[\"case\", \"alt\", \"dist\", \"cost\", \"ivt\", \"ovt\"]]\n", - "contexts_items_features = contexts_items_features.rename(columns={\"case\": \"context_id\", \"alt\": \"item_id\"})" + "contexts_features.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "contexts_items_features need to have the column \"item_id\" and is recommended to have the column \"context_id\" (otherwise index is used).\\\n", + "Of course \"item_id\" and \"context_id\" should match fixed_items_features and contexts_features." ] }, { @@ -193,7 +196,14 @@ "metadata": {}, "outputs": [], "source": [ - "canada_transport_df" + "contexts_items_features.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "choices should have a column \"context_id\" and a column \"choice\". The value in \"choice\" should match the values in the column \"item_id\" in items_features and contexts_items_features." ] }, { @@ -202,7 +212,7 @@ "metadata": {}, "outputs": [], "source": [ - "choices = canada_transport_df.loc[canada_transport_df.choice==1][[\"case\", \"alt\"]]" + "choices.head()" ] }, { @@ -211,10 +221,26 @@ "metadata": {}, "outputs": [], "source": [ + "# And now you can create the dataset with:\n", "dataset = ChoiceDataset(fixed_items_features=fixed_items_features,\n", " contexts_features=contexts_features,\n", " contexts_items_features=contexts_items_features,\n", - " choices=choices)" + " choices=choices)\n", + "print(dataset.summary())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### From several np.ndarrays" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, another alternative is to specify each type of feature as np.ndarrays. You can or not also give features names. It is not necessary unless you plan to use a model with specification w.r.t. to those features names." ] }, { @@ -222,7 +248,63 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "fixed_items_features, contexts_features, contexts_items_features, contexts_items_availabilities, choices =\\\n", + "load_modecanada(split_features=True, add_is_public=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you are using this method, it is your job to make sure that the arrays are well organized.\\\n", + "First, contexts_features, contexts_items_features, contexts_items_availabilities and choices must be in the right order and their dimension (first one) must match.\\\n", + "Second, fixed_items_features, contexts_items_availabilities and contexts_items_features must also have the same number of items and ordered the sames. Only it must be on the first dimension of fixed_items_features and the second one of contexts_items_features and contexts_items_availabilities.\\\n", + "Third, choices must indicate the index of the chosen item as ordered in fixed_items_features and contexts_items_features.\n", + "Finally you have to precise the contexts_items_availabilities, or which items were available (1) or not (0) for each context/choice.\n", + "\n", + "To summarize the shape of the arrays must be:\n", + "- (n_items, n_fixed_items_features) for fixed_items_features\n", + "- (n_choices, n_contexts_features) for contexts_features\n", + "- (n_choices, n_items, n_contexts_items_features) for contexts_items_features\n", + "- (n_choices, n_items) for contexts_items_availabilities\n", + "- (n_choices, ) for choice\n", + "\n", + "*Reminder:* One context corresponds to one choice." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\"For our example here are the arrays shapes:\")\n", + "print(f\"Fixed Items Features shape: {fixed_items_features.shape}, 4 items, 1 feature (is_public)\")\n", + "print(f\"Contexts Features shape: {contexts_features.shape}, 4324 choices, 3 features (income, dist, urban)\")\n", + "print(f\"Contexts Items Features shape: {contexts_items_features.shape}, 4324 choices, 4 items, 4 features (freq, cost, ivt, ovt)\")\n", + "print(f\"Contexts Items Availabilities shape: {contexts_items_availabilities.shape}, 4324 choices, 4 items\")\n", + "print(f\"Choices shape: {choices.shape}, 4324 choices\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset = ChoiceDataset(fixed_items_features=fixed_items_features,\n", + " contexts_features=contexts_features,\n", + " contexts_items_features=contexts_items_features,\n", + " choices=choices,\n", + " contexts_items_availabilities=contexts_items_availabilities,\n", + " # We can give the name of the features as follows, with the right order:\n", + " fixed_items_features_names=[\"is_public\"],\n", + " contexts_features_names=[\"income\", \"dist\", \"urban\"],\n", + " contexts_items_features_names=[\"freq\", \"cost\", \"ivt\", \"ovt\"],\n", + " )\n", + "print(dataset.summary())" + ] }, { "cell_type": "code", From c9ba611f1f574236a0252cffe2177823214145d3 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 16 Jan 2024 15:25:54 +0100 Subject: [PATCH 071/767] ENH: some better data doc --- .../choice_learn_introduction_data.ipynb | 150 +++++++++++------- 1 file changed, 96 insertions(+), 54 deletions(-) diff --git a/notebooks/choice_learn_introduction_data.ipynb b/notebooks/choice_learn_introduction_data.ipynb index 55bec28d..672613e8 100644 --- a/notebooks/choice_learn_introduction_data.ipynb +++ b/notebooks/choice_learn_introduction_data.ipynb @@ -27,23 +27,36 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### ChoiceDataset - Getting Started (Fast-track start ??)\n", + "### ChoiceDataset - Getting Started !\n", "\n", - "choice-learn package aims at being able to handle large datasets. It uses a data structure similar to the one defined in the torch-choice package.\n", + "choice-learn package aims at being able to handle large datasets. One of the main idea is to limit as much as possible the usage of memory to save several time the same feature.\n", + "We define two sources of features, the items and the contexts.\n", "\n", - "Particularly, it defines 5 types of different data, storing them separatly in order to avoid redundancy in memory:\n", + "**Items** represent a product, an alternative that can be chosen by the customer at some point.\n", "\n", - "- items_features: features of considered items that never change (e.g. size, color, etc...)\n", - "- session_features: features that depend on the session (time) of the choice and that are common to all items (e.g. day of week, etc...)\n", - "- session_items_features: features that depend on the item and on the session (e.g. price)\n", + "**Contexts** represent the different cases of the dataset. One context corresponds to one choice and regroups every factor that might be different from one choice to another.\n", "\n", - "- items_sessions_availabilities: For each session whether the item it present (1.) or not (0.)\n", - "- choices: chosen item among available ones\n", + "\n", + "From these two concepts, we defines 5 different types of data, storing them separatly in order to avoid redundancy in memory:\n", + "\n", + "- **choices:** The main information, indicating which item/alternative has been chosen among all availables\n", + "- **fixed_items_features:** The items features that never change (e.g. size, color, etc...) over the choices/contexts.\n", + "- **contexts_features:** It represents all the features that might change from one choice to another and that are **common** to all items (e.g. day of week, customer features, etc...)\n", + "- **contexts_items_features:** The features that are function of the item and of the context (e.g. prices change over contexts and are specific to each sold item, etc...)\n", + "\n", + "- **contexts_items_availabilities:** For each context it represents whether each item/alternative is proposed to the customer (1.) or not (0.).\n", "\n", "\n", "In order to estimate a model using the choice-learn API, you will first need to wrap your dataset within a ChoiceDataset. The easiest way to do it is to use a pandas DataFrame, let's see how to do it !" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will use the ModeCanada [1] dataset for this example. It is provided with the choice-learn package and can loaded as follows:" + ] + }, { "cell_type": "code", "execution_count": null, @@ -51,13 +64,6 @@ "keep_output": true }, "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Let's look at the dataframe:\n" - ] - }, { "data": { "text/html": [ @@ -103,7 +109,7 @@ " 50\n", " 66\n", " 4\n", - " 45\n", + " 45.0\n", " 0\n", " 2\n", " \n", @@ -117,7 +123,7 @@ " 61\n", " 0\n", " 0\n", - " 45\n", + " 45.0\n", " 0\n", " 2\n", " \n", @@ -131,7 +137,7 @@ " 50\n", " 66\n", " 4\n", - " 25\n", + " 25.0\n", " 0\n", " 2\n", " \n", @@ -145,7 +151,7 @@ " 61\n", " 0\n", " 0\n", - " 25\n", + " 25.0\n", " 0\n", " 2\n", " \n", @@ -159,7 +165,7 @@ " 50\n", " 66\n", " 4\n", - " 70\n", + " 70.0\n", " 0\n", " 2\n", " \n", @@ -169,11 +175,11 @@ ], "text/plain": [ " case alt choice dist cost ivt ovt freq income urban noalt\n", - "1 1 train 0 83 28.25 50 66 4 45 0 2\n", - "2 1 car 1 83 15.77 61 0 0 45 0 2\n", - "3 2 train 0 83 28.25 50 66 4 25 0 2\n", - "4 2 car 1 83 15.77 61 0 0 25 0 2\n", - "5 3 train 0 83 28.25 50 66 4 70 0 2" + "1 1 train 0 83 28.25 50 66 4 45.0 0 2\n", + "2 1 car 1 83 15.77 61 0 0 45.0 0 2\n", + "3 2 train 0 83 28.25 50 66 4 25.0 0 2\n", + "4 2 car 1 83 15.77 61 0 0 25.0 0 2\n", + "5 3 train 0 83 28.25 50 66 4 70.0 0 2" ] }, "execution_count": null, @@ -183,12 +189,9 @@ ], "source": [ "from choice_learn.data import ChoiceDataset\n", + "from choice_learn.datasets import load_modecanada\n", "\n", - "# path to dataset file is:\n", - "filepath = \"choice_learn/datasets/data/ModeCanada.csv.gz\"\n", - "canada_transport_df = pd.read_csv((Path(\"..\") / filepath), index_col=0)\n", - "\n", - "print(\"Let's look at the dataframe:\")\n", + "canada_transport_df = load_modecanada(as_frame=True)\n", "canada_transport_df.head()" ] }, @@ -196,9 +199,42 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This dataframe is the raw version of the Canada Transport Dataset \\cite. We need to follow some specifications in order to use it as a ChoiceDataset.\n", + "An extensive description of the dataset can be found [here](https://www.ssc.wisc.edu/~bhansen/econometrics/Koppelman_description.pdf).\n", + "An extract indicates:\n", + "\n", + "\"The dataset was assembled in 1989 by VIA Rail (the Canadian national rail carrier) to estimate the demand for high-speed rail in the Toronto-Montreal corridor. The main information source was a Passenger Review administered to business travelers augmented by information about each trip. The observations consist of a choice between four modes of transportation (train, air, bus, car) with information about the travel mode and about the passenger. The posted dataset has been balanced to only include cases where all four travel modes are recorded. The file contains 11,116 observations on 2779 individuals. \"\n", + "\n", + "Alright !\n", + "If we go back to our dataframe, we can see the following columns:\n", + "- case: an ID of the traveler\n", + "- alt: the alternative concerned by the row\n", + "- choice: 1 if the alternative was chosen, 0 otherwise\n", + "- dist: trip distance\n", + "- cost: trip cost\n", + "- ivt: travel time in-vehicule (minutes)\n", + "- ovt: travel time out-vehicule (minutes)\n", + "- income: housold income of traveler ($)\n", + "- urban: 1 if origin or destination is a large city\n", + "- noalt: the number of alternative among which the traveler had to chose\n", + "- freq: the frequence of the alternative (0 for car)\n", + "\n", + "Following our specification, we can see that one case corresponds to one customer thus one choice. In our choice-learn language it corresponds to \"one context\": a set of available alternatives and their features/specificites resulting in one choice.\n", + "Let's regroup our features:\n", "\n", - "The dataset does not contain any items_features (i.e. fixed features for the different items). We will create a One-Hot encoding that will be represent these items_features for the example." + "**choices**\n", + "Easy ! It is the alternative whenever the value is one.\n", + "\n", + "**contexts_features**\n", + "The income, urban and distance (also noalt which is not really a feature) features are the same for all the alternative within a context: they are contexts_features.\n", + "\n", + "**contexts_items_features**\n", + "Ivt, Ovt, cost and freq depends on the alternative and change over the contexts. They are contexts_items_features.\n", + "\n", + "**contexts_items_features**\n", + "It in not directly indicated, however it can be easily deduced. Whenever an alternative is not available, it is not precised for its case. For example for the case=1, our first context, only train and car are given as alternatives, meaning that air and bus were could not be chosen/were not available.\n", + "\n", + "Okay, but we are missing fixed_items_features... Indeed there isn't really any in this dataset. Let's create one for the example.\n", + "We will create is_public, indicating if an alternative is a public_transportation (1) or a private one (0)." ] }, { @@ -210,25 +246,28 @@ "transport_df = canada_transport_df.copy()\n", "items = [\"air\", \"bus\", \"car\", \"train\"]\n", "\n", - "transport_df[\"oh0\"] = transport_df.apply(lambda row: 1. if row.alt == items[0] else 0., axis=1)\n", - "transport_df[\"oh1\"] = transport_df.apply(lambda row: 1. if row.alt == items[1] else 0., axis=1)\n", - "transport_df[\"oh2\"] = transport_df.apply(lambda row: 1. if row.alt == items[2] else 0., axis=1)\n", - "transport_df[\"oh3\"] = transport_df.apply(lambda row: 1. if row.alt == items[3] else 0., axis=1)\n", + "transport_df[\"is_public\"] = transport_df.apply(lambda row: 0. if row.alt == \"car\" else 1., axis=1)\n", "\n", "# Just some typing\n", - "transport_df.income = transport_df.income.astype(\"float32\")" + "transport_df.income = transport_df.income.astype(\"float32\")\n", + "\n", + "# Let's take a look at our new df:\n", + "transport_df.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "In order to create the ChoiceDataset from the dataframe, we need to specify:\n", - "- the columns representing the items_features\n", - "- the columns representing the sessions_features\n", - "- the columns representing the sessions_items_features\n", + "Our feature, is_public is 0 for the car and 1 for all other alternatives, seems fine! We can now create our ChoiceDataset !\\\n", + "*Note that you do NOT need each type of feature, here the purpose was to give a complete example.*\n", + "\n", + "In order to create the ChoiceDataset from the DataFrame, we need to specify:\n", + "- the columns representing the fixed_items_features\n", + "- the columns representing the contexts_features\n", + "- the columns representing the contexts_items_features\n", "- the column where the item is identified \n", - "- the column where the session is identified\n", + "- the column where the context is identified\n", "- the column in which the choice is given\n", "\n", "For our Canada Transport example, here is how it should be done:" @@ -241,11 +280,11 @@ "outputs": [], "source": [ "dataset = ChoiceDataset.from_single_df(df=transport_df,\n", - " items_features_columns=[\"oh0\", \"oh1\", \"oh2\", \"oh3\"],\n", - " sessions_features_columns=[\"income\"],\n", - " sessions_items_features_columns=['cost', 'freq', 'ovt', 'ivt'],\n", + " fixed_items_features_columns=[\"is_public\"],\n", + " contexts_features_columns=[\"income\", \"urban\", \"dist\"],\n", + " contexts_items_features_columns=[\"cost\", \"freq\", \"ovt\", \"ivt\"],\n", " items_id_column=\"alt\",\n", - " sessions_id_column=\"case\",\n", + " contexts_id_column=\"case\",\n", " choices_column=\"choice\",\n", " choice_mode=\"one_zero\")" ] @@ -254,9 +293,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "In our case, the items_feature are the one-hot values we have created. The column 'income' represents the income of the subject and is shared by all items durint a session. It thus falls in the sessions_features category. On the contrary, 'cost', 'freq', 'ovt' and 'ivt' describe each transportation mode (items) and change for each session (or each case of the survey). They are considered sessions_items_features.\n", - "\n", - "An argument that needs to be precised is choice-mode. It precised how the choice is encoded in the dataframe. Currently two modes are availble:\n", + "I have added an argument without any warning, the \"choice_mode\". It only precises how the choice is encoded in the dataframe. Currently two modes are availble:\n", "\n", "**one_zero:**\n", "The choice column contains a 0 when the alternative/item is not chosen in the session and a 1 if it is chosen.\n", @@ -278,12 +315,15 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "dataset.sessions_features[0].shape, dataset.items_features[0].shape, dataset.sessions_items_features[0].shape" + "The ChoiceDataset is ready !\n", + "\n", + "You now have three possibilities to continue discovering the choice-learn package:\n", + "- You can directly go [here]() to the modelling tutorial if you want to understand how a first simple ConditionMNl would be implementd.\n", + "- You can go [here]() if your dataset is organized differently to see all the different ways to instantiate a ChoiceDataset. In particular it helps if you DataFrame is in the wide format or if it is splitted into several DataFrames.\n", + "- Or you can continue this current tutorial to better understand the ChoiceDataset machinery and everything there is to know about it." ] }, { @@ -942,7 +982,9 @@ { "cell_type": "markdown", "metadata": {}, - "source": [] + "source": [ + "[1] Koppelman et al. (1993), *Application and Interpretation of Nested Logit Models of Intercity Mode Choice*" + ] }, { "cell_type": "markdown", From f8248330dcfbee700dde8952b85b54b46f9478d1 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 16 Jan 2024 15:37:38 +0100 Subject: [PATCH 072/767] ADD: keepo outputs --- notebooks/dataset_creation.ipynb | 779 ++++++++++++++++++++++++++++++- 1 file changed, 754 insertions(+), 25 deletions(-) diff --git a/notebooks/dataset_creation.ipynb b/notebooks/dataset_creation.ipynb index efc5581b..2d9290d2 100644 --- a/notebooks/dataset_creation.ipynb +++ b/notebooks/dataset_creation.ipynb @@ -39,10 +39,148 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "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", + "
casealtchoicedistcostivtovtfreqincomeurbannoaltis_public
11train08328.255066445.0021.0
21car18315.77610045.0020.0
32train08328.255066425.0021.0
42car18315.77610025.0020.0
53train08328.255066470.0021.0
\n", + "
" + ], + "text/plain": [ + " case alt choice dist cost ivt ovt freq income urban noalt \\\n", + "1 1 train 0 83 28.25 50 66 4 45.0 0 2 \n", + "2 1 car 1 83 15.77 61 0 0 45.0 0 2 \n", + "3 2 train 0 83 28.25 50 66 4 25.0 0 2 \n", + "4 2 car 1 83 15.77 61 0 0 25.0 0 2 \n", + "5 3 train 0 83 28.25 50 66 4 70.0 0 2 \n", + "\n", + " is_public \n", + "1 1.0 \n", + "2 0.0 \n", + "3 1.0 \n", + "4 0.0 \n", + "5 1.0 " + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "from choice_learn.datasets import load_modecanada, load_swissmetro\n", + "from choice_learn.datasets import load_modecanada\n", "\n", "canada_df = load_modecanada(as_frame=True, add_is_public=True)\n", "canada_df.head()" @@ -65,8 +203,38 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "No features_by_ids given.\n", + "%=====================================================================%\n", + "%%% Summary of the dataset:\n", + "%=====================================================================%\n", + "Number of items: 4\n", + "Number of choices: 4324\n", + "Fixed Items Features:\n", + "1 items features\n", + "with names: (['is_public'],)\n", + "\n", + "\n", + "Sessions features:\n", + "3 session features\n", + "with names: (['dist', 'income', 'urban'],)\n", + "\n", + "\n", + "Session Items features:\n", + "4 sessions items features\n", + "with names: (['freq', 'cost', 'ivt', 'ovt'],)\n", + "%=====================================================================%\n", + "\n" + ] + } + ], "source": [ "dataset = ChoiceDataset.from_single_df(df=canada_df,\n", " fixed_items_features_columns=[\"is_public\"],\n", @@ -91,8 +259,146 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "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", + "
casealtchoicedistcostivtovtfreqincomeurbannoaltis_public
11traincar8328.255066445.0021.0
21carcar8315.77610045.0020.0
32traincar8328.255066425.0021.0
42carcar8315.77610025.0020.0
53traincar8328.255066470.0021.0
\n", + "
" + ], + "text/plain": [ + " case alt choice dist cost ivt ovt freq income urban noalt \\\n", + "1 1 train car 83 28.25 50 66 4 45.0 0 2 \n", + "2 1 car car 83 15.77 61 0 0 45.0 0 2 \n", + "3 2 train car 83 28.25 50 66 4 25.0 0 2 \n", + "4 2 car car 83 15.77 61 0 0 25.0 0 2 \n", + "5 3 train car 83 28.25 50 66 4 70.0 0 2 \n", + "\n", + " is_public \n", + "1 1.0 \n", + "2 0.0 \n", + "3 1.0 \n", + "4 0.0 \n", + "5 1.0 " + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "canada_df = load_modecanada(as_frame=True, add_is_public=True, choice_mode=\"items_id\")\n", "canada_df.head()" @@ -109,8 +415,38 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "No features_by_ids given.\n", + "%=====================================================================%\n", + "%%% Summary of the dataset:\n", + "%=====================================================================%\n", + "Number of items: 4\n", + "Number of choices: 4324\n", + "Fixed Items Features:\n", + "1 items features\n", + "with names: (['is_public'],)\n", + "\n", + "\n", + "Sessions features:\n", + "3 session features\n", + "with names: (['dist', 'income', 'urban'],)\n", + "\n", + "\n", + "Session Items features:\n", + "4 sessions items features\n", + "with names: (['freq', 'cost', 'ivt', 'ovt'],)\n", + "%=====================================================================%\n", + "\n" + ] + } + ], "source": [ "dataset = ChoiceDataset.from_single_df(df=canada_df,\n", " fixed_items_features_columns=[\"is_public\"],\n", @@ -143,7 +479,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "keep_output": true + }, "outputs": [], "source": [ "fixed_items_features, contexts_features, contexts_items_features, choices =\\\n", @@ -160,8 +498,73 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "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", + "
item_idis_public
0car0
1train1
2bus1
3air1
\n", + "
" + ], + "text/plain": [ + " item_id is_public\n", + "0 car 0\n", + "1 train 1\n", + "2 bus 1\n", + "3 air 1" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "fixed_items_features.head()" ] @@ -176,8 +579,91 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "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", + "
context_idincomedisturban
1145.0830
3225.0830
5370.0830
7470.0830
9555.0830
\n", + "
" + ], + "text/plain": [ + " context_id income dist urban\n", + "1 1 45.0 83 0\n", + "3 2 25.0 83 0\n", + "5 3 70.0 83 0\n", + "7 4 70.0 83 0\n", + "9 5 55.0 83 0" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "contexts_features.head()" ] @@ -193,8 +679,103 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "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", + "
context_iditem_idfreqcostivtovt
11train428.255066
21car015.77610
32train428.255066
42car015.77610
53train428.255066
\n", + "
" + ], + "text/plain": [ + " context_id item_id freq cost ivt ovt\n", + "1 1 train 4 28.25 50 66\n", + "2 1 car 0 15.77 61 0\n", + "3 2 train 4 28.25 50 66\n", + "4 2 car 0 15.77 61 0\n", + "5 3 train 4 28.25 50 66" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "contexts_items_features.head()" ] @@ -209,8 +790,79 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "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", + "
context_idchoice
21car
42car
63car
84car
105car
\n", + "
" + ], + "text/plain": [ + " context_id choice\n", + "2 1 car\n", + "4 2 car\n", + "6 3 car\n", + "8 4 car\n", + "10 5 car" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "choices.head()" ] @@ -218,8 +870,38 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "No features_by_ids given.\n", + "%=====================================================================%\n", + "%%% Summary of the dataset:\n", + "%=====================================================================%\n", + "Number of items: 4\n", + "Number of choices: 4324\n", + "Fixed Items Features:\n", + "1 items features\n", + "with names: (['is_public'],)\n", + "\n", + "\n", + "Sessions features:\n", + "3 session features\n", + "with names: (Index(['income', 'dist', 'urban'], dtype='object'),)\n", + "\n", + "\n", + "Session Items features:\n", + "4 sessions items features\n", + "with names: (Index(['cost', 'freq', 'ivt', 'ovt'], dtype='object'),)\n", + "%=====================================================================%\n", + "\n" + ] + } + ], "source": [ "# And now you can create the dataset with:\n", "dataset = ChoiceDataset(fixed_items_features=fixed_items_features,\n", @@ -246,7 +928,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "keep_output": true + }, "outputs": [], "source": [ "fixed_items_features, contexts_features, contexts_items_features, contexts_items_availabilities, choices =\\\n", @@ -276,8 +960,23 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "For our example here are the arrays shapes:\n", + "Fixed Items Features shape: (4, 1), 4 items, 1 feature (is_public)\n", + "Contexts Features shape: (4324, 3), 4324 choices, 3 features (income, dist, urban)\n", + "Contexts Items Features shape: (4324, 4, 4), 4324 choices, 4 items, 4 features (freq, cost, ivt, ovt)\n", + "Contexts Items Availabilities shape: (4324, 4), 4324 choices, 4 items\n", + "Choices shape: (4324,), 4324 choices\n" + ] + } + ], "source": [ "print(\"For our example here are the arrays shapes:\")\n", "print(f\"Fixed Items Features shape: {fixed_items_features.shape}, 4 items, 1 feature (is_public)\")\n", @@ -290,8 +989,38 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "No features_by_ids given.\n", + "%=====================================================================%\n", + "%%% Summary of the dataset:\n", + "%=====================================================================%\n", + "Number of items: 4\n", + "Number of choices: 4324\n", + "Fixed Items Features:\n", + "1 items features\n", + "with names: (['is_public'],)\n", + "\n", + "\n", + "Sessions features:\n", + "3 session features\n", + "with names: (['income', 'dist', 'urban'],)\n", + "\n", + "\n", + "Session Items features:\n", + "4 sessions items features\n", + "with names: (['freq', 'cost', 'ivt', 'ovt'],)\n", + "%=====================================================================%\n", + "\n" + ] + } + ], "source": [ "dataset = ChoiceDataset(fixed_items_features=fixed_items_features,\n", " contexts_features=contexts_features,\n", From 01392aba38a51a7f595ee678e656b7d581996792 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 16 Jan 2024 15:58:47 +0100 Subject: [PATCH 073/767] FIX: some important fixed --- choice_learn/data/choice_dataset.py | 29 +++++++++++++++------------- choice_learn/datasets/base.py | 30 +++++++++++++++-------------- 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index 2dc62582..a8f24135 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -752,6 +752,7 @@ def from_single_df( items_features_columns = (fixed_items_features_columns,) else: items_features = None + items_features_columns = None if contexts_features_columns is not None: contexts_features = df[ @@ -763,6 +764,7 @@ def from_single_df( contexts_features_columns = (contexts_features_columns,) else: contexts_features = None + contexts_features_columns = None ( contexts_items_features, @@ -825,34 +827,35 @@ def summary(self): "Number of choices:", len(self), ) + print("%=====================================================================%") if self.fixed_items_features is not None: - print("Fixed Items Features:") - print(f"{sum([f.shape[1] for f in self.fixed_items_features])} items features") + print(" Fixed Items Features:") + print(f" {sum([f.shape[1] for f in self.fixed_items_features])} items features") if self.fixed_items_features_names is not None: - print(f"with names: {self.fixed_items_features_names}") + print(f" with names: {self.fixed_items_features_names}") else: - print("No items features registered") + print(" No items features registered") print("\n") if self.contexts_features is not None: - print("Sessions features:") - print(f"{sum([f.shape[1] for f in self.contexts_features])} session features") + print(" Contexts features:") + print(f" {sum([f.shape[1] for f in self.contexts_features])} context features") if self.contexts_features_names is not None: - print(f"with names: {self.contexts_features_names}") + print(f" with names: {self.contexts_features_names}") else: - print("No sessions features registered") + print(" No sessions features registered") print("\n") if self.contexts_items_features is not None: - print("Session Items features:") + print(" Contexts Items features:") print( - f"{sum([f.shape[2] for f in self.contexts_items_features])} sessions \ - items features" + f""" {sum([f.shape[2] for f in self.contexts_items_features])} context + items features""" ) if self.contexts_items_features_names is not None: - print(f"with names: {self.contexts_items_features_names}") + print(f" with names: {self.contexts_items_features_names}") else: - print("No sessions items features registered") + print(" No sessions items features registered") print("%=====================================================================%") return "" diff --git a/choice_learn/datasets/base.py b/choice_learn/datasets/base.py index fbd42e7d..6e649634 100644 --- a/choice_learn/datasets/base.py +++ b/choice_learn/datasets/base.py @@ -180,14 +180,14 @@ def load_swissmetro( return pd.DataFrame(data, columns=names) return ChoiceDataset( - items_features=items_features, - sessions_features=session_features, - sessions_items_features=sessions_items_features, - sessions_items_availabilities=sessions_items_availabilities, + fixed_items_features=items_features, + contexts_features=session_features, + contexts_items_features=sessions_items_features, + contexts_items_availabilities=sessions_items_availabilities, choices=choices, - items_features_names=items_features_names, - sessions_features_names=session_features_names, - sessions_items_features_names=sessions_items_features_names, + fixed_items_features_names=items_features_names, + contexts_features_names=session_features_names, + contexts_items_features_names=sessions_items_features_names, ) @@ -239,7 +239,7 @@ def load_modecanada( items = ["air", "bus", "car", "train"] items_features = [] - session_features = ["income"] + session_features = ["income", "dist", "urban"] sessions_items_features = ["cost", "freq", "ovt", "ivt"] choice_column = "choice" @@ -257,13 +257,12 @@ def load_modecanada( lambda row: 1.0 if row.alt == items[3] else 0.0, axis=1 ) items_features = ["oh_air", "oh_bus", "oh_car", "oh_train"] - else: - items_features = None if add_is_public: canada_df["is_public"] = canada_df.apply( lambda row: 0.0 if row.alt == "car" else 1.0, axis=1 ) + items_features.append("is_public") if return_desc: # TODO @@ -355,13 +354,16 @@ def load_modecanada( choices, ) + if len(items_features) == 0: + items_features = None + return ChoiceDataset.from_single_df( df=canada_df, - items_features_columns=items_features, - sessions_features_columns=session_features, - sessions_items_features_columns=sessions_items_features, + fixed_items_features_columns=items_features, + contexts_features_columns=session_features, + contexts_items_features_columns=sessions_items_features, items_id_column="alt", - sessions_id_column="case", + contexts_id_column="case", choices_column=choice_column, choice_mode="one_zero", ) From 869b8fd8be325b2c042060772e64060d0d9fa8e5 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 16 Jan 2024 15:59:15 +0100 Subject: [PATCH 074/767] ADD: some updates on example --- .../choice_learn_introduction_data.ipynb | 344 +++++++++++------- 1 file changed, 215 insertions(+), 129 deletions(-) diff --git a/notebooks/choice_learn_introduction_data.ipynb b/notebooks/choice_learn_introduction_data.ipynb index 672613e8..23424bed 100644 --- a/notebooks/choice_learn_introduction_data.ipynb +++ b/notebooks/choice_learn_introduction_data.ipynb @@ -323,7 +323,9 @@ "You now have three possibilities to continue discovering the choice-learn package:\n", "- You can directly go [here]() to the modelling tutorial if you want to understand how a first simple ConditionMNl would be implementd.\n", "- You can go [here]() if your dataset is organized differently to see all the different ways to instantiate a ChoiceDataset. In particular it helps if you DataFrame is in the wide format or if it is splitted into several DataFrames.\n", - "- Or you can continue this current tutorial to better understand the ChoiceDataset machinery and everything there is to know about it." + "- Or you can continue this current tutorial to better understand the ChoiceDataset machinery and everything there is to know about it.\n", + "\n", + "Whatever your choice, you can also check [here](#ready-to-use-datasets) the list of open source datasets available directly with the package." ] }, { @@ -351,7 +353,7 @@ "# - price\n", "# - whether is is on promotion or not\n", "\n", - "items_features = [\n", + "fixed_items_features = [\n", " [1, 2], # item 1 [size, weight]\n", " [2, 4], # item 2 [size, weight]\n", " [1.5, 1.5], # item 3 [size, weight]\n", @@ -364,19 +366,19 @@ "# Customer 2 bought item 3 at session 2\n", "\n", "choices = [0, 2, 1]\n", - "sessions_items_availabilities = [\n", + "contexts_items_availabilities = [\n", " [1, 1, 1], # All items available at session 1\n", " [1, 1, 1], # All items available at session 2\n", " [0, 1, 1], # Item 1 not available at session 3\n", "]\n", "\n", - "sessions_features = [\n", + "contexts_features = [\n", " [100, 20], # session 1, customer 1 [budget, age]\n", " [200, 40], # session 2, customer 2 [budget, age]\n", " [80, 20], # session 3, customer 1 [budget, age]\n", "]\n", "\n", - "sessions_items_features = [\n", + "contexts_items_features = [\n", " [\n", " [100, 0], # Session 1, Item 1 [price, promotion]\n", " [140, 0], # Session 1, Item 2 [price, promotion]\n", @@ -399,14 +401,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Note that in items_features and sessions_items_features, the features need to be well ordered:\n", + "Note that in items_features and contexts_items_features, the features need to be well ordered:\n", "- The features are ordered the same for all items\n", - "- The items are ordered the same for items_features and sessions_items_features, and their index is used in choices:\n", + "- The items are ordered the same for items_features and contexts_items_features, and their index is used in choices:\n", "\n", "\n", "**items_features** = [[feature_1_item_A, feature_2_item_A, ...], [features_1_item_B, feature_2_item_B, ...], ...]\n", "\n", - "**session_items_features** = [[[session_1_feature_1_item_A, ...], [session_1_feature_1_item_B, ...]], [[session_2_feature_1_item_A, ...], [session_2_feature_1_item_B, ...]], ...]\n", + "**contexts_items_features** = [[[context_1_feature_1_item_A, ...], [context_1_feature_1_item_B, ...]], [[context_2_feature_1_item_A, ...], [context_2_feature_1_item_B, ...]], ...]\n", "\n", "**choices** then represent the index of the item: 0 when item_1 is chose, 1 when item_2, etc..., e.g. [0, 0, 2, 1, ...]" ] @@ -418,13 +420,13 @@ "outputs": [], "source": [ "dataset = ChoiceDataset(\n", - " items_features=items_features,\n", - " items_features_names=[\"size\", \"weight\"], # You can precise the names of the features if you want\n", - " sessions_features=sessions_features,\n", - " sessions_features_names=[\"budget\", \"age\"], # same, not mandatory\n", - " sessions_items_features=sessions_items_features,\n", - " sessions_items_features_names=[\"price\", \"promotion\"], # same, not mandatory\n", - " sessions_items_availabilities=sessions_items_availabilities,\n", + " fixed_items_features=fixed_items_features,\n", + " fixed_items_features_names=[\"size\", \"weight\"], # You can precise the names of the features if you want\n", + " contexts_features=contexts_features,\n", + " contexts_features_names=[\"budget\", \"age\"], # same, not mandatory\n", + " contexts_items_features=contexts_items_features,\n", + " contexts_items_features_names=[\"price\", \"promotion\"], # same, not mandatory\n", + " contexts_items_availabilities=contexts_items_availabilities,\n", " choices=choices,\n", ")" ] @@ -448,7 +450,7 @@ } ], "source": [ - "dataset.sessions_items_features[0].shape" + "dataset.contexts_items_features[0].shape" ] }, { @@ -470,7 +472,9 @@ "name": "stdout", "output_type": "stream", "text": [ + "No features_by_ids given.\n", "Some choices never happen in the dataset: {1}\n", + "No features_by_ids given.\n", "Some choices never happen in the dataset: {0, 2}\n", "Train Dataset length: 2 Test Dataset lenght: 1\n" ] @@ -492,10 +496,12 @@ "It returns the features in this order:\n", "\n", "- items_features (n_items, n_items_features)\n", - "- sessions_features (n_sessions_indexes, n_sessions_features)\n", - "- sessions_items_features (n_sessions_indexes, n_items, n_sessions_items_features)\n", - "- sessions_items_availabilities (n_sessions_indexes, n_items)\n", - "- choices (n_sessions_indexes,)" + "- contexts_features (n_choices, n_sessions_features)\n", + "- contexts_items_features (n_choices, n_items, n_sessions_items_features)\n", + "- contexts_items_availabilities (n_choices, n_items)\n", + "- choices (n_choices,)\n", + "\n", + "As a reminder, we have as many contexts as we have choices in the dataset !" ] }, { @@ -505,10 +511,10 @@ "| index | feature | shape | \n", "|---|---|---|\n", "| 0 | items_features | (n_items, n_items_features) |\n", - "| 1 | sessions_features | (n_sessions_indexes, n_sessions_features) |\n", - "| 2 | sessions_items_features | (n_sessions_indexes, n_items, n_sessions_items_features) |\n", - "| 3 | sessions_items_availabilities | (n_sessions_indexes, n_items) |\n", - "| 4 | choices | (n_sessions_indexes,) |" + "| 1 | contexts_features | (n_choices, n_contexts_features) |\n", + "| 2 | contexts_items_features | (n_choices, n_items, n_contexts_items_features) |\n", + "| 3 | context_items_availabilities | (n_choices, n_items) |\n", + "| 4 | choices | (n_choices,) |" ] }, { @@ -525,35 +531,35 @@ "Items features: (array([[1. , 2. ],\n", " [2. , 4. ],\n", " [1.5, 1.5]], dtype=float32),)\n", - "Sessions features: (array([[100, 20],\n", + "Contexts features: (array([[100, 20],\n", " [200, 40]], dtype=int32),)\n", - "Sessions Items features: (array([[[100, 0],\n", + "Contexts Items features: (array([[[100, 0],\n", " [140, 0],\n", " [200, 0]],\n", "\n", " [[100, 0],\n", " [120, 1],\n", " [200, 0]]], dtype=int32),)\n", - "Sessions Items Availabilities features: [[1. 1. 1.]\n", + "Contexts Items Availabilities features: [[1. 1. 1.]\n", " [1. 1. 1.]]\n", - "Sessions Choices: [0 2]\n" + "Contexts Choices: [0 2]\n" ] } ], "source": [ - "sessions_indexes = [0, 1]\n", - "print(\"Items features:\", train_dataset.batch[sessions_indexes][0])\n", - "print(\"Sessions features:\", train_dataset.batch[sessions_indexes][1])\n", - "print(\"Sessions Items features:\", train_dataset.batch[sessions_indexes][2])\n", - "print(\"Sessions Items Availabilities features:\", train_dataset.batch[sessions_indexes][3])\n", - "print(\"Sessions Choices:\", train_dataset.batch[sessions_indexes][4])" + "contexts_indexes = [0, 1]\n", + "print(\"Items features:\", train_dataset.batch[contexts_indexes][0])\n", + "print(\"Contexts features:\", train_dataset.batch[contexts_indexes][1])\n", + "print(\"Contexts Items features:\", train_dataset.batch[contexts_indexes][2])\n", + "print(\"Contexts Items Availabilities features:\", train_dataset.batch[contexts_indexes][3])\n", + "print(\"Contexts Choices:\", train_dataset.batch[contexts_indexes][4])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "To simplify the iteration over the dataset you can call the .batch method, with the batch_size argument.\n", + "To simplify the iteration over the dataset you can call the .iter_batch method, with the batch_size argument.\n", "\n", "Note that batch_size=-1 returns the whole dataset" ] @@ -620,10 +626,11 @@ " [11.5, 11.5], # item 3 \n", "]\n", "dataset = ChoiceDataset(\n", - " items_features=(items_features, items_features_2), # Here items_features specified as a tuple of the two features lists\n", - " sessions_features=sessions_features,\n", - " sessions_items_features=sessions_items_features,\n", - " sessions_items_availabilities=sessions_items_availabilities,\n", + " # Here items_features specified as a tuple of the two features lists\n", + " fixed_items_features=(fixed_items_features, items_features_2),\n", + " contexts_features=contexts_features,\n", + " contexts_items_features=contexts_items_features,\n", + " contexts_items_availabilities=contexts_items_availabilities,\n", " choices=choices,\n", ")" ] @@ -645,13 +652,13 @@ { "data": { "text/plain": [ - "((array([[1. , 2. ],\n", + "([array([[1. , 2. ],\n", " [2. , 4. ],\n", " [1.5, 1.5]], dtype=float32),\n", " array([[11. , 12. ],\n", " [12. , 14. ],\n", - " [11.5, 11.5]], dtype=float32)),\n", - " array([100, 20], dtype=int32),\n", + " [11.5, 11.5]], dtype=float32)],\n", + " array([100, 20]),\n", " array([[100, 0],\n", " [140, 0],\n", " [200, 0]], dtype=int32),\n", @@ -674,8 +681,8 @@ "source": [ "This is possible with:\n", "- items_features\n", - "- sessions_features\n", - "- sessions_items_features\n", + "- contexts_features\n", + "- contexts_items_features\n", "As the other should not need any superposition of values." ] }, @@ -686,10 +693,10 @@ "outputs": [], "source": [ "dataset = ChoiceDataset(\n", - " items_features=(items_features, items_features_2), # Here items_features specified as a tuple of the two features lists\n", - " sessions_features=(sessions_features, sessions_features),\n", - " sessions_items_features=(sessions_items_features, sessions_items_features),\n", - " sessions_items_availabilities=sessions_items_availabilities,\n", + " fixed_items_features=(fixed_items_features, items_features_2), # Here items_features specified as a tuple of the two features lists\n", + " contexts_features=(contexts_features, contexts_features),\n", + " contexts_items_features=(contexts_items_features, contexts_items_features),\n", + " contexts_items_availabilities=contexts_items_availabilities,\n", " choices=choices,\n", ")\n", "\n", @@ -817,10 +824,10 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Ready-to-use datasets\n", + "## Ready-to-use datasets\n", "A few well-known open source datasets are directly integrated and the package and can be downloaded in one line:\n", - "- SwissMetro from Bierlaire et al (2001)\n", - "- ModeCanada from Koppleman et al. (1993)\n", + "- SwissMetro from Bierlaire et al (2001) [2]\n", + "- ModeCanada from Koppleman et al. (1993) [1]\n", "\n", "If you feel like another open-source dataset should be included, reach out !" ] @@ -872,101 +879,178 @@ " \n", " \n", " \n", - " case\n", - " alt\n", - " choice\n", - " dist\n", - " cost\n", - " ivt\n", - " ovt\n", - " freq\n", - " income\n", - " urban\n", - " noalt\n", + " GROUP\n", + " SURVEY\n", + " SP\n", + " ID\n", + " PURPOSE\n", + " FIRST\n", + " TICKET\n", + " WHO\n", + " LUGGAGE\n", + " AGE\n", + " ...\n", + " TRAIN_CO\n", + " TRAIN_HE\n", + " SM_TT\n", + " SM_CO\n", + " SM_HE\n", + " SM_SEATS\n", + " CAR_TT\n", + " CAR_CO\n", + " CHOICE\n", + " CAR_HE\n", " \n", " \n", " \n", " \n", + " 0\n", + " 2.0\n", + " 0.0\n", + " 1.0\n", + " 1.0\n", + " 1.0\n", + " 0.0\n", + " 1.0\n", + " 1.0\n", + " 0.0\n", + " 3.0\n", + " ...\n", + " 48.0\n", + " 120.0\n", + " 63.0\n", + " 52.0\n", + " 20.0\n", + " 0.0\n", + " 117.0\n", + " 65.0\n", + " 2.0\n", + " 0.0\n", + " \n", + " \n", " 1\n", - " 1\n", - " train\n", - " 0\n", - " 83\n", - " 28.25\n", - " 50\n", - " 66\n", - " 4\n", - " 45.0\n", - " 0\n", - " 2\n", + " 2.0\n", + " 0.0\n", + " 1.0\n", + " 1.0\n", + " 1.0\n", + " 0.0\n", + " 1.0\n", + " 1.0\n", + " 0.0\n", + " 3.0\n", + " ...\n", + " 48.0\n", + " 30.0\n", + " 60.0\n", + " 49.0\n", + " 10.0\n", + " 0.0\n", + " 117.0\n", + " 84.0\n", + " 2.0\n", + " 0.0\n", " \n", " \n", " 2\n", - " 1\n", - " car\n", - " 1\n", - " 83\n", - " 15.77\n", - " 61\n", - " 0\n", - " 0\n", - " 45.0\n", - " 0\n", - " 2\n", + " 2.0\n", + " 0.0\n", + " 1.0\n", + " 1.0\n", + " 1.0\n", + " 0.0\n", + " 1.0\n", + " 1.0\n", + " 0.0\n", + " 3.0\n", + " ...\n", + " 48.0\n", + " 60.0\n", + " 67.0\n", + " 58.0\n", + " 30.0\n", + " 0.0\n", + " 117.0\n", + " 52.0\n", + " 2.0\n", + " 0.0\n", " \n", " \n", " 3\n", - " 2\n", - " train\n", - " 0\n", - " 83\n", - " 28.25\n", - " 50\n", - " 66\n", - " 4\n", - " 25.0\n", - " 0\n", - " 2\n", + " 2.0\n", + " 0.0\n", + " 1.0\n", + " 1.0\n", + " 1.0\n", + " 0.0\n", + " 1.0\n", + " 1.0\n", + " 0.0\n", + " 3.0\n", + " ...\n", + " 40.0\n", + " 30.0\n", + " 63.0\n", + " 52.0\n", + " 20.0\n", + " 0.0\n", + " 72.0\n", + " 52.0\n", + " 2.0\n", + " 0.0\n", " \n", " \n", " 4\n", - " 2\n", - " car\n", - " 1\n", - " 83\n", - " 15.77\n", - " 61\n", - " 0\n", - " 0\n", - " 25.0\n", - " 0\n", - " 2\n", - " \n", - " \n", - " 5\n", - " 3\n", - " train\n", - " 0\n", - " 83\n", - " 28.25\n", - " 50\n", - " 66\n", - " 4\n", - " 70.0\n", - " 0\n", - " 2\n", + " 2.0\n", + " 0.0\n", + " 1.0\n", + " 1.0\n", + " 1.0\n", + " 0.0\n", + " 1.0\n", + " 1.0\n", + " 0.0\n", + " 3.0\n", + " ...\n", + " 36.0\n", + " 60.0\n", + " 63.0\n", + " 42.0\n", + " 20.0\n", + " 0.0\n", + " 90.0\n", + " 84.0\n", + " 2.0\n", + " 0.0\n", " \n", " \n", "\n", + "

5 rows × 29 columns

\n", "" ], "text/plain": [ - " case alt choice dist cost ivt ovt freq income urban noalt\n", - "1 1 train 0 83 28.25 50 66 4 45.0 0 2\n", - "2 1 car 1 83 15.77 61 0 0 45.0 0 2\n", - "3 2 train 0 83 28.25 50 66 4 25.0 0 2\n", - "4 2 car 1 83 15.77 61 0 0 25.0 0 2\n", - "5 3 train 0 83 28.25 50 66 4 70.0 0 2" + " GROUP SURVEY SP ID PURPOSE FIRST TICKET WHO LUGGAGE AGE ... \\\n", + "0 2.0 0.0 1.0 1.0 1.0 0.0 1.0 1.0 0.0 3.0 ... \n", + "1 2.0 0.0 1.0 1.0 1.0 0.0 1.0 1.0 0.0 3.0 ... \n", + "2 2.0 0.0 1.0 1.0 1.0 0.0 1.0 1.0 0.0 3.0 ... \n", + "3 2.0 0.0 1.0 1.0 1.0 0.0 1.0 1.0 0.0 3.0 ... \n", + "4 2.0 0.0 1.0 1.0 1.0 0.0 1.0 1.0 0.0 3.0 ... \n", + "\n", + " TRAIN_CO TRAIN_HE SM_TT SM_CO SM_HE SM_SEATS CAR_TT CAR_CO CHOICE \\\n", + "0 48.0 120.0 63.0 52.0 20.0 0.0 117.0 65.0 2.0 \n", + "1 48.0 30.0 60.0 49.0 10.0 0.0 117.0 84.0 2.0 \n", + "2 48.0 60.0 67.0 58.0 30.0 0.0 117.0 52.0 2.0 \n", + "3 40.0 30.0 63.0 52.0 20.0 0.0 72.0 52.0 2.0 \n", + "4 36.0 60.0 63.0 42.0 20.0 0.0 90.0 84.0 2.0 \n", + "\n", + " CAR_HE \n", + "0 0.0 \n", + "1 0.0 \n", + "2 0.0 \n", + "3 0.0 \n", + "4 0.0 \n", + "\n", + "[5 rows x 29 columns]" ] }, "execution_count": null, @@ -975,15 +1059,17 @@ } ], "source": [ - "canada_df = load_modecanada(as_frame=True)\n", - "canada_df.head()" + "swissmetro_df = load_swissmetro(as_frame=True)\n", + "swissmetro_df.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "[1] Koppelman et al. (1993), *Application and Interpretation of Nested Logit Models of Intercity Mode Choice*" + "### References\n", + "[1] Koppelman et al. (1993), *Application and Interpretation of Nested Logit Models of Intercity Mode Choice*\\\n", + "[2] Bierlaire, M., Axhausen, K. and Abay, G. (2001), *The Acceptance of Modal Innovation: The Case of SwissMetro\"*" ] }, { From 0536435e10a80e13b4505f4cd290c292034b7a09 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 19 Jan 2024 15:59:16 +0100 Subject: [PATCH 075/767] ADD: Intro to DCM in readme --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8a614595..e1c0b619 100644 --- a/README.md +++ b/README.md @@ -20,16 +20,22 @@ Choice-Learn uses NumPy and pandas as data backend engines and TensorFlow for mo This repository contains a private version of the package. +## Introduction - Discrete Choice Modelling + +Discrete choice models aim at explaining or predicting a choice from a set of alternatives. Well known use-cases include analyzing people choice of mean of transport or products purchases in stores. + +If you are new to choice modelling, you can check this [resource](https://www.publichealth.columbia.edu/research/population-health-methods/discrete-choice-model-and-analysis). The different notebooks from the [Getting Started](#getting-started---fast-track) section can also help you understand choice modelling and more importantly help you for your usecase. ## Table of Contents - [choice-learn-private](#choice-learn-private) + - [Introduction - Discrete Choice Modelling](#introduction---discrete-choice-modelling) - [Table of Contents](#table-of-contents) - [What's in there ?](#whats-in-there) + - [Getting Started](#getting-started---fast-track) - [Installation](#installation) - [Usage](#usage) - [Documentation](#documentation) - [Citation](#citation) - ## What's in there ? ### Data From a924c979b6d816a03404f2f58f6ac05a2a5cde4f Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 19 Jan 2024 17:30:12 +0100 Subject: [PATCH 076/767] ENH: data exampel --- notebooks/choice_learn_introduction_data.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notebooks/choice_learn_introduction_data.ipynb b/notebooks/choice_learn_introduction_data.ipynb index 23424bed..ba559f1d 100644 --- a/notebooks/choice_learn_introduction_data.ipynb +++ b/notebooks/choice_learn_introduction_data.ipynb @@ -1069,7 +1069,7 @@ "source": [ "### References\n", "[1] Koppelman et al. (1993), *Application and Interpretation of Nested Logit Models of Intercity Mode Choice*\\\n", - "[2] Bierlaire, M., Axhausen, K. and Abay, G. (2001), *The Acceptance of Modal Innovation: The Case of SwissMetro\"*" + "[2] Bierlaire, M., Axhausen, K. and Abay, G. (2001), *The Acceptance of Modal Innovation: The Case of SwissMetro*" ] }, { From 8e212ec72c5ed7d4ed72ca7a319addfe69c445f4 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 19 Jan 2024 17:30:33 +0100 Subject: [PATCH 077/767] ADD: SwissMetro example beginning --- .../choice_learn_introduction_clogit.ipynb | 218 +++++++++++++++--- 1 file changed, 180 insertions(+), 38 deletions(-) diff --git a/notebooks/choice_learn_introduction_clogit.ipynb b/notebooks/choice_learn_introduction_clogit.ipynb index 60edd0d5..e7d3e5a2 100644 --- a/notebooks/choice_learn_introduction_clogit.ipynb +++ b/notebooks/choice_learn_introduction_clogit.ipynb @@ -30,13 +30,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### ChoiceModel - Getting Started\n", + "### Getting Started with the ConditionalMNL\n", "\n", - "choice-learn package offers a high level API to conceive and estimate discrete choice models.\n", + "The choice-learn package offers a high level API to conceive and estimate discrete choice models. Several models are ready to be used, you can check the list [here](../README.md). If you want to create your own model or another one that is not in the list, the lower level API can help you. Check the notebook [here](./custom_model.ipynb).\n", "\n", - "We begin this tutorial with the estimation of a Conditional Logit Model on the ModeCanada dataset.\n", + "We begin this tutorial with the estimation of a Conditional Logit Model on the ModeCanada dataset[1]. We try to reproduce the example [Torch-Choice](https://gsbdbi.github.io/torch-choice/conditional_logit_model_mode_canada/).\n", + "We also reproduce the example from [PyLogit](https://github.com/timothyb0912/pylogit/blob/master/examples/notebooks/Main%20PyLogit%20Example.ipynb) [here](#example-2-swissmetro).\n", "\n", - "First, we download our data as a ChoiceDataset. See the data management tutorial first if needed." + "First, we download our data as a ChoiceDataset. See the [data management tutorial](./choice_learn_introduction_data.ipynb) first if needed." ] }, { @@ -68,6 +69,7 @@ "metadata": {}, "outputs": [], "source": [ + "# Initialization of the ChoiceDataset\n", "from choice_learn.data import ChoiceDataset\n", "dataset = ChoiceDataset.from_single_df(df=transport_df,\n", " fixed_items_features_columns=[\"oh_air\", \"oh_bus\", \"oh_car\", \"oh_train\"],\n", @@ -83,7 +85,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now, we can import the needed modules:" + "Now, we can import the model from choice_learn.models:" ] }, { @@ -99,7 +101,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The conditional MNL \\ref{Train} specifies a linear utility for each item i during the session s with regards to the features:\n", + "The conditional MNL[2] specifies a linear utility for each item i during the session s with regards to the features:\n", "$$\n", "U(i, s) = \\sum_{features} a(i, s) * feat(i, s)\n", "$$\n", @@ -107,7 +109,7 @@ "We will use a ModelSpecification object to define our model with regards to our ChoiceDataset.\n", "For each feature in the choice dataset we can specify how it must be specified in the utility.\n", "\n", - "Let's re-use a common example from \\ref{} on the ModeCanda dataset:\n", + "Let's re-use a common example from on the ModeCanda[1] dataset:\n", "$$\n", "U(i, s) = \\beta^{inter}_i + \\beta^{price} \\cdot price(i, s) + \\beta^{freq} \\cdot freq(i, s) + \\beta^{ovt} \\cdot ovt(i, s) + \\beta^{income}_i \\cdot income(s) + \\beta^{ivt}_i \\cdot ivt(i, t) + \\epsilon(i, t)\n", "$$" @@ -213,21 +215,12 @@ }, "outputs": [ { - "data": { - "text/plain": [ - "[,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ]" - ] - }, - "execution_count": null, - "metadata": {}, - "output_type": "execute_result" + "name": "stdout", + "output_type": "stream", + "text": [ + "The average neg-loglikelihood is: 0.674474\n", + "The total neg-loglikelihood is: 1874.3632485866547\n" + ] } ], "source": [ @@ -261,8 +254,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "The average neg-loglikelihood is: 0.674474\n", - "The total neg-loglikelihood is: 1874.3632485866547\n" + "Using L-BFGS optimizer, setting up .fit() function\n" ] } ], @@ -303,18 +295,35 @@ "keep_output": true }, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Feature oh_air is in dataset but has no weight assigned in utility computations\n", + "Feature oh_bus is in dataset but has no weight assigned in utility computations\n", + "Feature oh_car is in dataset but has no weight assigned in utility computations\n", + "Feature oh_train is in dataset but has no weight assigned in utility computations\n" + ] + }, { "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 1/1 [00:01<00:00, 1.30s/it]\n" + "100%|██████████| 1/1 [00:01<00:00, 1.70s/it]" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "'Ground Truth' Negative LogLikelihood: tf.Tensor(1874.363, shape=(), dtype=float32)\n" + "'Ground Truth' Negative LogLikelihood: tf.Tensor(1874.3633, shape=(), dtype=float32)\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" ] } ], @@ -357,11 +366,11 @@ "output_type": "stream", "text": [ "Purchase probability of each item for the first 5 sessions: tf.Tensor(\n", - "[[0.19061294 0.00353295 0.40536764 0.40048242]\n", - " [0.34869465 0.00069692 0.36830828 0.28229645]\n", - " [0.14418268 0.00651326 0.4056784 0.4436212 ]\n", - " [0.34869465 0.00069692 0.36830828 0.28229645]\n", - " [0.34869465 0.00069692 0.36830828 0.28229645]], shape=(5, 4), dtype=float32)\n" + "[[0.1906135 0.00353266 0.4053667 0.4004831 ]\n", + " [0.34869286 0.00069682 0.36830992 0.28229675]\n", + " [0.14418365 0.00651285 0.40567666 0.44362238]\n", + " [0.34869286 0.00069682 0.36830992 0.28229675]\n", + " [0.34869286 0.00069682 0.36830992 0.28229675]], shape=(5, 4), dtype=float32)\n" ] } ], @@ -413,14 +422,14 @@ { "data": { "text/plain": [ - "[,\n", - " ,\n", - " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", - " ,\n", - " ,\n", - " ]" + " ]" ] }, "execution_count": null, @@ -517,6 +526,139 @@ "print(cmnl.weights)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Example 2: SwissMetro\n", + "\n", + "We reproduce the [PyLogit](https://github.com/timothyb0912/pylogit/blob/master/examples/notebooks/Main%20PyLogit%20Example.ipynb) example of ConditionalMNL, that is reproduction of a Biogeme example. It uses the SwissMetro dataset[3]." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from choice_learn.datasets import load_swissmetro\n", + "\n", + "swiss_df = load_swissmetro(as_frame=True)\n", + "\n", + "# Removing unknown choices\n", + "swiss_df = swiss_df.loc[swiss_df.CHOICE != 0]\n", + "# Keep only commute an dbusiness trips\n", + "swiss_df = swiss_df.loc[swiss_df.PURPOSE.isin([1, 3])]\n", + "\n", + "# Normalizing values\n", + "swiss_df[[\"TRAIN_TT\", \"SM_TT\", \"CAR_TT\"]] = swiss_df[[\"TRAIN_TT\", \"SM_TT\", \"CAR_TT\"]] / 60.\n", + "swiss_df[[\"TRAIN_HE\", \"SM_HE\"]] = swiss_df[[\"TRAIN_HE\", \"SM_HE\"]] / 60.\n", + "\n", + "swiss_df[\"train_free_ticket\"] = swiss_df.apply(lambda row: ((row[\"GA\"]==1 or row[\"WHO\"]==2) > 0).astype(int), axis=1)\n", + "swiss_df[\"sm_free_ticket\"] = swiss_df.apply(lambda row: ((row[\"GA\"]==1 or row[\"WHO\"]==2) > 0).astype(int), axis=1)\n", + "swiss_df[\"car_free_ticket\"] = 0\n", + "\n", + "swiss_df[\"train_travel_cost\"] = swiss_df.apply(lambda row: (row[\"TRAIN_CO\"] * (1 - row[\"train_free_ticket\"])) / 100, axis=1)\n", + "swiss_df[\"sm_travel_cost\"] = swiss_df.apply(lambda row: (row[\"SM_CO\"] * (1 - row[\"sm_free_ticket\"])) / 100, axis=1)\n", + "swiss_df[\"car_travel_cost\"] = swiss_df.apply(lambda row: row[\"CAR_CO\"] / 100, axis=1)\n", + "\n", + "swiss_df[\"single_luggage_piece\"] = swiss_df.apply(lambda row: (row[\"LUGGAGE\"] == 1).astype(int), axis=1)\n", + "swiss_df[\"multiple_luggage_piece\"] = swiss_df.apply(lambda row: (row[\"LUGGAGE\"] == 3).astype(int), axis=1)\n", + "swiss_df[\"regular_class\"] = swiss_df.apply(lambda row: 1 - row[\"FIRST\"], axis=1)\n", + "swiss_df[\"train_survey\"] = swiss_df.apply(lambda row: 1 - row[\"SURVEY\"], axis=1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "contexts_features = swiss_df[[\"train_survey\", \"FIRST\", \"single_luggage_piece\", \"multiple_luggage_piece\"]].to_numpy()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "train_features = swiss_df[[\"train_travel_cost\", \"TRAIN_TT\", \"TRAIN_HE\"]].to_numpy()\n", + "sm_features = swiss_df[[\"SM_TT\", \"SM_CO\", \"SM_HE\", \"SM_SEATS\"]].to_numpy()\n", + "car_features = swiss_df[[\"CAR_TT\", \"CAR_CO\"]].to_numpy()\n", + "\n", + "# We need to have the same number of features for each item, we create dummy ones:\n", + "car_features = np.concatenate([car_features, np.zeros((len(car_features), 2))], axis=1)\n", + "train_features = np.concatenate([train_features, np.zeros((len(train_features), 1))], axis=1)\n", + "assert train_features.shape == car_features.shape == sm_features.shape\n", + "\n", + "contexts_items_features = np.stack([car_features, sm_features, train_features], axis=1)\n", + "print(contexts_items_features.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "contexts_items_availabilities = swiss_df[[\"CAR_AV\", \"SM_AV\", \"TRAIN_AV\"]].to_numpy()\n", + "# Re-Indexing choices from 1 to 3 to 0 to 2\n", + "choices = swiss_df.CHOICE.to_numpy() - 1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "swiss_dataset = ChoiceDataset(contexts_features=contexts_features,\n", + " contexts_items_features=contexts_items_features,\n", + " contexts_items_availabilities=contexts_items_availabilities,\n", + " contexts_features_names=['GROUP', 'SURVEY', 'SP', 'ID', 'PURPOSE', 'FIRST', 'TICKET', 'WHO',\n", + " 'LUGGAGE', 'AGE', 'MALE', 'INCOME', 'GA', 'ORIGIN', 'DEST'],\n", + " contexts_items_features_names=[\"TT\", \"CO\", \"HE\", \"SEATS\"],\n", + " choices=choices\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "swiss_dataset.summary()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Initialization of the model\n", + "swiss_model = ConditionalMNL(optimizer=\"lbfgs\")\n", + "\n", + "# Creation of the different weights:\n", + "\n", + "\n", + "# add_coefficients adds one coefficient for each specified item_index\n", + "# intercept, and income are added for each item except the first one that needs to be zeroed\n", + "swiss_model.add_coefficients(coefficient_name=\"beta_inter\", feature_name=\"intercept\", items_indexes=[1, 2, 3])\n", + "model.add_coefficients(coefficient_name=\"beta_income\", feature_name=\"income\", items_indexes=[1, 2, 3])\n", + "\n", + "# ivt is added for each item:\n", + "model.add_coefficients(coefficient_name=\"beta_ivt\", feature_name=\"ivt\", items_indexes=[0, 1, 2, 3])\n", + "\n", + "# shared_coefficient add one coefficient that is used for all items specified in the items_indexes:\n", + "# Here, cost, freq and ovt coefficients are shared between all items\n", + "model.add_shared_coefficient(coefficient_name=\"beta_cost\", feature_name=\"cost\", items_indexes=[0, 1, 2, 3])\n", + "model.add_shared_coefficient(coefficient_name=\"beta_freq\", feature_name=\"freq\", items_indexes=[0, 1, 2, 3])\n", + "model.add_shared_coefficient(coefficient_name=\"beta_ovt\", feature_name=\"ovt\", items_indexes=[0, 1, 2, 3])" + ] + }, { "cell_type": "code", "execution_count": null, From 19567daa163029643116154aee3bf71080738f55 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 19 Jan 2024 19:26:21 +0100 Subject: [PATCH 078/767] FIX: possibility to define different weights for the same feature --- choice_learn/models/base_model.py | 5 + choice_learn/models/conditional_mnl.py | 334 ++++++++++++++----------- 2 files changed, 196 insertions(+), 143 deletions(-) diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index a5560f93..f2e7c489 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -622,6 +622,11 @@ def f(params_1d): # calculate gradients and convert to 1D tf.Tensor grads = tape.gradient(loss_value, self.weights) + print(idx) + print(grads) + tf.print(idx, grads) + print(len(idx)) + print(len(grads)) grads = tf.dynamic_stitch(idx, grads) # print out iteration & loss diff --git a/choice_learn/models/conditional_mnl.py b/choice_learn/models/conditional_mnl.py index f1374181..10ae868c 100644 --- a/choice_learn/models/conditional_mnl.py +++ b/choice_learn/models/conditional_mnl.py @@ -127,10 +127,20 @@ def add_weight(self, weight_name, weight_index): if weight_name not in self.coefficients.keys(): raise ValueError(f"Weight {weight_name} not in coefficients") - self.feature_to_weight[self.coefficients[weight_name]["feature_name"]] = ( - weight_name, - weight_index, - ) + if self.coefficients[weight_name]["feature_name"] in self.feature_to_weight.keys(): + self.feature_to_weight[self.coefficients[weight_name]["feature_name"]].append( + ( + weight_name, + weight_index, + ) + ) + else: + self.feature_to_weight[self.coefficients[weight_name]["feature_name"]] = [ + ( + weight_name, + weight_index, + ), + ] def list_features_with_weights(self): """Get a list of the features that have a weight to be estimated. @@ -157,8 +167,12 @@ def get_weight_item_indexes(self, feature_name): int The index of the weight in the conditionalMNL weights. """ - weight_name, weight_index = self.feature_to_weight[feature_name] - return self.coefficients[weight_name]["items_indexes"], weight_index + weights_info = self.feature_to_weight[feature_name] + weight_names = [weight_info[0] for weight_info in weights_info] + weight_indexs = [weight_info[1] for weight_info in weights_info] + return [ + self.coefficients[weight_name]["items_indexes"] for weight_name in weight_names + ], weight_indexs @property def coefficients_list(self): @@ -366,161 +380,195 @@ def compute_utility_from_specification( num_choices = availabilities_batch.shape[0] contexts_items_utilities = [] # Items features - for i, feat_tuple in enumerate(self._items_features_names): - for j, feat in enumerate(feat_tuple): - if feat in self.params.list_features_with_weights(): - item_index, weight_index = self.params.get_weight_item_indexes(feat) - - s_i_u = tf.zeros((num_items,)) - for q, idx in enumerate(item_index): - if isinstance(idx, list): - for k in idx: - s_i_u = tf.concat( - [ - s_i_u[:k], - tf.multiply( - items_batch[i][k, j], self.weights[weight_index][:, q] - ), - s_i_u[k + 1 :], - ], - axis=0, - ) - else: - s_i_u = tf.concat( - [ - s_i_u[:idx], - tf.multiply( - items_batch[i][idx, j], self.weights[weight_index][:, q] - ), - s_i_u[idx + 1 :], - ], - axis=0, - ) - s_i_u = tf.stack([s_i_u] * num_choices, axis=0) - - ### Need reshaping here - contexts_items_utilities.append(s_i_u) - else: - if verbose > 1: - print( - f"Feature {feat} is in dataset but has no weight assigned in utility\ - computations" + if self._items_features_names is not None: + for i, feat_tuple in enumerate(self._items_features_names): + for j, feat in enumerate(feat_tuple): + if feat in self.params.list_features_with_weights(): + print("found feat", feat) + item_index_list, weight_index_list = self.params.get_weight_item_indexes( + feat ) - - # Context features - for i, feat_tuple in enumerate(self._contexts_features_names): - for j, feat in enumerate(feat_tuple): - if feat in self.params.list_features_with_weights(): - item_index, weight_index = self.params.get_weight_item_indexes(feat) - - s_i_u = tf.zeros((num_choices, num_items)) - - for q, idx in enumerate(item_index): - if isinstance(idx, list): - for k in idx: - s_i_u = tf.concat( - [ - s_i_u[:, :k], - tf.expand_dims( + for item_index, weight_index in zip(item_index_list, weight_index_list): + s_i_u = tf.zeros((num_items,)) + for q, idx in enumerate(item_index): + if isinstance(idx, list): + for k in idx: + s_i_u = tf.concat( + [ + s_i_u[:k], + tf.multiply( + items_batch[i][k, j], + self.weights[weight_index][:, q], + ), + s_i_u[k + 1 :], + ], + axis=0, + ) + else: + s_i_u = tf.concat( + [ + s_i_u[:idx], tf.multiply( - contexts_batch[i][:, j], + items_batch[i][idx, j], self.weights[weight_index][:, q], ), - axis=-1, - ), - s_i_u[:, k + 1 :], - ], - axis=1, - ) + s_i_u[idx + 1 :], + ], + axis=0, + ) + s_i_u = tf.stack([s_i_u] * num_choices, axis=0) + + ### Need reshaping here + contexts_items_utilities.append(tf.cast(s_i_u, tf.float32)) else: - s_i_u = tf.concat( - [ - s_i_u[:, :idx], - tf.expand_dims( - tf.multiply( + if verbose > 1: + print( + f"Feature {feat} is in dataset but has no weight assigned\ + in utility computations" + ) + # Context features + if self._contexts_features_names is not None: + for i, feat_tuple in enumerate(self._contexts_features_names): + for j, feat in enumerate(feat_tuple): + if feat in self.params.list_features_with_weights(): + print("found feat", feat) + item_index_list, weight_index_list = self.params.get_weight_item_indexes( + feat + ) + for item_index, weight_index in zip(item_index_list, weight_index_list): + s_i_u = tf.zeros((num_choices, num_items)) + s_i_u = [tf.zeros(num_choices) for _ in range(num_items)] + + for q, idx in enumerate(item_index): + if isinstance(idx, list): + for k in idx: + """ + s_i_u = tf.concat( + [ + s_i_u[:, :k], + tf.expand_dims( + tf.multiply( + contexts_batch[i][:, j], + self.weights[weight_index][:, q], + ), + axis=-1, + ), + s_i_u[:, k + 1 :], + ], + axis=1, + ) + """ + contexts_batch[i][:, j] + compute = tf.multiply( contexts_batch[i][:, j], self.weights[weight_index][:, q], - ), - axis=-1, - ), - s_i_u[:, idx + 1 :], - ], - axis=1, + ) + s_i_u[k] += compute + else: + """ + s_i_u = tf.concat( + [ + s_i_u[:, :idx], + tf.expand_dims( + tf.multiply( + contexts_batch[i][:, j], + self.weights[weight_index][:, q], + ), + axis=-1, + ), + s_i_u[:, idx + 1 :], + ], + axis=1, + ) + """ + compute = tf.multiply( + contexts_batch[i][:, j], self.weights[weight_index][:, q] + ) + s_i_u[idx] += compute + + contexts_items_utilities.append( + tf.cast(tf.stack(s_i_u, axis=1), tf.float32) + ) + else: + print( + f"Feature {feat} is in dataset but has no weight assigned\ + in utility computations" ) - - contexts_items_utilities.append(s_i_u) - else: - print( - f"Feature {feat} is in dataset but has no weight assigned in utility\ - computations" - ) # context Items features - for i, feat_tuple in enumerate(self._contexts_items_features_names): - for j, feat in enumerate(feat_tuple): - if feat in self.params.list_features_with_weights(): - item_index, weight_index = self.params.get_weight_item_indexes(feat) - s_i_u = tf.zeros((num_choices, num_items)) - - for q, idx in enumerate(item_index): - if isinstance(idx, list): - for k in idx: - s_i_u = tf.concat( - [ - s_i_u[:, :k], - tf.expand_dims( - tf.multiply( - contexts_items_batch[i][:, k, j], - self.weights[weight_index][:, q], + if self._contexts_items_features_names is not None: + for i, feat_tuple in enumerate(self._contexts_items_features_names): + for j, feat in enumerate(feat_tuple): + if feat in self.params.list_features_with_weights(): + print("found feat", feat) + + item_index_list, weight_index_list = self.params.get_weight_item_indexes( + feat + ) + for item_index, weight_index in zip(item_index_list, weight_index_list): + s_i_u = tf.zeros((num_choices, num_items)) + + for q, idx in enumerate(item_index): + if isinstance(idx, list): + for k in idx: + s_i_u = tf.concat( + [ + s_i_u[:, :k], + tf.expand_dims( + tf.multiply( + contexts_items_batch[i][:, k, j], + self.weights[weight_index][:, q], + ), + axis=-1, + ), + s_i_u[:, k + 1 :], + ], + axis=1, + ) + else: + s_i_u = tf.concat( + [ + s_i_u[:, :idx], + tf.expand_dims( + tf.multiply( + contexts_items_batch[i][:, idx, j], + self.weights[weight_index][:, q], + ), + axis=-1, ), - axis=-1, - ), - s_i_u[:, k + 1 :], - ], - axis=1, - ) + s_i_u[:, idx + 1 :], + ], + axis=1, + ) + + contexts_items_utilities.append(tf.cast(s_i_u, tf.float32)) else: - s_i_u = tf.concat( - [ - s_i_u[:, :idx], - tf.expand_dims( - tf.multiply( - contexts_items_batch[i][:, idx, j], - self.weights[weight_index][:, q], - ), - axis=-1, - ), - s_i_u[:, idx + 1 :], - ], - axis=1, + print( + f"Feature {feat} is in dataset but has no weight assigned\ + in utility computations" ) - contexts_items_utilities.append(s_i_u) - else: - print( - f"Feature {feat} is in dataset but has no weight assigned in utility\ - computations" - ) - if "intercept" in self.params.list_features_with_weights(): - item_index, weight_index = self.params.get_weight_item_indexes("intercept") - - s_i_u = tf.zeros((num_items,)) - for q, idx in enumerate(item_index): - s_i_u = tf.concat( - [ - s_i_u[:idx], - self.weights[weight_index][:, q], - s_i_u[idx + 1 :], - ], - axis=0, - ) + print("found feat", "intercept") + item_index_list, weight_index_list = self.params.get_weight_item_indexes("intercept") + + for item_index, weight_index in zip(item_index_list, weight_index_list): + s_i_u = tf.zeros((num_items,)) + for q, idx in enumerate(item_index): + s_i_u = tf.concat( + [ + s_i_u[:idx], + self.weights[weight_index][:, q], + s_i_u[idx + 1 :], + ], + axis=0, + ) - s_i_u = tf.stack([s_i_u] * num_choices, axis=0) + s_i_u = tf.stack([s_i_u] * num_choices, axis=0) - ### Need reshaping here + ### Need reshaping here - contexts_items_utilities.append(s_i_u) + contexts_items_utilities.append(tf.cast(s_i_u, tf.float32)) return tf.reduce_sum(contexts_items_utilities, axis=0) From 018e0d5f403b922621d7e8bb171a527c75fe860c Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 19 Jan 2024 22:52:56 +0100 Subject: [PATCH 079/767] ENH: prints --- choice_learn/models/base_model.py | 5 ---- choice_learn/models/conditional_mnl.py | 33 +++++++++++++------------- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index f2e7c489..a5560f93 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -622,11 +622,6 @@ def f(params_1d): # calculate gradients and convert to 1D tf.Tensor grads = tape.gradient(loss_value, self.weights) - print(idx) - print(grads) - tf.print(idx, grads) - print(len(idx)) - print(len(grads)) grads = tf.dynamic_stitch(idx, grads) # print out iteration & loss diff --git a/choice_learn/models/conditional_mnl.py b/choice_learn/models/conditional_mnl.py index 10ae868c..daf935d6 100644 --- a/choice_learn/models/conditional_mnl.py +++ b/choice_learn/models/conditional_mnl.py @@ -384,7 +384,6 @@ def compute_utility_from_specification( for i, feat_tuple in enumerate(self._items_features_names): for j, feat in enumerate(feat_tuple): if feat in self.params.list_features_with_weights(): - print("found feat", feat) item_index_list, weight_index_list = self.params.get_weight_item_indexes( feat ) @@ -420,12 +419,12 @@ def compute_utility_from_specification( ### Need reshaping here contexts_items_utilities.append(tf.cast(s_i_u, tf.float32)) - else: - if verbose > 1: - print( - f"Feature {feat} is in dataset but has no weight assigned\ - in utility computations" - ) + else: + if verbose > 1: + print( + f"Feature {feat} is in dataset but has no weight assigned\ + in utility computations" + ) # Context features if self._contexts_features_names is not None: for i, feat_tuple in enumerate(self._contexts_features_names): @@ -489,11 +488,11 @@ def compute_utility_from_specification( contexts_items_utilities.append( tf.cast(tf.stack(s_i_u, axis=1), tf.float32) ) - else: - print( - f"Feature {feat} is in dataset but has no weight assigned\ - in utility computations" - ) + else: + print( + f"Feature {feat} is in dataset but has no weight assigned\ + in utility computations" + ) # context Items features if self._contexts_items_features_names is not None: @@ -542,11 +541,11 @@ def compute_utility_from_specification( ) contexts_items_utilities.append(tf.cast(s_i_u, tf.float32)) - else: - print( - f"Feature {feat} is in dataset but has no weight assigned\ - in utility computations" - ) + else: + print( + f"Feature {feat} is in dataset but has no weight assigned\ + in utility computations" + ) if "intercept" in self.params.list_features_with_weights(): print("found feat", "intercept") From 3f58f50738e0d0f94940ba168f6e01ebdec19247 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 19 Jan 2024 22:53:17 +0100 Subject: [PATCH 080/767] ADD: finalized PyLogit SwissMetro example --- .../choice_learn_introduction_clogit.ipynb | 148 +++++++++++++----- 1 file changed, 107 insertions(+), 41 deletions(-) diff --git a/notebooks/choice_learn_introduction_clogit.ipynb b/notebooks/choice_learn_introduction_clogit.ipynb index e7d3e5a2..08735f5c 100644 --- a/notebooks/choice_learn_introduction_clogit.ipynb +++ b/notebooks/choice_learn_introduction_clogit.ipynb @@ -54,12 +54,6 @@ "transport_df = transport_df.loc[transport_df.noalt == 4]\n", "\n", "items = [\"air\", \"bus\", \"car\", \"train\"]\n", - "\n", - "transport_df[\"oh_air\"] = transport_df.apply(lambda row: 1. if row.alt == items[0] else 0., axis=1)\n", - "transport_df[\"oh_bus\"] = transport_df.apply(lambda row: 1. if row.alt == items[1] else 0., axis=1)\n", - "transport_df[\"oh_car\"] = transport_df.apply(lambda row: 1. if row.alt == items[2] else 0., axis=1)\n", - "transport_df[\"oh_train\"] = transport_df.apply(lambda row: 1. if row.alt == items[3] else 0., axis=1)\n", - "\n", "transport_df.income = transport_df.income.astype(\"float32\")" ] }, @@ -72,7 +66,6 @@ "# Initialization of the ChoiceDataset\n", "from choice_learn.data import ChoiceDataset\n", "dataset = ChoiceDataset.from_single_df(df=transport_df,\n", - " fixed_items_features_columns=[\"oh_air\", \"oh_bus\", \"oh_car\", \"oh_train\"],\n", " contexts_features_columns=[\"income\"],\n", " contexts_items_features_columns=[\"cost\", \"freq\", \"ovt\", \"ivt\"],\n", " items_id_column=\"alt\",\n", @@ -232,7 +225,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "A faster specification can be done using a dictionnary. It follows torch-choice \\ref{} method to create conditional logit models.\n", + "A faster specification can be done using a dictionnary. It follows torch-choice method to create conditional logit models.\n", "The parameters dict needs to be as follows:\n", "- The key is the feature name\n", "- The value is the mode. Currently three modes are available:\n", @@ -261,9 +254,9 @@ "source": [ "# Instantiation of the parameters dictionnary\n", "params = {\"income\": \"item\",\n", - " \"cost\": \"constant\", \n", + " \"cost\": \"constant\",\n", " \"freq\": \"constant\",\n", - " \"ovt\": \"constant\", \n", + " \"ovt\": \"constant\",\n", " \"ivt\": \"item-full\",\n", " \"intercept\": \"item\"}\n", "\n", @@ -285,7 +278,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We can compare the estimated coefficients and the negative log-likelihood obtained in \\ref{} and \\ref{torch-choice}, and it is similar !" + "We can compare the estimated coefficients and the negative log-likelihood obtained in torch-choice example, and it is similar !" ] }, { @@ -486,9 +479,9 @@ "source": [ "# Instantiation of the parameters dictionnary\n", "params = {\"income\": \"item\",\n", - " \"cost\": \"constant\", \n", + " \"cost\": \"constant\",\n", " \"freq\": \"constant\",\n", - " \"ovt\": \"constant\", \n", + " \"ovt\": \"constant\",\n", " \"ivt\": \"item-full\",\n", " \"intercept\": \"item\"}\n", "\n", @@ -565,7 +558,13 @@ "swiss_df[\"single_luggage_piece\"] = swiss_df.apply(lambda row: (row[\"LUGGAGE\"] == 1).astype(int), axis=1)\n", "swiss_df[\"multiple_luggage_piece\"] = swiss_df.apply(lambda row: (row[\"LUGGAGE\"] == 3).astype(int), axis=1)\n", "swiss_df[\"regular_class\"] = swiss_df.apply(lambda row: 1 - row[\"FIRST\"], axis=1)\n", - "swiss_df[\"train_survey\"] = swiss_df.apply(lambda row: 1 - row[\"SURVEY\"], axis=1)" + "swiss_df[\"train_survey\"] = swiss_df.apply(lambda row: 1 - row[\"SURVEY\"], axis=1)\n", + "swiss_df.head()[[\"train_travel_cost\", \"TRAIN_TT\", \"TRAIN_HE\",\n", + " \"sm_travel_cost\", \"SM_TT\", \"SM_HE\", \"SM_SEATS\",\n", + " \"car_travel_cost\", \"CAR_TT\",\n", + " \"TRAIN_AV\", \"SM_AV\", \"CAR_AV\",\n", + " \"train_survey\", \"regular_class\", \"single_luggage_piece\", \"multiple_luggage_piece\",\n", + " \"CHOICE\"]]" ] }, { @@ -574,7 +573,7 @@ "metadata": {}, "outputs": [], "source": [ - "contexts_features = swiss_df[[\"train_survey\", \"FIRST\", \"single_luggage_piece\", \"multiple_luggage_piece\"]].to_numpy()" + "contexts_features = swiss_df[[\"train_survey\", \"regular_class\", \"single_luggage_piece\", \"multiple_luggage_piece\"]].to_numpy()" ] }, { @@ -584,15 +583,15 @@ "outputs": [], "source": [ "train_features = swiss_df[[\"train_travel_cost\", \"TRAIN_TT\", \"TRAIN_HE\"]].to_numpy()\n", - "sm_features = swiss_df[[\"SM_TT\", \"SM_CO\", \"SM_HE\", \"SM_SEATS\"]].to_numpy()\n", - "car_features = swiss_df[[\"CAR_TT\", \"CAR_CO\"]].to_numpy()\n", + "sm_features = swiss_df[[\"sm_travel_cost\", \"SM_TT\", \"SM_HE\", \"SM_SEATS\"]].to_numpy()\n", + "car_features = swiss_df[[\"car_travel_cost\", \"CAR_TT\"]].to_numpy()\n", "\n", "# We need to have the same number of features for each item, we create dummy ones:\n", "car_features = np.concatenate([car_features, np.zeros((len(car_features), 2))], axis=1)\n", "train_features = np.concatenate([train_features, np.zeros((len(train_features), 1))], axis=1)\n", "assert train_features.shape == car_features.shape == sm_features.shape\n", "\n", - "contexts_items_features = np.stack([car_features, sm_features, train_features], axis=1)\n", + "contexts_items_features = np.stack([train_features, sm_features, car_features], axis=1)\n", "print(contexts_items_features.shape)" ] }, @@ -602,7 +601,7 @@ "metadata": {}, "outputs": [], "source": [ - "contexts_items_availabilities = swiss_df[[\"CAR_AV\", \"SM_AV\", \"TRAIN_AV\"]].to_numpy()\n", + "contexts_items_availabilities = swiss_df[[\"TRAIN_AV\", \"SM_AV\", \"CAR_AV\"]].to_numpy()\n", "# Re-Indexing choices from 1 to 3 to 0 to 2\n", "choices = swiss_df.CHOICE.to_numpy() - 1" ] @@ -613,12 +612,11 @@ "metadata": {}, "outputs": [], "source": [ - "swiss_dataset = ChoiceDataset(contexts_features=contexts_features,\n", - " contexts_items_features=contexts_items_features,\n", + "swiss_dataset = ChoiceDataset(contexts_features=(contexts_features, ),\n", + " contexts_items_features=(contexts_items_features, ),\n", " contexts_items_availabilities=contexts_items_availabilities,\n", - " contexts_features_names=['GROUP', 'SURVEY', 'SP', 'ID', 'PURPOSE', 'FIRST', 'TICKET', 'WHO',\n", - " 'LUGGAGE', 'AGE', 'MALE', 'INCOME', 'GA', 'ORIGIN', 'DEST'],\n", - " contexts_items_features_names=[\"TT\", \"CO\", \"HE\", \"SEATS\"],\n", + " contexts_features_names=([\"train_survey\", \"regular_class\", \"single_luggage_piece\", \"multiple_luggage_piece\"], ),\n", + " contexts_items_features_names=([\"cost\", \"travel_time\", \"headway\", \"seats\"], ),\n", " choices=choices\n", " )" ] @@ -641,22 +639,17 @@ "# Initialization of the model\n", "swiss_model = ConditionalMNL(optimizer=\"lbfgs\")\n", "\n", - "# Creation of the different weights:\n", - "\n", - "\n", - "# add_coefficients adds one coefficient for each specified item_index\n", - "# intercept, and income are added for each item except the first one that needs to be zeroed\n", - "swiss_model.add_coefficients(coefficient_name=\"beta_inter\", feature_name=\"intercept\", items_indexes=[1, 2, 3])\n", - "model.add_coefficients(coefficient_name=\"beta_income\", feature_name=\"income\", items_indexes=[1, 2, 3])\n", - "\n", - "# ivt is added for each item:\n", - "model.add_coefficients(coefficient_name=\"beta_ivt\", feature_name=\"ivt\", items_indexes=[0, 1, 2, 3])\n", - "\n", - "# shared_coefficient add one coefficient that is used for all items specified in the items_indexes:\n", - "# Here, cost, freq and ovt coefficients are shared between all items\n", - "model.add_shared_coefficient(coefficient_name=\"beta_cost\", feature_name=\"cost\", items_indexes=[0, 1, 2, 3])\n", - "model.add_shared_coefficient(coefficient_name=\"beta_freq\", feature_name=\"freq\", items_indexes=[0, 1, 2, 3])\n", - "model.add_shared_coefficient(coefficient_name=\"beta_ovt\", feature_name=\"ovt\", items_indexes=[0, 1, 2, 3])" + "swiss_model.add_coefficients(coefficient_name=\"beta_inter\", feature_name=\"intercept\", items_indexes=[0, 1])\n", + "swiss_model.add_shared_coefficient(coefficient_name=\"beta_tt_transit\", feature_name=\"travel_time\", items_indexes=[0, 1])\n", + "swiss_model.add_coefficients(coefficient_name=\"beta_tt_car\", feature_name=\"travel_time\", items_indexes=[2])\n", + "swiss_model.add_coefficients(coefficient_name=\"beta_tc\", feature_name=\"cost\", items_indexes=[0, 1, 2])\n", + "swiss_model.add_coefficients(coefficient_name=\"beta_hw\", feature_name=\"headway\", items_indexes=[0, 1])\n", + "swiss_model.add_coefficients(coefficient_name=\"beta_seat\", feature_name=\"seats\", items_indexes=[1])\n", + "swiss_model.add_shared_coefficient(coefficient_name=\"beta_survey\", feature_name=\"train_survey\", items_indexes=[0, 1])\n", + "swiss_model.add_coefficients(coefficient_name=\"beta_first_class\", feature_name=\"regular_class\", items_indexes=[0])\n", + "swiss_model.add_coefficients(coefficient_name=\"beta_luggage=1\", feature_name=\"single_luggage_piece\", items_indexes=[2])\n", + "swiss_model.add_coefficients(coefficient_name=\"beta_luggage>1\", feature_name=\"multiple_luggage_piece\", items_indexes=[2])\n", + "\n" ] }, { @@ -664,7 +657,80 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "history = swiss_model.fit(swiss_dataset, n_epochs=10000)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " 1:0' shape=(1, 1) dtype=float32, numpy=array([[1.413982]], dtype=float32)>]" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "swiss_model.weights" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(swiss_dataset) * swiss_model.evaluate(swiss_dataset)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We find the same results (estimation of parameters and negative log-likelihood) as the PyLogit package." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### References\n", + "\n", + "[1] ModeCanada dataset in *Application and interpretation of nested logit models of intercity mode choice*, Christophier, V. F.; Koppelman, S. (1993)\\\n", + "[2] Conditional MultiNomialLogit, Train, K.; McFadden, D.; Ben-Akiva, M. (1987)\\\n", + "[3] Siwssmetro dataset in *The acceptance of modal innovation: The case of Swissmetro*, Bierlaire, M.; Axhausen, K.; Abay, G (2001)\\" + ] } ], "metadata": { From c3a4573daf6aec00ccb5acf7feefef3739bf02be Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 19 Jan 2024 22:54:06 +0100 Subject: [PATCH 081/767] ADD: init rumnet example --- notebooks/rumnet_example.ipynb | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 notebooks/rumnet_example.ipynb diff --git a/notebooks/rumnet_example.ipynb b/notebooks/rumnet_example.ipynb new file mode 100644 index 00000000..cd1945da --- /dev/null +++ b/notebooks/rumnet_example.ipynb @@ -0,0 +1,23 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Introduction to modelling with RUMnet" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From ef771ff6e8b4ce78e15d500aee964c7cec2ae62e Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 19 Jan 2024 23:02:49 +0100 Subject: [PATCH 082/767] ENH: documentation --- README.md | 22 ++++++++++++++++------ mkdocs.yaml | 6 +++++- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index e1c0b619..76d0c248 100644 --- a/README.md +++ b/README.md @@ -20,11 +20,6 @@ Choice-Learn uses NumPy and pandas as data backend engines and TensorFlow for mo This repository contains a private version of the package. -## Introduction - Discrete Choice Modelling - -Discrete choice models aim at explaining or predicting a choice from a set of alternatives. Well known use-cases include analyzing people choice of mean of transport or products purchases in stores. - -If you are new to choice modelling, you can check this [resource](https://www.publichealth.columbia.edu/research/population-health-methods/discrete-choice-model-and-analysis). The different notebooks from the [Getting Started](#getting-started---fast-track) section can also help you understand choice modelling and more importantly help you for your usecase. ## Table of Contents - [choice-learn-private](#choice-learn-private) @@ -36,6 +31,13 @@ If you are new to choice modelling, you can check this [resource](https://www.pu - [Usage](#usage) - [Documentation](#documentation) - [Citation](#citation) + +## Introduction - Discrete Choice Modelling + +Discrete choice models aim at explaining or predicting a choice from a set of alternatives. Well known use-cases include analyzing people choice of mean of transport or products purchases in stores. + +If you are new to choice modelling, you can check this [resource](https://www.publichealth.columbia.edu/research/population-health-methods/discrete-choice-model-and-analysis). The different notebooks from the [Getting Started](#getting-started---fast-track) section can also help you understand choice modelling and more importantly help you for your usecase. + ## What's in there ? ### Data @@ -47,7 +49,7 @@ If you are new to choice modelling, you can check this [resource](https://www.pu ### Models - Ready to use models: - Conditional MultiNomialLogit, Train, K.; McFadden, D.; Ben-Akiva, M. (1987) - - RUMnet, Aouad A.; Désir A. (2022) + - RUMnet, Aouad A.; Désir A. (2022) [1] - Ready to use models to be implemented: - Nested MultiNomialLogit - MultiNomialLogit with latent variables (MixedLogit) @@ -106,3 +108,11 @@ A detailed documentation of this project is available [here](https://artefactory ### Contributors ## References + +### Papers +[1][Representing Random Utility Choice Models with Neural Networks](https://arxiv.org/abs/2207.12877), Aouad A.; Désir A. (2022) + +### Code and Repositories +- [PyLogit](https://github.com/timothyb0912/pylogit) +- [Torch Choice](https://gsbdbi.github.io/torch-choice/) +- [1][RUMnet](https://github.com/antoinedesir/rumnet) diff --git a/mkdocs.yaml b/mkdocs.yaml index 93d3cd97..f3edefda 100644 --- a/mkdocs.yaml +++ b/mkdocs.yaml @@ -54,11 +54,15 @@ plugins: nav: - HomePage: index.md - - tutorials.md + - Tutorials: + - Introduction: tutorials/introduction.md + - Getting Started with Data: notebooks/choice_learn_introduction_data.md + - Getting Started with Conditional Logit: notebooks/choice_learn_introduction_clogit.md - How-To Guides: - Introduction: how-to-guides.md - ChoiceDataset Usage: notebooks/choice_learn_introduction_data.md - Conditional Logit Estimation: notebooks/choice_learn_introduction_clogit.md + - RUMnet Estimation: notebooks/rumnet_example.md - Custom Choice Model Creation: notebooks/custom_model.md - References: - Data: From 0aae20e19aff30193de675cee1d48e2b1e497436 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 19 Jan 2024 23:08:20 +0100 Subject: [PATCH 083/767] small addition --- mkdocs.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mkdocs.yaml b/mkdocs.yaml index f3edefda..16ef3f68 100644 --- a/mkdocs.yaml +++ b/mkdocs.yaml @@ -60,9 +60,8 @@ nav: - Getting Started with Conditional Logit: notebooks/choice_learn_introduction_clogit.md - How-To Guides: - Introduction: how-to-guides.md - - ChoiceDataset Usage: notebooks/choice_learn_introduction_data.md - - Conditional Logit Estimation: notebooks/choice_learn_introduction_clogit.md - - RUMnet Estimation: notebooks/rumnet_example.md + - Exhaustive example of ChoiceDataset creation: notebooks/dataset_creation.md + - RUMnet Usage: notebooks/rumnet_example.md - Custom Choice Model Creation: notebooks/custom_model.md - References: - Data: From 7b160bfbb952fda17afe0fe198a23d5731123e64 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 22 Jan 2024 10:42:45 +0100 Subject: [PATCH 084/767] ADD: refreshed RUMnet Off implem --- choice_learn/models/rumnet.py | 473 +++++++++------------------------- 1 file changed, 116 insertions(+), 357 deletions(-) diff --git a/choice_learn/models/rumnet.py b/choice_learn/models/rumnet.py index 4436b62c..72a79ffa 100644 --- a/choice_learn/models/rumnet.py +++ b/choice_learn/models/rumnet.py @@ -2,6 +2,7 @@ import tensorflow as tf from choice_learn.models.base_model import ChoiceModel +from choice_learn.tf_ops import CustomCategoricalCrossEntropy class PaperRUMnet(ChoiceModel): @@ -139,17 +140,17 @@ def instantiate(self): # Storing weights for back-propagation self.weights = self.x_model.weights + self.z_model.weights + self.u_model.weights - self.loss = tf.keras.losses.CategoricalCrossentropy( + self.loss = CustomCategoricalCrossEntropy( from_logits=False, label_smoothing=self.label_smoothing ) - def compute_utility( + def compute_batch_utility( self, - items_features_batch, - session_features_batch, - session_items_features_batch, - availabilities_batch, - choices_batch, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, ): """Compute utility from a batch of ChoiceDataset. @@ -158,17 +159,17 @@ def compute_utility( Parameters ---------- - items_features_batch : tuple of np.ndarray (items_features) + fixed_items_features : tuple of np.ndarray (n_items, n_features) Items-Features: formatting from ChoiceDataset: a matrix representing the - products constant features. - session_features_batch : tuple of np.ndarray (sessions_features) - Time-Features - session_items_features_batch :tuple of np.ndarray (sessions_items_features) - Time-Item-Features - availabilities_batch : np.ndarray - Availabilities (sessions_items_availabilities) - choices_batch : np.ndarray - Choices + products fixed features. + contexts_features : tuple of np.ndarray (n_contexts, n_features) + Contexts-Features: features varying with contexts, shared by all products + contexts_items_features :tuple of np.ndarray (n_contexts, n_items, n_features) + Features varying with contexts and products + contexts_items_availabilities : np.ndarray (n_contexts, n_items) + Availabilities: here for ChoiceModel signature + choices : np.ndarray (n_contexts, ) + Choices: here for ChoiceModel signature Returns: -------- @@ -176,11 +177,11 @@ def compute_utility( Utility of each product for each session. Shape must be (n_sessions, n_items) """ - del availabilities_batch, choices_batch + (_, _) = contexts_items_availabilities, choices ### Restacking of the item features - items_features_batch = tf.concat([*items_features_batch], axis=-1) - session_features_batch = tf.concat([*session_features_batch], axis=-1) - session_items_features_batch = tf.concat([*session_items_features_batch], axis=-1) + items_features_batch = tf.concat([*fixed_items_features], axis=-1) + session_features_batch = tf.concat([*contexts_features], axis=-1) + session_items_features_batch = tf.concat([*contexts_items_features], axis=-1) full_item_features = tf.stack( [items_features_batch] * session_items_features_batch.shape[0], axis=0 @@ -215,32 +216,30 @@ def compute_utility( @tf.function def train_step( self, - items_batch, - sessions_batch, - sessions_items_batch, - availabilities_batch, - choices_batch, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, sample_weight=None, ): """Modified version of train step, as we have to average probabilities over heterogeneities. - Mayber split into two functions? - One for computing probabilities, one for gradient descent ? - Parameters to be renamed ! Function that represents one training step (= one gradient descent step) of the model. + Handles a batch of data of size n_contexts = n_choices = batch_size Parameters ---------- - items_batch : tuple of np.ndarray (items_features) - Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing - the products constant features. - sessions_batch : tuple of np.ndarray (sessions_features) - Time-Features - sessions_items_batch : tuple of np.ndarray (sessions_items_features) - Time-Item-Features - availabilities_batch : np.ndarray - Availabilities (sessions_items_availabilities) - choices_batch : np.ndarray + fixed_items_features : tuple of np.ndarray (n_items, n_features) + Items-Features: formatting from ChoiceDataset: a matrix representing the + products fixed features. + contexts_features : tuple of np.ndarray (n_contexts, n_features) + Contexts-Features: features varying with contexts, shared by all products + contexts_items_features :tuple of np.ndarray (n_contexts, n_items, n_features) + Features varying with contexts and products + contexts_items_availabilities : np.ndarray (n_contexts, n_items) + Availabilities of items + choices : np.ndarray (n_contexts, ) Choices sample_weight : np.ndarray, optional List samples weights to apply during the gradient descent to the batch elements, @@ -253,12 +252,12 @@ def train_step( """ with tf.GradientTape() as tape: ### Computation of utilities - all_u = self.compute_utility( - items_batch, - sessions_batch, - sessions_items_batch, - availabilities_batch, - choices_batch, + all_u = self.compute_batch_utility( + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, + choices=choices, ) probabilities = [] @@ -271,20 +270,20 @@ def train_step( # Average probabilities over heterogeneities probabilities = tf.reduce_mean(eps_probabilities, axis=1) - """ - # Test with availability normalization - probabilities = tf.multiply(probabilities, ia_batch) + + # It is not in the paper, but let's normalize with availabilities + probabilities = tf.multiply(probabilities, contexts_items_availabilities) probabilities = tf.divide( probabilities, tf.reduce_sum(probabilities, axis=1, keepdims=True) + 1e-5 ) - """ + # Probabilities of selected products # chosen_probabilities = tf.gather_nd(indices=choices_nd, params=probabilities) # Negative Log-Likelihood - nll = self.loss( + batch_nll = self.loss( y_pred=probabilities, - y_true=tf.one_hot(choices_batch, depth=probabilities.shape[1]), + y_true=tf.one_hot(choices, depth=probabilities.shape[1]), sample_weight=sample_weight, ) # nll = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False)( @@ -292,18 +291,18 @@ def train_step( # ) # nll = -tf.reduce_sum(tf.math.log(chosen_probabilities + self.logmin)) - grads = tape.gradient(nll, self.weights) + grads = tape.gradient(batch_nll, self.weights) self.optimizer.apply_gradients(zip(grads, self.weights)) - return nll + return batch_nll @tf.function def batch_predict( self, - items_batch, - sessions_batch, - sessions_items_batch, - availabilities_batch, - choices_batch, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, sample_weight=None, ): """Function that represents one prediction (Probas + Loss) for one batch of a ChoiceDataset. @@ -313,16 +312,16 @@ def batch_predict( Parameters ---------- - items_batch : tuple of np.ndarray (items_features) - Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products - constant features. - sessions_batch : tuple of np.ndarray (sessions_features) - Time-Features - sessions_items_batch : tuple of np.ndarray (sessions_items_features) - Time-Item-Features - availabilities_batch : np.ndarray - Availabilities (sessions_items_availabilities) - choices_batch : np.ndarray + fixed_items_features : tuple of np.ndarray (n_items, n_features) + Items-Features: formatting from ChoiceDataset: a matrix representing the + products fixed features. + contexts_features : tuple of np.ndarray (n_contexts, n_features) + Contexts-Features: features varying with contexts, shared by all products + contexts_items_features :tuple of np.ndarray (n_contexts, n_items, n_features) + Features varying with contexts and products + contexts_items_availabilities : np.ndarray (n_contexts, n_items) + Availabilities of items + choices : np.ndarray (n_contexts, ) Choices sample_weight : np.ndarray, optional List samples weights to apply during the gradient descent to the batch elements, @@ -336,117 +335,41 @@ def batch_predict( Probabilities for each product to be chosen for each session """ utilities = self.compute_utility( - items_batch, sessions_batch, sessions_items_batch, availabilities_batch, choices_batch + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, + choices=choices, ) probabilities = tf.nn.softmax(utilities, axis=2) probabilities = tf.reduce_mean(probabilities, axis=1) - # Test with availability normalization - """ - probabilities = tf.multiply(probabilities, ia_batch) + # Normalization with availabilties + probabilities = tf.multiply(probabilities, contexts_items_availabilities) probabilities = tf.divide( probabilities, tf.reduce_sum(probabilities, axis=1, keepdims=True) + 1e-5 ) - """ - batch_loss = self.loss( + batch_nll = self.loss( y_pred=probabilities, - y_true=tf.one_hot(choices_batch, depth=probabilities.shape[1]), + y_true=tf.one_hot(choices, depth=probabilities.shape[1]), sample_weight=sample_weight, ) - return batch_loss, probabilities - - -class PaperRUMnet2(PaperRUMnet): - """Other implementation.""" - - def compute_utility( - self, - items_features_batch, - session_features_batch, - session_items_features_batch, - availabilities_batch, - choices_batch, - ): - """Compute utility from a batch of ChoiceDataset. - - Here we asssume that: item features = {fixed item features + session item features} - user features = {session features} - - Parameters - ---------- - items_features_batch : tuple of np.ndarray (items_features) - Items-Features: formatting from ChoiceDataset: a matrix representing - the products constant features. - session_features_batch : tuple of np.ndarray (sessions_features) - Time-Features - session_items_features_batch :tuple of np.ndarray (sessions_items_features) - Time-Item-Features - availabilities_batch : np.ndarray - Availabilities (sessions_items_availabilities) - choices_batch : np.ndarray - Choices - - Returns: - -------- - np.ndarray - Utility of each product for each session. - Shape must be (n_sessions, n_items) - """ - del availabilities_batch, choices_batch - ### Restacking of the item features - items_features_batch = tf.concat([*items_features_batch], axis=-1) - session_features_batch = tf.concat([*session_features_batch], axis=-1) - session_items_features_batch = tf.concat([*session_items_features_batch], axis=-1) - - full_item_features = tf.stack( - [items_features_batch] * session_items_features_batch.shape[0], axis=0 - ) - full_item_features = tf.concat([session_items_features_batch, full_item_features], axis=-1) - - ### Computation of utilities - utilities = [] + return batch_nll, probabilities - # Computation of the customer features embeddings - z_embeddings = self.z_model(session_features_batch) - # Iterate over items in - def apply_u(x): - return self.u_model(x) +class CPURUMnet(PaperRUMnet): + """CPU-optimized Re-Implementation of the RUMnet model. - for item_i in range(full_item_features.shape[1]): - # Computation of item features embeddings - x_embeddings = self.x_model(full_item_features[:, item_i, :]) - - # utilities.append([]) - - # Computation of utilites from embeddings, iteration over heterogeneities - # (eps_x * eps_z) - _utilities = [] - for _x in x_embeddings: - for _z in z_embeddings: - _u = tf.keras.layers.Concatenate()( - [full_item_features[:, item_i, :], _x, session_features_batch, _z] - ) - _utilities.append(_u) - utilities.append( - tf.map_fn( - fn=apply_u, elems=tf.stack(_utilities, axis=0), fn_output_signature=tf.float32 - ) - ) - ### Reshape utilities: (batch_size, num_items, heterogeneity) - return tf.transpose(tf.squeeze(tf.stack(utilities, axis=0), -1)) - - -class PaperRUMnet3(PaperRUMnet): - """Other Implementation.""" + This implementation handles in parallel the heterogenneities so that the training is faster. + """ - def compute_utility( + def compute_batch_utility( self, - items_features_batch, - session_features_batch, - session_items_features_batch, - availabilities_batch, - choices_batch, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, ): """Compute utility from a batch of ChoiceDataset. @@ -455,16 +378,16 @@ def compute_utility( Parameters ---------- - items_features_batch : tuple of np.ndarray (items_features) - Items-Features: formatting from ChoiceDataset: a matrix representing the products - constant features. - session_features_batch : tuple of np.ndarray (sessions_features) - Time-Features - session_items_features_batch :tuple of np.ndarray (sessions_items_features) - Time-Item-Features - availabilities_batch : np.ndarray - Availabilities (sessions_items_availabilities) - choices_batch : np.ndarray + fixed_items_features : tuple of np.ndarray (n_items, n_features) + Items-Features: formatting from ChoiceDataset: a matrix representing the + products fixed features. + contexts_features : tuple of np.ndarray (n_contexts, n_features) + Contexts-Features: features varying with contexts, shared by all products + contexts_items_features :tuple of np.ndarray (n_contexts, n_items, n_features) + Features varying with contexts and products + contexts_items_availabilities : np.ndarray (n_contexts, n_items) + Availabilities of items + choices : np.ndarray (n_contexts, ) Choices Returns: @@ -473,114 +396,41 @@ def compute_utility( Utility of each product for each session. Shape must be (n_sessions, n_items) """ - del availabilities_batch, choices_batch + (_, _) = contexts_items_availabilities, choices ### Restacking of the item features - items_features_batch = tf.concat([*items_features_batch], axis=-1) - session_features_batch = tf.concat([*session_features_batch], axis=-1) - session_items_features_batch = tf.concat([*session_items_features_batch], axis=-1) + stacked_fixed_items_features = tf.concat([*fixed_items_features], axis=-1) + stacked_contexts_features = tf.concat([*contexts_features], axis=-1) + stacked_contexts_items_features = tf.concat([*contexts_items_features], axis=-1) full_item_features = tf.stack( - [items_features_batch] * session_items_features_batch.shape[0], axis=0 + [stacked_fixed_items_features] * stacked_contexts_items_features.shape[0], axis=0 ) - full_item_features = tf.concat([session_items_features_batch, full_item_features], axis=-1) - - ### Computation of utilities - utilities = [] - - # Computation of the customer features embeddings - z_embeddings = self.z_model(session_features_batch) - - # Iterate over items in assortment - # for item_i in range(full_item_features.shape[1]): - def apply_u(x): - # Computation of item features embeddings - x_embeddings = self.x_model(x) - - utilities = [] - - # Computation of utilites from embeddings, iteration over heterogeneities - # (eps_x * eps_z) - for _x in x_embeddings: - for _z in z_embeddings: - _u = tf.keras.layers.Concatenate()([x, _x, session_features_batch, _z]) - utilities.append(self.u_model(_u)) - return tf.stack(utilities, axis=0) - - utilities = tf.map_fn(fn=apply_u, elems=tf.transpose(full_item_features, perm=[1, 0, 2])) - ### Reshape utilities: (batch_size, num_items, heterogeneity) - return tf.transpose(tf.squeeze(tf.stack(utilities, axis=0), -1)) - - -class PaperRUMnet4(PaperRUMnet): - """Other Implementation.""" - - def compute_utility( - self, - items_features_batch, - session_features_batch, - session_items_features_batch, - availabilities_batch, - choices_batch, - ): - """Compute utility from a batch of ChoiceDataset. - - Here we asssume that: item features = {fixed item features + session item features} - user features = {session features} - - Parameters - ---------- - items_features_batch : tuple of np.ndarray (items_features) - Items-Features: formatting from ChoiceDataset: a matrix representing - the products constant features. - session_features_batch : tuple of np.ndarray (sessions_features) - Time-Features - session_items_features_batch :tuple of np.ndarray (sessions_items_features) - Time-Item-Features - availabilities_batch : np.ndarray - Availabilities (sessions_items_availabilities) - choices_batch : np.ndarray - Choices - - Returns: - -------- - np.ndarray - Utility of each product for each session. - Shape must be (n_sessions, n_items) - """ - del availabilities_batch, choices_batch - ### Restacking of the item features - items_features_batch = tf.concat([*items_features_batch], axis=-1) - session_features_batch = tf.concat([*session_features_batch], axis=-1) - session_items_features_batch = tf.concat([*session_items_features_batch], axis=-1) - - full_item_features = tf.stack( - [items_features_batch] * session_items_features_batch.shape[0], axis=0 + full_item_features = tf.concat( + [stacked_contexts_items_features, full_item_features], axis=-1 ) - full_item_features = tf.concat([session_items_features_batch, full_item_features], axis=-1) ### Computation of utilities utilities = [] - batch_size = session_features_batch.shape[0] + batch_size = stacked_contexts_features.shape[0] # Computation of the customer features embeddings - z_embeddings = self.z_model(session_features_batch) + z_embeddings = self.z_model(stacked_contexts_features) # Iterate over items in assortment for item_i in range(full_item_features.shape[1]): # Computation of item features embeddings x_embeddings = self.x_model(full_item_features[:, item_i, :]) - # utilities.append([]) - _utilities = [] + stacked_heterogeneities = [] # Computation of utilites from embeddings, iteration over heterogeneities - # (eps_x * eps_z) + # eps_x * eps_z for _x in x_embeddings: for _z in z_embeddings: - _u = tf.keras.layers.Concatenate()( - [full_item_features[:, item_i, :], _x, session_features_batch, _z] + full_embedding = tf.keras.layers.Concatenate()( + [full_item_features[:, item_i, :], _x, stacked_contexts_features, _z] ) - _utilities.append(_u) - item_utilities = self.u_model(tf.concat(_utilities, axis=0)) + stacked_heterogeneities.append(full_embedding) + item_utilities = self.u_model(tf.concat(stacked_heterogeneities, axis=0)) item_utilities = tf.stack( [ item_utilities[batch_size * i : batch_size * (i + 1)] @@ -593,100 +443,9 @@ def compute_utility( return tf.squeeze(tf.stack(utilities, axis=1), -1) -class PaperRUMnet5(PaperRUMnet): - """Other Implementation.""" - - def compute_utility( - self, - items_features_batch, - session_features_batch, - session_items_features_batch, - availabilities_batch, - choices_batch, - ): - """Compute utility from a batch of ChoiceDataset. - - Here we asssume that: item features = {fixed item features + session item features} - user features = {session features} - - Parameters - ---------- - items_features_batch : tuple of np.ndarray (items_features) - Items-Features: formatting from ChoiceDataset: a matrix representing - the products constant features. - session_features_batch : tuple of np.ndarray (sessions_features) - Time-Features - session_items_features_batch :tuple of np.ndarray (sessions_items_features) - Time-Item-Features - availabilities_batch : np.ndarray - Availabilities (sessions_items_availabilities) - choices_batch : np.ndarray - Choices - - Returns: - -------- - np.ndarray - Utility of each product for each session. - Shape must be (n_sessions, n_items) - """ - del availabilities_batch, choices_batch - ### Restacking of the item features - items_features_batch = tf.concat([*items_features_batch], axis=-1) - session_features_batch = tf.concat([*session_features_batch], axis=-1) - session_items_features_batch = tf.concat([*session_items_features_batch], axis=-1) - - full_item_features = tf.stack( - [items_features_batch] * session_items_features_batch.shape[0], axis=0 - ) - full_item_features = tf.concat([session_items_features_batch, full_item_features], axis=-1) - - ### Computation of utilities - utilities = [] - batch_size = session_features_batch.shape[0] - num_items = full_item_features.shape[1] - - # Computation of the customer features embeddings - z_embeddings = self.z_model(session_features_batch) - - _utilities = [] - # Iterate over items in assortment - for item_i in range(num_items): - # Computation of item features embeddings - x_embeddings = self.x_model(full_item_features[:, item_i, :]) - - # utilities.append([]) - # Computation of utilites from embeddings, iteration over heterogeneities - # (eps_x * eps_z) - for _x in x_embeddings: - for _z in z_embeddings: - _u = tf.keras.layers.Concatenate()( - [full_item_features[:, item_i, :], _x, session_features_batch, _z] - ) - _utilities.append(_u) - utilities = self.u_model(tf.concat(_utilities, axis=0)) - length_one_item = len(x_embeddings) * len(z_embeddings) * batch_size - reshaped_utilities = [] - for item_i in range(num_items): - item_utilities = tf.stack( - [ - utilities[ - item_i * length_one_item + batch_size * i : item_i * length_one_item - + batch_size * (i + 1) - ] - for i in range(len(x_embeddings) * len(z_embeddings)) - ], - axis=1, - ) - print(item_i, "item_u", item_utilities.shape) - reshaped_utilities.append(item_utilities) - ### Reshape utilities: (batch_size, num_items, heterogeneity) - utilities = tf.squeeze(tf.stack(reshaped_utilities, axis=1), -1) - print("u", utilities.shape) - # utilities = tf.stack(utilities, axis=0) - return utilities - - -def create_ff_network(input_shape, depth, width, add_last=False, l2_regularization_coeff=0.0): +def create_ff_network( + input_shape, depth, width, activation="elu", add_last=False, l2_regularization_coeff=0.0 +): """Base function to create a simple fully connected (Dense) network. Parameters @@ -714,7 +473,7 @@ def create_ff_network(input_shape, depth, width, add_last=False, l2_regularizati out = input for _ in range(depth): out = tf.keras.layers.Dense( - width, activation="elu", kernel_regularizer=regularizer, use_bias=True + width, activation=activation, kernel_regularizer=regularizer, use_bias=True )(out) if add_last: out = tf.keras.layers.Dense(1, activation="linear", use_bias=False)(out) From f85683cf34581eebc842fa601555983c77f9d7d3 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 22 Jan 2024 11:26:46 +0100 Subject: [PATCH 085/767] ADD: MatrixRUMnet --- choice_learn/models/rumnet.py | 563 +++++++++++++++++++++++++++++++++- 1 file changed, 562 insertions(+), 1 deletion(-) diff --git a/choice_learn/models/rumnet.py b/choice_learn/models/rumnet.py index 72a79ffa..8e122e06 100644 --- a/choice_learn/models/rumnet.py +++ b/choice_learn/models/rumnet.py @@ -360,7 +360,7 @@ def batch_predict( class CPURUMnet(PaperRUMnet): """CPU-optimized Re-Implementation of the RUMnet model. - This implementation handles in parallel the heterogenneities so that the training is faster. + This implementation handles in parallel the heterogeneities so that the training is faster. """ def compute_batch_utility( @@ -443,6 +443,567 @@ def compute_batch_utility( return tf.squeeze(tf.stack(utilities, axis=1), -1) +class ParallelDense(tf.keras.layers.Layer): + """Layer that represents several Dense layers in Parallel. + + Parallel means that they have the same input, but then are not intricated and + are totally independant from each other. + """ + + def __init__(self, width, depth, heterogeneity, activation="relu", **kwargs): + """Instantiation of the layer. + + Following tf.keras.Layer API. Note that there will be width * depth * heterogeneity + number of neurons in the layer. + + Parameters + ---------- + width : int + Number of neurons for each dense layer. + depth : int + Number of neuron layers. + heterogeneity : int + Number of dense layers that are in parallel + activation : str, optional + activation function at the end of each layer, by default "relu" + """ + super().__init__(**kwargs) + self.width = width + self.depth = depth + self.heterogeneity = heterogeneity + self.activation = tf.keras.layers.Activation(activation) + + def build(self, input_shape): + """Lazy build of the layer. + + Parameters + ---------- + input_shape : tuple + shape of the input of the layer. Typically (batch_size, num_features). + Batch_size (None) is ignored, but num_features is the shape of the input. + """ + super().build(input_shape) + + weights = [ + ( + self.add_weight( + shape=(input_shape[-1], self.width, self.heterogeneity), + initializer="glorot_normal", + trainable=True, + ), + self.add_weight( + shape=(self.width, self.heterogeneity), + initializer="glorot_normal", + trainable=True, + ), + ) + ] + for i in range(self.depth - 1): + weights.append( + ( + self.add_weight( + shape=(self.width, self.width, self.heterogeneity), + initializer="glorot_normal", + trainable=True, + ), + self.add_weight( + shape=(self.width, self.heterogeneity), + initializer="glorot_normal", + trainable=True, + ), + ) + ) + + self.w = weights + + def call(self, inputs): + """Predict of the layer. + + Follows tf.keras.Layer API. + + Parameters + ---------- + inputs : tf.Tensor, np.ndarray + Tensor of shape (batch_size, n_features) as input of the model. + + Returns: + -------- + outputs + tensor of shape (batch_size, width, heterogeneity) + """ + outputs = tf.tensordot(inputs, self.w[0][0], axes=1) + self.w[0][1] + outputs = self.activation(outputs) + # tf.nn.bias_add(y, weights[0][1], data_format="NC...") + + for w, b in self.w[1:]: + outputs = tf.einsum("ijk,jlk->ilk", outputs, w) + b + outputs = self.activation(outputs) + + return outputs + + +class AssortmentParallelDense(tf.keras.layers.Layer): + """Several Dense layers in Parallel applied to an Assortment. + + Parallel means that they have the same input, but then are not intricated and + are totally independant from each other. The layer applies the same Dense layers + to an assortment of items. + """ + + def __init__(self, width, depth, heterogeneity, activation="relu", **kwargs): + """Inialization of the layer. + + Parameters + ---------- + width : int + Number of neurons of each dense layer. + depth : int + Number of dense layers + heterogeneity : int + Number of dense networks in parallel. + activation : str, optional + activation function of each dense, by default "relu" + """ + super().__init__(**kwargs) + self.width = width + self.depth = depth + self.heterogeneity = heterogeneity + self.activation = tf.keras.layers.Activation(activation) + + def build(self, input_shape): + """Lazy build of the layer. + + Follows tf.keras API. + + Parameters + ---------- + input_shape : tuple + Shape of the input of the layer. + Typically (batch_size, num_items, num_features). + """ + super().build(input_shape) + + weights = [ + ( + self.add_weight( + shape=(input_shape[-1], self.width, self.heterogeneity), + initializer="glorot_normal", + trainable=True, + ), + self.add_weight( + shape=(self.width, self.heterogeneity), + initializer="glorot_normal", + trainable=True, + ), + ) + ] + for i in range(self.depth - 1): + weights.append( + ( + self.add_weight( + shape=(self.width, self.width, self.heterogeneity), + initializer="glorot_normal", + trainable=True, + ), + self.add_weight( + shape=(self.width, self.heterogeneity), + initializer="glorot_normal", + trainable=True, + ), + ) + ) + + self.w = weights + + def call(self, inputs): + """Predict of the layer. + + Follows tf.keras.Layer API. + + Parameters + ---------- + inputs : tf.Tensor, np.ndarray + Tensor of shape (batch_size, n_items, n_features) as input of the model. + + Returns: + -------- + tf.Tensor + Embeddings of shape (batch_size, n_items, width, heterogeneity) + """ + outputs = tf.tensordot(inputs, self.w[0][0], axes=[[2], [0]]) + self.w[0][1] + outputs = self.activation(outputs) + + for w, b in self.w[1:]: + outputs = tf.einsum("imjk,jlk->imlk", outputs, w) + b + outputs = self.activation(outputs) + + return outputs + + +class AssortmentUtilityDenseNetwork(tf.keras.layers.Layer): + """Dense Network that is applied to an assortment of items. + + We apply to the same network over several items and several heterogeneitites. + """ + + def __init__(self, width, depth, activation="relu", add_last=True, **kwargs): + """Initialization of the layer. + + Parameters + ---------- + width : int + Nnumber of neurons of each dense layer. + depth : int + Number of dense layers. + activation : str, optional + Activation function for each layer, by default "relu" + add_last : bool, optional + Whether to add a final dense layer with 1 neuron, by default True + """ + super().__init__(**kwargs) + self.width = width + self.depth = depth + self.activation = tf.keras.layers.Activation(activation) + self.add_last = add_last + + def build(self, input_shape): + """Lazy build of the layer. + + Follows tf.keras.Layer API. + + Parameters + ---------- + input_shape : tuple + Shape of the input of the layer. + Typically (batch_size, num_items, width, heterogeneity). + """ + super().build(input_shape) + + weights = [ + ( + self.add_weight( + shape=(input_shape[-2], self.width), + initializer="glorot_normal", + trainable=True, + ), + self.add_weight( + shape=(self.width, 1), + initializer="glorot_normal", + trainable=True, + ), + ) + ] + for i in range(self.depth - 1): + weights.append( + ( + self.add_weight( + shape=(self.width, self.width), + initializer="glorot_normal", + trainable=True, + ), + self.add_weight( + shape=(self.width, 1), + initializer="glorot_normal", + trainable=True, + ), + ) + ) + if self.add_last: + self.last = self.add_weight( + shape=(self.width, 1), initializer="glorot_normal", trainable=True + ) + + self.w = weights + + def call(self, inputs): + """Predict of the layer. + + Parameters + ---------- + inputs : tf.Tensor, np.ndarray + Input Tensor of shape (batch_size, num_items, width, heterogeneity) + + Returns: + -------- + tf.Tensor + Utilities of shape (batch_size, num_items, heterogeneity) + """ + outputs = inputs + + for w, b in self.w: + # bs, items, features, heterogeneities + outputs = tf.einsum("ijlk, lm->ijmk", outputs, w) + b + outputs = self.activation(outputs) + + if self.add_last: + outputs = tf.einsum("ijlk, lm->ijmk", outputs, self.last) + + return outputs + + +class GPURUMnet(PaperRUMnet): + """GPU-optimized Re-Implementation of the RUMnet model. + + This implementation handles in parallel the heterogeneities so that the training is faster + on GPU. + """ + + def instantiate(self): + """Instatiation of the RUMnet model. + + Instantiation of the three nets: + - x_model encoding products features, + - z_model encoding customers features, + - u_model computing utilities from product, customer features and their embeddings + """ + # Instatiation of the different nets + self.x_model = AssortmentParallelDense( + width=self.width_eps_x, depth=self.depth_eps_x, heterogeneity=self.heterogeneity_x + ) + self.z_model = ParallelDense( + width=self.width_eps_z, depth=self.depth_eps_z, heterogeneity=self.heterogeneity_z + ) + self.u_model = AssortmentUtilityDenseNetwork( + width=self.width_u, depth=self.depth_u, add_last=True + ) + + # Storing weights for back-propagation + self.weights = ( + self.x_model.trainable_variables + + self.z_model.trainable_variables + + self.u_model.trainable_variables + ) + self.loss = CustomCategoricalCrossEntropy( + from_logits=False, label_smoothing=self.label_smoothing + ) + self.time_dict = {} + + def compute_batch_utility( + self, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, + ): + """Compute utility from a batch of ChoiceDataset. + + Here we asssume that: item features = {fixed item features + session item features} + user features = {session features} + + Parameters + ---------- + fixed_items_features : tuple of np.ndarray (n_items, n_features) + Items-Features: formatting from ChoiceDataset: a matrix representing the + products fixed features. + contexts_features : tuple of np.ndarray (n_contexts, n_features) + Contexts-Features: features varying with contexts, shared by all products + contexts_items_features :tuple of np.ndarray (n_contexts, n_items, n_features) + Features varying with contexts and products + contexts_items_availabilities : np.ndarray (n_contexts, n_items) + Availabilities of items + choices : np.ndarray (n_contexts, ) + Choices + + Returns: + -------- + np.ndarray + Utility of each product for each session. + Shape must be (n_sessions, n_items) + """ + (_, _) = contexts_items_availabilities, choices + + ### Restacking of the item features + stacked_fixed_items_features = tf.concat([*fixed_items_features], axis=-1) + stacked_contexts_features = tf.concat([*contexts_features], axis=-1) + stacked_contexts_items_features = tf.concat([*contexts_items_features], axis=-1) + + # Reshaping + # Beware if contexts_items_features is None...! + full_item_features = tf.repeat( + [stacked_fixed_items_features], repeats=stacked_contexts_items_features.shape[0], axis=0 + ) + full_item_features = tf.concat( + [stacked_contexts_items_features, full_item_features], axis=-1 + ) + utilities = [] + + # Computation of the customer features embeddings + z_embeddings = self.z_model(stacked_contexts_features) + x_embeddings = self.x_model(full_item_features) + # Reshaping + big_z = tf.tile( + tf.expand_dims(stacked_contexts_features, axis=2), + multiples=[1, 1, self.heterogeneity_z], + ) + big_z = tf.repeat( + tf.concat([big_z, z_embeddings], axis=1), repeats=self.heterogeneity_x, axis=2 + ) + + # Iterate over items in assortment + for item_i in range(full_item_features.shape[1]): + # Computation of item features embeddings + # utilities.append([]) + + # Computation of utilites from embeddings, iteration over heterogeneities + # (eps_x * eps_z) + x_fixed_features = tf.repeat( + tf.expand_dims(full_item_features[:, item_i, :], axis=2), + repeats=self.heterogeneity_x * self.heterogeneity_z, + axis=2, + ) + big_x = tf.repeat(x_embeddings[:, item_i], repeats=self.heterogeneity_z, axis=2) + + utilities.append(tf.concat([big_z, x_fixed_features, big_x], axis=1)) + + # Computing resulting utilitiies + utilities = self.u_model(tf.stack(utilities, axis=1)) + utilities = tf.squeeze(utilities, -2) + + # Reshape & return + return tf.transpose(utilities, perm=[0, 2, 1]) + + @tf.function + def train_step( + self, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, + sample_weight=None, + ): + """Function that represents one training step (= one gradient descent step) of the model. + + Recoded because heterogeneities generate different shapes of tensors. + # TODO: verify that it is indeed different than PaperRUMnet + + Parameters + ---------- + items_batch : tuple of np.ndarray (items_features) + Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products + constant features. + sessions_batch : tuple of np.ndarray (sessions_features) + Time-Features + sessions_items_batch : tuple of np.ndarray (sessions_items_features) + Time-Item-Features + availabilities_batch : np.ndarray + Availabilities (sessions_items_availabilities) + choices_batch : np.ndarray + Choices + sample_weight : np.ndarray, optional + List samples weights to apply during the gradient descent to the batch elements, + by default None + + Returns: + -------- + tf.Tensor + Value of NegativeLogLikelihood loss for the batch + """ + with tf.GradientTape() as tape: + ### Computation of utilities + all_u = self.compute_utility( + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, + choices=choices, + ) + eps_probabilities = tf.nn.softmax(all_u, axis=2) + + # Average probabilities over heterogeneities + probabilities = tf.reduce_mean(eps_probabilities, axis=1) + + # Availability normalization + probabilities = tf.multiply(probabilities, contexts_items_availabilities) + probabilities = tf.divide( + probabilities, tf.reduce_sum(probabilities, axis=1, keepdims=True) + 1e-5 + ) + # Probabilities of selected products + # chosen_probabilities = tf.gather_nd(indices=choices_nd, params=probabilities) + + # Negative Log-Likelihood + batch_nll = self.loss( + y_pred=probabilities, + y_true=tf.one_hot(choices, depth=probabilities.shape[1]), + sample_weight=sample_weight, + ) + + grads = tape.gradient( + batch_nll, + self.x_model.trainable_variables + + self.z_model.trainable_variables + + self.u_model.trainable_variables, + ) + self.optimizer.apply_gradients( + zip( + grads, + self.x_model.trainable_variables + + self.z_model.trainable_variables + + self.u_model.trainable_variables, + ) + ) + return batch_nll + + @tf.function + def batch_predict( + self, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, + sample_weight=None, + ): + """RUMnet batch_predict. + + Parameters + ---------- + items_batch : tuple of np.ndarray (items_features) + Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products + constant features. + sessions_batch : tuple of np.ndarray (sessions_features) + Time-Features + sessions_items_batch : tuple of np.ndarray (sessions_items_features) + Time-Item-Features + availabilities_batch : np.ndarray + Availabilities (sessions_items_availabilities) + choices_batch : np.ndarray + Choices + sample_weight : np.ndarray, optional + List samples weights to apply during the gradient descent to the batch elements, + by default None + + Returns: + -------- + tf.Tensor (1, ) + Value of NegativeLogLikelihood loss for the batch + tf.Tensor (batch_size, n_items) + Probabilities for each product to be chosen for each session + """ + utilities = self.compute_utility( + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, + choices=choices, + ) + probabilities = tf.nn.softmax(utilities, axis=2) + probabilities = tf.reduce_mean(probabilities, axis=1) + + # Test with availability normalization + probabilities = tf.multiply(probabilities, contexts_items_availabilities) + probabilities = tf.divide( + probabilities, tf.reduce_sum(probabilities, axis=1, keepdims=True) + 1e-5 + ) + batch_loss = self.loss( + y_pred=probabilities, + y_true=tf.one_hot(choices, depth=probabilities.shape[1]), + sample_weight=sample_weight, + ) + return batch_loss, probabilities + + def create_ff_network( input_shape, depth, width, activation="elu", add_last=False, l2_regularization_coeff=0.0 ): From e576f58eb3dbbd5d603e23ac01c1e248dcbfb650 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 22 Jan 2024 11:35:48 +0100 Subject: [PATCH 086/767] ADD: automatic import of RUMnet with device detection --- choice_learn/models/__init__.py | 14 ++++++++--- choice_learn/models/rumnet.py | 1 + notebooks/rumnet_example.ipynb | 41 ++++++++++++++++++++++++++++++++- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/choice_learn/models/__init__.py b/choice_learn/models/__init__.py index 708fec6d..340806a6 100644 --- a/choice_learn/models/__init__.py +++ b/choice_learn/models/__init__.py @@ -1,6 +1,14 @@ """Models classes and functions.""" +import tensorflow as tf -from .conditional_mnl import ConditionalMNL, ModelSpecification -from .rumnet import PaperRUMnet as RUMnet +from .conditional_mnl import ConditionalMNL -__all__ = ["ModelSpecification", "ConditionalMNL", "RUMnet"] +if len(tf.config.list_physical_devices("GPU")) > 0: + print("GPU detected, importing GPU version of RUMnet.") + from .rumnet import GPURUMnet as RUMnet +else: + from .rumnet import CPURUMnet as RUMnet + + print("No GPU detected, importing CPU version of RUMnet.") + +__all__ = ["ConditionalMNL", "RUMnet"] diff --git a/choice_learn/models/rumnet.py b/choice_learn/models/rumnet.py index 8e122e06..7e4e7c4b 100644 --- a/choice_learn/models/rumnet.py +++ b/choice_learn/models/rumnet.py @@ -13,6 +13,7 @@ class PaperRUMnet(ChoiceModel): https://arxiv.org/abs/2207.12877 Inherits from base_model.ChoiceModel + TODO: Verify that all parameters are implemented. """ def __init__( diff --git a/notebooks/rumnet_example.ipynb b/notebooks/rumnet_example.ipynb index cd1945da..6ef8af36 100644 --- a/notebooks/rumnet_example.ipynb +++ b/notebooks/rumnet_example.ipynb @@ -11,11 +11,50 @@ "cell_type": "markdown", "metadata": {}, "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "\n", + "# Remove GPU use\n", + "os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"\"\n", + "\n", + "import sys\n", + "\n", + "sys.path.append(\"../\")\n", + "\n", + "from choice_learn.models import RUMnet" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { + "kernelspec": { + "display_name": "tf_env", + "language": "python", + "name": "python3" + }, "language_info": { - "name": "python" + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.4" } }, "nbformat": 4, From 07cfe20ec6dff780a3415ea8b9eca4f1ff3b8139 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Wed, 24 Jan 2024 18:14:48 +0100 Subject: [PATCH 087/767] FIX: epsU->epsP->P shapes --- choice_learn/models/rumnet.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/choice_learn/models/rumnet.py b/choice_learn/models/rumnet.py index 7e4e7c4b..90d469ad 100644 --- a/choice_learn/models/rumnet.py +++ b/choice_learn/models/rumnet.py @@ -270,7 +270,7 @@ def train_step( # probabilities.append(eps_probabilities) # Average probabilities over heterogeneities - probabilities = tf.reduce_mean(eps_probabilities, axis=1) + probabilities = tf.reduce_mean(eps_probabilities, axis=-1) # It is not in the paper, but let's normalize with availabilities probabilities = tf.multiply(probabilities, contexts_items_availabilities) @@ -913,7 +913,7 @@ def train_step( eps_probabilities = tf.nn.softmax(all_u, axis=2) # Average probabilities over heterogeneities - probabilities = tf.reduce_mean(eps_probabilities, axis=1) + probabilities = tf.reduce_mean(eps_probabilities, axis=-1) # Availability normalization probabilities = tf.multiply(probabilities, contexts_items_availabilities) From dfe2270150d4c1a78617a728aab3d0ffb11b81f0 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Wed, 24 Jan 2024 18:16:13 +0100 Subject: [PATCH 088/767] ADD: SwissMetro training of rumnet example --- notebooks/rumnet_example.ipynb | 155 ++++++++++++++++++++++++++++++++- 1 file changed, 154 insertions(+), 1 deletion(-) diff --git a/notebooks/rumnet_example.ipynb b/notebooks/rumnet_example.ipynb index 6ef8af36..72fce808 100644 --- a/notebooks/rumnet_example.ipynb +++ b/notebooks/rumnet_example.ipynb @@ -27,7 +27,160 @@ "\n", "sys.path.append(\"../\")\n", "\n", - "from choice_learn.models import RUMnet" + "import numpy as np\n", + "import pandas as pd\n", + "\n", + "from choice_learn.data import ChoiceDataset\n", + "from choice_learn.models import RUMnet\n", + "from choice_learn.datasets import load_swissmetro" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df = load_swissmetro(as_frame=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df = df.loc[df.CHOICE!=0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "len(df)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "choices = df.CHOICE.to_numpy() - 1\n", + "contexts_items_availabilities = df[[\"TRAIN_AV\", \"SM_AV\", \"CAR_AV\"]].to_numpy()\n", + "contexts_items_features = np.stack([df[[\"TRAIN_TT\", \"TRAIN_CO\", \"TRAIN_HE\"]].to_numpy(),\n", + " df[[\"SM_TT\", \"SM_CO\", \"SM_HE\"]].to_numpy(),\n", + " df[[\"CAR_TT\", \"CAR_CO\", \"CAR_HE\"]].to_numpy()], axis=1)\n", + "# contexts_features = df[[\"GROUP\", \"PURPOSE\", \"FIRST\", \"TICKET\", \"WHO\", \"LUGGAGE\", \"AGE\", \"MALE\",\n", + "# \"INCOME\", \"GA\", \"ORIGIN\", \"DEST\"]].to_numpy()\n", + "fixed_items_features = np.eye(3)\n", + "\n", + "contexts_items_features[:, :, 0] = contexts_items_features[:, :, 0] / 1000\n", + "contexts_items_features[:, :, 1] = contexts_items_features[:, :, 1] / 5000\n", + "contexts_items_features[:, :, 2] = contexts_items_features[:, :, 2] / 100\n", + "\n", + "long_data = pd.get_dummies(df, columns=[\"GROUP\", \"PURPOSE\", \"FIRST\", \"TICKET\", \"WHO\", \"LUGGAGE\", \"AGE\", \"MALE\",\n", + " \"INCOME\", \"GA\", \"ORIGIN\", \"DEST\"], drop_first=False)\n", + "\n", + "contexts_features = []\n", + "for col in long_data.columns:\n", + " if col.startswith(\"GROUP\"):\n", + " contexts_features.append(col)\n", + " if col.startswith(\"PURPOSE\"):\n", + " contexts_features.append(col)\n", + " if col.startswith(\"FIRST\"):\n", + " contexts_features.append(col)\n", + " if col.startswith(\"TICKET\"):\n", + " contexts_features.append(col)\n", + " if col.startswith(\"WHO\"):\n", + " contexts_features.append(col)\n", + " if col.startswith(\"LUGGAGE\"):\n", + " contexts_features.append(col)\n", + " if col.startswith(\"AGE\"):\n", + " contexts_features.append(col)\n", + " if col.startswith(\"MALE\"):\n", + " contexts_features.append(col)\n", + " if col.startswith(\"INCOME\"):\n", + " contexts_features.append(col)\n", + " if col.startswith(\"GA\"):\n", + " contexts_features.append(col)\n", + " if col.startswith(\"ORIGIN\"):\n", + " contexts_features.append(col)\n", + " if col.startswith(\"DEST\"):\n", + " print(col)\n", + " contexts_features.append(col)\n", + "\n", + "contexts_features = long_data[contexts_features].to_numpy()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "contexts_features.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset = ChoiceDataset(fixed_items_features=(fixed_items_features.astype(\"float32\"), ),\n", + " contexts_features=(contexts_features.astype(\"float32\"), ),\n", + " contexts_items_features=(contexts_items_features.astype(\"float32\"), ),\n", + " contexts_items_availabilities=contexts_items_availabilities,\n", + " choices=choices)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model_args = {\n", + " \"num_products_features\": 6,\n", + " \"num_customer_features\": 83,\n", + " \"width_eps_x\": 20,\n", + " \"depth_eps_x\": 5,\n", + " \"heterogeneity_x\": 10,\n", + " \"width_eps_z\": 20,\n", + " \"depth_eps_z\": 5,\n", + " \"heterogeneity_z\": 10,\n", + " \"width_u\": 20,\n", + " \"depth_u\": 5,\n", + " \"tol\": 1,\n", + " \"optimizer\": \"Adam\",\n", + " \"lr\": 0.002,\n", + " \"logmin\": 1e-10,\n", + " \"label_smoothing\": 0.02,\n", + " \"callbacks\": [],\n", + "}\n", + "model = RUMnet(**model_args)\n", + "model.instantiate()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.fit(dataset, n_epochs=100, batch_size=100)" ] }, { From 6bc67cc2ff3d5e59606f940a0cbc6af2346982c4 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Wed, 24 Jan 2024 18:36:53 +0100 Subject: [PATCH 089/767] FIX: softmax & mean axis, tbv --- choice_learn/models/rumnet.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/choice_learn/models/rumnet.py b/choice_learn/models/rumnet.py index 90d469ad..13fe9c4d 100644 --- a/choice_learn/models/rumnet.py +++ b/choice_learn/models/rumnet.py @@ -266,7 +266,7 @@ def train_step( # for i in range(all_u.shape[2]): # Assortment(t) Utility # eps_probabilities = availability_softmax(all_u[:, :, i], ia_batch, axis=2) - eps_probabilities = tf.nn.softmax(all_u, axis=2) + eps_probabilities = tf.nn.softmax(all_u, axis=1) # probabilities.append(eps_probabilities) # Average probabilities over heterogeneities @@ -335,15 +335,15 @@ def batch_predict( tf.Tensor (batch_size, n_items) Probabilities for each product to be chosen for each session """ - utilities = self.compute_utility( + utilities = self.compute_batch_utility( fixed_items_features=fixed_items_features, contexts_features=contexts_features, contexts_items_features=contexts_items_features, contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) - probabilities = tf.nn.softmax(utilities, axis=2) - probabilities = tf.reduce_mean(probabilities, axis=1) + probabilities = tf.nn.softmax(utilities, axis=1) + probabilities = tf.reduce_mean(probabilities, axis=-1) # Normalization with availabilties probabilities = tf.multiply(probabilities, contexts_items_availabilities) @@ -910,7 +910,7 @@ def train_step( contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) - eps_probabilities = tf.nn.softmax(all_u, axis=2) + eps_probabilities = tf.nn.softmax(all_u, axis=1) # Average probabilities over heterogeneities probabilities = tf.reduce_mean(eps_probabilities, axis=-1) @@ -989,8 +989,8 @@ def batch_predict( contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) - probabilities = tf.nn.softmax(utilities, axis=2) - probabilities = tf.reduce_mean(probabilities, axis=1) + probabilities = tf.nn.softmax(utilities, axis=1) + probabilities = tf.reduce_mean(probabilities, axis=-1) # Test with availability normalization probabilities = tf.multiply(probabilities, contexts_items_availabilities) From bd0f6360107adb9e1229d351f64c79dea2897554 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Wed, 24 Jan 2024 18:37:05 +0100 Subject: [PATCH 090/767] ADD: train/test in example --- notebooks/rumnet_example.ipynb | 39 +++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/notebooks/rumnet_example.ipynb b/notebooks/rumnet_example.ipynb index 72fce808..12a10693 100644 --- a/notebooks/rumnet_example.ipynb +++ b/notebooks/rumnet_example.ipynb @@ -27,6 +27,7 @@ "\n", "sys.path.append(\"../\")\n", "\n", + "import matplotlib.pyplot as plt\n", "import numpy as np\n", "import pandas as pd\n", "\n", @@ -90,9 +91,13 @@ "contexts_items_features[:, :, 1] = contexts_items_features[:, :, 1] / 5000\n", "contexts_items_features[:, :, 2] = contexts_items_features[:, :, 2] / 100\n", "\n", - "long_data = pd.get_dummies(df, columns=[\"GROUP\", \"PURPOSE\", \"FIRST\", \"TICKET\", \"WHO\", \"LUGGAGE\", \"AGE\", \"MALE\",\n", - " \"INCOME\", \"GA\", \"ORIGIN\", \"DEST\"], drop_first=False)\n", + "long_data = pd.get_dummies(df,\n", + " columns=[\"GROUP\", \"PURPOSE\", \"FIRST\", \"TICKET\", \"WHO\",\n", + " \"LUGGAGE\", \"AGE\", \"MALE\",\n", + " \"INCOME\", \"GA\", \"ORIGIN\", \"DEST\"],\n", + " drop_first=False)\n", "\n", + "# Transorming the category data into OneHot\n", "contexts_features = []\n", "for col in long_data.columns:\n", " if col.startswith(\"GROUP\"):\n", @@ -118,7 +123,6 @@ " if col.startswith(\"ORIGIN\"):\n", " contexts_features.append(col)\n", " if col.startswith(\"DEST\"):\n", - " print(col)\n", " contexts_features.append(col)\n", "\n", "contexts_features = long_data[contexts_features].to_numpy()" @@ -146,6 +150,20 @@ " choices=choices)" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "indexes = np.random.permutation(list(range(len(dataset))))\n", + "train_indexes = indexes[:int(len(indexes) * 0.8)]\n", + "test_indexes = indexes[int(len(indexes) * 0.8):]\n", + "\n", + "train_dataset = dataset[train_indexes]\n", + "test_dataset = dataset[test_indexes]" + ] + }, { "cell_type": "code", "execution_count": null, @@ -180,7 +198,7 @@ "metadata": {}, "outputs": [], "source": [ - "model.fit(dataset, n_epochs=100, batch_size=100)" + "losses =model.fit(train_dataset, n_epochs=2, batch_size=128)" ] }, { @@ -188,7 +206,18 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "plt.plot(losses[\"train_loss\"])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.evaluate(test_dataset)" + ] } ], "metadata": { From e73e2e9654bbd3eb0350fa115e46786507a7ad41 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 25 Jan 2024 11:54:45 +0100 Subject: [PATCH 091/767] ENH: return type list then tuple --- choice_learn/data/choice_dataset.py | 69 ++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 10 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index a8f24135..a31d4d32 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -401,7 +401,7 @@ def _build_features_by_ids(self): if len(fixed_items_features_map) + len(contexts_features_map) + len( contexts_items_features_map - ) == len(self.features_by_ids): + ) != len(self.features_by_ids): raise ValueError("Some features_by_ids were not matched with features_names.") return fixed_items_features_map, contexts_features_map, contexts_items_features_map @@ -1009,21 +1009,21 @@ def get_choices_batch(self, choices_indexes, features=None): if self.fixed_items_features is None: fixed_items_features = None else: - fixed_items_features = tuple( + fixed_items_features = list( items_feature for items_feature in self.fixed_items_features ) if self.contexts_features is None: contexts_features = None else: - contexts_features = tuple( + contexts_features = list( contexts_feature[choices_indexes] for contexts_feature in self.contexts_features ) if self.contexts_items_features is None: contexts_items_features = None else: - contexts_items_features = tuple( + contexts_items_features = list( contexts_items_feature[choices_indexes] for contexts_items_feature in self.contexts_items_features ) @@ -1034,17 +1034,66 @@ def get_choices_batch(self, choices_indexes, features=None): contexts_items_availabilities = self.contexts_items_availabilities[choices_indexes] for indexes, f_by_id in self.fixed_items_features_map: - fixed_items_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = f_by_id.batch[ - fixed_items_features[indexes[0]][:, indexes[1]] - ] + fixed_items_features[indexes[0]] = np.concatenate( + [ + fixed_items_features[indexes[0]][:, : indexes[1]], + f_by_id.batch[fixed_items_features[indexes[0]][:, indexes[1]]], + fixed_items_features[indexes[0]][:, indexes[1] + 1 :], + ], + axis=1, + ) + for indexes, f_by_id in self.contexts_features_map: - contexts_features[indexes[0]][indexes[1] : indexes[1] + 1] = f_by_id.batch[ - contexts_features[indexes[0]][indexes[1]] - ] + contexts_features[indexes[0]] = np.concatenate( + [ + contexts_features[indexes[0]][: indexes[1]], + f_by_id.batch[contexts_features[indexes[0]][indexes[1]]], + contexts_features[indexes[0]][indexes[1] + 1 :], + ], + axis=0, + ) + for indexes, f_by_id in self.contexts_items_features_map: contexts_items_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = f_by_id.batch[ contexts_items_features[indexes[0]][:, indexes[1]] ] + contexts_items_features[indexes[0]] = np.concatenate( + [ + contexts_items_features[indexes[0]][:, : indexes[1]], + f_by_id.batch[contexts_items_features[indexes[0]][:, indexes[1]]], + contexts_items_features[indexes[0]][:, indexes[1] + 1 :], + ], + axis=1, + ) + + if fixed_items_features is not None: + for i in range(len(fixed_items_features)): + fixed_items_features[i] = fixed_items_features[i].astype(self._return_types[0][i]) + # items_features were not given as a tuple, so we return do not return it as a tuple + if not self._return_items_features_tuple: + fixed_items_features = fixed_items_features[0] + else: + fixed_items_features = tuple(fixed_items_features) + + if contexts_features is not None: + for i in range(len(contexts_features)): + contexts_features[i] = contexts_features[i].astype(self._return_types[1][i]) + if not self._return_contexts_features_tuple: + contexts_features = contexts_features[0] + else: + contexts_features = tuple(contexts_features) + + if contexts_items_features is not None: + for i in range(len(contexts_items_features)): + contexts_items_features[i] = contexts_items_features[i].astype( + self._return_types[2][i] + ) + # sessions_items_features were not given as a tuple, so we return do not return + # it as a tuple + if not self._return_contexts_items_features_tuple: + contexts_items_features = contexts_items_features[0] + else: + contexts_items_features = tuple(contexts_items_features) return ( fixed_items_features, From 2fb820df38e1b08e233955a331bacfc95a0b6475 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 25 Jan 2024 11:55:15 +0100 Subject: [PATCH 092/767] ADD: latest changes from CD.get_choices_batch --- choice_learn/data/indexer.py | 100 +++++++++++++++++++++++------------ 1 file changed, 65 insertions(+), 35 deletions(-) diff --git a/choice_learn/data/indexer.py b/choice_learn/data/indexer.py index d070ee09..fbfce0d5 100644 --- a/choice_learn/data/indexer.py +++ b/choice_learn/data/indexer.py @@ -397,50 +397,80 @@ def __getitem__(self, choices_indexes): contexts_features = self._get_contexts_features(choices_indexes) contexts_items_features = self._get_contexts_items_features(choices_indexes) - # Get availabilities + choice = self.choice_dataset.choices[choices_indexes] + if self.choice_dataset.contexts_items_availabilities is None: - contexts_items_availabilities = None + contexts_items_availabilities = np.ones((self.choice_dataset.base_num_items)) else: - if hasattr(self.choice_dataset.contexts_items_availabilities, "batch"): - contexts_items_availabilities = ( - self.choice_dataset.contexts_items_availabilities.iloc[ - choices_indexes - ].astype(self.choice_dataset._return_types[3]) - ) - else: - contexts_items_availabilities = ( - self.choice_dataset.contexts_items_availabilities[choices_indexes].astype( - self.choice_dataset._return_types[3] - ) - ) - # Features by ID mapping - for indexes, f_by_id in self.choice_dataset.fixed_items_features_map: - fixed_items_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = f_by_id.batch[ - fixed_items_features[indexes[0]][:, indexes[1]] + contexts_items_availabilities = self.choice_dataset.contexts_items_availabilities[ + choices_indexes ] + + for indexes, f_by_id in self.choice_dataset.fixed_items_features_map: + fixed_items_features[indexes[0]] = np.concatenate( + [ + fixed_items_features[indexes[0]][:, : indexes[1]], + f_by_id.batch[fixed_items_features[indexes[0]][:, indexes[1]]], + fixed_items_features[indexes[0]][:, indexes[1] + 1 :], + ], + axis=1, + ) + for indexes, f_by_id in self.choice_dataset.contexts_features_map: - contexts_features[indexes[0]][indexes[1] : indexes[1] + 1] = f_by_id.batch[ - contexts_features[indexes[0]][indexes[1]] - ] + contexts_features[indexes[0]] = np.concatenate( + [ + contexts_features[indexes[0]][: indexes[1]], + f_by_id.batch[contexts_features[indexes[0]][indexes[1]]], + contexts_features[indexes[0]][indexes[1] + 1 :], + ], + axis=0, + ) + for indexes, f_by_id in self.choice_dataset.contexts_items_features_map: contexts_items_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = f_by_id.batch[ contexts_items_features[indexes[0]][:, indexes[1]] ] + contexts_items_features[indexes[0]] = np.concatenate( + [ + contexts_items_features[indexes[0]][:, : indexes[1]], + f_by_id.batch[contexts_items_features[indexes[0]][:, indexes[1]]], + contexts_items_features[indexes[0]][:, indexes[1] + 1 :], + ], + axis=1, + ) - # Shaping and typing - # items_features were not given as a tuple, so we return do not return it as a tuple - if not self.choice_dataset._return_items_features_tuple: - fixed_items_features = fixed_items_features[0] - if not self.choice_dataset._return_contexts_features_tuple: - contexts_features = contexts_features[0] - # sessions_items_features were not given as a tuple, so we return do not return - # it as a tuple - if not self.choice_dataset._return_contexts_items_features_tuple: - contexts_items_features = contexts_items_features[0] - - choice = self.choice_dataset.choices[choices_indexes].astype( - self.choice_dataset._return_types[4] - ) + if fixed_items_features is not None: + for i in range(len(fixed_items_features)): + fixed_items_features[i] = fixed_items_features[i].astype( + self.choice_dataset._return_types[0][i] + ) + # items_features were not given as a tuple, so we return do not return it as a tuple + if not self.choice_dataset._return_items_features_tuple: + fixed_items_features = fixed_items_features[0] + else: + fixed_items_features = tuple(fixed_items_features) + + if contexts_features is not None: + for i in range(len(contexts_features)): + contexts_features[i] = contexts_features[i].astype( + self.choice_dataset._return_types[1][i] + ) + if not self.choice_dataset._return_contexts_features_tuple: + contexts_features = contexts_features[0] + else: + contexts_features = tuple(contexts_features) + + if contexts_items_features is not None: + for i in range(len(contexts_items_features)): + contexts_items_features[i] = contexts_items_features[i].astype( + self.choice_dataset._return_types[2][i] + ) + # sessions_items_features were not given as a tuple, so we return do not return + # it as a tuple + if not self.choice_dataset._return_contexts_items_features_tuple: + contexts_items_features = contexts_items_features[0] + else: + contexts_items_features = tuple(contexts_items_features) return ( fixed_items_features, From d6cfb77b14f65a9d749f63dafdd3d750a2890715 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 25 Jan 2024 14:01:43 +0100 Subject: [PATCH 093/767] FIX: some checks on featuresByID --- choice_learn/data/choice_dataset.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index a31d4d32..2f433243 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -105,7 +105,7 @@ def __init__( if contexts_features is not None: if not isinstance(contexts_features, tuple): self._return_contexts_features_tuple = False - if contexts_items_features_names is not None: + if contexts_features_names is not None: if len(contexts_features[0]) != len(contexts_features_names): raise ValueError( f"""Number of features given does not match @@ -397,7 +397,7 @@ def _build_features_by_ids(self): for k, column_name in enumerate(feature): for feature_by_id in self.features_by_ids: if column_name == feature_by_id.name: - contexts_items_features_map.append(((i, j), feature_by_id)) + contexts_items_features_map.append(((i, k), feature_by_id)) if len(fixed_items_features_map) + len(contexts_features_map) + len( contexts_items_features_map @@ -552,7 +552,7 @@ def _check_types(self): else: session_item_types.append(np.float32) for indexes, f_by_id in self.contexts_items_features_map: - sample_dtype = f_by_id.get_storage_types() + sample_dtype = f_by_id.get_storage_type() session_item_types[indexes[0]] = sample_dtype return_types.append(tuple(session_item_types)) return_types.append(np.float32) @@ -946,13 +946,13 @@ def get_choices_batch(self, choices_indexes, features=None): axis=1, ) for indexes, f_by_id in self.contexts_items_features_map: - contexts_items_features[indexes[0]][ - :, :, indexes[1] : indexes[1] + 1 - ] = f_by_id.batch[contexts_items_features[indexes[0]][:, :, indexes[1]]] + mapped_features = f_by_id.batch[ + contexts_items_features[indexes[0]][:, :, indexes[1]] + ] contexts_items_features[indexes[0]] = np.concatenate( [ contexts_items_features[indexes[0]][:, :, : indexes[1]], - f_by_id.batch[contexts_items_features[indexes[0]][:, :, indexes[1]]], + mapped_features, contexts_items_features[indexes[0]][:, :, indexes[1] + 1 :], ], axis=2, From 5df2da2ab6e960c8f8bb34c9f44ba625b0928f4a Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 25 Jan 2024 14:02:31 +0100 Subject: [PATCH 094/767] ADD: Indexers now handle batching over several dimensions --- choice_learn/data/indexer.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/choice_learn/data/indexer.py b/choice_learn/data/indexer.py index fbfce0d5..eb6bab6e 100644 --- a/choice_learn/data/indexer.py +++ b/choice_learn/data/indexer.py @@ -92,7 +92,10 @@ def __getitem__(self, sequence_keys): features corresponding to the sequence_keys """ if isinstance(sequence_keys, list) or isinstance(sequence_keys, np.ndarray): + if len(np.array(sequence_keys).shape) > 1: + return np.stack([self.storage.batch[key] for key in sequence_keys], axis=0) return np.array([self.storage.storage[key] for key in sequence_keys]) + if isinstance(sequence_keys, slice): raise ValueError("Slicing is not supported for storage") return np.array(self.storage.storage[sequence_keys]) @@ -294,7 +297,9 @@ def __getitem__(self, choices_indexes): # Get availabilities if self.choice_dataset.contexts_items_availabilities is None: - contexts_items_availabilities = None + contexts_items_availabilities = np.ones( + (len(choices_indexes), self.choice_dataset.base_num_items) + ) else: if hasattr(self.choice_dataset.contexts_items_availabilities, "batch"): contexts_items_availabilities = ( From 1dd13748118bd7b415e9839a6ed4601dab982677 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 25 Jan 2024 18:01:33 +0100 Subject: [PATCH 095/767] on going change of fID mapping --- choice_learn/data/choice_dataset.py | 50 +++++++++++++++++++++++------ choice_learn/data/indexer.py | 18 +++++------ 2 files changed, 48 insertions(+), 20 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index 2f433243..cabb2749 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -4,6 +4,7 @@ import pandas as pd from choice_learn.data.indexer import ChoiceDatasetIndexer +from choice_learn.data.storage import Storage class ChoiceDataset(object): @@ -320,6 +321,9 @@ def __init__( self.contexts_items_availabilities = contexts_items_availabilities self.choices = choices + for fid in features_by_ids: + if not isinstance(fid, Storage): + raise ValueError("FeaturesByID must be Storage object") self.features_by_ids = features_by_ids self.fixed_items_features_names = fixed_items_features_names @@ -373,7 +377,7 @@ def _build_features_by_ids(self): fixed_items_features_map = [] contexts_features_map = [] - contexts_items_features_map = [] + contexts_items_features_map = {} if self.fixed_items_features_names is not None: for i, feature in enumerate(self.fixed_items_features_names): @@ -397,10 +401,13 @@ def _build_features_by_ids(self): for k, column_name in enumerate(feature): for feature_by_id in self.features_by_ids: if column_name == feature_by_id.name: - contexts_items_features_map.append(((i, k), feature_by_id)) + index_dict = contexts_items_features_map.get(i, {}) + index_dict[k] = feature_by_id + contexts_items_features_map[i] = index_dict + # contexts_items_features_map.append(((i, k), feature_by_id)) - if len(fixed_items_features_map) + len(contexts_features_map) + len( - contexts_items_features_map + if len(fixed_items_features_map) + len(contexts_features_map) + sum( + [len(c.keys()) for c in contexts_items_features_map.values()] ) != len(self.features_by_ids): raise ValueError("Some features_by_ids were not matched with features_names.") @@ -551,9 +558,9 @@ def _check_types(self): session_item_types.append(np.int32) else: session_item_types.append(np.float32) - for indexes, f_by_id in self.contexts_items_features_map: - sample_dtype = f_by_id.get_storage_type() - session_item_types[indexes[0]] = sample_dtype + for indexes, f_dict in self.contexts_items_features_map.items(): + sample_dtype = next(iter(f_dict.values())).get_storage_type() + session_item_types[indexes] = sample_dtype return_types.append(tuple(session_item_types)) return_types.append(np.float32) return_types.append(np.int32) @@ -945,10 +952,32 @@ def get_choices_batch(self, choices_indexes, features=None): ], axis=1, ) - for indexes, f_by_id in self.contexts_items_features_map: - mapped_features = f_by_id.batch[ + if len(self.contexts_items_features_map) > 0: + mapped_features = [] + for tuple_index in np.sort(list(self.contexts_items_features_map.keys())): + feat_ind_min = 0 + unstacked_feat = [] + for feature_index in np.sort( + list(self.contexts_items_features_map[tuple_index].keys()) + ): + unstacked_feat.append( + contexts_items_features[tuple_index][:, :, feat_ind_min:feature_index] + ) + unstacked_feat.append( + self.contexts_items_features_map[tuple_index][feature_index].batch[ + contexts_items_features[tuple_index][:, :, feature_index] + ] + ) + mapped_features.append(np.concatenate(unstacked_feat, axis=2)) + + contexts_items_features = mapped_features + print(contexts_items_features) + """for order, (indexes, f_by_id) in enumerate(self.contexts_items_features_map): + mapped_features.append(f_by_id.batch[ contexts_items_features[indexes[0]][:, :, indexes[1]] - ] + ]) + mapped_features_mapping.get(indexes[0], {})[indexes[1]] = order + contexts_items_features[indexes[0]] = np.concatenate( [ contexts_items_features[indexes[0]][:, :, : indexes[1]], @@ -957,6 +986,7 @@ def get_choices_batch(self, choices_indexes, features=None): ], axis=2, ) + """ if fixed_items_features is not None: for i in range(len(fixed_items_features)): diff --git a/choice_learn/data/indexer.py b/choice_learn/data/indexer.py index eb6bab6e..68863279 100644 --- a/choice_learn/data/indexer.py +++ b/choice_learn/data/indexer.py @@ -91,6 +91,8 @@ def __getitem__(self, sequence_keys): array_like features corresponding to the sequence_keys """ + print(sequence_keys) + print(self.storage.storage) if isinstance(sequence_keys, list) or isinstance(sequence_keys, np.ndarray): if len(np.array(sequence_keys).shape) > 1: return np.stack([self.storage.batch[key] for key in sequence_keys], axis=0) @@ -261,14 +263,10 @@ def _get_contexts_items_features(self, choices_indexes): contexts_items_features = [] for i, contexts_items_feature in enumerate(self.choice_dataset.contexts_items_features): if hasattr(contexts_items_feature, "iloc"): - contexts_items_features.append( - contexts_items_feature.iloc[choices_indexes].astype(self._return_types[2][i]) - ) + contexts_items_features.append(contexts_items_feature.iloc[choices_indexes]) else: contexts_items_features.append( - np.stack(contexts_items_feature[choices_indexes], axis=0).astype( - self.choice_dataset._return_types[2][i] - ) + np.stack(contexts_items_feature[choices_indexes], axis=0) ) return contexts_items_features @@ -334,13 +332,13 @@ def __getitem__(self, choices_indexes): axis=1, ) for indexes, f_by_id in self.choice_dataset.contexts_items_features_map: - contexts_items_features[indexes[0]][ - :, :, indexes[1] : indexes[1] + 1 - ] = f_by_id.batch[contexts_items_features[indexes[0]][:, :, indexes[1]]] + mapped_features = f_by_id.batch[ + contexts_items_features[indexes[0]][:, :, indexes[1]] + ] contexts_items_features[indexes[0]] = np.concatenate( [ contexts_items_features[indexes[0]][:, :, : indexes[1]], - f_by_id.batch[contexts_items_features[indexes[0]][:, :, indexes[1]]], + mapped_features, contexts_items_features[indexes[0]][:, :, indexes[1] + 1 :], ], axis=2, From 8e69af77cef58060c9c955ac88d44578718f6118 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 25 Jan 2024 18:01:46 +0100 Subject: [PATCH 096/767] unfinished fixes --- choice_learn/models/rumnet.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/choice_learn/models/rumnet.py b/choice_learn/models/rumnet.py index 13fe9c4d..ae6b7967 100644 --- a/choice_learn/models/rumnet.py +++ b/choice_learn/models/rumnet.py @@ -903,17 +903,17 @@ def train_step( """ with tf.GradientTape() as tape: ### Computation of utilities - all_u = self.compute_utility( + all_u = self.compute_batch_utility( fixed_items_features=fixed_items_features, contexts_features=contexts_features, contexts_items_features=contexts_items_features, contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) - eps_probabilities = tf.nn.softmax(all_u, axis=1) + eps_probabilities = tf.nn.softmax(all_u, axis=1) # Average probabilities over heterogeneities - probabilities = tf.reduce_mean(eps_probabilities, axis=-1) + probabilities = tf.reduce_mean(eps_probabilities, axis=1) # Availability normalization probabilities = tf.multiply(probabilities, contexts_items_availabilities) From f37f76b4f8814a4c1ff5992541406af71ff07049 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 26 Jan 2024 10:47:22 +0100 Subject: [PATCH 097/767] ADD: new fID mapping for cif --- choice_learn/data/choice_dataset.py | 4 ++-- choice_learn/data/indexer.py | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index cabb2749..b83d2b72 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -405,7 +405,7 @@ def _build_features_by_ids(self): index_dict[k] = feature_by_id contexts_items_features_map[i] = index_dict # contexts_items_features_map.append(((i, k), feature_by_id)) - + print(contexts_items_features_map) if len(fixed_items_features_map) + len(contexts_features_map) + sum( [len(c.keys()) for c in contexts_items_features_map.values()] ) != len(self.features_by_ids): @@ -968,10 +968,10 @@ def get_choices_batch(self, choices_indexes, features=None): contexts_items_features[tuple_index][:, :, feature_index] ] ) + feat_ind_min = feature_index + 1 mapped_features.append(np.concatenate(unstacked_feat, axis=2)) contexts_items_features = mapped_features - print(contexts_items_features) """for order, (indexes, f_by_id) in enumerate(self.contexts_items_features_map): mapped_features.append(f_by_id.batch[ contexts_items_features[indexes[0]][:, :, indexes[1]] diff --git a/choice_learn/data/indexer.py b/choice_learn/data/indexer.py index 68863279..862e7f9a 100644 --- a/choice_learn/data/indexer.py +++ b/choice_learn/data/indexer.py @@ -91,8 +91,6 @@ def __getitem__(self, sequence_keys): array_like features corresponding to the sequence_keys """ - print(sequence_keys) - print(self.storage.storage) if isinstance(sequence_keys, list) or isinstance(sequence_keys, np.ndarray): if len(np.array(sequence_keys).shape) > 1: return np.stack([self.storage.batch[key] for key in sequence_keys], axis=0) From 17c07f6a040e5c709720139c753efe4067c69d4f Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 26 Jan 2024 10:48:10 +0100 Subject: [PATCH 098/767] ADD: renamed notebook + new better examples --- notebooks/features_byID_example.ipynb | 416 +++++++++++++++++++++++ notebooks/features_storage_example.ipynb | 200 ----------- 2 files changed, 416 insertions(+), 200 deletions(-) create mode 100644 notebooks/features_byID_example.ipynb delete mode 100644 notebooks/features_storage_example.ipynb diff --git a/notebooks/features_byID_example.ipynb b/notebooks/features_byID_example.ipynb new file mode 100644 index 00000000..6237dcd6 --- /dev/null +++ b/notebooks/features_byID_example.ipynb @@ -0,0 +1,416 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "\n", + "# Remove GPU use\n", + "os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"\"\n", + "\n", + "import sys\n", + "from pathlib import Path\n", + "\n", + "sys.path.append(\"../\")\n", + "\n", + "import numpy as np\n", + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from choice_learn.data.storage import FeaturesStorage, OneHotStorage\n", + "from choice_learn.data import ChoiceDataset" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Different Instantiation Possibilities for Storage:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "features = {\"customerA\": [1, 2, 3], \"customerB\": [4, 5, 6], \"customerC\": [7, 8, 9]}\n", + "storage = FeaturesStorage(values=features, values_names=[\"age\", \"income\", \"children_nb\"], name=\"customers_features\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "storage[[\"customerA\", \"customerC\"]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "storage.batch[[\"customerA\", \"customerC\", \"customerA\", \"customerC\"]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "features = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n", + "ids = [\"customerA\", \"customerB\", \"customerC\"]\n", + "\n", + "storage = FeaturesStorage(ids=ids, values=features, values_names=[\"age\", \"income\", \"children_nb\"], name=\"customers\")\n", + "storage.batch[[\"customerA\", \"customerC\", \"customerA\", \"customerC\"]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "features = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n", + "\n", + "storage = FeaturesStorage(values=features, values_names=[\"age\", \"income\", \"children_nb\"], name=\"customers\")\n", + "storage.batch[[0, 2, 0, 2]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "features = {\"age\": [1, 2, 3], \"income\": [4, 5, 6], \"children_nb\": [7, 8, 9], \"id\": [\"customerA\", \"customerB\", \"customerC\"]}\n", + "features = pd.DataFrame(features)\n", + "storage = FeaturesStorage(values=features, name=\"customers\")\n", + "storage.batch[[\"customerA\", \"customerC\", \"customerA\", \"customerC\"]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "features = {\"age\": [1, 2, 3], \"income\": [4, 5, 6], \"children_nb\": [7, 8, 9]}\n", + "features = pd.DataFrame(features, index=[\"customerA\", \"customerB\", \"customerC\"])\n", + "storage = FeaturesStorage(values=features, name=\"customers\")\n", + "storage.batch[[\"customerA\", \"customerC\", \"customerA\", \"customerC\"]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ids = [0, 1, 2, 3, 4]\n", + "values = [4, 3, 2, 1, 0]\n", + "\n", + "oh_storage = OneHotStorage(ids=ids, values=values, name=\"OneHotTest\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "oh_storage.batch[[0, 2, 4]], oh_storage.get_element_from_index(0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "oh_storage = OneHotStorage(values=values, name=\"OneHotTest\")\n", + "oh_storage.batch[[0, 2, 4]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "oh_storage = OneHotStorage(ids=ids, name=\"OneHotTest\")\n", + "oh_storage.batch[[0, 2, 4]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "values_dict = {k:v for k, v in zip(ids, values)}\n", + "oh_storage = OneHotStorage(values=values_dict, name=\"OneHotTest\")\n", + "oh_storage.batch[[0, 2, 4]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "oh_storage = OneHotStorage(ids=ids, values=values_dict, name=\"OneHotTest\")\n", + "try:\n", + " oh_storage = OneHotStorage(name=\"OneHotTest\")\n", + " assert False\n", + "except:\n", + " assert True" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Use of FeaturesByID and Storage in the ChoiceDataset" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "features = {\"customerA\": [1, 2, 3], \"customerB\": [4, 5, 6], \"customerC\": [7, 8, 9]}\n", + "storage = FeaturesStorage(values=features, values_names=[\"age\", \"income\", \"children_nb\"], name=\"customers_features\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fixed_items_features = np.eye(3)\n", + "prices = [[[4, 1], [4, 1], [5, 1]], [[5, 2], [4, 2], [6, 2]],\n", + " [[6, 3], [7, 3], [8, 3]], [[4, 4], [5, 4], [4, 4]]]\n", + "choices = [0, 1 , 2, 2]\n", + "contexts_features = [[\"customerA\"], [\"customerB\"], [\"customerC\"], [\"customerA\"]]\n", + "\n", + "dataset = ChoiceDataset(\n", + " fixed_items_features=fixed_items_features,\n", + " contexts_features=contexts_features,\n", + " choices=choices,\n", + " contexts_items_features=prices,\n", + " features_by_ids=[storage],\n", + " contexts_features_names=[\"customers_features\"],\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset.get_choices_batch(0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset.batch[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset.get_choices_batch([1, 2])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "myd = {1: 2, 2:3, 3:4, 4:5}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.sort(list(myd.keys()))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset.batch[1:3]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "features = {\"item1\": [1, 2, 3], \"item2\": [4, 5, 6], \"item3\": [7, 8, 9], \"item4\": [10, 11, 12]}\n", + "storage = FeaturesStorage(values=features, values_names=[\"f1\", \"f2\", \"f3\"], name=\"items_features\")\n", + "\n", + "price_storage = {\"price1\": [1], \"price2\": [2], \"price3\": [3], \"price4\": [4]}\n", + "price_storage = FeaturesStorage(values=price_storage, values_names=[\"price\"], name=\"items_prices\")\n", + "\n", + "fixed_items_features = np.eye(3)\n", + "prices = [[[4, 1], [4, 1], [5, 1]], [[5, 2], [4, 2], [6, 2]],\n", + " [[6, 3], [7, 3], [8, 3]], [[4, 4], [5, 4], [4, 4]]]\n", + "contexts_items_features = [[[\"item1\", \"price1\"], [\"item2\", \"price2\"], [\"item3\", \"price3\"]],\n", + " [[\"item1\", \"price1\"], [\"item4\", \"price2\"], [\"item3\", \"price4\"]],\n", + " [[\"item1\", \"price1\"], [\"item2\", \"price3\"], [\"item3\", \"price4\"]],\n", + " [[\"item1\", \"price1\"], [\"item2\", \"price3\"], [\"item3\", \"price4\"]]]\n", + "choices = [0, 1 , 2, 2]\n", + "contexts_features = [[0, 1], [1, 0], [1, 1], [0, 0]]\n", + "\n", + "dataset = ChoiceDataset(\n", + " fixed_items_features=fixed_items_features,\n", + " contexts_features=contexts_features,\n", + " choices=choices,\n", + " contexts_items_features=contexts_items_features,\n", + " features_by_ids=[storage, price_storage],\n", + " contexts_items_features_names=[\"items_features\", \"items_prices\"],\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset.contexts_items_features_map[0][0].storage" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset.get_choices_batch([0, 1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset.batch[[0, 1]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a = np.array([1, 2, 3])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a[2:2]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.concatenate([a[:2], a[2:2], a[2:3]])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "myd = {1:2, 2:3}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "next(iter(myd.values()))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "tf_env", + "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.11.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/features_storage_example.ipynb b/notebooks/features_storage_example.ipynb deleted file mode 100644 index 5e8df68a..00000000 --- a/notebooks/features_storage_example.ipynb +++ /dev/null @@ -1,200 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "\n", - "# Remove GPU use\n", - "os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"\"\n", - "\n", - "import sys\n", - "from pathlib import Path\n", - "\n", - "sys.path.append(\"../\")\n", - "\n", - "import numpy as np\n", - "import pandas as pd" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from choice_learn.data.storage import FeaturesStorage, OneHotStorage" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "features = {\"customerA\": [1, 2, 3], \"customerB\": [4, 5, 6], \"customerC\": [7, 8, 9]}\n", - "storage = FeaturesStorage(values=features, values_names=[\"age\", \"income\", \"children_nb\"], name=\"customers\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "storage[[\"customerA\", \"customerC\"]]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "storage.batch[[\"customerA\", \"customerC\", \"customerA\", \"customerC\"]]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "features = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n", - "ids = [\"customerA\", \"customerB\", \"customerC\"]\n", - "\n", - "storage = FeaturesStorage(ids=ids, values=features, values_names=[\"age\", \"income\", \"children_nb\"], name=\"customers\")\n", - "storage.batch[[\"customerA\", \"customerC\", \"customerA\", \"customerC\"]]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "features = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n", - "\n", - "storage = FeaturesStorage(values=features, values_names=[\"age\", \"income\", \"children_nb\"], name=\"customers\")\n", - "storage.batch[[0, 2, 0, 2]]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "features = {\"age\": [1, 2, 3], \"income\": [4, 5, 6], \"children_nb\": [7, 8, 9], \"id\": [\"customerA\", \"customerB\", \"customerC\"]}\n", - "features = pd.DataFrame(features)\n", - "storage = FeaturesStorage(values=features, name=\"customers\")\n", - "storage.batch[[\"customerA\", \"customerC\", \"customerA\", \"customerC\"]]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "features = {\"age\": [1, 2, 3], \"income\": [4, 5, 6], \"children_nb\": [7, 8, 9]}\n", - "features = pd.DataFrame(features, index=[\"customerA\", \"customerB\", \"customerC\"])\n", - "storage = FeaturesStorage(values=features, name=\"customers\")\n", - "storage.batch[[\"customerA\", \"customerC\", \"customerA\", \"customerC\"]]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ids = [0, 1, 2, 3, 4]\n", - "values = [4, 3, 2, 1, 0]\n", - "\n", - "oh_storage = OneHotStorage(ids=ids, values=values, name=\"OneHotTest\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "oh_storage.batch[[0, 2, 4]], oh_storage.get_element_from_index(0)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "oh_storage = OneHotStorage(values=values, name=\"OneHotTest\")\n", - "oh_storage.batch[[0, 2, 4]]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "oh_storage = OneHotStorage(ids=ids, name=\"OneHotTest\")\n", - "oh_storage.batch[[0, 2, 4]]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "values_dict = {k:v for k, v in zip(ids, values)}\n", - "oh_storage = OneHotStorage(values=values_dict, name=\"OneHotTest\")\n", - "oh_storage.batch[[0, 2, 4]]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "oh_storage = OneHotStorage(ids=ids, values=values_dict, name=\"OneHotTest\")\n", - "oh_storage = OneHotStorage(name=\"OneHotTest\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "tf_env", - "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.11.4" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} From d15dd3055b2ff8bfdcf7755e5d7e23b9003d87db Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 26 Jan 2024 11:17:59 +0100 Subject: [PATCH 099/767] ADD: change in fID handling now for all features and indexer --- choice_learn/data/choice_dataset.py | 191 ++++++++++++++++----------- choice_learn/data/indexer.py | 197 +++++++++++++++++++--------- 2 files changed, 250 insertions(+), 138 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index b83d2b72..c32ba0f2 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -375,8 +375,8 @@ def _build_features_by_ids(self): "No features_names given, match with fiven features_by_ids impossible." ) - fixed_items_features_map = [] - contexts_features_map = [] + fixed_items_features_map = {} + contexts_features_map = {} contexts_items_features_map = {} if self.fixed_items_features_names is not None: @@ -385,7 +385,9 @@ def _build_features_by_ids(self): for j, column_name in enumerate(feature): for feature_by_id in self.features_by_ids: if column_name == feature_by_id.name: - fixed_items_features_map.append(((i, j), feature_by_id)) + index_dict = fixed_items_features_map.get(i, {}) + index_dict[j] = feature_by_id + fixed_items_features_map[i] = index_dict if self.contexts_features_names is not None: for i, feature in enumerate(self.contexts_features_names): @@ -393,7 +395,9 @@ def _build_features_by_ids(self): for j, column_name in enumerate(feature): for feature_by_id in self.features_by_ids: if column_name == feature_by_id.name: - contexts_features_map.append(((i, j), feature_by_id)) + index_dict = contexts_features_map.get(i, {}) + index_dict[j] = feature_by_id + contexts_features_map[i] = index_dict if self.contexts_items_features_names is not None: for i, feature in enumerate(self.contexts_items_features_names): @@ -405,7 +409,7 @@ def _build_features_by_ids(self): index_dict[k] = feature_by_id contexts_items_features_map[i] = index_dict # contexts_items_features_map.append(((i, k), feature_by_id)) - print(contexts_items_features_map) + if len(fixed_items_features_map) + len(contexts_features_map) + sum( [len(c.keys()) for c in contexts_items_features_map.values()] ) != len(self.features_by_ids): @@ -534,9 +538,9 @@ def _check_types(self): else: item_types.append(np.float32) - for indexes, f_by_id in self.fixed_items_features_map: - sample_dtype = f_by_id.get_storage_types() - item_types[indexes[0]] = sample_dtype + for indexes, f_dict in self.fixed_items_features_map.items(): + sample_dtype = next(iter(f_dict.values())).get_storage_type() + item_types[indexes] = sample_dtype return_types.append(tuple(item_types)) session_types = [] @@ -546,9 +550,9 @@ def _check_types(self): session_types.append(np.int32) else: session_types.append(np.float32) - for indexes, f_by_id in self.contexts_features_map: - sample_dtype = f_by_id.get_storage_type() - session_types[indexes[0]] = sample_dtype + for indexes, f_dict in self.contexts_features_map.items(): + sample_dtype = next(iter(f_dict.values())).get_storage_type() + session_types[indexes] = sample_dtype return_types.append(tuple(session_types)) session_item_types = [] @@ -934,24 +938,48 @@ def get_choices_batch(self, choices_indexes, features=None): choices = self.choices[choices_indexes].astype(self._return_types[4]) - for indexes, f_by_id in self.fixed_items_features_map: - fixed_items_features[indexes[0]] = np.concatenate( - [ - fixed_items_features[indexes[0]][:, : indexes[1]], - f_by_id.batch[fixed_items_features[indexes[0]][:, indexes[1]]], - fixed_items_features[indexes[0]][:, indexes[1] + 1 :], - ], - axis=1, - ) - for indexes, f_by_id in self.contexts_features_map: - contexts_features[indexes[0]] = np.concatenate( - [ - contexts_features[indexes[0]][:, : indexes[1]], - f_by_id.batch[contexts_features[indexes[0]][:, indexes[1]]], - contexts_features[indexes[0]][:, indexes[1] + 1 :], - ], - axis=1, - ) + if len(self.fixed_items_features_map) > 0: + mapped_features = [] + for tuple_index in np.sort(list(self.fixed_items_features_map.keys())): + feat_ind_min = 0 + unstacked_feat = [] + for feature_index in np.sort( + list(self.fixed_items_features_map[tuple_index].keys()) + ): + unstacked_feat.append( + fixed_items_features[tuple_index][:, feat_ind_min:feature_index] + ) + unstacked_feat.append( + self.fixed_items_features_map[tuple_index][feature_index].batch[ + fixed_items_features[tuple_index][:, feature_index] + ] + ) + feat_ind_min = feature_index + 1 + mapped_features.append(np.concatenate(unstacked_feat, axis=1)) + + fixed_items_features = mapped_features + + if len(self.contexts_features_map) > 0: + mapped_features = [] + for tuple_index in np.sort(list(self.contexts_features_map.keys())): + feat_ind_min = 0 + unstacked_feat = [] + for feature_index in np.sort( + list(self.contexts_features_map[tuple_index].keys()) + ): + unstacked_feat.append( + contexts_features[tuple_index][:, feat_ind_min:feature_index] + ) + unstacked_feat.append( + self.contexts_features_map[tuple_index][feature_index].batch[ + contexts_features[tuple_index][:, feature_index] + ] + ) + feat_ind_min = feature_index + 1 + mapped_features.append(np.concatenate(unstacked_feat, axis=1)) + + contexts_features = mapped_features + if len(self.contexts_items_features_map) > 0: mapped_features = [] for tuple_index in np.sort(list(self.contexts_items_features_map.keys())): @@ -972,21 +1000,6 @@ def get_choices_batch(self, choices_indexes, features=None): mapped_features.append(np.concatenate(unstacked_feat, axis=2)) contexts_items_features = mapped_features - """for order, (indexes, f_by_id) in enumerate(self.contexts_items_features_map): - mapped_features.append(f_by_id.batch[ - contexts_items_features[indexes[0]][:, :, indexes[1]] - ]) - mapped_features_mapping.get(indexes[0], {})[indexes[1]] = order - - contexts_items_features[indexes[0]] = np.concatenate( - [ - contexts_items_features[indexes[0]][:, :, : indexes[1]], - mapped_features, - contexts_items_features[indexes[0]][:, :, indexes[1] + 1 :], - ], - axis=2, - ) - """ if fixed_items_features is not None: for i in range(len(fixed_items_features)): @@ -1063,38 +1076,66 @@ def get_choices_batch(self, choices_indexes, features=None): else: contexts_items_availabilities = self.contexts_items_availabilities[choices_indexes] - for indexes, f_by_id in self.fixed_items_features_map: - fixed_items_features[indexes[0]] = np.concatenate( - [ - fixed_items_features[indexes[0]][:, : indexes[1]], - f_by_id.batch[fixed_items_features[indexes[0]][:, indexes[1]]], - fixed_items_features[indexes[0]][:, indexes[1] + 1 :], - ], - axis=1, - ) - - for indexes, f_by_id in self.contexts_features_map: - contexts_features[indexes[0]] = np.concatenate( - [ - contexts_features[indexes[0]][: indexes[1]], - f_by_id.batch[contexts_features[indexes[0]][indexes[1]]], - contexts_features[indexes[0]][indexes[1] + 1 :], - ], - axis=0, - ) + if len(self.fixed_items_features_map) > 0: + mapped_features = [] + for tuple_index in np.sort(list(self.fixed_items_features_map.keys())): + feat_ind_min = 0 + unstacked_feat = [] + for feature_index in np.sort( + list(self.fixed_items_features_map[tuple_index].keys()) + ): + unstacked_feat.append( + fixed_items_features[tuple_index][:, feat_ind_min:feature_index] + ) + unstacked_feat.append( + self.fixed_items_features_map[tuple_index][feature_index].batch[ + fixed_items_features[tuple_index][:, feature_index] + ] + ) + feat_ind_min = feature_index + 1 + mapped_features.append(np.concatenate(unstacked_feat, axis=1)) + + fixed_items_features = mapped_features + + if len(self.contexts_features_map) > 0: + mapped_features = [] + for tuple_index in np.sort(list(self.contexts_features_map.keys())): + feat_ind_min = 0 + unstacked_feat = [] + for feature_index in np.sort(list(self.contexts_features_map[tuple_index].keys())): + unstacked_feat.append( + contexts_features[tuple_index][feat_ind_min:feature_index] + ) + unstacked_feat.append( + self.contexts_features_map[tuple_index][feature_index].batch[ + contexts_features[tuple_index][feature_index] + ] + ) + feat_ind_min = feature_index + 1 + mapped_features.append(np.concatenate(unstacked_feat, axis=0)) + + contexts_features = mapped_features + + if len(self.contexts_items_features_map) > 0: + mapped_features = [] + for tuple_index in np.sort(list(self.contexts_items_features_map.keys())): + feat_ind_min = 0 + unstacked_feat = [] + for feature_index in np.sort( + list(self.contexts_items_features_map[tuple_index].keys()) + ): + unstacked_feat.append( + contexts_items_features[tuple_index][:, feat_ind_min:feature_index] + ) + unstacked_feat.append( + self.contexts_items_features_map[tuple_index][feature_index].batch[ + contexts_items_features[tuple_index][:, feature_index] + ] + ) + feat_ind_min = feature_index + 1 + mapped_features.append(np.concatenate(unstacked_feat, axis=1)) - for indexes, f_by_id in self.contexts_items_features_map: - contexts_items_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = f_by_id.batch[ - contexts_items_features[indexes[0]][:, indexes[1]] - ] - contexts_items_features[indexes[0]] = np.concatenate( - [ - contexts_items_features[indexes[0]][:, : indexes[1]], - f_by_id.batch[contexts_items_features[indexes[0]][:, indexes[1]]], - contexts_items_features[indexes[0]][:, indexes[1] + 1 :], - ], - axis=1, - ) + contexts_items_features = mapped_features if fixed_items_features is not None: for i in range(len(fixed_items_features)): diff --git a/choice_learn/data/indexer.py b/choice_learn/data/indexer.py index 862e7f9a..46440b2c 100644 --- a/choice_learn/data/indexer.py +++ b/choice_learn/data/indexer.py @@ -309,38 +309,74 @@ def __getitem__(self, choices_indexes): self.choice_dataset._return_types[3] ) ) - # Get choices - for indexes, f_by_id in self.choice_dataset.fixed_items_features_map: - fixed_items_features[indexes[0]] = np.concatenate( - [ - fixed_items_features[indexes[0]][:, : indexes[1]], - f_by_id.batch[fixed_items_features[indexes[0]][:, indexes[1]]], - fixed_items_features[indexes[0]][:, indexes[1] + 1 :], - ], - axis=1, - ) - # Features by ID mapping - for indexes, f_by_id in self.choice_dataset.contexts_features_map: - contexts_features[indexes[0]] = np.concatenate( - [ - contexts_features[indexes[0]][:, : indexes[1]], - f_by_id.batch[contexts_features[indexes[0]][:, indexes[1]]], - contexts_features[indexes[0]][:, indexes[1] + 1 :], - ], - axis=1, - ) - for indexes, f_by_id in self.choice_dataset.contexts_items_features_map: - mapped_features = f_by_id.batch[ - contexts_items_features[indexes[0]][:, :, indexes[1]] - ] - contexts_items_features[indexes[0]] = np.concatenate( - [ - contexts_items_features[indexes[0]][:, :, : indexes[1]], - mapped_features, - contexts_items_features[indexes[0]][:, :, indexes[1] + 1 :], - ], - axis=2, - ) + + if len(self.choice_dataset.fixed_items_features_map) > 0: + mapped_features = [] + for tuple_index in np.sort( + list(self.choice_dataset.fixed_items_features_map.keys()) + ): + feat_ind_min = 0 + unstacked_feat = [] + for feature_index in np.sort( + list(self.choice_dataset.fixed_items_features_map[tuple_index].keys()) + ): + unstacked_feat.append( + fixed_items_features[tuple_index][:, feat_ind_min:feature_index] + ) + unstacked_feat.append( + self.choice_dataset.fixed_items_features_map[tuple_index][ + feature_index + ].batch[fixed_items_features[tuple_index][:, feature_index]] + ) + feat_ind_min = feature_index + 1 + mapped_features.append(np.concatenate(unstacked_feat, axis=1)) + + fixed_items_features = mapped_features + + if len(self.choice_dataset.contexts_features_map) > 0: + mapped_features = [] + for tuple_index in np.sort(list(self.choice_dataset.contexts_features_map.keys())): + feat_ind_min = 0 + unstacked_feat = [] + for feature_index in np.sort( + list(self.choice_dataset.contexts_features_map[tuple_index].keys()) + ): + unstacked_feat.append( + contexts_features[tuple_index][:, feat_ind_min:feature_index] + ) + unstacked_feat.append( + self.choice_dataset.contexts_features_map[tuple_index][ + feature_index + ].batch[contexts_features[tuple_index][:, feature_index]] + ) + feat_ind_min = feature_index + 1 + mapped_features.append(np.concatenate(unstacked_feat, axis=1)) + + contexts_features = mapped_features + + if len(self.choice_dataset.contexts_items_features_map) > 0: + mapped_features = [] + for tuple_index in np.sort( + list(self.choice_dataset.contexts_items_features_map.keys()) + ): + feat_ind_min = 0 + unstacked_feat = [] + for feature_index in np.sort( + list(self.choice_dataset.contexts_items_features_map[tuple_index].keys()) + ): + unstacked_feat.append( + contexts_items_features[tuple_index][:, :, feat_ind_min:feature_index] + ) + unstacked_feat.append( + self.choice_dataset.contexts_items_features_map[tuple_index][ + feature_index + ].batch[contexts_items_features[tuple_index][:, :, feature_index]] + ) + feat_ind_min = feature_index + 1 + mapped_features.append(np.concatenate(unstacked_feat, axis=2)) + + contexts_items_features = mapped_features + # Shaping and typing if fixed_items_features is not None: for i in range(len(fixed_items_features)): @@ -407,38 +443,72 @@ def __getitem__(self, choices_indexes): choices_indexes ] - for indexes, f_by_id in self.choice_dataset.fixed_items_features_map: - fixed_items_features[indexes[0]] = np.concatenate( - [ - fixed_items_features[indexes[0]][:, : indexes[1]], - f_by_id.batch[fixed_items_features[indexes[0]][:, indexes[1]]], - fixed_items_features[indexes[0]][:, indexes[1] + 1 :], - ], - axis=1, - ) - - for indexes, f_by_id in self.choice_dataset.contexts_features_map: - contexts_features[indexes[0]] = np.concatenate( - [ - contexts_features[indexes[0]][: indexes[1]], - f_by_id.batch[contexts_features[indexes[0]][indexes[1]]], - contexts_features[indexes[0]][indexes[1] + 1 :], - ], - axis=0, - ) + if len(self.choice_dataset.fixed_items_features_map) > 0: + mapped_features = [] + for tuple_index in np.sort( + list(self.choice_dataset.fixed_items_features_map.keys()) + ): + feat_ind_min = 0 + unstacked_feat = [] + for feature_index in np.sort( + list(self.choice_dataset.fixed_items_features_map[tuple_index].keys()) + ): + unstacked_feat.append( + fixed_items_features[tuple_index][:, feat_ind_min:feature_index] + ) + unstacked_feat.append( + self.choice_dataset.fixed_items_features_map[tuple_index][ + feature_index + ].batch[fixed_items_features[tuple_index][:, feature_index]] + ) + feat_ind_min = feature_index + 1 + mapped_features.append(np.concatenate(unstacked_feat, axis=1)) + + fixed_items_features = mapped_features + + if len(self.choice_dataset.contexts_features_map) > 0: + mapped_features = [] + for tuple_index in np.sort(list(self.choice_dataset.contexts_features_map.keys())): + feat_ind_min = 0 + unstacked_feat = [] + for feature_index in np.sort( + list(self.choice_dataset.contexts_features_map[tuple_index].keys()) + ): + unstacked_feat.append( + contexts_features[tuple_index][feat_ind_min:feature_index] + ) + unstacked_feat.append( + self.choice_dataset.contexts_features_map[tuple_index][ + feature_index + ].batch[contexts_features[tuple_index][feature_index]] + ) + feat_ind_min = feature_index + 1 + mapped_features.append(np.concatenate(unstacked_feat, axis=0)) + + contexts_features = mapped_features + + if len(self.choice_dataset.contexts_items_features_map) > 0: + mapped_features = [] + for tuple_index in np.sort( + list(self.choice_dataset.contexts_items_features_map.keys()) + ): + feat_ind_min = 0 + unstacked_feat = [] + for feature_index in np.sort( + list(self.choice_dataset.contexts_items_features_map[tuple_index].keys()) + ): + unstacked_feat.append( + contexts_items_features[tuple_index][:, feat_ind_min:feature_index] + ) + unstacked_feat.append( + self.choice_dataset.contexts_items_features_map[tuple_index][ + feature_index + ].batch[contexts_items_features[tuple_index][:, feature_index]] + ) + feat_ind_min = feature_index + 1 + mapped_features.append(np.concatenate(unstacked_feat, axis=1)) - for indexes, f_by_id in self.choice_dataset.contexts_items_features_map: - contexts_items_features[indexes[0]][:, indexes[1] : indexes[1] + 1] = f_by_id.batch[ - contexts_items_features[indexes[0]][:, indexes[1]] - ] - contexts_items_features[indexes[0]] = np.concatenate( - [ - contexts_items_features[indexes[0]][:, : indexes[1]], - f_by_id.batch[contexts_items_features[indexes[0]][:, indexes[1]]], - contexts_items_features[indexes[0]][:, indexes[1] + 1 :], - ], - axis=1, - ) + contexts_items_features = mapped_features if fixed_items_features is not None: for i in range(len(fixed_items_features)): @@ -480,4 +550,5 @@ def __getitem__(self, choices_indexes): contexts_items_availabilities, choice, ) + print(f"Type{type(choices_indexes)} not handled") raise NotImplementedError From 246d4bc0532c4319618e4aa03944dda6d71470b8 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 26 Jan 2024 11:25:41 +0100 Subject: [PATCH 100/767] FIX: default val of fID is now {} --- choice_learn/data/choice_dataset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index c32ba0f2..8ba0f5b1 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -364,7 +364,7 @@ def _build_features_by_ids(self): """ if len(self.features_by_ids) == 0: print("No features_by_ids given.") - return [], [], [] + return {}, {}, {} if ( self.fixed_items_features_names is None From 9e34aa8d89af492ce8050a95ab9e9f5a01d9e757 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 26 Jan 2024 11:35:21 +0100 Subject: [PATCH 101/767] FIX: softmax/mean dimensions after U --- choice_learn/models/rumnet.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/choice_learn/models/rumnet.py b/choice_learn/models/rumnet.py index ae6b7967..dce7efca 100644 --- a/choice_learn/models/rumnet.py +++ b/choice_learn/models/rumnet.py @@ -910,8 +910,8 @@ def train_step( contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) - - eps_probabilities = tf.nn.softmax(all_u, axis=1) + print(all_u.shape) + eps_probabilities = tf.nn.softmax(all_u, axis=2) # Average probabilities over heterogeneities probabilities = tf.reduce_mean(eps_probabilities, axis=1) @@ -982,15 +982,15 @@ def batch_predict( tf.Tensor (batch_size, n_items) Probabilities for each product to be chosen for each session """ - utilities = self.compute_utility( + utilities = self.compute_batch_utility( fixed_items_features=fixed_items_features, contexts_features=contexts_features, contexts_items_features=contexts_items_features, contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) - probabilities = tf.nn.softmax(utilities, axis=1) - probabilities = tf.reduce_mean(probabilities, axis=-1) + probabilities = tf.nn.softmax(utilities, axis=2) + probabilities = tf.reduce_mean(probabilities, axis=1) # Test with availability normalization probabilities = tf.multiply(probabilities, contexts_items_availabilities) From 68ba7f3ef95e31c1d1c1abde10bd66bc8eb3b9d4 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 26 Jan 2024 12:06:58 +0100 Subject: [PATCH 102/767] ADD: checks on model.instantiate() called or not --- choice_learn/models/base_model.py | 3 +++ choice_learn/models/rumnet.py | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index a5560f93..1c237631 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -210,6 +210,9 @@ def fit( dict: Different metrics values over epochs. """ + if hasattr(self, "instantiated"): + if not self.instantiated: + raise ValueError("Model not instantiated. Please call .instantiate() first.") losses_history = {"train_loss": []} t_range = tqdm.trange(n_epochs, position=0) diff --git a/choice_learn/models/rumnet.py b/choice_learn/models/rumnet.py index dce7efca..6fbe47e8 100644 --- a/choice_learn/models/rumnet.py +++ b/choice_learn/models/rumnet.py @@ -116,6 +116,8 @@ def __init__( print(f"Optimizer {optimizer} not implemnted, switching for default Adam") self.optimizer = tf.keras.optimizers.Adam(lr) + self.instantiated = False + def instantiate(self): """Instatiation of the RUMnet model. @@ -144,6 +146,7 @@ def instantiate(self): self.loss = CustomCategoricalCrossEntropy( from_logits=False, label_smoothing=self.label_smoothing ) + self.instantiated = True def compute_batch_utility( self, @@ -778,6 +781,7 @@ def instantiate(self): from_logits=False, label_smoothing=self.label_smoothing ) self.time_dict = {} + self.instantiated = True def compute_batch_utility( self, @@ -910,7 +914,6 @@ def train_step( contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) - print(all_u.shape) eps_probabilities = tf.nn.softmax(all_u, axis=2) # Average probabilities over heterogeneities probabilities = tf.reduce_mean(eps_probabilities, axis=1) From 2fbb8be759b92fca385bf5c391c915585a1a544e Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 26 Jan 2024 12:07:17 +0100 Subject: [PATCH 103/767] update notebooks --- notebooks/rumnet_example.ipynb | 128 +++++++---- notebooks/test_new_dataset.ipynb | 362 +++++++++++++++++++++++++++++++ 2 files changed, 445 insertions(+), 45 deletions(-) create mode 100644 notebooks/test_new_dataset.ipynb diff --git a/notebooks/rumnet_example.ipynb b/notebooks/rumnet_example.ipynb index 12a10693..ce18c800 100644 --- a/notebooks/rumnet_example.ipynb +++ b/notebooks/rumnet_example.ipynb @@ -4,14 +4,11 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Introduction to modelling with RUMnet" + "## Introduction to modelling with RUMnet\n", + "\n", + "We reproduce in this notebook the results of the paper Reprensenting Random Uility Models with Neural Networks on the SwissMetro dataset." ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, { "cell_type": "code", "execution_count": null, @@ -20,8 +17,9 @@ "source": [ "import os\n", "\n", - "# Remove GPU use\n", - "os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"\"\n", + "# Remove/Add GPU use\n", + "os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"0\"\n", + "\n", "\n", "import sys\n", "\n", @@ -37,21 +35,17 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "df = load_swissmetro(as_frame=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "df = df.loc[df.CHOICE!=0]" + "Note that there are two implementation of RUMnet: One more CPU-oriented and one more GPU-oriented.\n", + "The import of the right model is automatically done. You can also import the model directly with:\n", + "\n", + "```python\n", + "from choice_learn.models import CPURUMnet, GPURUMnet\n", + "```\n", + "\n", + "First, we download the SwissMetro dataset:" ] }, { @@ -60,16 +54,15 @@ "metadata": {}, "outputs": [], "source": [ - "len(df)" + "df = load_swissmetro(as_frame=True)\n", + "df.head()" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "df.head()" + "We follow the same data preparation as in the original paper in order to get the exact same results.\n" ] }, { @@ -78,6 +71,7 @@ "metadata": {}, "outputs": [], "source": [ + "df = df.loc[df.CHOICE!=0]\n", "choices = df.CHOICE.to_numpy() - 1\n", "contexts_items_availabilities = df[[\"TRAIN_AV\", \"SM_AV\", \"CAR_AV\"]].to_numpy()\n", "contexts_items_features = np.stack([df[[\"TRAIN_TT\", \"TRAIN_CO\", \"TRAIN_HE\"]].to_numpy(),\n", @@ -129,12 +123,10 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "contexts_features.shape" + "Now, we can create our ChoiceDataset from the dataframe." ] }, { @@ -151,17 +143,30 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "indexes = np.random.permutation(list(range(len(dataset))))\n", - "train_indexes = indexes[:int(len(indexes) * 0.8)]\n", - "test_indexes = indexes[int(len(indexes) * 0.8):]\n", + "Let's Cross-Validate !\n", + "We keep a scikit-learn-like structure.\n", + "To avoid creating dependancies, we use a different train/test split code, but the following would totally work:\n", + "\n", + "\n", + "```python\n", + "from sklearn.model_selection import ShuffleSplit\n", + "\n", + "rs = ShuffleSplit(n_splits=5, test_size=.2, random_state=0)\n", "\n", - "train_dataset = dataset[train_indexes]\n", - "test_dataset = dataset[test_indexes]" + "for i, (train_index, test_index) in enumerate(rs.split(dataset.choices)):\n", + " train_dataset = dataset[train_index]\n", + " test_dataset = dataset[test_index]\n", + "\n", + " model = RUMnet(**args)\n", + " model.instantiate()\n", + " model.fit(train_dataset)\n", + " model.evaluate(test_dataset)\n", + "```\n", + "\n", + "We just use a numpy based split, but the core code is the same!" ] }, { @@ -183,13 +188,11 @@ " \"depth_u\": 5,\n", " \"tol\": 1,\n", " \"optimizer\": \"Adam\",\n", - " \"lr\": 0.002,\n", + " \"lr\": 0.0002,\n", " \"logmin\": 1e-10,\n", " \"label_smoothing\": 0.02,\n", " \"callbacks\": [],\n", - "}\n", - "model = RUMnet(**model_args)\n", - "model.instantiate()" + "}" ] }, { @@ -198,7 +201,26 @@ "metadata": {}, "outputs": [], "source": [ - "losses =model.fit(train_dataset, n_epochs=2, batch_size=128)" + "indexes = np.random.permutation(list(range(len(dataset))))\n", + "\n", + "fit_losses = []\n", + "test_eval = []\n", + "for i in range(5):\n", + " test_indexes = indexes[int(len(indexes) * 0.2 * i):int(len(indexes) * 0.2 * (i + 1))]\n", + " train_indexes = np.concatenate([indexes[:int(len(indexes) * 0.2 * i)],\n", + " indexes[int(len(indexes) * 0.2 * (i + 1)):]],\n", + " axis=0)\n", + "\n", + " train_dataset = dataset[train_indexes]\n", + " test_dataset = dataset[test_indexes]\n", + "\n", + " model = RUMnet(**model_args)\n", + " model.instantiate()\n", + "\n", + " losses = model.fit(train_dataset, n_epochs=5000, batch_size=128)\n", + " test_eval.append(model.evaluate(test_dataset))\n", + "\n", + " fit_losses.append(losses)" ] }, { @@ -207,7 +229,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.plot(losses[\"train_loss\"])" + "for i in range(len(fit_losses)):\n", + " plt.plot(fit_losses[i][\"train_loss\"], label=f\"fold {i}\")\n", + "plt.legend()" ] }, { @@ -216,8 +240,22 @@ "metadata": {}, "outputs": [], "source": [ - "model.evaluate(test_dataset)" + "print(\"Average LogLikeliHood on test:\", np.mean(test_eval))" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/notebooks/test_new_dataset.ipynb b/notebooks/test_new_dataset.ipynb new file mode 100644 index 00000000..9a320ad0 --- /dev/null +++ b/notebooks/test_new_dataset.ipynb @@ -0,0 +1,362 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "from pathlib import Path\n", + "\n", + "sys.path.append(\"../\")æ©\n", + "\n", + "import numpy as np\n", + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from choice_learn.data import ChoiceDataset\n", + "from choice_learn.data.storage import FeaturesStorage\n", + "# path to dataset file is:\n", + "filepath = \"choice_learn/datasets/data/ModeCanada.csv.gz\"\n", + "canada_transport_df = pd.read_csv((Path(\"..\") / filepath), index_col=0)\n", + "\n", + "print(\"Let's look at the dataframe:\")\n", + "canada_transport_df.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "load_modecanada = 1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"\n", + "from choice_learn.models import ConditionalLogitModel\n", + "\n", + "model = ConditionalLogitModel()\n", + "model.add_coefficient(coefficient_name=\"beta_customer_income\",\n", + " feature_name=\"customer_income\",\n", + " items_indexes=[0, 1, 2])\n", + "model.add_coefficient(coefficient_name=\"beta_price\",\n", + " feature_name=\"price\",\n", + " items_indexes=[0, 1, 2])\n", + "model.add_shared_coefficient(coefficient_name=\"beta_travel_time\",\n", + " feature_name=\"travel_time\",\n", + " items_indexes=[0, 1, 2])\n", + "model.add_shared_coefficient(coefficient_name=\"conditional_intercept\",\n", + " feature_name=\"is_individual\",\n", + " items_indexes=[0, 1, 2])\n", + "\n", + "model.compile()\n", + "model.fit(dataset)\n", + "model.evaluate()\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "transport_df = canada_transport_df.copy()\n", + "items = [\"air\", \"bus\", \"car\", \"train\"]\n", + "\n", + "transport_df[\"oh0\"] = transport_df.apply(lambda row: 1. if row.alt == items[0] else 0., axis=1)\n", + "transport_df[\"oh1\"] = transport_df.apply(lambda row: 1. if row.alt == items[1] else 0., axis=1)\n", + "transport_df[\"oh2\"] = transport_df.apply(lambda row: 1. if row.alt == items[2] else 0., axis=1)\n", + "transport_df[\"oh3\"] = transport_df.apply(lambda row: 1. if row.alt == items[3] else 0., axis=1)\n", + "\n", + "# Just some typing\n", + "transport_df.income = transport_df.income.astype(\"float32\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "transport_df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cf = np.array([[1], [2], [3], [4]])\n", + "cif = np.array([[[1], [2], [3], [4]], [[1], [2], [3], [4]], [[1], [2], [3], [4]], [[1], [2], [3], [4]]])\n", + "av = np.array([[1, 1, 1, 1], [1, 0, 0, 1], [0, 1, 1, 1], [1, 1, 0, 0]])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset = ChoiceDataset(fixed_items_features = np.eye(4),\n", + " contexts_features=cf,\n", + " contexts_items_features=cif,\n", + " contexts_items_availabilities=av,\n", + " choices=[0, 3, 2, 1],\n", + " fixed_items_features_names=[\"air\", \"bus\", \"car\", \"train\"],\n", + " contexts_features_names=[\"income\"],\n", + " contexts_items_features_names=[\"zut\"],\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fif_df = pd.DataFrame(np.eye(4), columns=[\"air\", \"bus\", \"car\", \"train\"], index=[\"air\", \"bus\", \"car\", \"train\"])\n", + "\n", + "cif_df = {\n", + " \"item_id\": [\"air\", \"bus\", \"car\", \"train\", \"air\", \"bus\", \"car\", \"train\", \"air\", \"bus\", \"car\", \"train\", \"air\", \"bus\", \"car\", \"train\"],\n", + " \"session_id\": [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " \"zut\": [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4],\n", + "}\n", + "cif_df = pd.DataFrame(cif_df)\n", + "\n", + "cf_df = pd.DataFrame(cf, columns=[\"income\"])\n", + "\n", + "dataset = ChoiceDataset(fixed_items_features=fif_df,\n", + " contexts_features=cf_df,\n", + " contexts_items_features=cif_df,\n", + " contexts_items_availabilities=av,\n", + " choices=[0, 3, 2, 1],\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset.fixed_items_features_names" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset.contexts_items_features_names" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset.contexts_features_names" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset.summary()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "storage = FeaturesStorage(values={\"a\": [1, 1], \"b\": [2, 2]}, name=\"test\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "test_df = transport_df[[\"income\"]]\n", + "test_df[\"test\"] = \"a\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset = ChoiceDataset(fixed_items_features=np.eye(4),\n", + "contexts_features=test_df,\n", + "choices=np.ones((len(test_df), 1)),\n", + "features_by_ids=[storage])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset.contexts_features[0][[0, 1]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset.get_choices_batch([0, 1]), dataset.batch[[0, 1]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "batch = (dataset.contexts_features[0][:16], )\n", + "batch" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "transport_df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset = ChoiceDataset.from_single_df(\n", + " df=transport_df,\n", + " fixed_items_features_columns=[\"oh0\", \"oh1\", \"oh2\", \"oh3\"],\n", + " contexts_features_columns=[\"income\"],\n", + " contexts_items_features_columns=[\"dist\", \"cost\", \"freq\", \"ivt\", \"ovt\"],\n", + " items_id_column=\"alt\",\n", + " contexts_id_column=\"case\",\n", + " choices_column=\"choice\",\n", + " choice_mode=\"one_zero\",\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "len(dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset[[0, 1, 2, 3, 4]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset.get_choices_batch([0, 1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset.batch[[0, 1]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for a, b in zip(dataset.batch[[0, 1]], dataset.get_choices_batch([0, 1])):\n", + " for _a, _b in zip(a, b):\n", + " if not ((_a == _b).all()):\n", + " print(_a, _b)\n", + " print(_a==_b)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(dataset.batch[[0, 1]][2][0][0][2][1]), type(dataset.get_choices_batch([0, 1])[2][0][0][2][1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "tf_env", + "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.11.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From fc287c50b640bbbc2ae98a62030c4b558e07d1b9 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 26 Jan 2024 12:07:26 +0100 Subject: [PATCH 104/767] update doc --- mkdocs.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/mkdocs.yaml b/mkdocs.yaml index 16ef3f68..3164a009 100644 --- a/mkdocs.yaml +++ b/mkdocs.yaml @@ -57,6 +57,7 @@ nav: - Tutorials: - Introduction: tutorials/introduction.md - Getting Started with Data: notebooks/choice_learn_introduction_data.md + - Optimize RAM usage with Features Storage: notebooks/features_byID_example.md - Getting Started with Conditional Logit: notebooks/choice_learn_introduction_clogit.md - How-To Guides: - Introduction: how-to-guides.md From 5665f8682f348a4d78b1548ea8a078318396af15 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 26 Jan 2024 12:09:49 +0100 Subject: [PATCH 105/767] RM notebook --- notebooks/test_new_dataset.ipynb | 362 ------------------------------- 1 file changed, 362 deletions(-) delete mode 100644 notebooks/test_new_dataset.ipynb diff --git a/notebooks/test_new_dataset.ipynb b/notebooks/test_new_dataset.ipynb deleted file mode 100644 index 9a320ad0..00000000 --- a/notebooks/test_new_dataset.ipynb +++ /dev/null @@ -1,362 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import sys\n", - "from pathlib import Path\n", - "\n", - "sys.path.append(\"../\")æ©\n", - "\n", - "import numpy as np\n", - "import pandas as pd" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from choice_learn.data import ChoiceDataset\n", - "from choice_learn.data.storage import FeaturesStorage\n", - "# path to dataset file is:\n", - "filepath = \"choice_learn/datasets/data/ModeCanada.csv.gz\"\n", - "canada_transport_df = pd.read_csv((Path(\"..\") / filepath), index_col=0)\n", - "\n", - "print(\"Let's look at the dataframe:\")\n", - "canada_transport_df.head()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "load_modecanada = 1" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"\"\"\n", - "from choice_learn.models import ConditionalLogitModel\n", - "\n", - "model = ConditionalLogitModel()\n", - "model.add_coefficient(coefficient_name=\"beta_customer_income\",\n", - " feature_name=\"customer_income\",\n", - " items_indexes=[0, 1, 2])\n", - "model.add_coefficient(coefficient_name=\"beta_price\",\n", - " feature_name=\"price\",\n", - " items_indexes=[0, 1, 2])\n", - "model.add_shared_coefficient(coefficient_name=\"beta_travel_time\",\n", - " feature_name=\"travel_time\",\n", - " items_indexes=[0, 1, 2])\n", - "model.add_shared_coefficient(coefficient_name=\"conditional_intercept\",\n", - " feature_name=\"is_individual\",\n", - " items_indexes=[0, 1, 2])\n", - "\n", - "model.compile()\n", - "model.fit(dataset)\n", - "model.evaluate()\n", - "\"\"\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "transport_df = canada_transport_df.copy()\n", - "items = [\"air\", \"bus\", \"car\", \"train\"]\n", - "\n", - "transport_df[\"oh0\"] = transport_df.apply(lambda row: 1. if row.alt == items[0] else 0., axis=1)\n", - "transport_df[\"oh1\"] = transport_df.apply(lambda row: 1. if row.alt == items[1] else 0., axis=1)\n", - "transport_df[\"oh2\"] = transport_df.apply(lambda row: 1. if row.alt == items[2] else 0., axis=1)\n", - "transport_df[\"oh3\"] = transport_df.apply(lambda row: 1. if row.alt == items[3] else 0., axis=1)\n", - "\n", - "# Just some typing\n", - "transport_df.income = transport_df.income.astype(\"float32\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "transport_df" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "cf = np.array([[1], [2], [3], [4]])\n", - "cif = np.array([[[1], [2], [3], [4]], [[1], [2], [3], [4]], [[1], [2], [3], [4]], [[1], [2], [3], [4]]])\n", - "av = np.array([[1, 1, 1, 1], [1, 0, 0, 1], [0, 1, 1, 1], [1, 1, 0, 0]])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset = ChoiceDataset(fixed_items_features = np.eye(4),\n", - " contexts_features=cf,\n", - " contexts_items_features=cif,\n", - " contexts_items_availabilities=av,\n", - " choices=[0, 3, 2, 1],\n", - " fixed_items_features_names=[\"air\", \"bus\", \"car\", \"train\"],\n", - " contexts_features_names=[\"income\"],\n", - " contexts_items_features_names=[\"zut\"],\n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fif_df = pd.DataFrame(np.eye(4), columns=[\"air\", \"bus\", \"car\", \"train\"], index=[\"air\", \"bus\", \"car\", \"train\"])\n", - "\n", - "cif_df = {\n", - " \"item_id\": [\"air\", \"bus\", \"car\", \"train\", \"air\", \"bus\", \"car\", \"train\", \"air\", \"bus\", \"car\", \"train\", \"air\", \"bus\", \"car\", \"train\"],\n", - " \"session_id\": [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", - " \"zut\": [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4],\n", - "}\n", - "cif_df = pd.DataFrame(cif_df)\n", - "\n", - "cf_df = pd.DataFrame(cf, columns=[\"income\"])\n", - "\n", - "dataset = ChoiceDataset(fixed_items_features=fif_df,\n", - " contexts_features=cf_df,\n", - " contexts_items_features=cif_df,\n", - " contexts_items_availabilities=av,\n", - " choices=[0, 3, 2, 1],\n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset.fixed_items_features_names" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset.contexts_items_features_names" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset.contexts_features_names" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset.summary()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "storage = FeaturesStorage(values={\"a\": [1, 1], \"b\": [2, 2]}, name=\"test\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "test_df = transport_df[[\"income\"]]\n", - "test_df[\"test\"] = \"a\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset = ChoiceDataset(fixed_items_features=np.eye(4),\n", - "contexts_features=test_df,\n", - "choices=np.ones((len(test_df), 1)),\n", - "features_by_ids=[storage])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset.contexts_features[0][[0, 1]]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset.get_choices_batch([0, 1]), dataset.batch[[0, 1]]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "batch = (dataset.contexts_features[0][:16], )\n", - "batch" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "transport_df" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset = ChoiceDataset.from_single_df(\n", - " df=transport_df,\n", - " fixed_items_features_columns=[\"oh0\", \"oh1\", \"oh2\", \"oh3\"],\n", - " contexts_features_columns=[\"income\"],\n", - " contexts_items_features_columns=[\"dist\", \"cost\", \"freq\", \"ivt\", \"ovt\"],\n", - " items_id_column=\"alt\",\n", - " contexts_id_column=\"case\",\n", - " choices_column=\"choice\",\n", - " choice_mode=\"one_zero\",\n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "len(dataset)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset[[0, 1, 2, 3, 4]]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset.get_choices_batch([0, 1])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset.batch[[0, 1]]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for a, b in zip(dataset.batch[[0, 1]], dataset.get_choices_batch([0, 1])):\n", - " for _a, _b in zip(a, b):\n", - " if not ((_a == _b).all()):\n", - " print(_a, _b)\n", - " print(_a==_b)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "type(dataset.batch[[0, 1]][2][0][0][2][1]), type(dataset.get_choices_batch([0, 1])[2][0][0][2][1])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "tf_env", - "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.11.4" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} From 60e680ba224b514f2206e0484a19a9c551209ac5 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 26 Jan 2024 19:00:37 +0100 Subject: [PATCH 106/767] ADD: report function, std err, pval, z val, etc --- choice_learn/models/conditional_mnl.py | 107 +++++++++++++++++++++++-- 1 file changed, 102 insertions(+), 5 deletions(-) diff --git a/choice_learn/models/conditional_mnl.py b/choice_learn/models/conditional_mnl.py index daf935d6..465908f9 100644 --- a/choice_learn/models/conditional_mnl.py +++ b/choice_learn/models/conditional_mnl.py @@ -1,6 +1,10 @@ """Conditional MNL model.""" +import copy + +import pandas as pd import tensorflow as tf +import tensorflow_probability as tfp from .base_model import ChoiceModel @@ -627,6 +631,12 @@ def instantiate( When a mode is wrongly precised. """ # Possibility to stack weights to be faster ???? + if items_features_names is None: + items_features_names = [] + if contexts_features_names is None: + contexts_features_names = [] + if contexts_items_features_names is None: + contexts_items_features_names = [] weights = [] weights_count = 0 self._items_features_names = [] @@ -853,11 +863,14 @@ def compute_utility_from_dict( tf.Tensor Utilities corresponding of shape (n_choices, n_items) """ - del availabilities_batch, choices_batch + _, _ = availabilities_batch, choices_batch contexts_items_utilities = [] - num_items = items_batch[0].shape[0] - num_choices = contexts_batch[0].shape[0] + if items_batch is not None: + num_items = items_batch[0].shape[0] + else: + num_items = contexts_items_batch[0].shape[1] + num_choices = availabilities_batch.shape[0] # Items features for i, feat_tuple in enumerate(self._items_features_names): @@ -970,7 +983,9 @@ def fit(self, choice_dataset, **kwargs): contexts_items_features_names=choice_dataset.contexts_items_features_names, ) self.instantiated = True - return super().fit(choice_dataset=choice_dataset, **kwargs) + fit = super().fit(choice_dataset=choice_dataset, **kwargs) + self.report = self.compute_report(choice_dataset) + return fit def _fit_with_lbfgs(self, choice_dataset, n_epochs, tolerance=1e-8): """Specific fit function to estimate the paramters with LBFGS. @@ -1001,4 +1016,86 @@ def _fit_with_lbfgs(self, choice_dataset, n_epochs, tolerance=1e-8): contexts_items_features_names=choice_dataset.contexts_items_features_names, ) self.instantiated = True - return super()._fit_with_lbfgs(choice_dataset, n_epochs, tolerance) + fit = super()._fit_with_lbfgs(choice_dataset, n_epochs, tolerance) + self.report = self.compute_report(choice_dataset) + return fit + + def compute_report(self, dataset): + """Computes a report of the estimated weights. + + Parameters + ---------- + dataset : ChoiceDataset + ChoiceDataset used for the estimation of the weights that will be + used to compute the Std Err of this estimation. + + Returns: + -------- + pandas.DataFrame + A DF with estimation, Std Err, z_value and p_value for each coefficient. + """ + weights_std = self.get_weights_std(dataset) + dist = tfp.distributions.Normal(loc=0.0, scale=1.0) + + names = [] + z_values = [] + estimations = [] + p_z = [] + i = 0 + for weight in self.weights: + for j in range(weight.shape[1]): + names.append(f"{weight.name}_{j}") + estimations.append(weight.numpy()[0][j]) + z_values.append(weight.numpy()[0][j] / weights_std[i].numpy()) + p_z.append(2 * (1 - dist.cdf(tf.math.abs(z_values[-1])).numpy())) + i += 1 + + return pd.DataFrame( + { + "Coefficient Name": names, + "Coefficient Estimation": estimations, + "Std. Err": weights_std.numpy(), + "z_value": z_values, + "P(.>z)": p_z, + }, + ) + + def get_weights_std(self, dataset): + """Approximates Std Err with Hessian matrix. + + Parameters + ---------- + dataset : ChoiceDataset + ChoiceDataset used for the estimation of the weights that will be + used to compute the Std Err of this estimation. + + Returns: + -------- + tf.Tensor + Estimation of the Std Err for the weights. + """ + # Loops of differentiation + with tf.GradientTape() as tape_1: + with tf.GradientTape(persistent=True) as tape_2: + model = copy.deepcopy(self) + w = tf.concat(self.weights, axis=1) + tape_2.watch(w) + tape_1.watch(w) + mw = [] + index = 0 + for _w in self.weights: + mw.append(w[:, index : index + _w.shape[1]]) + index += _w.shape[1] + model.weights = mw + for batch in dataset.iter_batch(batch_size=-1): + utilities = model.compute_utility(*batch) + probabilities = tf.nn.softmax(utilities, axis=-1) + loss = tf.keras.losses.CategoricalCrossentropy(reduction="sum")( + y_pred=probabilities, + y_true=tf.one_hot(dataset.choices, depth=4), + ) + # Compute the Jacobian + jacobian = tape_2.jacobian(loss, w) + # Compute the Hessian from the Jacobian + hessian = tape_1.batch_jacobian(jacobian, w) + return tf.sqrt([tf.linalg.inv(tf.squeeze(hessian))[i][i] for i in range(13)]) From ee13a05652f2f9fab67520c92b7e7fe7e4f2d5a6 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 26 Jan 2024 19:02:20 +0100 Subject: [PATCH 107/767] ADD: report in example --- .../choice_learn_introduction_clogit.ipynb | 209 ++++++++++++++++-- 1 file changed, 186 insertions(+), 23 deletions(-) diff --git a/notebooks/choice_learn_introduction_clogit.ipynb b/notebooks/choice_learn_introduction_clogit.ipynb index 08735f5c..51886a9d 100644 --- a/notebooks/choice_learn_introduction_clogit.ipynb +++ b/notebooks/choice_learn_introduction_clogit.ipynb @@ -211,8 +211,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "The average neg-loglikelihood is: 0.674474\n", - "The total neg-loglikelihood is: 1874.3632485866547\n" + "The average neg-loglikelihood is: 0.67447394\n", + "The total neg-loglikelihood is: 1874.3630829453468\n" ] } ], @@ -221,6 +221,183 @@ "print(\"The total neg-loglikelihood is:\", model.evaluate(dataset).numpy()*len(dataset))" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The model automatically creates a report for each of the coefficient, with its estimation, its standard deviation and more:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "keep_output": true + }, + "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", + "
Coefficient NameCoefficient EstimationStd. Errz_valueP(.>z)
0beta_inter:0_00.6983671.2802080.5455115.854024e-01
1beta_inter:0_11.8441040.7084542.6029989.241223e-03
2beta_inter:0_23.2741870.6243665.2440181.192093e-07
3beta_income:0_0-0.0890870.018347-4.8556431.192093e-06
4beta_income:0_1-0.0279930.003873-7.2286730.000000e+00
5beta_income:0_2-0.0381470.004083-9.3426900.000000e+00
6beta_ivt:0_00.0595090.0100735.9079920.000000e+00
7beta_ivt:0_1-0.0067840.004433-1.5301371.259828e-01
8beta_ivt:0_2-0.0064600.001898-3.4030376.663799e-04
9beta_ivt:0_3-0.0014500.001187-1.2214012.219341e-01
10beta_cost:0_0-0.0333390.007095-4.6989252.622604e-06
11beta_freq:0_00.0925290.00509818.1518330.000000e+00
12beta_ovt:0_0-0.0430040.003225-13.3356430.000000e+00
\n", + "
" + ], + "text/plain": [ + " Coefficient Name Coefficient Estimation Std. Err z_value P(.>z)\n", + "0 beta_inter:0_0 0.698367 1.280208 0.545511 5.854024e-01\n", + "1 beta_inter:0_1 1.844104 0.708454 2.602998 9.241223e-03\n", + "2 beta_inter:0_2 3.274187 0.624366 5.244018 1.192093e-07\n", + "3 beta_income:0_0 -0.089087 0.018347 -4.855643 1.192093e-06\n", + "4 beta_income:0_1 -0.027993 0.003873 -7.228673 0.000000e+00\n", + "5 beta_income:0_2 -0.038147 0.004083 -9.342690 0.000000e+00\n", + "6 beta_ivt:0_0 0.059509 0.010073 5.907992 0.000000e+00\n", + "7 beta_ivt:0_1 -0.006784 0.004433 -1.530137 1.259828e-01\n", + "8 beta_ivt:0_2 -0.006460 0.001898 -3.403037 6.663799e-04\n", + "9 beta_ivt:0_3 -0.001450 0.001187 -1.221401 2.219341e-01\n", + "10 beta_cost:0_0 -0.033339 0.007095 -4.698925 2.622604e-06\n", + "11 beta_freq:0_0 0.092529 0.005098 18.151833 0.000000e+00\n", + "12 beta_ovt:0_0 -0.043004 0.003225 -13.335643 0.000000e+00" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model.report" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -288,21 +465,11 @@ "keep_output": true }, "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Feature oh_air is in dataset but has no weight assigned in utility computations\n", - "Feature oh_bus is in dataset but has no weight assigned in utility computations\n", - "Feature oh_car is in dataset but has no weight assigned in utility computations\n", - "Feature oh_train is in dataset but has no weight assigned in utility computations\n" - ] - }, { "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 1/1 [00:01<00:00, 1.70s/it]" + "100%|██████████| 1/1 [00:02<00:00, 2.46s/it]" ] }, { @@ -415,14 +582,14 @@ { "data": { "text/plain": [ - "[,\n", - " ,\n", - " ,\n", - " ,\n", + "[,\n", + " ,\n", + " ,\n", + " ,\n", " ,\n", - " ]" + " ]" ] }, "execution_count": null, @@ -500,10 +667,6 @@ "name": "stdout", "output_type": "stream", "text": [ - "Feature oh_air is in dataset but has no weight assigned in utility computations\n", - "Feature oh_bus is in dataset but has no weight assigned in utility computations\n", - "Feature oh_car is in dataset but has no weight assigned in utility computations\n", - "Feature oh_train is in dataset but has no weight assigned in utility computations\n", "L-BFGS Opimization finished:\n", "---------------------------------------------------------------\n", "Number of iterations: 170\n", From 362b80999ee68974ee0e7196bc47fb8ea9cc5f50 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 26 Jan 2024 19:31:05 +0100 Subject: [PATCH 108/767] ADD: method to clone ConditionalMNL --- choice_learn/models/base_model.py | 1 + choice_learn/models/conditional_mnl.py | 47 ++++++++++++++++++++++---- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index 1c237631..ca8aae7a 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -55,6 +55,7 @@ def __init__( self.callbacks.set_model(self) # Was originally in BaseMNL, moved here. + self.optimizer_name = optimizer if optimizer.lower() == "adam": self.optimizer = tf.keras.optimizers.Adam(lr) elif optimizer.lower() == "sgd": diff --git a/choice_learn/models/conditional_mnl.py b/choice_learn/models/conditional_mnl.py index 465908f9..da03fe95 100644 --- a/choice_learn/models/conditional_mnl.py +++ b/choice_learn/models/conditional_mnl.py @@ -1,7 +1,5 @@ """Conditional MNL model.""" -import copy - import pandas as pd import tensorflow as tf import tensorflow_probability as tfp @@ -958,13 +956,15 @@ def compute_utility_from_dict( return tf.reduce_sum(contexts_items_utilities, axis=0) - def fit(self, choice_dataset, **kwargs): + def fit(self, choice_dataset, get_report=False, **kwargs): """Main fit function to estimate the paramters. Parameters ---------- choice_dataset : ChoiceDataset Choice dataset to use for the estimation. + get_report: bool, optional + Whether or not to compute a report of the estimation, by default False Returns: -------- @@ -984,10 +984,11 @@ def fit(self, choice_dataset, **kwargs): ) self.instantiated = True fit = super().fit(choice_dataset=choice_dataset, **kwargs) - self.report = self.compute_report(choice_dataset) + if get_report: + self.report = self.compute_report(choice_dataset) return fit - def _fit_with_lbfgs(self, choice_dataset, n_epochs, tolerance=1e-8): + def _fit_with_lbfgs(self, choice_dataset, n_epochs, tolerance=1e-8, get_report=False): """Specific fit function to estimate the paramters with LBFGS. Parameters @@ -998,6 +999,8 @@ def _fit_with_lbfgs(self, choice_dataset, n_epochs, tolerance=1e-8): Number of epochs to run. tolerance : float, optional Tolerance in the research of minimum, by default 1e-8 + get_report: bool, optional + Whether or not to compute a report of the estimation, by default False Returns: -------- @@ -1017,7 +1020,8 @@ def _fit_with_lbfgs(self, choice_dataset, n_epochs, tolerance=1e-8): ) self.instantiated = True fit = super()._fit_with_lbfgs(choice_dataset, n_epochs, tolerance) - self.report = self.compute_report(choice_dataset) + if get_report: + self.report = self.compute_report(choice_dataset) return fit def compute_report(self, dataset): @@ -1077,7 +1081,7 @@ def get_weights_std(self, dataset): # Loops of differentiation with tf.GradientTape() as tape_1: with tf.GradientTape(persistent=True) as tape_2: - model = copy.deepcopy(self) + model = self.clone() w = tf.concat(self.weights, axis=1) tape_2.watch(w) tape_1.watch(w) @@ -1099,3 +1103,32 @@ def get_weights_std(self, dataset): # Compute the Hessian from the Jacobian hessian = tape_1.batch_jacobian(jacobian, w) return tf.sqrt([tf.linalg.inv(tf.squeeze(hessian))[i][i] for i in range(13)]) + + def clone(self): + """Returns a clone of the model.""" + clone = ConditionalMNL( + parameters=self.params, + add_exit_choice=self.normalize_non_buy, + optimizer=self.optimizer_name, + ) + if hasattr(self, "history"): + clone.history = self.history + if hasattr(self, "is_fitted"): + clone.is_fitted = self.is_fitted + if hasattr(self, "instantiated"): + clone.instantiated = self.instantiated + clone.loss = self.loss + clone.label_smoothing = self.label_smoothing + if hasattr(self, "report"): + clone.report = self.report + if hasattr(self, "weights"): + clone.weights = self.weights + if hasattr(self, "lr"): + clone.lr = self.lr + if hasattr(self, "_items_features_names"): + clone._items_features_names = self._items_features_names + if hasattr(self, "_contexts_features_names"): + clone._contexts_features_names = self._contexts_features_names + if hasattr(self, "_contexts_items_features_names"): + clone._contexts_items_features_names = self._contexts_items_features_names + return clone From 5ed22cb383fe20db634fad90761ffbb25947092f Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 29 Jan 2024 11:07:32 +0100 Subject: [PATCH 109/767] FIX store -> storage in init' --- choice_learn/data/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/choice_learn/data/__init__.py b/choice_learn/data/__init__.py index 83ca8df0..5f54051a 100644 --- a/choice_learn/data/__init__.py +++ b/choice_learn/data/__init__.py @@ -1,5 +1,5 @@ """Data handling classes and functions.""" from .choice_dataset import ChoiceDataset -from .store import FeaturesStore, OneHotStore +from .storage import FeaturesStorage, OneHotStorage -__all__ = ["ChoiceDataset", "FeaturesStore", "OneHotStore"] +__all__ = ["ChoiceDataset", "FeaturesStorage", "OneHotStorage"] From 055b3b47f8ea73e4fe966e7eb8e621dd4eeb9d55 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 29 Jan 2024 11:07:49 +0100 Subject: [PATCH 110/767] FIX: forgotten end of features when using fID --- choice_learn/data/indexer.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/choice_learn/data/indexer.py b/choice_learn/data/indexer.py index 46440b2c..ddba5383 100644 --- a/choice_learn/data/indexer.py +++ b/choice_learn/data/indexer.py @@ -329,6 +329,7 @@ def __getitem__(self, choices_indexes): ].batch[fixed_items_features[tuple_index][:, feature_index]] ) feat_ind_min = feature_index + 1 + unstacked_feat.append(fixed_items_features[tuple_index][feat_ind_min:]) mapped_features.append(np.concatenate(unstacked_feat, axis=1)) fixed_items_features = mapped_features @@ -350,6 +351,7 @@ def __getitem__(self, choices_indexes): ].batch[contexts_features[tuple_index][:, feature_index]] ) feat_ind_min = feature_index + 1 + unstacked_feat.append(contexts_features[tuple_index][:, feat_ind_min:]) mapped_features.append(np.concatenate(unstacked_feat, axis=1)) contexts_features = mapped_features @@ -373,6 +375,7 @@ def __getitem__(self, choices_indexes): ].batch[contexts_items_features[tuple_index][:, :, feature_index]] ) feat_ind_min = feature_index + 1 + unstacked_feat.append(contexts_features[tuple_index][:, :, feat_ind_min:]) mapped_features.append(np.concatenate(unstacked_feat, axis=2)) contexts_items_features = mapped_features @@ -462,6 +465,7 @@ def __getitem__(self, choices_indexes): ].batch[fixed_items_features[tuple_index][:, feature_index]] ) feat_ind_min = feature_index + 1 + unstacked_feat.append(fixed_items_features[tuple_index][:, feat_ind_min:]) mapped_features.append(np.concatenate(unstacked_feat, axis=1)) fixed_items_features = mapped_features @@ -483,6 +487,7 @@ def __getitem__(self, choices_indexes): ].batch[contexts_features[tuple_index][feature_index]] ) feat_ind_min = feature_index + 1 + unstacked_feat.append(contexts_features[tuple_index][feat_ind_min:]) mapped_features.append(np.concatenate(unstacked_feat, axis=0)) contexts_features = mapped_features @@ -506,6 +511,7 @@ def __getitem__(self, choices_indexes): ].batch[contexts_items_features[tuple_index][:, feature_index]] ) feat_ind_min = feature_index + 1 + unstacked_feat.append(contexts_items_features[tuple_index][:, feat_ind_min:]) mapped_features.append(np.concatenate(unstacked_feat, axis=1)) contexts_items_features = mapped_features From 28d3e019ea00bc26c30c46dee1b77e13432508ff Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 29 Jan 2024 12:17:34 +0100 Subject: [PATCH 111/767] ADD: better Storage example --- .../choice_learn_introduction_data.ipynb | 390 ++++++++++++++++-- 1 file changed, 348 insertions(+), 42 deletions(-) diff --git a/notebooks/choice_learn_introduction_data.ipynb b/notebooks/choice_learn_introduction_data.ipynb index ba559f1d..f4ff9c51 100644 --- a/notebooks/choice_learn_introduction_data.ipynb +++ b/notebooks/choice_learn_introduction_data.ipynb @@ -652,17 +652,17 @@ { "data": { "text/plain": [ - "([array([[1. , 2. ],\n", + "((array([[1. , 2. ],\n", " [2. , 4. ],\n", " [1.5, 1.5]], dtype=float32),\n", " array([[11. , 12. ],\n", " [12. , 14. ],\n", - " [11.5, 11.5]], dtype=float32)],\n", - " array([100, 20]),\n", + " [11.5, 11.5]], dtype=float32)),\n", + " array([100, 20], dtype=int32),\n", " array([[100, 0],\n", " [140, 0],\n", " [200, 0]], dtype=int32),\n", - " array([1., 1., 1.], dtype=float32),\n", + " array([1, 1, 1], dtype=object),\n", " 0)" ] }, @@ -707,15 +707,81 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## More Advanced use: the FeatureStore & OneHotStore" + "## More Advanced use: the FeatureStorage & RAM optimization" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The FeaturseStore class is here to stock values that regularly repeat themselves over a sequence.\n", - "Let's take an example where several stores are considered. If we want to model the utility from store features (such as surface, average number of customers, etc...), these features are shared by several choices in our dataset." + "## FeaturesStorage, why should I use it ?\n", + "Regularly, you have features that repeat themselves over several choices. It can happen if you have several times the same customer, if you have store features or if you use OneHot representations... And those are only example.\n", + "\n", + "The FeaturesStorage object is designed to help you better handle these cases. It is mainly built to work well with ChoiceDataset, but here is a small introduction on how it works:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's consider a case where we consider three supermarkets: \n", + "- supermarket_1 with surface of 100 and 250 average nb of customers\n", + "- supermarket_2 with surface of 150 and 500 average nb of customers\n", + "- supermarket_3 with surface of 80 and 100 average nb of customers \n", + "\n", + "In each store, we have 4 available products for which we have little information. For the example'sake, let's consider the following utility:\n", + "$$U(i) = u_i + \\beta_1 \\cdot S_s + \\beta_2 \\cdot C_s$$\n", + "With $S_s$ the surface of the store and $C_s$ its average number of customers.\n", + "\n", + "We want to estimate the base utilities $u_i$ and the two coefficients: $\\beta_1$ and $\\beta_2$.\n", + "\n", + "Let's start with creating a ChoiceDataset without the FeaturesStorage:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Usual Supermakerket Features Shape: (18, 2)\n", + "No features_by_ids given.\n" + ] + } + ], + "source": [ + "# Here are our choices:\n", + "choices = [0, 1, 2, 0, 2, 1, 1, 0, 2, 1, 2, 0, 2, 0, 1, 2, 1, 0]\n", + "supermarket_features = [[100, 250], [150, 500], [80, 100]]\n", + "# Now our store sequence of supermarkets is:\n", + "supermarkets_sequence = [1, 1, 2, 3, 2, 1, 2, 1, 1, 2, 3, 2, 1, 2, 2, 3, 1, 2]\n", + "\n", + "# The usual way to store the features would be to create the contexts_features array that contains\n", + "# the right features:\n", + "usual_supermarket_features = np.array([supermarket_features[supermarket_id - 1] for supermarket_id in supermarkets_sequence])\n", + "print(\"Usual Supermakerket Features Shape:\", usual_supermarket_features.shape)\n", + "\n", + "# And now we can create our ChoiceDataset:\n", + "\n", + "usual_dataset = ChoiceDataset(choices=choices,\n", + " fixed_items_features=np.eye(3),\n", + " contexts_features=usual_supermarket_features)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we have our dataset, we only need to create our ChoiceModel and we are good to go. However, it would also be natural to feel unsatisfied because your dataset is not well optimized. Indeed we have repeated the same information several times having a lot of redundant information.\n", + "\n", + "If in our small use-case it does not really matter, if we consider hundreds of stores on several millions - or billions - of choices, it would become... unreasonable!\n", + "\n", + "Let's now welcome the FeaturesStorage to help us:" ] }, { @@ -724,20 +790,20 @@ "metadata": {}, "outputs": [], "source": [ - "# We have three stores, represented by their (surface, average_number_of_customers):\n", - "store_features = [[100, 250], [150, 500], [80, 100]]\n", - "# Now we consider a sequence of choices that happen in [store_1, store_1, store_2, store_3, store_2, store_1, store_3]\n", - "# The usual way to store the features would be:\n", - "usual_store_features = [[100, 250], [100, 250], [150, 500], [80, 100], [150, 500], [100, 250], [80, 100]]\n", - "# There are a lot of repetetitions, which is not very efficient...\n", - "# Let's multiply this with 600 stores represented as one-hot over thousands of sessions, we will have a memory problem !\n", - "# Now the StoreFeatures tries to be more efficient:\n", + "from choice_learn.data import FeaturesStorage\n", "\n", - "store = {1: [100, 250], 2: [150, 500], 3: [80, 100]} # We can use a dictionary to store the features of each store\n", - "sequence = [1, 1, 2, 3, 2, 1, 3] # We can use a sequence of keys to represent the sequence of stores\n", + "features_dict = {f\"supermarket_{i+1}\": supermarket_features[i] for i in range(3)}\n", + "storage = FeaturesStorage(values=features_dict, name=\"supermarket_features\")\n", "\n", - "from choice_learn.data import FeaturesStore\n", - "feat_store = FeaturesStore.from_dict(store, sequence)" + "# Let's see how we can use this bad boy:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The FeaturesStorage is basically a Python dictionnary with a wrap-up to easily get batches of data.\\\n", + "You can ask for a sequence of features with .batch. It works with the keys of our dictionnary that can be int, float, str, etc..." ] }, { @@ -751,26 +817,262 @@ "name": "stdout", "output_type": "stream", "text": [ - "[100, 250]\n", - "[[100, 250], [100, 250], [100, 250]]\n" + "Retrieving features of first supermarket:\n", + "[100 250]\n", + "Retrieving a batch of features:\n", + "[[100 250]\n", + " [150 500]\n", + " [100 250]]\n" ] } ], "source": [ - "# Now we can access the features of the store appearing at index i in the sequence with the iloc method:\n", + "print(\"Retrieving features of first supermarket:\")\n", + "print(storage.batch[\"supermarket_1\"])\n", + "print(\"Retrieving a batch of features:\")\n", + "print(storage.batch[[\"supermarket_1\", \"supermarket_2\", \"supermarket_1\"]])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The FeaturesStorage is handy for its transparent use with ChoiceDataset. For it to work well you need:\n", + "- to specify a FeaturesStorage name\n", + "- to match FeaturesStorage ids with the sequence\n", "\n", - "# Let's see the features of the store at index 0\n", - "print(feat_store.batch[0])\n", - "# Now we can also take a whole batch:\n", - "print(feat_store.batch[[0, 1, 5]])\n", - "# Ah ! We selected all the indexes where the store is 1, which is why we always have the same features !" + "In our case we call our FeaturesStorage \"supermarket_features\", the ids are now strings, let's maker the sequence match:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "str_supermarkets_sequence = [[f\"supermarket_{i}\"] for i in supermarkets_sequence]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And now we can create our ChoiceDataset:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "storage_dataset = ChoiceDataset(choices=choices,\n", + " contexts_features=str_supermarkets_sequence,\n", + " contexts_features_names=[\"supermarket_features\"],\n", + " fixed_items_features=np.eye(3),\n", + " features_by_ids=[storage],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you have paid attention, we have specified the FeaturesStorage in the features_by_ids argument and we HAVE TO match the contexts_features_names column with the name of the Features Storage.\\\n", + "When calling for a batch of data, the ChoiceDataset will look into the FeaturesStorage call \"supermarket_features\" to match the values in contexts_features with the ones store in it." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Batch Fixed Items Features: [[1. 0. 0.]\n", + " [0. 1. 0.]\n", + " [0. 0. 1.]]\n", + "Batch Contexts Features: [100 250]\n", + "Batch Choice: 0\n", + "%-------------------------%\n", + "Batch Fixed Items Features: [[1. 0. 0.]\n", + " [0. 1. 0.]\n", + " [0. 0. 1.]]\n", + "Batch Contexts Features: [[100 250]\n", + " [150 500]\n", + " [ 80 100]]\n", + "Batch Choice: [1 2 0]\n", + "%-------------------------%\n", + "Batch Fixed Items Features: [[1. 0. 0.]\n", + " [0. 1. 0.]\n", + " [0. 0. 1.]]\n", + "Batch Contexts Features: [[100 250]\n", + " [100 250]\n", + " [100 250]]\n", + "Batch Choice: [0 1 1]\n" + ] + } + ], + "source": [ + "batch = storage_dataset.batch[0]\n", + "print(\"Batch Fixed Items Features:\", batch[0])\n", + "print(\"Batch Contexts Features:\", batch[1])\n", + "print(\"Batch Choice:\", batch[4])\n", + "print(\"%-------------------------%\")\n", + "batch = storage_dataset.batch[[1, 2, 3]]\n", + "print(\"Batch Fixed Items Features:\", batch[0])\n", + "print(\"Batch Contexts Features:\", batch[1])\n", + "print(\"Batch Choice:\", batch[4])\n", + "print(\"%-------------------------%\")\n", + "batch = storage_dataset.batch[[0, 1, 5]]\n", + "print(\"Batch Fixed Items Features:\", batch[0])\n", + "print(\"Batch Contexts Features:\", batch[1])\n", + "print(\"Batch Choice:\", batch[4])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Everything is mapped as needed. And the great thing is that you can easily mix ''classical'' features with FeaturesStorages.\\\n", + "Let's add a 'is_week_end' feature to our problem that will also be stored as a contexts_features." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "keep_output": true + }, + "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", + "
supermarket_featuresis_week_end
0supermarket_10
1supermarket_10
2supermarket_20
3supermarket_31
4supermarket_21
\n", + "
" + ], + "text/plain": [ + " supermarket_features is_week_end\n", + "0 supermarket_1 0\n", + "1 supermarket_1 0\n", + "2 supermarket_2 0\n", + "3 supermarket_3 1\n", + "4 supermarket_2 1" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "contexts_features = pd.DataFrame({\"supermarket_features\": np.array(str_supermarkets_sequence).squeeze(),\n", + "\"is_week_end\": [0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0]})\n", + "contexts_features.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Creation of the ChoiceDataset\n", + "storage_dataset = ChoiceDataset(choices=choices,\n", + " contexts_features=contexts_features,\n", + " fixed_items_features=np.eye(3),\n", + " features_by_ids=[storage],\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Batch Fixed Items Features: [[1. 0. 0.]\n", + " [0. 1. 0.]\n", + " [0. 0. 1.]]\n", + "Batch Contexts Features: [[100 250 0]\n", + " [150 500 0]\n", + " [ 80 100 1]]\n", + "Batch Choice: [1 2 0]\n" + ] + } + ], + "source": [ + "# And now it's ready\n", + "batch = storage_dataset.batch[[1, 2, 3]]\n", + "print(\"Batch Fixed Items Features:\", batch[0])\n", + "print(\"Batch Contexts Features:\", batch[1])\n", + "print(\"Batch Choice:\", batch[4])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "In order to further optimize RAM usage, you can use the OneHotStore, built specifically for one-hot encoded features. The store will only keep the index of the one of each element and will consitute the one-hot vector only when needed." + "### Specific sub-example: the OneHot Storage\n", + "A recurring usecase is the use of **OneHot** representation of features. The OneHotStorage is built specifically for one-hot encoded features and further improves memory consumption. The storage is to be used the same way as FeaturesStorage, but behind will only keep the index of the one of each element and will consitute the one-hot vector only when needed." ] }, { @@ -779,7 +1081,7 @@ "metadata": {}, "outputs": [], "source": [ - "from choice_learn.data import OneHotStore" + "from choice_learn.data import OneHotStorage" ] }, { @@ -793,31 +1095,35 @@ "name": "stdout", "output_type": "stream", "text": [ - "RAM storage of the OneHotStore: {'a': 0, 'b': 1, 'c': 2} with sequence: ['a' 'a' 'a' 'c' 'b' 'b' 'a']\n", - "One-hot vector at index 0: [1. 0. 0.]\n", + "RAM storage of the OneHotStore: {'a': 0, 'b': 1, 'c': 2}\n", + "One-hot vector batch: [1 0 0]\n", "One-hot vector at indexes [0, 1, 3]:\n", - "[[1. 0. 0.]\n", - " [1. 0. 0.]\n", - " [0. 0. 1.]]\n" + "[[1 0 0]\n", + " [0 1 0]\n", + " [0 0 1]\n", + " [0 0 1]\n", + " [0 1 0]\n", + " [1 0 0]]\n" ] } ], "source": [ - "store = OneHotStore.from_sequence([\"a\", \"a\", \"a\", \"c\", \"b\", \"b\", \"a\"])\n", + "storage = OneHotStorage(ids=[\"a\", \"b\", \"c\"])\n", "\n", - "# When using from_sequence, the store collects ranked order (lower to higher) of each element as index\n", - "print(\"RAM storage of the OneHotStore:\", store.store, \"with sequence:\", store.sequence)\n", - "# When indexing with iloc, we can access the one-hot encoding of the element at index i in the sequence\n", - "print(\"One-hot vector at index 0:\", store.batch[0])\n", - "print(\"One-hot vector at indexes [0, 1, 3]:\")\n", - "print(store.batch[[0, 1, 3]])" + "print(\"RAM storage of the OneHotStore:\", storage.storage)\n", + "# When indexing with .batch, we can access the one-hot encoding of the element using its id\n", + "print(\"One-hot vector batch:\", storage.batch[\"a\"])\n", + "print(\"One-hot vector :\")\n", + "print(storage.batch[[\"a\", \"b\", \"c\", \"c\", \"b\", \"a\"]])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "- Add: Example from pandas.DataFrame" + "- Add: Example from pandas.DataFrame\n", + "- Note that we use strings as ids for the example, however we recommend to use integers.\n", + "- More in-depth examples and explanations can be found here:" ] }, { From 3bfe1a79f0a8ff46c41d131ff14f7002282c32b5 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 29 Jan 2024 12:40:57 +0100 Subject: [PATCH 112/767] small modifs --- notebooks/choice_learn_introduction_data.ipynb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/notebooks/choice_learn_introduction_data.ipynb b/notebooks/choice_learn_introduction_data.ipynb index f4ff9c51..a007a157 100644 --- a/notebooks/choice_learn_introduction_data.ipynb +++ b/notebooks/choice_learn_introduction_data.ipynb @@ -1096,8 +1096,8 @@ "output_type": "stream", "text": [ "RAM storage of the OneHotStore: {'a': 0, 'b': 1, 'c': 2}\n", - "One-hot vector batch: [1 0 0]\n", - "One-hot vector at indexes [0, 1, 3]:\n", + "One-hot vector batch: storage.batch['a'] [1 0 0]\n", + "One-hot vector batch: storage.batch[['a', 'b', 'c', 'c', 'b', 'a']]\n", "[[1 0 0]\n", " [0 1 0]\n", " [0 0 1]\n", @@ -1112,8 +1112,8 @@ "\n", "print(\"RAM storage of the OneHotStore:\", storage.storage)\n", "# When indexing with .batch, we can access the one-hot encoding of the element using its id\n", - "print(\"One-hot vector batch:\", storage.batch[\"a\"])\n", - "print(\"One-hot vector :\")\n", + "print(\"One-hot vector batch: storage.batch['a']\", storage.batch[\"a\"])\n", + "print(\"One-hot vector batch: storage.batch[['a', 'b', 'c', 'c', 'b', 'a']]\")\n", "print(storage.batch[[\"a\", \"b\", \"c\", \"c\", \"b\", \"a\"]])" ] }, From 71ebe91365865ae59f0cd6f6bf11c52c66c44fd4 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 29 Jan 2024 15:29:14 +0100 Subject: [PATCH 113/767] Update examples --- .../choice_learn_introduction_data.ipynb | 14 +- notebooks/features_byID_example.ipynb | 652 ++++++++++++++---- 2 files changed, 529 insertions(+), 137 deletions(-) diff --git a/notebooks/choice_learn_introduction_data.ipynb b/notebooks/choice_learn_introduction_data.ipynb index a007a157..11d92b1d 100644 --- a/notebooks/choice_learn_introduction_data.ipynb +++ b/notebooks/choice_learn_introduction_data.ipynb @@ -1121,9 +1121,10 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "- Add: Example from pandas.DataFrame\n", - "- Note that we use strings as ids for the example, however we recommend to use integers.\n", - "- More in-depth examples and explanations can be found here:" + "**Note that:**\n", + "- we use strings as ids for the example, however we recommend to use integers.\n", + "- FeaturesStorage can be instantiated from dict, np.ndarray, list, pandas.DataFrame, etc...\n", + "- More in-depth examples and explanations can be found [here](./features_byID_example.ipynb)" ] }, { @@ -1382,6 +1383,13 @@ "cell_type": "markdown", "metadata": {}, "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/notebooks/features_byID_example.ipynb b/notebooks/features_byID_example.ipynb index 6237dcd6..d285beb7 100644 --- a/notebooks/features_byID_example.ipynb +++ b/notebooks/features_byID_example.ipynb @@ -1,5 +1,12 @@ { "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Deep dive on FeaturesStorage" + ] + }, { "cell_type": "code", "execution_count": null, @@ -34,250 +41,407 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Different Instantiation Possibilities for Storage:" + "## Different Instantiation Possibilities for Storage:\n", + "### 1 - from dict" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "keep_output": true + }, "outputs": [], "source": [ "features = {\"customerA\": [1, 2, 3], \"customerB\": [4, 5, 6], \"customerC\": [7, 8, 9]}\n", - "storage = FeaturesStorage(values=features, values_names=[\"age\", \"income\", \"children_nb\"], name=\"customers_features\")" + "# dict must be {id: features}\n", + "storage = FeaturesStorage(values=features,\n", + " values_names=[\"age\", \"income\", \"children_nb\"],\n", + " name=\"customers_features\")" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Subset in order to only keep som ids\n", "storage[[\"customerA\", \"customerC\"]]" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 2, 3],\n", + " [7, 8, 9],\n", + " [1, 2, 3],\n", + " [7, 8, 9]])" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Batch to access the features values\n", "storage.batch[[\"customerA\", \"customerC\", \"customerA\", \"customerC\"]]" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "### 2 - from list" + ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 2, 3],\n", + " [7, 8, 9],\n", + " [1, 2, 3],\n", + " [7, 8, 9]])" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "features = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n", "ids = [\"customerA\", \"customerB\", \"customerC\"]\n", "\n", - "storage = FeaturesStorage(ids=ids, values=features, values_names=[\"age\", \"income\", \"children_nb\"], name=\"customers\")\n", + "storage = FeaturesStorage(ids=ids,\n", + " values=features,\n", + " values_names=[\"age\", \"income\", \"children_nb\"],\n", + " name=\"customers\")\n", + "# We get the same result as before\n", "storage.batch[[\"customerA\", \"customerC\", \"customerA\", \"customerC\"]]" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "features = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n", + "### 3 - from list, without ids\n", "\n", - "storage = FeaturesStorage(values=features, values_names=[\"age\", \"income\", \"children_nb\"], name=\"customers\")\n", - "storage.batch[[0, 2, 0, 2]]" + "The ids are generated automatically as increasing integers:" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 2, 3],\n", + " [7, 8, 9],\n", + " [1, 2, 3],\n", + " [7, 8, 9]])" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "features = {\"age\": [1, 2, 3], \"income\": [4, 5, 6], \"children_nb\": [7, 8, 9], \"id\": [\"customerA\", \"customerB\", \"customerC\"]}\n", - "features = pd.DataFrame(features)\n", - "storage = FeaturesStorage(values=features, name=\"customers\")\n", - "storage.batch[[\"customerA\", \"customerC\", \"customerA\", \"customerC\"]]" + "features = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n", + "\n", + "storage = FeaturesStorage(values=features, values_names=[\"age\", \"income\", \"children_nb\"], name=\"customers\")\n", + "storage.batch[[0, 2, 0, 2]]" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "features = {\"age\": [1, 2, 3], \"income\": [4, 5, 6], \"children_nb\": [7, 8, 9]}\n", - "features = pd.DataFrame(features, index=[\"customerA\", \"customerB\", \"customerC\"])\n", - "storage = FeaturesStorage(values=features, name=\"customers\")\n", - "storage.batch[[\"customerA\", \"customerC\", \"customerA\", \"customerC\"]]" + "### 4 - from pandas.DataFrame" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ids = [0, 1, 2, 3, 4]\n", - "values = [4, 3, 2, 1, 0]\n", - "\n", - "oh_storage = OneHotStorage(ids=ids, values=values, name=\"OneHotTest\")" + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 2, 3],\n", + " [7, 8, 9],\n", + " [1, 2, 3],\n", + " [7, 8, 9]])" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Here the DataFrame has a column \"id\" that identifies the keys from the features values\n", + "features = {\"age\": [1, 4, 7], \"income\": [2, 5, 8], \"children_nb\": [3, 6, 9], \"id\": [\"customerA\", \"customerB\", \"customerC\"]}\n", + "features = pd.DataFrame(features)\n", + "storage = FeaturesStorage(values=features, name=\"customers\")\n", + "storage.batch[[\"customerA\", \"customerC\", \"customerA\", \"customerC\"]]" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "oh_storage.batch[[0, 2, 4]], oh_storage.get_element_from_index(0)" + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 2, 3],\n", + " [7, 8, 9],\n", + " [1, 2, 3],\n", + " [7, 8, 9]])" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Here the DataFrame does not have a column \"id\" that identifies the keys from the features values\n", + "# We thus specify the 'index'\n", + "features = {\"age\": [1, 4, 7], \"income\": [2, 5, 8], \"children_nb\": [3, 6, 9]}\n", + "features = pd.DataFrame(features, index=[\"customerA\", \"customerB\", \"customerC\"])\n", + "storage = FeaturesStorage(values=features, name=\"customers\")\n", + "storage.batch[[\"customerA\", \"customerC\", \"customerA\", \"customerC\"]]" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "oh_storage = OneHotStorage(values=values, name=\"OneHotTest\")\n", - "oh_storage.batch[[0, 2, 4]]" + "### 5 - OneHotStorage from list" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "keep_output": true + }, "outputs": [], "source": [ - "oh_storage = OneHotStorage(ids=ids, name=\"OneHotTest\")\n", - "oh_storage.batch[[0, 2, 4]]" + "ids = [0, 1, 2, 3, 4]\n", + "values = [4, 3, 2, 1, 0]\n", + "\n", + "# Here the Storage will map the ids to the values\n", + "# value = 4 means that the fifth value is a one, the rest are zeros\n", + "oh_storage = OneHotStorage(ids=ids, values=values, name=\"OneHotTest\")" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "values_dict = {k:v for k, v in zip(ids, values)}\n", - "oh_storage = OneHotStorage(values=values_dict, name=\"OneHotTest\")\n", + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0, 0, 0, 0, 1],\n", + " [0, 0, 1, 0, 0],\n", + " [1, 0, 0, 0, 0]], dtype=uint8)" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Get OneHot vectors:\n", "oh_storage.batch[[0, 2, 4]]" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(4, {0: 4, 1: 3, 2: 2, 3: 1, 4: 0})" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "oh_storage = OneHotStorage(ids=ids, values=values_dict, name=\"OneHotTest\")\n", - "try:\n", - " oh_storage = OneHotStorage(name=\"OneHotTest\")\n", - " assert False\n", - "except:\n", - " assert True" + "# Get the Storage value\n", + "oh_storage.get_element_from_index(0), oh_storage.storage" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Use of FeaturesByID and Storage in the ChoiceDataset" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "features = {\"customerA\": [1, 2, 3], \"customerB\": [4, 5, 6], \"customerC\": [7, 8, 9]}\n", - "storage = FeaturesStorage(values=features, values_names=[\"age\", \"income\", \"children_nb\"], name=\"customers_features\")" + "### 6 - OneHotStorage from single list\n", + "\n", + "If only the values are given, the ids are created as increasing integers." ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0, 0, 0, 0, 1],\n", + " [0, 0, 1, 0, 0],\n", + " [1, 0, 0, 0, 0]], dtype=uint8)" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "fixed_items_features = np.eye(3)\n", - "prices = [[[4, 1], [4, 1], [5, 1]], [[5, 2], [4, 2], [6, 2]],\n", - " [[6, 3], [7, 3], [8, 3]], [[4, 4], [5, 4], [4, 4]]]\n", - "choices = [0, 1 , 2, 2]\n", - "contexts_features = [[\"customerA\"], [\"customerB\"], [\"customerC\"], [\"customerA\"]]\n", - "\n", - "dataset = ChoiceDataset(\n", - " fixed_items_features=fixed_items_features,\n", - " contexts_features=contexts_features,\n", - " choices=choices,\n", - " contexts_items_features=prices,\n", - " features_by_ids=[storage],\n", - " contexts_features_names=[\"customers_features\"],\n", - " )" + "oh_storage = OneHotStorage(values=values, name=\"OneHotTest\")\n", + "oh_storage.batch[[0, 2, 4]]" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "dataset.get_choices_batch(0)" + "If the values are not given, they are also created from the ids as increasing integers." ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 0, 0, 0, 0],\n", + " [0, 0, 1, 0, 0],\n", + " [0, 0, 0, 0, 1]], dtype=uint8)" + ] + }, + "execution_count": null, + "metadata": { + "keep_output": true + }, + "output_type": "execute_result" + } + ], "source": [ - "dataset.batch[0]" + "oh_storage = OneHotStorage(ids=ids, name=\"OneHotTest\")\n", + "oh_storage.batch[[0, 2, 4]]\n", + "# Note that here it changes the order !" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "dataset.get_choices_batch([1, 2])" + "### 7 - OneHotStorage from dict" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0, 0, 0, 0, 1],\n", + " [0, 0, 1, 0, 0],\n", + " [1, 0, 0, 0, 0]], dtype=uint8)" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "myd = {1: 2, 2:3, 3:4, 4:5}" + "values_dict = {k:v for k, v in zip(ids, values)}\n", + "oh_storage = OneHotStorage(values=values_dict, name=\"OneHotTest\")\n", + "oh_storage.batch[[0, 2, 4]]" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "np.sort(list(myd.keys()))" + "## Use of FeaturesByID and Storage in the ChoiceDataset" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "keep_output": true + }, "outputs": [], "source": [ - "dataset.batch[1:3]" + "features = {\"customerA\": [1, 2, 3], \"customerB\": [4, 5, 6], \"customerC\": [7, 8, 9]}\n", + "storage = FeaturesStorage(values=features, values_names=[\"age\", \"income\", \"children_nb\"], name=\"customers_features\")" ] }, { @@ -313,30 +477,232 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "dataset.contexts_items_features_map[0][0].storage" + "## Example with the SwissMetro dataset" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset.get_choices_batch([0, 1])" + "metadata": { + "keep_output": true + }, + "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", + "
GROUPSURVEYSPIDPURPOSEFIRSTTICKETWHOLUGGAGEAGE...TRAIN_COTRAIN_HESM_TTSM_COSM_HESM_SEATSCAR_TTCAR_COCHOICECAR_HE
02.00.01.01.01.00.01.01.00.03.0...48.0120.063.052.020.00.0117.065.02.00.0
12.00.01.01.01.00.01.01.00.03.0...48.030.060.049.010.00.0117.084.02.00.0
22.00.01.01.01.00.01.01.00.03.0...48.060.067.058.030.00.0117.052.02.00.0
32.00.01.01.01.00.01.01.00.03.0...40.030.063.052.020.00.072.052.02.00.0
42.00.01.01.01.00.01.01.00.03.0...36.060.063.042.020.00.090.084.02.00.0
\n", + "

5 rows × 29 columns

\n", + "
" + ], + "text/plain": [ + " GROUP SURVEY SP ID PURPOSE FIRST TICKET WHO LUGGAGE AGE ... \\\n", + "0 2.0 0.0 1.0 1.0 1.0 0.0 1.0 1.0 0.0 3.0 ... \n", + "1 2.0 0.0 1.0 1.0 1.0 0.0 1.0 1.0 0.0 3.0 ... \n", + "2 2.0 0.0 1.0 1.0 1.0 0.0 1.0 1.0 0.0 3.0 ... \n", + "3 2.0 0.0 1.0 1.0 1.0 0.0 1.0 1.0 0.0 3.0 ... \n", + "4 2.0 0.0 1.0 1.0 1.0 0.0 1.0 1.0 0.0 3.0 ... \n", + "\n", + " TRAIN_CO TRAIN_HE SM_TT SM_CO SM_HE SM_SEATS CAR_TT CAR_CO CHOICE \\\n", + "0 48.0 120.0 63.0 52.0 20.0 0.0 117.0 65.0 2.0 \n", + "1 48.0 30.0 60.0 49.0 10.0 0.0 117.0 84.0 2.0 \n", + "2 48.0 60.0 67.0 58.0 30.0 0.0 117.0 52.0 2.0 \n", + "3 40.0 30.0 63.0 52.0 20.0 0.0 72.0 52.0 2.0 \n", + "4 36.0 60.0 63.0 42.0 20.0 0.0 90.0 84.0 2.0 \n", + "\n", + " CAR_HE \n", + "0 0.0 \n", + "1 0.0 \n", + "2 0.0 \n", + "3 0.0 \n", + "4 0.0 \n", + "\n", + "[5 rows x 29 columns]" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from choice_learn.datasets import load_swissmetro\n", + "\n", + "df = load_swissmetro(as_frame=True)\n", + "df = df.loc[df.CHOICE!=0]\n", + "df.head()" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "dataset.batch[[0, 1]]" + "The ID column refers to a unique participant to the survey. Each participant answered several cases. We therefore have several times the features concerning this participant. A perfect example for FeaturesStorage." ] }, { @@ -345,7 +711,14 @@ "metadata": {}, "outputs": [], "source": [ - "a = np.array([1, 2, 3])" + "customer_columns = ['ID', 'GROUP', 'SURVEY', 'SP', 'PURPOSE', 'FIRST', 'TICKET', 'WHO',\n", + " 'LUGGAGE', 'AGE', 'MALE', 'INCOME', 'GA', 'ORIGIN', 'DEST']\n", + "customer_features = df[customer_columns].drop_duplicates()\n", + "customer_features = customer_features.rename(columns={\"ID\": \"id\"})\n", + "customer_storage = FeaturesStorage(values=customer_features, name=\"customer_features\")\n", + "\n", + "contexts_features = df[[\"ID\"]]\n", + "contexts_features = contexts_features.rename(columns={\"ID\": \"customer_features\"})" ] }, { @@ -354,7 +727,11 @@ "metadata": {}, "outputs": [], "source": [ - "a[2:2]" + "choices = df.CHOICE.to_numpy() - 1\n", + "contexts_items_availabilities = df[[\"TRAIN_AV\", \"SM_AV\", \"CAR_AV\"]].to_numpy()\n", + "contexts_items_features = np.stack([df[[\"TRAIN_TT\", \"TRAIN_CO\", \"TRAIN_HE\"]].to_numpy(),\n", + " df[[\"SM_TT\", \"SM_CO\", \"SM_HE\"]].to_numpy(),\n", + " df[[\"CAR_TT\", \"CAR_CO\", \"CAR_HE\"]].to_numpy()], axis=1)" ] }, { @@ -363,16 +740,18 @@ "metadata": {}, "outputs": [], "source": [ - "np.concatenate([a[:2], a[2:2], a[2:3]])" + "choice_dataset = ChoiceDataset(contexts_features=contexts_features,\n", + " contexts_items_features=contexts_items_features,\n", + " contexts_items_availabilities=contexts_items_availabilities,\n", + " choices=choices,\n", + " features_by_ids=[customer_storage],)" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "myd = {1:2, 2:3}" + "Et voilà !" ] }, { @@ -381,7 +760,12 @@ "metadata": {}, "outputs": [], "source": [ - "next(iter(myd.values()))" + "batch = choice_dataset.batch[[0, 10, 200]]\n", + "print(\"Batch Fixed Items Features:\", batch[0])\n", + "print(\"Batch Contexts Features:\", batch[1])\n", + "print(\"Batch Contexts Items Features:\", batch[2])\n", + "print(\"Batch Contexts Items Availabilities:\", batch[3])\n", + "print(\"Batch Choices:\", batch[4])" ] }, { From 80d75436df5939293089c874e4d2aeb0cbeee69c Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 29 Jan 2024 17:53:50 +0100 Subject: [PATCH 114/767] ADD little doc --- docs/how-to-guides.md | 11 +++++++++++ docs/index.md | 8 ++++++++ docs/tutorials.md | 3 +++ mkdocs.yaml | 4 ++-- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/docs/how-to-guides.md b/docs/how-to-guides.md index e69de29b..ab492e41 100644 --- a/docs/how-to-guides.md +++ b/docs/how-to-guides.md @@ -0,0 +1,11 @@ +Here a some in-depth examples to help you with the package. + +In particular you will find notebooks to handle: + +**DATA** +- ChoiceDataset +- FeaturesStorage + +**MODELS** +- Custom modelling - important if you want to build your own model +- RUMnet diff --git a/docs/index.md b/docs/index.md index cdef8bfb..d49209b0 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,3 +1,11 @@ # Welcome to the choice-learn documentation! A toolbox for choice-modeling + + +Choice-Learn is a Python package designed to help you build discrete choice models. +The package provides ready to use datasets and different models from the litterature. It also provides a lower level use if you want to customize any model or create your own from scratch. In particular you will find smart datasets handling to limit RAM usage and different structure commons to any choice model. + +Choice-Learn uses NumPy and pandas as data backend engines and TensorFlow for models. + +In this documentation you will find examples to be quickly getting started as well as some more in-depth example. diff --git a/docs/tutorials.md b/docs/tutorials.md index e69de29b..a85916b5 100644 --- a/docs/tutorials.md +++ b/docs/tutorials.md @@ -0,0 +1,3 @@ +Here are two tutorials to get started with the choice-learn package. +In particular it shows how to create a ChoiceDataset. It's important as its the main object that will handle your data for the model. +The other example shows a few example on how to handle ConditionalMNL with the package. diff --git a/mkdocs.yaml b/mkdocs.yaml index 3164a009..06a75f8f 100644 --- a/mkdocs.yaml +++ b/mkdocs.yaml @@ -55,13 +55,13 @@ plugins: nav: - HomePage: index.md - Tutorials: - - Introduction: tutorials/introduction.md + - Introduction: tutorials.md - Getting Started with Data: notebooks/choice_learn_introduction_data.md - - Optimize RAM usage with Features Storage: notebooks/features_byID_example.md - Getting Started with Conditional Logit: notebooks/choice_learn_introduction_clogit.md - How-To Guides: - Introduction: how-to-guides.md - Exhaustive example of ChoiceDataset creation: notebooks/dataset_creation.md + - Optimize RAM usage with Features Storage: notebooks/features_byID_example.md - RUMnet Usage: notebooks/rumnet_example.md - Custom Choice Model Creation: notebooks/custom_model.md - References: From 0b32e7c508a7d155e638aa30e943f00aca48165b Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 30 Jan 2024 18:00:24 +0100 Subject: [PATCH 115/767] ADD: from single wide df methdo --- choice_learn/data/choice_dataset.py | 107 ++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index 8ba0f5b1..780d1b93 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -712,6 +712,113 @@ def _contexts_items_features_df_to_np( sessions_items_features = None return sessions_items_features, np.array(contexts_items_availabilities) + @classmethod + def from_single_wide_df( + cls, + df, + items_id, + fixed_items_suffixes=None, + contexts_features_columns=None, + contexts_items_features_suffixes=None, + contexts_items_availabilities_suffix=None, + choices_column="choice", + choice_mode="items_id", + ): + """Builds numpy arrays for ChoiceDataset from a single dataframe. + + Parameters + ---------- + df : pandas.DataFrame + dataframe in Wide format + items_id : list + List of items ids + fixed_items_suffixes : list + Suffixes of the columns of the dataframe that are item features, default is None + contexts_features_suffixes : list + Suffixes of the columns of the dataframe that are contexts features, default is None + contexts_items_suffixes : list + Suffixes of the columns of the dataframe that are context-item features, default is None + contexts_items_availabilities_suffix: list + Suffixes of the columns of the dataframe that are context-item availabilities, + choice_column: str, optional + Name of the column containing the choices, default is "choice" + choice_mode: str, optional + How choice is indicated in df, either "items_name" or "items_index", + default is "items_id" + + Returns: + ------- + ChoiceDataset + corresponding ChoiceDataset + """ + if fixed_items_suffixes is not None: + fixed_items_features = {"item_id": []} + for item in items_id: + fixed_items_features["item_id"].append(item) + for feature in fixed_items_suffixes: + feature_value = df[f"{feature}_{item}"].unique() + if len(feature_value) > 1: + raise ValueError( + f"More than one value for feature {feature} for item {item}" + ) + fixed_items_features[feature] = ( + fixed_items_features.get(feature, []), + +[feature_value], + ) + fixed_items_features = pd.DataFrame(fixed_items_features) + else: + fixed_items_features = None + + if contexts_features_columns is not None: + contexts_features = df[contexts_features_columns] + else: + contexts_features = None + + if contexts_items_features_suffixes is not None: + contexts_items_features = [] + for item in items_id: + columns = [f"{item}_{feature}" for feature in contexts_items_features_suffixes] + for col in columns: + if col not in df.columns: + print( + f"Column {col} was not in DataFrame,\ + dummy creation of the feature with zeros." + ) + df[col] = 0 + contexts_items_features.append(df[columns].to_numpy()) + contexts_items_features = np.stack(contexts_items_features, axis=1) + else: + contexts_items_features = None + + if contexts_items_availabilities_suffix is not None: + if isinstance(contexts_items_availabilities_suffix, list): + if not len(contexts_items_availabilities_suffix) == len(items_id): + raise ValueError( + "You have given a list of columns for availabilities." + "We consider that it is one for each item but lenght do not match" + ) + print("You have given a list of columns for availabilities.") + print("We consider that it is one for each item") + contexts_items_availabilities = df[contexts_items_availabilities_suffix].to_numpy() + else: + columns = [f"{item}_{contexts_items_availabilities_suffix}" for item in items_id] + contexts_items_availabilities = df[columns].to_numpy() + else: + contexts_items_availabilities = None + + choices = df[choices_column] + if choice_mode == "items_id": + choices = np.squeeze([np.where(items_id == c)[0] for c in choices]) + + return ChoiceDataset( + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_features_names=contexts_items_features_suffixes, + contexts_items_availabilities=contexts_items_availabilities, + choices=choices, + ) + @classmethod def from_single_df( cls, From fb88d24ee11b2b6b58dcc4228132ffc793acad8f Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 30 Jan 2024 18:00:56 +0100 Subject: [PATCH 116/767] ADD: from single wide df example --- notebooks/dataset_creation.ipynb | 122 ++++++++++++++++++++++--------- 1 file changed, 86 insertions(+), 36 deletions(-) diff --git a/notebooks/dataset_creation.ipynb b/notebooks/dataset_creation.ipynb index 2d9290d2..75209981 100644 --- a/notebooks/dataset_creation.ipynb +++ b/notebooks/dataset_creation.ipynb @@ -217,19 +217,21 @@ "%=====================================================================%\n", "Number of items: 4\n", "Number of choices: 4324\n", - "Fixed Items Features:\n", - "1 items features\n", - "with names: (['is_public'],)\n", + "%=====================================================================%\n", + " Fixed Items Features:\n", + " 1 items features\n", + " with names: (['is_public'],)\n", "\n", "\n", - "Sessions features:\n", - "3 session features\n", - "with names: (['dist', 'income', 'urban'],)\n", + " Contexts features:\n", + " 3 context features\n", + " with names: (['dist', 'income', 'urban'],)\n", "\n", "\n", - "Session Items features:\n", - "4 sessions items features\n", - "with names: (['freq', 'cost', 'ivt', 'ovt'],)\n", + " Contexts Items features:\n", + " 4 context\n", + " items features\n", + " with names: (['freq', 'cost', 'ivt', 'ovt'],)\n", "%=====================================================================%\n", "\n" ] @@ -429,19 +431,21 @@ "%=====================================================================%\n", "Number of items: 4\n", "Number of choices: 4324\n", - "Fixed Items Features:\n", - "1 items features\n", - "with names: (['is_public'],)\n", + "%=====================================================================%\n", + " Fixed Items Features:\n", + " 1 items features\n", + " with names: (['is_public'],)\n", "\n", "\n", - "Sessions features:\n", - "3 session features\n", - "with names: (['dist', 'income', 'urban'],)\n", + " Contexts features:\n", + " 3 context features\n", + " with names: (['dist', 'income', 'urban'],)\n", "\n", "\n", - "Session Items features:\n", - "4 sessions items features\n", - "with names: (['freq', 'cost', 'ivt', 'ovt'],)\n", + " Contexts Items features:\n", + " 4 context\n", + " items features\n", + " with names: (['freq', 'cost', 'ivt', 'ovt'],)\n", "%=====================================================================%\n", "\n" ] @@ -461,6 +465,48 @@ "print(dataset.summary())" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### From a wide format DataFrame\n", + "\n", + "If your DataFrame is in the wide format you can use the 'from_single_wide_df' method. Here is an example with the SwissMetro dataset." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from choice_learn.datasets import load_swissmetro\n", + "\n", + "swiss_df = load_swissmetro(as_frame=True,)\n", + "swiss_df.loc[swiss_df.CHOICE != 0]\n", + "swiss_df[\"CHOICE\"] = swiss_df[\"CHOICE\"] - 1\n", + "swiss_df.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset = ChoiceDataset.from_single_wide_df(\n", + " df=swiss_df,\n", + " items_id=[\"TRAIN\", \"SM\", \"CAR\"],\n", + " fixed_items_suffixes=None,\n", + " contexts_features_columns=[\"GROUP\", \"SURVEY\", \"SP\", \"PURPOSE\", \"FIRST\", \"TICKET\", \"WHO\", \"LUGGAGE\", \"AGE\",\n", + " \"MALE\", \"INCOME\", \"GA\", \"ORIGIN\", \"DEST\"],\n", + " contexts_items_features_suffixes=[\"CO\", \"TT\", \"HE\", \"SEATS\"],\n", + " contexts_items_availabilities_suffix=\"AV\", # [\"TRAIN_AV\", \"SM_AV\", \"CAR_AV\"] also works\n", + " choices_column=\"CHOICE\",\n", + " choice_mode=\"item_index\",\n", + ")" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -884,19 +930,21 @@ "%=====================================================================%\n", "Number of items: 4\n", "Number of choices: 4324\n", - "Fixed Items Features:\n", - "1 items features\n", - "with names: (['is_public'],)\n", + "%=====================================================================%\n", + " Fixed Items Features:\n", + " 1 items features\n", + " with names: (['is_public'],)\n", "\n", "\n", - "Sessions features:\n", - "3 session features\n", - "with names: (Index(['income', 'dist', 'urban'], dtype='object'),)\n", + " Contexts features:\n", + " 3 context features\n", + " with names: (Index(['income', 'dist', 'urban'], dtype='object'),)\n", "\n", "\n", - "Session Items features:\n", - "4 sessions items features\n", - "with names: (Index(['cost', 'freq', 'ivt', 'ovt'], dtype='object'),)\n", + " Contexts Items features:\n", + " 4 context\n", + " items features\n", + " with names: (Index(['cost', 'freq', 'ivt', 'ovt'], dtype='object'),)\n", "%=====================================================================%\n", "\n" ] @@ -1003,19 +1051,21 @@ "%=====================================================================%\n", "Number of items: 4\n", "Number of choices: 4324\n", - "Fixed Items Features:\n", - "1 items features\n", - "with names: (['is_public'],)\n", + "%=====================================================================%\n", + " Fixed Items Features:\n", + " 1 items features\n", + " with names: (['is_public'],)\n", "\n", "\n", - "Sessions features:\n", - "3 session features\n", - "with names: (['income', 'dist', 'urban'],)\n", + " Contexts features:\n", + " 3 context features\n", + " with names: (['income', 'dist', 'urban'],)\n", "\n", "\n", - "Session Items features:\n", - "4 sessions items features\n", - "with names: (['freq', 'cost', 'ivt', 'ovt'],)\n", + " Contexts Items features:\n", + " 4 context\n", + " items features\n", + " with names: (['freq', 'cost', 'ivt', 'ovt'],)\n", "%=====================================================================%\n", "\n" ] From 5eb2201fc458a10c5a8efaf8d74b9197c28e197f Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 1 Feb 2024 09:25:22 +0100 Subject: [PATCH 117/767] FIX: typo in issue --- choice_learn/models/conditional_mnl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/choice_learn/models/conditional_mnl.py b/choice_learn/models/conditional_mnl.py index da03fe95..00733cf2 100644 --- a/choice_learn/models/conditional_mnl.py +++ b/choice_learn/models/conditional_mnl.py @@ -1102,7 +1102,7 @@ def get_weights_std(self, dataset): jacobian = tape_2.jacobian(loss, w) # Compute the Hessian from the Jacobian hessian = tape_1.batch_jacobian(jacobian, w) - return tf.sqrt([tf.linalg.inv(tf.squeeze(hessian))[i][i] for i in range(13)]) + return tf.sqrt([tf.linalg.inv(tf.squeeze(hessian))[i][i] for i in range(len(w))]) def clone(self): """Returns a clone of the model.""" From bbe7666c157ee2dd0669bf0b589ef24d9896912e Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 2 Feb 2024 11:52:45 +0100 Subject: [PATCH 118/767] ENH: renaming, cleaning --- choice_learn/tf_ops.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/choice_learn/tf_ops.py b/choice_learn/tf_ops.py index cf8d617e..243fb8ba 100644 --- a/choice_learn/tf_ops.py +++ b/choice_learn/tf_ops.py @@ -3,8 +3,8 @@ import tensorflow as tf -def custom_softmax( - sessions_items_logits, sessions_items_availabilities, axis=-1, normalize_exit=False, eps=1e-5 +def softmax_with_availabilities( + contexts_items_logits, contexts_items_availabilities, axis=-1, normalize_exit=False, eps=1e-5 ): """Function to compute softmax probabilities from utilities. @@ -14,9 +14,9 @@ def custom_softmax( Parameters ---------- - sessions_items_logits : np.ndarray (n_sessions, n_products) + contexts_items_logits : np.ndarray (n_sessions, n_products) Utilities / Logits on which to compute the softmax - sessions_items_availabilities : np.ndarray (n_sessions, n_products) + contexts_items_availabilities : np.ndarray (n_sessions, n_products) Matrix indicating the availabitily (1) or not (0) of the products axis : int, optional Axis of sessions_logits on which to apply the softmax, by default -1 @@ -34,10 +34,10 @@ def custom_softmax( """ # Substract max utility to avoid overflow numerator = tf.exp( - sessions_items_logits - tf.reduce_max(sessions_items_logits, axis=axis, keepdims=True) + contexts_items_logits - tf.reduce_max(contexts_items_logits, axis=axis, keepdims=True) ) # Set unavailable products utility to 0 - numerator = tf.multiply(numerator, sessions_items_availabilities) + numerator = tf.multiply(numerator, contexts_items_availabilities) # Sum of total available utilities denominator = tf.reduce_sum(numerator, axis=axis, keepdims=True) # Add 1 to the denominator to take into account the exit choice From 41adb38d459aaba54534644a5f0c3f1d33cb1a31 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 2 Feb 2024 11:53:52 +0100 Subject: [PATCH 119/767] ENH: new signature, better names & doc --- choice_learn/models/base_model.py | 357 +++++++++++++++++------------- 1 file changed, 197 insertions(+), 160 deletions(-) diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index ca8aae7a..488e32cc 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -9,10 +9,7 @@ import tensorflow as tf import tqdm -from choice_learn.tf_ops import ( - CustomCategoricalCrossEntropy, - custom_softmax, -) +import choice_learn.tf_ops as tf_ops class ChoiceModel(object): @@ -25,6 +22,8 @@ def __init__( optimizer="Adam", callbacks=None, lr=0.001, + epochs=1, + batch_size=32, ): """Instantiates the ChoiceModel. @@ -45,10 +44,9 @@ def __init__( self.label_smoothing = label_smoothing self.stop_training = False - # self.loss = tf.keras.losses.CategoricalCrossentropy( - # from_logits=False, label_smoothing=self.label_smoothing - # ) - self.loss = CustomCategoricalCrossEntropy( + # Loss function wrapping tf.keras.losses.CategoricalCrossEntropy + # with smoothing and normalization options + self.loss = tf_ops.CustomCategoricalCrossEntropy( from_logits=False, label_smoothing=self.label_smoothing ) self.callbacks = tf.keras.callbacks.CallbackList(callbacks, add_history=True, model=None) @@ -69,9 +67,17 @@ def __init__( print(f"Optimizer {optimizer} not implemnted, switching for default Adam") self.optimizer = tf.keras.optimizers.Adam(lr) + self.epochs = epochs + self.batch_size = batch_size + @abstractmethod - def compute_utility( - self, items_batch, sessions_batch, sessions_items_batch, availabilities_batch, choices_batch + def compute_batch_utility( + self, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, ): """Method that defines how the model computes the utility of a product. @@ -80,28 +86,28 @@ def compute_utility( Parameters ---------- - items_batch : tuple of np.ndarray (items_features) + fixed_items_features : tuple of np.ndarray Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products constant/fixed features. Shape must be (n_items, n_items_features) - sessions_batch : tuple of np.ndarray (sessions_features) - Time-Features - Shape must be (n_sessions, n_sessions_features) - sessions_items_batch : tuple of np.ndarray (sessions_items_features) - Time-Item-Features - Shape must be (n_sessions, n_sessions_items_features) - availabilities_batch : np.ndarray - Availabilities (sessions_items_availabilities) - Shape must be (n_sessions, n_items) + contexts_features : tuple of np.ndarray (contexts_features) + a batch of contexts features + Shape must be (n_contexts, n_contexts_features) + contexts_items_features : tuple of np.ndarray (contexts_items_features) + a batch of contexts items features + Shape must be (n_contexts, n_contexts_items_features) + contexts_items_availabilities : np.ndarray + A batch of contexts items availabilities + Shape must be (n_contexts, n_items) choices_batch : np.ndarray Choices - Shape must be (n_sessions, ) + Shape must be (n_contexts, ) Returns: -------- np.ndarray - Utility of each product for each session. - Shape must be (n_sessions, n_items) + Utility of each product for each context. + Shape must be (n_contexts, n_items) """ # To be implemented in children classes # Can be numpy or tensorflow based @@ -110,28 +116,33 @@ def compute_utility( @tf.function def train_step( self, - items_batch, - sessions_batch, - sessions_items_batch, - availabilities_batch, - choices_batch, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, sample_weight=None, ): """Function that represents one training step (= one gradient descent step) of the model. Parameters ---------- - items_batch : tuple of np.ndarray (items_features) + fixed_items_features : tuple of np.ndarray Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products constant/fixed features. - sessions_batch : tuple of np.ndarray (sessions_features) - Time-Features - sessions_items_batch : tuple of np.ndarray (sessions_items_features) - Time-Item-Features - availabilities_batch : np.ndarray - Availabilities (sessions_items_availabilities) + Shape must be (n_items, n_items_features) + contexts_features : tuple of np.ndarray (contexts_features) + a batch of contexts features + Shape must be (n_contexts, n_contexts_features) + contexts_items_features : tuple of np.ndarray (contexts_items_features) + a batch of contexts items features + Shape must be (n_contexts, n_contexts_items_features) + contexts_items_availabilities : np.ndarray + A batch of contexts items availabilities + Shape must be (n_contexts, n_items) choices_batch : np.ndarray Choices + Shape must be (n_contexts, ) sample_weight : np.ndarray, optional List samples weights to apply during the gradient descent to the batch elements, by default None @@ -142,69 +153,56 @@ def train_step( Value of NegativeLogLikelihood loss for the batch """ with tf.GradientTape() as tape: - all_u = self.compute_utility( - items_batch, - sessions_batch, - sessions_items_batch, - availabilities_batch, - choices_batch, + utilities = self.compute_batch_utility( + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, + choices=choices, ) - """ - all_u = tf.math.exp(all_u) - - # Assortment(t) Utility - norms = tf.reduce_sum(tf.multiply(all_u, ia_batch), axis=1) - if self.normalize_non_buy: - norms += 1 - # Probabilities - final_utilities = tf.divide( - all_u, - tf.repeat(tf.expand_dims(norms, 1), fif_batch[0].shape[0], axis=1), - ) - # Probabilities of selected product - available_utilities = tf.gather_nd(indices=choices_nd, params=final_utilities) - """ - # probabilities = availability_softmax(all_u, availabilities_batch, axis=-1) - probabilities = custom_softmax( - all_u, availabilities_batch, normalize_exit=self.normalize_non_buy, axis=-1 + + probabilities = tf_ops.softmax_with_availabilities( + contexts_items_logits=utilities, + contexts_items_availabilities=contexts_items_availabilities, + normalize_exit=self.normalize_non_buy, + axis=-1, ) # Negative Log-Likelihood neg_loglikelihood = self.loss( y_pred=probabilities, - y_true=tf.one_hot(choices_batch, depth=probabilities.shape[1]), + y_true=tf.one_hot(choices, depth=probabilities.shape[1]), sample_weight=sample_weight, ) - """ - if sample_weight is not None: - neg_loglikelihood = -tf.reduce_sum( - tf.math.log(available_utilities + 1e-10) * sample_weight - ) - else: - neg_loglikelihood = -tf.reduce_sum(tf.math.log(available_utilities + 1e-10)) - """ + grads = tape.gradient(neg_loglikelihood, self.weights) self.optimizer.apply_gradients(zip(grads, self.weights)) return neg_loglikelihood def fit( - self, choice_dataset, n_epochs, batch_size, sample_weight=None, val_dataset=None, verbose=0 + self, + choice_dataset, + sample_weight=None, + val_dataset=None, + verbose=0, + epochs=None, + batch_size=None, ): """Method to train the model with a ChoiceDataset. Parameters ---------- choice_dataset : ChoiceDataset - _description_ - n_epochs : int - Number of epochs - batch_size : int - Batch size + Input data in the form of a ChoiceDataset sample_weight : np.ndarray, optional Sample weights to apply, by default None val_dataset : ChoiceDataset, optional Test ChoiceDataset to evaluate performances on test at each epoch, by default None verbose : int, optional print level, for debugging, by default 0 + epochs : int, optional + Number of epochs, default is None, meaning we use self.epochs + batch_size : int, optional + Batch size, default is None, meaning we use self.batch_size Returns: -------- @@ -214,8 +212,13 @@ def fit( if hasattr(self, "instantiated"): if not self.instantiated: raise ValueError("Model not instantiated. Please call .instantiate() first.") + if epochs is None: + epochs = self.epochs + if batch_size is None: + batch_size = self.batch_size + losses_history = {"train_loss": []} - t_range = tqdm.trange(n_epochs, position=0) + t_range = tqdm.trange(epochs, position=0) self.callbacks.on_train_begin() @@ -245,8 +248,8 @@ def fit( for batch_nb, ( ( items_batch, - sessions_batch, - sessions_items_batch, + contexts_batch, + contexts_items_batch, availabilities_batch, choices_batch, ), @@ -256,8 +259,8 @@ def fit( neg_loglikelihood = self.train_step( items_batch, - sessions_batch, - sessions_items_batch, + contexts_batch, + contexts_items_batch, availabilities_batch, choices_batch, sample_weight=weight_batch, @@ -283,16 +286,16 @@ def fit( inner_range = choice_dataset.iter_batch(shuffle=True, batch_size=batch_size) for batch_nb, ( items_batch, - sessions_batch, - sessions_items_batch, + contexts_batch, + contexts_items_batch, availabilities_batch, choices_batch, ) in enumerate(inner_range): self.callbacks.on_train_batch_begin(batch_nb) neg_loglikelihood = self.train_step( items_batch, - sessions_batch, - sessions_items_batch, + contexts_batch, + contexts_items_batch, availabilities_batch, choices_batch, ) @@ -329,8 +332,8 @@ def fit( test_losses = [] for batch_nb, ( items_batch, - sessions_batch, - sessions_items_batch, + contexts_batch, + contexts_items_batch, availabilities_batch, choices_batch, ) in enumerate(val_dataset.iter_batch(shuffle=False, batch_size=batch_size)): @@ -339,8 +342,8 @@ def fit( test_losses.append( self.batch_predict( items_batch, - sessions_batch, - sessions_items_batch, + contexts_batch, + contexts_items_batch, availabilities_batch, choices_batch, )[0] @@ -373,28 +376,33 @@ def fit( @tf.function def batch_predict( self, - items_batch, - sessions_batch, - sessions_items_batch, - availabilities_batch, - choices_batch, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, sample_weight=None, ): """Function that represents one prediction (Probas + Loss) for one batch of a ChoiceDataset. Parameters ---------- - items_batch : tuple of np.ndarray (items_features) + fixed_items_features : tuple of np.ndarray Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products - constant features. - sessions_batch : tuple of np.ndarray (sessions_features) - Time-Features - sessions_items_batch : tuple of np.ndarray (sessions_items_features) - Time-Item-Features - availabilities_batch : np.ndarray - Availabilities (sessions_items_availabilities) + constant/fixed features. + Shape must be (n_items, n_items_features) + contexts_features : tuple of np.ndarray (contexts_features) + a batch of contexts features + Shape must be (n_contexts, n_contexts_features) + contexts_items_features : tuple of np.ndarray (contexts_items_features) + a batch of contexts items features + Shape must be (n_contexts, n_contexts_items_features) + contexts_items_availabilities : np.ndarray + A batch of contexts items availabilities + Shape must be (n_contexts, n_items) choices_batch : np.ndarray Choices + Shape must be (n_contexts, ) sample_weight : np.ndarray, optional List samples weights to apply during the gradient descent to the batch elements, by default None @@ -404,23 +412,29 @@ def batch_predict( tf.Tensor (1, ) Value of NegativeLogLikelihood loss for the batch tf.Tensor (batch_size, n_items) - Probabilities for each product to be chosen for each session + Probabilities for each product to be chosen for each context """ # Compute utilities from features utilities = self.compute_utility( - items_batch, sessions_batch, sessions_items_batch, availabilities_batch, choices_batch + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, ) # Compute probabilities from utilities & availabilties - # probabilities = availability_softmax(utilities, availabilities_batch, axis=-1) - probabilities = custom_softmax( - utilities, availabilities_batch, normalize_exit=self.normalize_non_buy, axis=-1 + probabilities = tf_ops.softmax_with_availabilities( + contexts_items_logits=utilities, + contexts_items_availabilities=contexts_items_availabilities, + normalize_exit=self.normalize_non_buy, + axis=-1, ) # Compute loss from probabilities & actual choices # batch_loss = self.loss(probabilities, c_batch, sample_weight=sample_weight) batch_loss = self.loss( y_pred=probabilities, - y_true=tf.one_hot(choices_batch, depth=probabilities.shape[1]), + y_true=tf.one_hot(choices, depth=probabilities.shape[1]), sample_weight=sample_weight, ) return batch_loss, probabilities @@ -477,7 +491,7 @@ def load_model(cls, path): return cls def predict_probas(self, choice_dataset, batch_size=-1): - """Predicts the choice probabilities for each session and each product of a ChoiceDataset. + """Predicts the choice probabilities for each context and each product of a ChoiceDataset. Parameters ---------- @@ -488,30 +502,30 @@ def predict_probas(self, choice_dataset, batch_size=-1): Returns: -------- - np.ndarray (n_sessions, n_items) - Choice probabilties for each session and each product + np.ndarray (n_contexts, n_items) + Choice probabilties for each context and each product """ stacked_probabilities = [] for ( - items_batch, - sessions_batch, - sessions_items_batch, - availabilities_batch, - choices_batch, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, ) in choice_dataset.iter_batch(batch_size=batch_size): _, probabilities = self.batch_predict( - items_batch, - sessions_batch, - sessions_items_batch, - availabilities_batch, - choices_batch, + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, + choices=choices, ) stacked_probabilities.append(probabilities) return tf.concat(stacked_probabilities, axis=0) def evaluate(self, choice_dataset, batch_size=-1): - """Evaluates the model for each session and each product of a ChoiceDataset. + """Evaluates the model for each context and each product of a ChoiceDataset. Predicts the probabilities according to the model and computes the Negative-Log-Likelihood loss from the actual choices. @@ -523,27 +537,27 @@ def evaluate(self, choice_dataset, batch_size=-1): Returns: -------- - np.ndarray (n_sessions, n_items) - Choice probabilties for each session and each product + np.ndarray (n_contexts, n_items) + Choice probabilties for each context and each product """ batch_losses = [] for ( - items_batch, - sessions_batch, - sessions_items_batch, - availabilities_batch, - choices_batch, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, ) in choice_dataset.iter_batch(batch_size=batch_size): loss, _ = self.batch_predict( - items_batch, - sessions_batch, - sessions_items_batch, - availabilities_batch, - choices_batch, + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, + choices=choices, ) batch_losses.append(loss) if batch_size != -1: - last_batch_size = availabilities_batch.shape[0] + last_batch_size = contexts_items_availabilities.shape[0] coefficients = tf.concat( [tf.ones(len(batch_losses) - 1) * batch_size, [last_batch_size]], axis=0 ) @@ -700,37 +714,49 @@ def __init__(self, **kwargs): """Initialization of the model.""" super().__init__(**kwargs) - def compute_utility( - self, items_batch, sessions_batch, sessions_items_batch, availabilities_batch, choices_batch + def compute_batch_utility( + self, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, ): - """Computes the random utility for each product of each session. + """Computes the random utility for each product of each context. Parameters ---------- - items_batch : tuple of np.ndarray (items_features) + fixed_items_features : tuple of np.ndarray Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products constant/fixed features. - sessions_batch : tuple of np.ndarray (sessions_features) - Time-Features - sessions_items_batch : tuple of np.ndarray (sessions_items_features) - Time-Item-Features - availabilities_batch : np.ndarray - Availabilities (sessions_items_availabilities) + Shape must be (n_items, n_items_features) + contexts_features : tuple of np.ndarray (contexts_features) + a batch of contexts features + Shape must be (n_contexts, n_contexts_features) + contexts_items_features : tuple of np.ndarray (contexts_items_features) + a batch of contexts items features + Shape must be (n_contexts, n_contexts_items_features) + contexts_items_availabilities : np.ndarray + A batch of contexts items availabilities + Shape must be (n_contexts, n_items) choices_batch : np.ndarray Choices + Shape must be (n_contexts, ) Returns: -------- tf.Tensor - (n_sessions, n_items) matrix of random utilities + (n_contexts, n_items) matrix of random utilities """ # In order to avoid unused arguments warnings - del items_batch, sessions_batch, availabilities_batch, choices_batch - return np.squeeze(np.random.uniform(shape=(sessions_items_batch.shape), minval=0, maxval=1)) + _ = fixed_items_features, contexts_features, contexts_items_availabilities, choices + return np.squeeze( + np.random.uniform(shape=(contexts_items_features.shape), minval=0, maxval=1) + ) def fit(**kwargs): """Make sure that nothing happens during .fit.""" - del kwargs + _ = kwargs return {} @@ -747,34 +773,44 @@ def __init__(self, **kwargs): def fit(self, choice_dataset, **kwargs): """Computes the choice frequency of each product and defines it as choice probabilities.""" - del kwargs + _ = kwargs choices = choice_dataset.choices for i in range(choice_dataset.get_num_items()): self.weights.append(tf.reduce_sum(tf.cast(choices == i, tf.float32))) self.weights = tf.stack(self.weights) / len(choices) - def compute_utility( - self, items_batch, sessions_batch, sessions_items_batch, availabilities_batch, choices_batch + def compute_batch_utility( + self, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, ): """Returns utility that is fixed. U = log(P). Parameters ---------- - items_batch : tuple of np.ndarray (items_features) + fixed_items_features : tuple of np.ndarray Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products constant/fixed features. - sessions_batch : tuple of np.ndarray (sessions_features) - Time-Features - sessions_items_batch : tuple of np.ndarray (sessions_items_features) - Time-Item-Features - availabilities_batch : np.ndarray - Availabilities (sessions_items_availabilities) + Shape must be (n_items, n_items_features) + contexts_features : tuple of np.ndarray (contexts_features) + a batch of contexts features + Shape must be (n_contexts, n_contexts_features) + contexts_items_features : tuple of np.ndarray (contexts_items_features) + a batch of contexts items features + Shape must be (n_contexts, n_contexts_items_features) + contexts_items_availabilities : np.ndarray + A batch of contexts items availabilities + Shape must be (n_contexts, n_items) choices_batch : np.ndarray Choices + Shape must be (n_contexts, ) Returns: -------- - np.ndarray (n_sessions, n_items) + np.ndarray (n_contexts, n_items) Utilities Raises: @@ -783,7 +819,8 @@ def compute_utility( If the model has not been fitted cannot evaluate the utility """ # In order to avoid unused arguments warnings - del items_batch, sessions_batch, sessions_items_batch, availabilities_batch + _ = fixed_items_features, contexts_features, contexts_items_availabilities + _ = contexts_items_features if self.weights is None: raise ValueError("Model not fitted") - return np.stack([np.log(self.weights.numpy())] * len(choices_batch), axis=0) + return np.stack([np.log(self.weights.numpy())] * len(choices), axis=0) From c53222ae0368915a616602f6afe431b6e73705c4 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 2 Feb 2024 16:09:52 +0100 Subject: [PATCH 120/767] ENH: some cleaning in code --- choice_learn/models/rumnet.py | 1436 ++++++++++++++++----------------- 1 file changed, 718 insertions(+), 718 deletions(-) diff --git a/choice_learn/models/rumnet.py b/choice_learn/models/rumnet.py index 6fbe47e8..09f08fa9 100644 --- a/choice_learn/models/rumnet.py +++ b/choice_learn/models/rumnet.py @@ -1,502 +1,388 @@ """Implementation of RUMnet for easy use.""" import tensorflow as tf +import choice_learn.tf_ops as tf_ops from choice_learn.models.base_model import ChoiceModel -from choice_learn.tf_ops import CustomCategoricalCrossEntropy -class PaperRUMnet(ChoiceModel): - """Re-Implementation of the RUMnet model. +def create_ff_network( + input_shape, depth, width, activation="elu", add_last=False, l2_regularization_coeff=0.0 +): + """Base function to create a simple fully connected (Dense) network. - Re-implemented from the paper: - Representing Random Utility Choice Models with Neural Networks from Ali Aouad and Antoine Désir - https://arxiv.org/abs/2207.12877 + Parameters + ---------- + input_shape : tuple of int + shape of the input of the network. Typically (num_features, ) + depth : int + Number of dense/fully-connected of the network to create. + width : int + Neurons number for all dense layers. + add_last : bool, optional + Whether to add a Dense layer with a single output at the end, by default False + Typically to be used when creating the utility network, that outputs a single number: + the utility. + l2_regularization_coeff : float, optional + Regularization coefficient for Dense layers weights during training, by default 0.0 - Inherits from base_model.ChoiceModel - TODO: Verify that all parameters are implemented. + Returns: + -------- + tf.keras.Model + Dense Neural Network with tensorflow backend. """ + input = tf.keras.layers.Input(shape=input_shape) + regularizer = tf.keras.regularizers.L2(l2_regularization_coeff) + out = input + for _ in range(depth): + out = tf.keras.layers.Dense( + width, activation=activation, kernel_regularizer=regularizer, use_bias=True + )(out) + if add_last: + out = tf.keras.layers.Dense(1, activation="linear", use_bias=False)(out) + return tf.keras.Model(inputs=input, outputs=out) - def __init__( - self, - num_products_features, - num_customer_features, - width_eps_x, - depth_eps_x, - heterogeneity_x, - width_eps_z, - depth_eps_z, - heterogeneity_z, - width_u, - depth_u, - tol, - optimizer, - lr, - normalize_non_buy=True, - logmin=1e-5, - l2_regularization_coef=0.0, - label_smoothing=0.0, - **kwargs, - ): - """Initiation of the RUMnet Model. - - Parameters - ---------- - num_products_features : int - Number of features each product will be described with. - In terms of ChoiceDataset it is the number of - { items_features + sessions_items_features } for one product. - num_customer_features : int - Number of features each customer will be described with. - In terms of ChoiceDataset it is the number of sessions_features. - width_eps_x : int - Number of neurons for each dense layer for the products encoding net. - depth_eps_x : int - Number of dense layers for the products encoding net. - heterogeneity_x : int - Number of nets of products features encoding. - width_eps_z : int - Number of neurons for each dense layer for the customers encoding net. - depth_eps_z : int - Number of dense layers for the customers encoding net. - heterogeneity_z : int - Number of nets of customers features encoding. - width_u : int - Number of neurons for each dense layer for the utility net. - depth_u : int - Number of dense layers for the utility net. - tol : float - # To be Implemented - optimizer : str - String representation of the optimizer to use. By default is Adam if not specified. - Should be within tf.keras.optimizers. - lr : float - Starting learning rate to associate with optimizer. - normalize_non_buy : bool, optional - Whether or not to add exit option with utility 1, by default True - logmin : float, optional - Value to be added within log computation to avoid infinity, by default 1e-5 - l2_regularization_coef : float, optional - Value of dense layers weights regulariation to apply during training, by default 0.0 - label_smoothing : float, optional - Value of smoothing to apply in CrossEntropy loss computation, by default 0.0 - """ - super().__init__(normalize_non_buy=normalize_non_buy, **kwargs) - # Number of features - self.num_products_features = num_products_features - self.num_customer_features = num_customer_features - - # Dimension of encoding nets - self.width_eps_x = width_eps_x - self.depth_eps_x = depth_eps_x - self.heterogeneity_x = heterogeneity_x - - self.width_eps_z = width_eps_z - self.depth_eps_z = depth_eps_z - self.heterogeneity_z = heterogeneity_z - - # Dimension of utility net - self.width_u = width_u - self.depth_u = depth_u - - # Optimization parameters - self.logmin = logmin - self.tol = tol - self.lr = lr - self.normalize_non_buy = normalize_non_buy - self.l2_regularization_coef = l2_regularization_coef - self.label_smoothing = label_smoothing - - if optimizer == "Adam": - self.optimizer = tf.keras.optimizers.Adam(lr) - elif optimizer == "SGD": - self.optimizer = tf.keras.optimizers.SGD(lr) - elif optimizer == "Adamax": - self.optimizer = tf.keras.optimizers.Adamax(lr) - else: - print(f"Optimizer {optimizer} not implemnted, switching for default Adam") - self.optimizer = tf.keras.optimizers.Adam(lr) - - self.instantiated = False - def instantiate(self): - """Instatiation of the RUMnet model. +def recreate_official_nets( + num_products_features, + x_width, + x_depth, + x_eps, + num_customer_features, + z_width, + z_depth, + z_eps, + width_u, + depth_u, + l2_regularization_coeff=0.0, +): + """Function to create the three nets used in RUMnet: X_net, Z_net and U_net. - Creation of : - - x_model encoding products features, - - z_model encoding customers features, - - u_model computing utilities from product, customer features and their embeddings - """ - # Instatiation of the different nets - self.x_model, self.z_model, self.u_model = recreate_official_nets( - num_products_features=self.num_products_features, - num_customer_features=self.num_customer_features, - x_width=self.width_eps_x, - x_depth=self.depth_eps_x, - x_eps=self.heterogeneity_x, - z_width=self.width_eps_z, - z_depth=self.depth_eps_z, - z_eps=self.heterogeneity_z, - width_u=self.width_u, - depth_u=self.depth_u, - l2_regularization_coeff=self.l2_regularization_coef, - ) + Parameters + ---------- + num_products_features : int + Number of features each product will be described with. + In terms of ChoiceDataset it is the number of { items_features + contexts_items_features } + for one product. + num_customer_features : int + Number of features each customer will be described with. + In terms of ChoiceDataset it is the number of contexts_features. + width_eps_x : int + Number of neurons for each dense layer for the products encoding net. + depth_eps_x : int + Number of dense layers for the products encoding net. + heterogeneity_x : int + Number of nets of products features encoding. + width_eps_z : int + Number of neurons for each dense layer for the customers encoding net. + depth_eps_z : int + Number of dense layers for the customers encoding net. + heterogeneity_z : int + Number of nets of customers features encoding. + width_u : int + Number of neurons for each dense layer for the utility net. + depth_u : int + Number of dense layers for the utility net. + l2_regularization_coef : float, optional + Value of dense layers weights regulariation to apply during training, by default 0.0 - # Storing weights for back-propagation - self.weights = self.x_model.weights + self.z_model.weights + self.u_model.weights - self.loss = CustomCategoricalCrossEntropy( - from_logits=False, label_smoothing=self.label_smoothing - ) - self.instantiated = True + Returns: + -------- + tf.keras.Model + Product features encoding network + tf.keras.Model + Customer features encoding network + tf.keras.Model + Features and encoding to utility computation network + """ + # Products and Customers embeddings nets, quiet symmetrical + products_input = tf.keras.layers.Input(shape=(num_products_features)) + customer_input = tf.keras.layers.Input(shape=(num_customer_features)) + x_embeddings = [] + z_embeddings = [] - def compute_batch_utility( - self, - fixed_items_features, - contexts_features, - contexts_items_features, - contexts_items_availabilities, - choices, - ): - """Compute utility from a batch of ChoiceDataset. + # Creating independant nets for each heterogeneity + for _ in range(x_eps): + x_embedding = create_ff_network( + input_shape=num_products_features, + depth=x_depth, + width=x_width, + l2_regularization_coeff=l2_regularization_coeff, + )(products_input) + x_embeddings.append(x_embedding) - Here we asssume that: item features = {fixed item features + session item features} - user features = {session features} + # Creating independant nets for each heterogeneity + for _ in range(z_eps): + z_embedding = create_ff_network( + input_shape=num_customer_features, + depth=z_depth, + width=z_width, + l2_regularization_coeff=l2_regularization_coeff, + )(customer_input) - Parameters - ---------- - fixed_items_features : tuple of np.ndarray (n_items, n_features) - Items-Features: formatting from ChoiceDataset: a matrix representing the - products fixed features. - contexts_features : tuple of np.ndarray (n_contexts, n_features) - Contexts-Features: features varying with contexts, shared by all products - contexts_items_features :tuple of np.ndarray (n_contexts, n_items, n_features) - Features varying with contexts and products - contexts_items_availabilities : np.ndarray (n_contexts, n_items) - Availabilities: here for ChoiceModel signature - choices : np.ndarray (n_contexts, ) - Choices: here for ChoiceModel signature + z_embeddings.append(z_embedding) - Returns: - -------- - np.ndarray - Utility of each product for each session. - Shape must be (n_sessions, n_items) - """ - (_, _) = contexts_items_availabilities, choices - ### Restacking of the item features - items_features_batch = tf.concat([*fixed_items_features], axis=-1) - session_features_batch = tf.concat([*contexts_features], axis=-1) - session_items_features_batch = tf.concat([*contexts_items_features], axis=-1) + x_net = tf.keras.Model(inputs=products_input, outputs=x_embeddings, name="X_embedding") + z_net = tf.keras.Model(inputs=customer_input, outputs=z_embeddings, name="Z_embedding") - full_item_features = tf.stack( - [items_features_batch] * session_items_features_batch.shape[0], axis=0 - ) - full_item_features = tf.concat([session_items_features_batch, full_item_features], axis=-1) + # Utility network + u_net = create_ff_network( + input_shape=( + x_width + z_width + num_products_features + num_customer_features + ), # Input shape from previous nets + width=width_u, + depth=depth_u, + add_last=True, # Add last for utility + l2_regularization_coeff=l2_regularization_coeff, + ) - ### Computation of utilities - utilities = [] + return x_net, z_net, u_net - # Computation of the customer features embeddings - z_embeddings = self.z_model(session_features_batch) - # Iterate over items in assortment - for item_i in range(full_item_features.shape[1]): - # Computation of item features embeddings - x_embeddings = self.x_model(full_item_features[:, item_i, :]) +class ParallelDense(tf.keras.layers.Layer): + """Layer that represents several Dense layers in Parallel. - utilities.append([]) + Parallel means that they have the same input, but then are not intricated and + are totally independant from each other. + """ - # Computation of utilites from embeddings, iteration over heterogeneities - # (eps_x * eps_z) - for _x in x_embeddings: - for _z in z_embeddings: - _u = tf.keras.layers.Concatenate()( - [full_item_features[:, item_i, :], _x, session_features_batch, _z] - ) - utilities[-1].append(self.u_model(_u)) + def __init__(self, width, depth, heterogeneity, activation="relu", **kwargs): + """Instantiation of the layer. - ### Reshape utilities: (batch_size, num_items, heterogeneity) - return tf.transpose(tf.squeeze(tf.stack(utilities, axis=0), -1)) + Following tf.keras.Layer API. Note that there will be width * depth * heterogeneity + number of neurons in the layer. - @tf.function - def train_step( - self, - fixed_items_features, - contexts_features, - contexts_items_features, - contexts_items_availabilities, - choices, - sample_weight=None, - ): - """Modified version of train step, as we have to average probabilities over heterogeneities. + Parameters + ---------- + width : int + Number of neurons for each dense layer. + depth : int + Number of neuron layers. + heterogeneity : int + Number of dense layers that are in parallel + activation : str, optional + activation function at the end of each layer, by default "relu" + """ + super().__init__(**kwargs) + self.width = width + self.depth = depth + self.heterogeneity = heterogeneity + self.activation = tf.keras.layers.Activation(activation) - Function that represents one training step (= one gradient descent step) of the model. - Handles a batch of data of size n_contexts = n_choices = batch_size + def build(self, input_shape): + """Lazy build of the layer. Parameters ---------- - fixed_items_features : tuple of np.ndarray (n_items, n_features) - Items-Features: formatting from ChoiceDataset: a matrix representing the - products fixed features. - contexts_features : tuple of np.ndarray (n_contexts, n_features) - Contexts-Features: features varying with contexts, shared by all products - contexts_items_features :tuple of np.ndarray (n_contexts, n_items, n_features) - Features varying with contexts and products - contexts_items_availabilities : np.ndarray (n_contexts, n_items) - Availabilities of items - choices : np.ndarray (n_contexts, ) - Choices - sample_weight : np.ndarray, optional - List samples weights to apply during the gradient descent to the batch elements, - by default None - - Returns: - -------- - tf.Tensor - Value of NegativeLogLikelihood loss for the batch + input_shape : tuple + shape of the input of the layer. Typically (batch_size, num_features). + Batch_size (None) is ignored, but num_features is the shape of the input. """ - with tf.GradientTape() as tape: - ### Computation of utilities - all_u = self.compute_batch_utility( - fixed_items_features=fixed_items_features, - contexts_features=contexts_features, - contexts_items_features=contexts_items_features, - contexts_items_availabilities=contexts_items_availabilities, - choices=choices, - ) - probabilities = [] - - # Iterate over heterogeneities - # for i in range(all_u.shape[2]): - # Assortment(t) Utility - # eps_probabilities = availability_softmax(all_u[:, :, i], ia_batch, axis=2) - eps_probabilities = tf.nn.softmax(all_u, axis=1) - # probabilities.append(eps_probabilities) - - # Average probabilities over heterogeneities - probabilities = tf.reduce_mean(eps_probabilities, axis=-1) + super().build(input_shape) - # It is not in the paper, but let's normalize with availabilities - probabilities = tf.multiply(probabilities, contexts_items_availabilities) - probabilities = tf.divide( - probabilities, tf.reduce_sum(probabilities, axis=1, keepdims=True) + 1e-5 + weights = [ + ( + self.add_weight( + shape=(input_shape[-1], self.width, self.heterogeneity), + initializer="glorot_normal", + trainable=True, + ), + self.add_weight( + shape=(self.width, self.heterogeneity), + initializer="glorot_normal", + trainable=True, + ), ) - - # Probabilities of selected products - # chosen_probabilities = tf.gather_nd(indices=choices_nd, params=probabilities) - - # Negative Log-Likelihood - batch_nll = self.loss( - y_pred=probabilities, - y_true=tf.one_hot(choices, depth=probabilities.shape[1]), - sample_weight=sample_weight, + ] + for i in range(self.depth - 1): + weights.append( + ( + self.add_weight( + shape=(self.width, self.width, self.heterogeneity), + initializer="glorot_normal", + trainable=True, + ), + self.add_weight( + shape=(self.width, self.heterogeneity), + initializer="glorot_normal", + trainable=True, + ), + ) ) - # nll = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False)( - # y_pred=probabilities, y_true=c_batch - # ) - # nll = -tf.reduce_sum(tf.math.log(chosen_probabilities + self.logmin)) - grads = tape.gradient(batch_nll, self.weights) - self.optimizer.apply_gradients(zip(grads, self.weights)) - return batch_nll + self.w = weights - @tf.function - def batch_predict( - self, - fixed_items_features, - contexts_features, - contexts_items_features, - contexts_items_availabilities, - choices, - sample_weight=None, - ): - """Function that represents one prediction (Probas + Loss) for one batch of a ChoiceDataset. + def call(self, inputs): + """Predict of the layer. - Specific version for RUMnet because it is needed to average probabilities over - heterogeneities. + Follows tf.keras.Layer API. Parameters ---------- - fixed_items_features : tuple of np.ndarray (n_items, n_features) - Items-Features: formatting from ChoiceDataset: a matrix representing the - products fixed features. - contexts_features : tuple of np.ndarray (n_contexts, n_features) - Contexts-Features: features varying with contexts, shared by all products - contexts_items_features :tuple of np.ndarray (n_contexts, n_items, n_features) - Features varying with contexts and products - contexts_items_availabilities : np.ndarray (n_contexts, n_items) - Availabilities of items - choices : np.ndarray (n_contexts, ) - Choices - sample_weight : np.ndarray, optional - List samples weights to apply during the gradient descent to the batch elements, - by default None + inputs : tf.Tensor, np.ndarray + Tensor of shape (batch_size, n_features) as input of the model. Returns: -------- - tf.Tensor (1, ) - Value of NegativeLogLikelihood loss for the batch - tf.Tensor (batch_size, n_items) - Probabilities for each product to be chosen for each session + outputs + tensor of shape (batch_size, width, heterogeneity) """ - utilities = self.compute_batch_utility( - fixed_items_features=fixed_items_features, - contexts_features=contexts_features, - contexts_items_features=contexts_items_features, - contexts_items_availabilities=contexts_items_availabilities, - choices=choices, - ) - probabilities = tf.nn.softmax(utilities, axis=1) - probabilities = tf.reduce_mean(probabilities, axis=-1) + outputs = tf.tensordot(inputs, self.w[0][0], axes=1) + self.w[0][1] + outputs = self.activation(outputs) + # tf.nn.bias_add(y, weights[0][1], data_format="NC...") - # Normalization with availabilties - probabilities = tf.multiply(probabilities, contexts_items_availabilities) - probabilities = tf.divide( - probabilities, tf.reduce_sum(probabilities, axis=1, keepdims=True) + 1e-5 - ) - batch_nll = self.loss( - y_pred=probabilities, - y_true=tf.one_hot(choices, depth=probabilities.shape[1]), - sample_weight=sample_weight, - ) - return batch_nll, probabilities + for w, b in self.w[1:]: + outputs = tf.einsum("ijk,jlk->ilk", outputs, w) + b + outputs = self.activation(outputs) + return outputs -class CPURUMnet(PaperRUMnet): - """CPU-optimized Re-Implementation of the RUMnet model. - This implementation handles in parallel the heterogeneities so that the training is faster. +class AssortmentParallelDense(tf.keras.layers.Layer): + """Several Dense layers in Parallel applied to an Assortment. + + Parallel means that they have the same input, but then are not intricated and + are totally independant from each other. The layer applies the same Dense layers + to an assortment of items. """ - def compute_batch_utility( - self, - fixed_items_features, - contexts_features, - contexts_items_features, - contexts_items_availabilities, - choices, - ): - """Compute utility from a batch of ChoiceDataset. + def __init__(self, width, depth, heterogeneity, activation="relu", **kwargs): + """Inialization of the layer. + + Parameters + ---------- + width : int + Number of neurons of each dense layer. + depth : int + Number of dense layers + heterogeneity : int + Number of dense networks in parallel. + activation : str, optional + activation function of each dense, by default "relu" + """ + super().__init__(**kwargs) + self.width = width + self.depth = depth + self.heterogeneity = heterogeneity + self.activation = tf.keras.layers.Activation(activation) + + def build(self, input_shape): + """Lazy build of the layer. - Here we asssume that: item features = {fixed item features + session item features} - user features = {session features} + Follows tf.keras API. Parameters ---------- - fixed_items_features : tuple of np.ndarray (n_items, n_features) - Items-Features: formatting from ChoiceDataset: a matrix representing the - products fixed features. - contexts_features : tuple of np.ndarray (n_contexts, n_features) - Contexts-Features: features varying with contexts, shared by all products - contexts_items_features :tuple of np.ndarray (n_contexts, n_items, n_features) - Features varying with contexts and products - contexts_items_availabilities : np.ndarray (n_contexts, n_items) - Availabilities of items - choices : np.ndarray (n_contexts, ) - Choices + input_shape : tuple + Shape of the input of the layer. + Typically (batch_size, num_items, num_features). + """ + super().build(input_shape) + + weights = [ + ( + self.add_weight( + shape=(input_shape[-1], self.width, self.heterogeneity), + initializer="glorot_normal", + trainable=True, + ), + self.add_weight( + shape=(self.width, self.heterogeneity), + initializer="glorot_normal", + trainable=True, + ), + ) + ] + for i in range(self.depth - 1): + weights.append( + ( + self.add_weight( + shape=(self.width, self.width, self.heterogeneity), + initializer="glorot_normal", + trainable=True, + ), + self.add_weight( + shape=(self.width, self.heterogeneity), + initializer="glorot_normal", + trainable=True, + ), + ) + ) + + self.w = weights + + def call(self, inputs): + """Predict of the layer. + + Follows tf.keras.Layer API. + + Parameters + ---------- + inputs : tf.Tensor, np.ndarray + Tensor of shape (batch_size, n_items, n_features) as input of the model. Returns: -------- - np.ndarray - Utility of each product for each session. - Shape must be (n_sessions, n_items) + tf.Tensor + Embeddings of shape (batch_size, n_items, width, heterogeneity) """ - (_, _) = contexts_items_availabilities, choices - ### Restacking of the item features - stacked_fixed_items_features = tf.concat([*fixed_items_features], axis=-1) - stacked_contexts_features = tf.concat([*contexts_features], axis=-1) - stacked_contexts_items_features = tf.concat([*contexts_items_features], axis=-1) - - full_item_features = tf.stack( - [stacked_fixed_items_features] * stacked_contexts_items_features.shape[0], axis=0 - ) - full_item_features = tf.concat( - [stacked_contexts_items_features, full_item_features], axis=-1 - ) - - ### Computation of utilities - utilities = [] - batch_size = stacked_contexts_features.shape[0] - - # Computation of the customer features embeddings - z_embeddings = self.z_model(stacked_contexts_features) + outputs = tf.tensordot(inputs, self.w[0][0], axes=[[2], [0]]) + self.w[0][1] + outputs = self.activation(outputs) - # Iterate over items in assortment - for item_i in range(full_item_features.shape[1]): - # Computation of item features embeddings - x_embeddings = self.x_model(full_item_features[:, item_i, :]) + for w, b in self.w[1:]: + outputs = tf.einsum("imjk,jlk->imlk", outputs, w) + b + outputs = self.activation(outputs) - stacked_heterogeneities = [] - # Computation of utilites from embeddings, iteration over heterogeneities - # eps_x * eps_z - for _x in x_embeddings: - for _z in z_embeddings: - full_embedding = tf.keras.layers.Concatenate()( - [full_item_features[:, item_i, :], _x, stacked_contexts_features, _z] - ) - stacked_heterogeneities.append(full_embedding) - item_utilities = self.u_model(tf.concat(stacked_heterogeneities, axis=0)) - item_utilities = tf.stack( - [ - item_utilities[batch_size * i : batch_size * (i + 1)] - for i in range(len(x_embeddings) * len(z_embeddings)) - ], - axis=1, - ) - utilities.append(item_utilities) - ### Reshape utilities: (batch_size, num_items, heterogeneity) - return tf.squeeze(tf.stack(utilities, axis=1), -1) + return outputs -class ParallelDense(tf.keras.layers.Layer): - """Layer that represents several Dense layers in Parallel. +class AssortmentUtilityDenseNetwork(tf.keras.layers.Layer): + """Dense Network that is applied to an assortment of items. - Parallel means that they have the same input, but then are not intricated and - are totally independant from each other. + We apply to the same network over several items and several heterogeneitites. """ - def __init__(self, width, depth, heterogeneity, activation="relu", **kwargs): - """Instantiation of the layer. - - Following tf.keras.Layer API. Note that there will be width * depth * heterogeneity - number of neurons in the layer. + def __init__(self, width, depth, activation="relu", add_last=True, **kwargs): + """Initialization of the layer. Parameters ---------- width : int - Number of neurons for each dense layer. + Nnumber of neurons of each dense layer. depth : int - Number of neuron layers. - heterogeneity : int - Number of dense layers that are in parallel + Number of dense layers. activation : str, optional - activation function at the end of each layer, by default "relu" + Activation function for each layer, by default "relu" + add_last : bool, optional + Whether to add a final dense layer with 1 neuron, by default True """ super().__init__(**kwargs) self.width = width self.depth = depth - self.heterogeneity = heterogeneity self.activation = tf.keras.layers.Activation(activation) + self.add_last = add_last def build(self, input_shape): """Lazy build of the layer. + Follows tf.keras.Layer API. + Parameters ---------- input_shape : tuple - shape of the input of the layer. Typically (batch_size, num_features). - Batch_size (None) is ignored, but num_features is the shape of the input. + Shape of the input of the layer. + Typically (batch_size, num_items, width, heterogeneity). """ super().build(input_shape) weights = [ ( self.add_weight( - shape=(input_shape[-1], self.width, self.heterogeneity), + shape=(input_shape[-2], self.width), initializer="glorot_normal", trainable=True, ), self.add_weight( - shape=(self.width, self.heterogeneity), + shape=(self.width, 1), initializer="glorot_normal", trainable=True, ), @@ -506,243 +392,488 @@ def build(self, input_shape): weights.append( ( self.add_weight( - shape=(self.width, self.width, self.heterogeneity), + shape=(self.width, self.width), initializer="glorot_normal", trainable=True, ), self.add_weight( - shape=(self.width, self.heterogeneity), + shape=(self.width, 1), initializer="glorot_normal", trainable=True, ), ) ) + if self.add_last: + self.last = self.add_weight( + shape=(self.width, 1), initializer="glorot_normal", trainable=True + ) self.w = weights def call(self, inputs): """Predict of the layer. - Follows tf.keras.Layer API. - Parameters ---------- inputs : tf.Tensor, np.ndarray - Tensor of shape (batch_size, n_features) as input of the model. + Input Tensor of shape (batch_size, num_items, width, heterogeneity) Returns: -------- - outputs - tensor of shape (batch_size, width, heterogeneity) + tf.Tensor + Utilities of shape (batch_size, num_items, heterogeneity) """ - outputs = tf.tensordot(inputs, self.w[0][0], axes=1) + self.w[0][1] - outputs = self.activation(outputs) - # tf.nn.bias_add(y, weights[0][1], data_format="NC...") + outputs = inputs - for w, b in self.w[1:]: - outputs = tf.einsum("ijk,jlk->ilk", outputs, w) + b + for w, b in self.w: + # bs, items, features, heterogeneities + outputs = tf.einsum("ijlk, lm->ijmk", outputs, w) + b outputs = self.activation(outputs) + if self.add_last: + outputs = tf.einsum("ijlk, lm->ijmk", outputs, self.last) + return outputs -class AssortmentParallelDense(tf.keras.layers.Layer): - """Several Dense layers in Parallel applied to an Assortment. +class PaperRUMnet(ChoiceModel): + """Re-Implementation of the RUMnet model. + + Re-implemented from the paper: + Representing Random Utility Choice Models with Neural Networks from Ali Aouad and Antoine Désir + https://arxiv.org/abs/2207.12877 + + Inherits from base_model.ChoiceModel + TODO: Verify that all parameters are implemented. + """ + + def __init__( + self, + num_products_features, + num_customer_features, + width_eps_x, + depth_eps_x, + heterogeneity_x, + width_eps_z, + depth_eps_z, + heterogeneity_z, + width_u, + depth_u, + tol, + optimizer, + lr, + normalize_non_buy=False, + logmin=1e-5, + l2_regularization_coef=0.0, + label_smoothing=0.0, + **kwargs, + ): + """Initiation of the RUMnet Model. + + Parameters + ---------- + num_products_features : int + Number of features each product will be described with. + In terms of ChoiceDataset it is the number of + { items_features + contexts_items_features } for one product. + num_customer_features : int + Number of features each customer will be described with. + In terms of ChoiceDataset it is the number of contexts_features. + width_eps_x : int + Number of neurons for each dense layer for the products encoding net. + depth_eps_x : int + Number of dense layers for the products encoding net. + heterogeneity_x : int + Number of nets of products features encoding. + width_eps_z : int + Number of neurons for each dense layer for the customers encoding net. + depth_eps_z : int + Number of dense layers for the customers encoding net. + heterogeneity_z : int + Number of nets of customers features encoding. + width_u : int + Number of neurons for each dense layer for the utility net. + depth_u : int + Number of dense layers for the utility net. + tol : float + # To be Implemented + optimizer : str + String representation of the optimizer to use. By default is Adam if not specified. + Should be within tf.keras.optimizers. + lr : float + Starting learning rate to associate with optimizer. + normalize_non_buy : bool, optional + Whether or not to add exit option with utility 1, by default True + logmin : float, optional + Value to be added within log computation to avoid infinity, by default 1e-5 + l2_regularization_coef : float, optional + Value of dense layers weights regulariation to apply during training, by default 0.0 + label_smoothing : float, optional + Value of smoothing to apply in CrossEntropy loss computation, by default 0.0 + """ + super().__init__(normalize_non_buy=normalize_non_buy, **kwargs) + # Number of features + self.num_products_features = num_products_features + self.num_customer_features = num_customer_features + + # Dimension of encoding nets + self.width_eps_x = width_eps_x + self.depth_eps_x = depth_eps_x + self.heterogeneity_x = heterogeneity_x + + self.width_eps_z = width_eps_z + self.depth_eps_z = depth_eps_z + self.heterogeneity_z = heterogeneity_z + + # Dimension of utility net + self.width_u = width_u + self.depth_u = depth_u + + # Optimization parameters + self.logmin = logmin + self.tol = tol + self.lr = lr + self.normalize_non_buy = normalize_non_buy + self.l2_regularization_coef = l2_regularization_coef + self.label_smoothing = label_smoothing + + if optimizer == "Adam": + self.optimizer = tf.keras.optimizers.Adam(lr) + elif optimizer == "SGD": + self.optimizer = tf.keras.optimizers.SGD(lr) + elif optimizer == "Adamax": + self.optimizer = tf.keras.optimizers.Adamax(lr) + else: + print(f"Optimizer {optimizer} not implemnted, switching for default Adam") + self.optimizer = tf.keras.optimizers.Adam(lr) + + self.instantiated = False + + def instantiate(self): + """Instatiation of the RUMnet model. + + Creation of : + - x_model encoding products features, + - z_model encoding customers features, + - u_model computing utilities from product, customer features and their embeddings + """ + # Instatiation of the different nets + self.x_model, self.z_model, self.u_model = recreate_official_nets( + num_products_features=self.num_products_features, + num_customer_features=self.num_customer_features, + x_width=self.width_eps_x, + x_depth=self.depth_eps_x, + x_eps=self.heterogeneity_x, + z_width=self.width_eps_z, + z_depth=self.depth_eps_z, + z_eps=self.heterogeneity_z, + width_u=self.width_u, + depth_u=self.depth_u, + l2_regularization_coeff=self.l2_regularization_coef, + ) + + # Storing weights for back-propagation + self.weights = self.x_model.weights + self.z_model.weights + self.u_model.weights + self.loss = tf_ops.CustomCategoricalCrossEntropy( + from_logits=False, + label_smoothing=self.label_smoothing, + epsilon=self.logmin, + ) + self.instantiated = True - Parallel means that they have the same input, but then are not intricated and - are totally independant from each other. The layer applies the same Dense layers - to an assortment of items. - """ + def compute_batch_utility( + self, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, + ): + """Compute utility from a batch of ChoiceDataset. - def __init__(self, width, depth, heterogeneity, activation="relu", **kwargs): - """Inialization of the layer. + Here we asssume that: item features = {fixed item features + contexts item features} + user features = {contexts features} Parameters ---------- - width : int - Number of neurons of each dense layer. - depth : int - Number of dense layers - heterogeneity : int - Number of dense networks in parallel. - activation : str, optional - activation function of each dense, by default "relu" + fixed_items_features : tuple of np.ndarray (n_items, n_features) + Items-Features: formatting from ChoiceDataset: a matrix representing the + products fixed features. + contexts_features : tuple of np.ndarray (n_contexts, n_features) + Contexts-Features: features varying with contexts, shared by all products + contexts_items_features :tuple of np.ndarray (n_contexts, n_items, n_features) + Features varying with contexts and products + contexts_items_availabilities : np.ndarray (n_contexts, n_items) + Availabilities: here for ChoiceModel signature + choices : np.ndarray (n_contexts, ) + Choices: here for ChoiceModel signature + + Returns: + -------- + np.ndarray + Utility of each product for each contexts. + Shape must be (n_contexts, n_items) """ - super().__init__(**kwargs) - self.width = width - self.depth = depth - self.heterogeneity = heterogeneity - self.activation = tf.keras.layers.Activation(activation) + (_, _) = contexts_items_availabilities, choices + ### Restacking of the item features + items_features_batch = tf.concat([*fixed_items_features], axis=-1) + contexts_features_batch = tf.concat([*contexts_features], axis=-1) + contexts_items_features_batch = tf.concat([*contexts_items_features], axis=-1) - def build(self, input_shape): - """Lazy build of the layer. + full_item_features = tf.stack( + [items_features_batch] * contexts_items_features_batch.shape[0], axis=0 + ) + full_item_features = tf.concat([contexts_items_features_batch, full_item_features], axis=-1) - Follows tf.keras API. + ### Computation of utilities + utilities = [] - Parameters - ---------- - input_shape : tuple - Shape of the input of the layer. - Typically (batch_size, num_items, num_features). - """ - super().build(input_shape) + # Computation of the customer features embeddings + z_embeddings = self.z_model(contexts_features_batch) - weights = [ - ( - self.add_weight( - shape=(input_shape[-1], self.width, self.heterogeneity), - initializer="glorot_normal", - trainable=True, - ), - self.add_weight( - shape=(self.width, self.heterogeneity), - initializer="glorot_normal", - trainable=True, - ), - ) - ] - for i in range(self.depth - 1): - weights.append( - ( - self.add_weight( - shape=(self.width, self.width, self.heterogeneity), - initializer="glorot_normal", - trainable=True, - ), - self.add_weight( - shape=(self.width, self.heterogeneity), - initializer="glorot_normal", - trainable=True, - ), - ) - ) + # Iterate over items in assortment + for item_i in range(full_item_features.shape[1]): + # Computation of item features embeddings + x_embeddings = self.x_model(full_item_features[:, item_i, :]) - self.w = weights + utilities.append([]) - def call(self, inputs): - """Predict of the layer. + # Computation of utilites from embeddings, iteration over heterogeneities + # (eps_x * eps_z) + for _x in x_embeddings: + for _z in z_embeddings: + _u = tf.keras.layers.Concatenate()( + [full_item_features[:, item_i, :], _x, contexts_features_batch, _z] + ) + utilities[-1].append(self.u_model(_u)) - Follows tf.keras.Layer API. + ### Reshape utilities: (batch_size, num_items, heterogeneity) + return tf.transpose(tf.squeeze(tf.stack(utilities, axis=0), -1)) + + @tf.function + def train_step( + self, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, + sample_weight=None, + ): + """Modified version of train step, as we have to average probabilities over heterogeneities. + + Function that represents one training step (= one gradient descent step) of the model. + Handles a batch of data of size n_contexts = n_choices = batch_size Parameters ---------- - inputs : tf.Tensor, np.ndarray - Tensor of shape (batch_size, n_items, n_features) as input of the model. + fixed_items_features : tuple of np.ndarray (n_items, n_features) + Items-Features: formatting from ChoiceDataset: a matrix representing the + products fixed features. + contexts_features : tuple of np.ndarray (n_contexts, n_features) + Contexts-Features: features varying with contexts, shared by all products + contexts_items_features :tuple of np.ndarray (n_contexts, n_items, n_features) + Features varying with contexts and products + contexts_items_availabilities : np.ndarray (n_contexts, n_items) + Availabilities of items + choices : np.ndarray (n_contexts, ) + Choices + sample_weight : np.ndarray, optional + List samples weights to apply during the gradient descent to the batch elements, + by default None Returns: -------- tf.Tensor - Embeddings of shape (batch_size, n_items, width, heterogeneity) + Value of NegativeLogLikelihood loss for the batch """ - outputs = tf.tensordot(inputs, self.w[0][0], axes=[[2], [0]]) + self.w[0][1] - outputs = self.activation(outputs) + with tf.GradientTape() as tape: + ### Computation of utilities + all_u = self.compute_batch_utility( + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, + choices=choices, + ) + probabilities = [] - for w, b in self.w[1:]: - outputs = tf.einsum("imjk,jlk->imlk", outputs, w) + b - outputs = self.activation(outputs) + # Iterate over heterogeneities + eps_probabilities = tf.nn.softmax(all_u, axis=1) - return outputs + # Average probabilities over heterogeneities + probabilities = tf.reduce_mean(eps_probabilities, axis=-1) + # It is not in the paper, but let's normalize with availabilities + probabilities = tf.multiply(probabilities, contexts_items_availabilities) + probabilities = tf.divide( + probabilities, tf.reduce_sum(probabilities, axis=1, keepdims=True) + 1e-5 + ) + if self.tol > 0: + probabilities = (1 - self.tol) * probabilities + self.tol * tf.ones_like( + probabilities + ) / probabilities.shape[-1] -class AssortmentUtilityDenseNetwork(tf.keras.layers.Layer): - """Dense Network that is applied to an assortment of items. + # Probabilities of selected products - We apply to the same network over several items and several heterogeneitites. - """ + # Negative Log-Likelihood + batch_nll = self.loss( + y_pred=probabilities, + y_true=tf.one_hot(choices, depth=probabilities.shape[1]), + sample_weight=sample_weight, + ) - def __init__(self, width, depth, activation="relu", add_last=True, **kwargs): - """Initialization of the layer. + grads = tape.gradient(batch_nll, self.weights) + self.optimizer.apply_gradients(zip(grads, self.weights)) + return batch_nll + + @tf.function + def batch_predict( + self, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, + sample_weight=None, + ): + """Function that represents one prediction (Probas + Loss) for one batch of a ChoiceDataset. + + Specific version for RUMnet because it is needed to average probabilities over + heterogeneities. Parameters ---------- - width : int - Nnumber of neurons of each dense layer. - depth : int - Number of dense layers. - activation : str, optional - Activation function for each layer, by default "relu" - add_last : bool, optional - Whether to add a final dense layer with 1 neuron, by default True + fixed_items_features : tuple of np.ndarray (n_items, n_features) + Items-Features: formatting from ChoiceDataset: a matrix representing the + products fixed features. + contexts_features : tuple of np.ndarray (n_contexts, n_features) + Contexts-Features: features varying with contexts, shared by all products + contexts_items_features :tuple of np.ndarray (n_contexts, n_items, n_features) + Features varying with contexts and products + contexts_items_availabilities : np.ndarray (n_contexts, n_items) + Availabilities of items + choices : np.ndarray (n_contexts, ) + Choices + sample_weight : np.ndarray, optional + List samples weights to apply during the gradient descent to the batch elements, + by default None + + Returns: + -------- + tf.Tensor (1, ) + Value of NegativeLogLikelihood loss for the batch + tf.Tensor (batch_size, n_items) + Probabilities for each product to be chosen for each contexts """ - super().__init__(**kwargs) - self.width = width - self.depth = depth - self.activation = tf.keras.layers.Activation(activation) - self.add_last = add_last + utilities = self.compute_batch_utility( + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, + choices=choices, + ) + probabilities = tf.nn.softmax(utilities, axis=1) + probabilities = tf.reduce_mean(probabilities, axis=-1) - def build(self, input_shape): - """Lazy build of the layer. + # Normalization with availabilties + probabilities = tf.multiply(probabilities, contexts_items_availabilities) + probabilities = tf.divide( + probabilities, tf.reduce_sum(probabilities, axis=1, keepdims=True) + 1e-5 + ) + + batch_nll = self.loss( + y_pred=probabilities, + y_true=tf.one_hot(choices, depth=probabilities.shape[1]), + sample_weight=sample_weight, + ) + return batch_nll, probabilities - Follows tf.keras.Layer API. - Parameters - ---------- - input_shape : tuple - Shape of the input of the layer. - Typically (batch_size, num_items, width, heterogeneity). - """ - super().build(input_shape) +class CPURUMnet(PaperRUMnet): + """CPU-optimized Re-Implementation of the RUMnet model. - weights = [ - ( - self.add_weight( - shape=(input_shape[-2], self.width), - initializer="glorot_normal", - trainable=True, - ), - self.add_weight( - shape=(self.width, 1), - initializer="glorot_normal", - trainable=True, - ), - ) - ] - for i in range(self.depth - 1): - weights.append( - ( - self.add_weight( - shape=(self.width, self.width), - initializer="glorot_normal", - trainable=True, - ), - self.add_weight( - shape=(self.width, 1), - initializer="glorot_normal", - trainable=True, - ), - ) - ) - if self.add_last: - self.last = self.add_weight( - shape=(self.width, 1), initializer="glorot_normal", trainable=True - ) + This implementation handles in parallel the heterogeneities so that the training is faster. + """ - self.w = weights + def compute_batch_utility( + self, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, + ): + """Compute utility from a batch of ChoiceDataset. - def call(self, inputs): - """Predict of the layer. + Here we asssume that: item features = {fixed item features + contexts item features} + user features = {contexts features} Parameters ---------- - inputs : tf.Tensor, np.ndarray - Input Tensor of shape (batch_size, num_items, width, heterogeneity) + fixed_items_features : tuple of np.ndarray (n_items, n_features) + Items-Features: formatting from ChoiceDataset: a matrix representing the + products fixed features. + contexts_features : tuple of np.ndarray (n_contexts, n_features) + Contexts-Features: features varying with contexts, shared by all products + contexts_items_features :tuple of np.ndarray (n_contexts, n_items, n_features) + Features varying with contexts and products + contexts_items_availabilities : np.ndarray (n_contexts, n_items) + Availabilities of items + choices : np.ndarray (n_contexts, ) + Choices Returns: -------- - tf.Tensor - Utilities of shape (batch_size, num_items, heterogeneity) + np.ndarray + Utility of each product for each contexts. + Shape must be (n_contexts, n_items) """ - outputs = inputs + (_, _) = contexts_items_availabilities, choices + ### Restacking of the item features + stacked_fixed_items_features = tf.concat([*fixed_items_features], axis=-1) + stacked_contexts_features = tf.concat([*contexts_features], axis=-1) + stacked_contexts_items_features = tf.concat([*contexts_items_features], axis=-1) - for w, b in self.w: - # bs, items, features, heterogeneities - outputs = tf.einsum("ijlk, lm->ijmk", outputs, w) + b - outputs = self.activation(outputs) + full_item_features = tf.stack( + [stacked_fixed_items_features] * stacked_contexts_items_features.shape[0], axis=0 + ) + full_item_features = tf.concat( + [stacked_contexts_items_features, full_item_features], axis=-1 + ) - if self.add_last: - outputs = tf.einsum("ijlk, lm->ijmk", outputs, self.last) + ### Computation of utilities + utilities = [] + batch_size = stacked_contexts_features.shape[0] - return outputs + # Computation of the customer features embeddings + z_embeddings = self.z_model(stacked_contexts_features) + + # Iterate over items in assortment + for item_i in range(full_item_features.shape[1]): + # Computation of item features embeddings + x_embeddings = self.x_model(full_item_features[:, item_i, :]) + + stacked_heterogeneities = [] + # Computation of utilites from embeddings, iteration over heterogeneities + # eps_x * eps_z + for _x in x_embeddings: + for _z in z_embeddings: + full_embedding = tf.keras.layers.Concatenate()( + [full_item_features[:, item_i, :], _x, stacked_contexts_features, _z] + ) + stacked_heterogeneities.append(full_embedding) + item_utilities = self.u_model(tf.concat(stacked_heterogeneities, axis=0)) + item_utilities = tf.stack( + [ + item_utilities[batch_size * i : batch_size * (i + 1)] + for i in range(len(x_embeddings) * len(z_embeddings)) + ], + axis=1, + ) + utilities.append(item_utilities) + ### Reshape utilities: (batch_size, num_items, heterogeneity) + return tf.squeeze(tf.stack(utilities, axis=1), -1) class GPURUMnet(PaperRUMnet): @@ -777,7 +908,7 @@ def instantiate(self): + self.z_model.trainable_variables + self.u_model.trainable_variables ) - self.loss = CustomCategoricalCrossEntropy( + self.loss = tf_ops.CustomCategoricalCrossEntropy( from_logits=False, label_smoothing=self.label_smoothing ) self.time_dict = {} @@ -793,8 +924,8 @@ def compute_batch_utility( ): """Compute utility from a batch of ChoiceDataset. - Here we asssume that: item features = {fixed item features + session item features} - user features = {session features} + Here we asssume that: item features = {fixed item features + contexts item features} + user features = {contexts features} Parameters ---------- @@ -813,8 +944,8 @@ def compute_batch_utility( Returns: -------- np.ndarray - Utility of each product for each session. - Shape must be (n_sessions, n_items) + Utility of each product for each contexts. + Shape must be (n_contexts, n_items) """ (_, _) = contexts_items_availabilities, choices @@ -888,12 +1019,12 @@ def train_step( items_batch : tuple of np.ndarray (items_features) Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products constant features. - sessions_batch : tuple of np.ndarray (sessions_features) + contexts_batch : tuple of np.ndarray (contexts_features) Time-Features - sessions_items_batch : tuple of np.ndarray (sessions_items_features) + contexts_items_batch : tuple of np.ndarray (contexts_items_features) Time-Item-Features availabilities_batch : np.ndarray - Availabilities (sessions_items_availabilities) + Availabilities (contexts_items_availabilities) choices_batch : np.ndarray Choices sample_weight : np.ndarray, optional @@ -907,14 +1038,14 @@ def train_step( """ with tf.GradientTape() as tape: ### Computation of utilities - all_u = self.compute_batch_utility( + utilities = self.compute_batch_utility( fixed_items_features=fixed_items_features, contexts_features=contexts_features, contexts_items_features=contexts_items_features, contexts_items_availabilities=contexts_items_availabilities, choices=choices, ) - eps_probabilities = tf.nn.softmax(all_u, axis=2) + eps_probabilities = tf.nn.softmax(utilities, axis=2) # Average probabilities over heterogeneities probabilities = tf.reduce_mean(eps_probabilities, axis=1) @@ -923,8 +1054,10 @@ def train_step( probabilities = tf.divide( probabilities, tf.reduce_sum(probabilities, axis=1, keepdims=True) + 1e-5 ) - # Probabilities of selected products - # chosen_probabilities = tf.gather_nd(indices=choices_nd, params=probabilities) + if self.tol > 0: + probabilities = (1 - self.tol) * probabilities + self.tol * tf.ones_like( + probabilities + ) / probabilities.shape[-1] # Negative Log-Likelihood batch_nll = self.loss( @@ -966,12 +1099,12 @@ def batch_predict( items_batch : tuple of np.ndarray (items_features) Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products constant features. - sessions_batch : tuple of np.ndarray (sessions_features) + contexts_batch : tuple of np.ndarray (contexts_features) Time-Features - sessions_items_batch : tuple of np.ndarray (sessions_items_features) + contexts_items_batch : tuple of np.ndarray (contexts_items_features) Time-Item-Features availabilities_batch : np.ndarray - Availabilities (sessions_items_availabilities) + Availabilities (contexts_items_availabilities) choices_batch : np.ndarray Choices sample_weight : np.ndarray, optional @@ -983,7 +1116,7 @@ def batch_predict( tf.Tensor (1, ) Value of NegativeLogLikelihood loss for the batch tf.Tensor (batch_size, n_items) - Probabilities for each product to be chosen for each session + Probabilities for each product to be chosen for each contexts """ utilities = self.compute_batch_utility( fixed_items_features=fixed_items_features, @@ -1006,136 +1139,3 @@ def batch_predict( sample_weight=sample_weight, ) return batch_loss, probabilities - - -def create_ff_network( - input_shape, depth, width, activation="elu", add_last=False, l2_regularization_coeff=0.0 -): - """Base function to create a simple fully connected (Dense) network. - - Parameters - ---------- - input_shape : tuple of int - shape of the input of the network. Typically (num_features, ) - depth : int - Number of dense/fully-connected of the network to create. - width : int - Neurons number for all dense layers. - add_last : bool, optional - Whether to add a Dense layer with a single output at the end, by default False - Typically to be used when creating the utility network, that outputs a single number: - the utility. - l2_regularization_coeff : float, optional - Regularization coefficient for Dense layers weights during training, by default 0.0 - - Returns: - -------- - tf.keras.Model - Dense Neural Network with tensorflow backend. - """ - input = tf.keras.layers.Input(shape=input_shape) - regularizer = tf.keras.regularizers.L2(l2_regularization_coeff) - out = input - for _ in range(depth): - out = tf.keras.layers.Dense( - width, activation=activation, kernel_regularizer=regularizer, use_bias=True - )(out) - if add_last: - out = tf.keras.layers.Dense(1, activation="linear", use_bias=False)(out) - return tf.keras.Model(inputs=input, outputs=out) - - -def recreate_official_nets( - num_products_features, - x_width, - x_depth, - x_eps, - num_customer_features, - z_width, - z_depth, - z_eps, - width_u, - depth_u, - l2_regularization_coeff=0.0, -): - """Function to create the three nets used in RUMnet: X_net, Z_net and U_net. - - Parameters - ---------- - num_products_features : int - Number of features each product will be described with. - In terms of ChoiceDataset it is the number of { items_features + sessions_items_features } - for one product. - num_customer_features : int - Number of features each customer will be described with. - In terms of ChoiceDataset it is the number of sessions_features. - width_eps_x : int - Number of neurons for each dense layer for the products encoding net. - depth_eps_x : int - Number of dense layers for the products encoding net. - heterogeneity_x : int - Number of nets of products features encoding. - width_eps_z : int - Number of neurons for each dense layer for the customers encoding net. - depth_eps_z : int - Number of dense layers for the customers encoding net. - heterogeneity_z : int - Number of nets of customers features encoding. - width_u : int - Number of neurons for each dense layer for the utility net. - depth_u : int - Number of dense layers for the utility net. - l2_regularization_coef : float, optional - Value of dense layers weights regulariation to apply during training, by default 0.0 - - Returns: - -------- - tf.keras.Model - Product features encoding network - tf.keras.Model - Customer features encoding network - tf.keras.Model - Features and encoding to utility computation network - """ - # Products and Customers embeddings nets, quiet symmetrical - products_input = tf.keras.layers.Input(shape=(num_products_features)) - customer_input = tf.keras.layers.Input(shape=(num_customer_features)) - x_embeddings = [] - z_embeddings = [] - - # Creating independant nets for each heterogeneity - for _ in range(x_eps): - x_embedding = create_ff_network( - input_shape=num_products_features, - depth=x_depth, - width=x_width, - l2_regularization_coeff=l2_regularization_coeff, - )(products_input) - x_embeddings.append(x_embedding) - - # Creating independant nets for each heterogeneity - for _ in range(z_eps): - z_embedding = create_ff_network( - input_shape=num_customer_features, - depth=z_depth, - width=z_width, - l2_regularization_coeff=l2_regularization_coeff, - )(customer_input) - - z_embeddings.append(z_embedding) - - x_net = tf.keras.Model(inputs=products_input, outputs=x_embeddings, name="X_embedding") - z_net = tf.keras.Model(inputs=customer_input, outputs=z_embeddings, name="Z_embedding") - - # Utility network - u_net = create_ff_network( - input_shape=( - x_width + z_width + num_products_features + num_customer_features - ), # Input shape from previous nets - width=width_u, - depth=depth_u, - add_last=True, # Add last for utility - l2_regularization_coeff=l2_regularization_coeff, - ) - - return x_net, z_net, u_net From a3b83fb69ef10b71b08fe7631c5b53fb99c067f5 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 2 Feb 2024 16:18:02 +0100 Subject: [PATCH 121/767] ENH: moved tfp import inside report function --- choice_learn/models/conditional_mnl.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/choice_learn/models/conditional_mnl.py b/choice_learn/models/conditional_mnl.py index 00733cf2..712f38fc 100644 --- a/choice_learn/models/conditional_mnl.py +++ b/choice_learn/models/conditional_mnl.py @@ -2,7 +2,6 @@ import pandas as pd import tensorflow as tf -import tensorflow_probability as tfp from .base_model import ChoiceModel @@ -1038,6 +1037,8 @@ def compute_report(self, dataset): pandas.DataFrame A DF with estimation, Std Err, z_value and p_value for each coefficient. """ + import tensorflow_probability as tfp + weights_std = self.get_weights_std(dataset) dist = tfp.distributions.Normal(loc=0.0, scale=1.0) From 8894dd216e1ab9b9e109db52069c0a7a5a22cd68 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 2 Feb 2024 16:18:14 +0100 Subject: [PATCH 122/767] ADD: requirements.txt --- requirements.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index d23458ee..3c9de3ac 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,5 @@ --e . +numpy==1.24.3 pandas==1.5.3 -numpy==1.24.2 +tensorflow==2.13.0 +tensorflow_probability==0.20.1 +tqdm==4.65.0 From 36e2755e5a748421ff184367d58c214789f2982e Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 2 Feb 2024 16:22:21 +0100 Subject: [PATCH 123/767] ADD: tfp as requirement in README --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 76d0c248..976714b8 100644 --- a/README.md +++ b/README.md @@ -90,8 +90,11 @@ git clone git@github.com:artefactory/choice-learn-private.git Choice-Learn requires the following: - Python (>=3.8) - NumPy (>=1.24) -- TensorFlow (>=2.13) - pandas (>=1.5) +For modelling you need: +- TensorFlow (>=2.13) +Finally, an optional requirement used for specific functions is: +- tensorflow_probability (>=0.20.1) ## Usage ```python From 5109415b3fee6195f7be5af15b5ccbc294493fcd Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 2 Feb 2024 17:07:45 +0100 Subject: [PATCH 124/767] ENH: match latest signature --- choice_learn/models/base_model.py | 8 +- choice_learn/models/conditional_mnl.py | 184 ++++++++++++++----------- 2 files changed, 106 insertions(+), 86 deletions(-) diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index 488e32cc..4808324e 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -415,7 +415,7 @@ def batch_predict( Probabilities for each product to be chosen for each context """ # Compute utilities from features - utilities = self.compute_utility( + utilities = self.compute_batch_utility( fixed_items_features, contexts_features, contexts_items_features, @@ -659,7 +659,7 @@ def f(params_1d): f.history = [] return f - def _fit_with_lbfgs(self, dataset, n_epochs, tolerance=1e-8): + def _fit_with_lbfgs(self, dataset, epochs=None, tolerance=1e-8): """Fit function for L-BFGS optimizer. Replaces the .fit method when the optimizer is set to L-BFGS. @@ -682,6 +682,8 @@ def _fit_with_lbfgs(self, dataset, n_epochs, tolerance=1e-8): # dependency import tensorflow_probability as tfp + if epochs is None: + epochs = self.epochs func = self._lbfgs_train_step(dataset) # convert initial model parameters to a 1D tf.Tensor @@ -691,7 +693,7 @@ def _fit_with_lbfgs(self, dataset, n_epochs, tolerance=1e-8): results = tfp.optimizer.lbfgs_minimize( value_and_gradients_function=func, initial_position=init_params, - max_iterations=n_epochs, + max_iterations=epochs, tolerance=tolerance, f_absolute_tolerance=-1, f_relative_tolerance=-1, diff --git a/choice_learn/models/conditional_mnl.py b/choice_learn/models/conditional_mnl.py index 712f38fc..5a95b60c 100644 --- a/choice_learn/models/conditional_mnl.py +++ b/choice_learn/models/conditional_mnl.py @@ -338,35 +338,35 @@ def _store_dataset_features_names(self, dataset): self._contexts_features_names = dataset.contexts_features_names self._contexts_items_features_names = dataset.contexts_items_features_names - def compute_utility_from_specification( + def compute_batch_utility_from_specification( self, - items_batch, - contexts_batch, - contexts_items_batch, - availabilities_batch, - choices_batch, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, verbose=0, ): """Computes the utility when the model is constructed from a ModelSpecification object. Parameters ---------- - tems_batch : tuple of np.ndarray (items_features) + fixed_items_features : tuple of np.ndarray Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products constant/fixed features. Shape must be (n_items, n_items_features) - contexts_batch : tuple of np.ndarray (contexts_features) - Time-Features - Shape must be (n_choices, n_contexts_features) - contexts_items_batch : tuple of np.ndarray (contexts_items_features) - Time-Item-Features - Shape must be (n_choices, n_contexts_items_features) - availabilities_batch : np.ndarray - Availabilities (contexts_items_availabilities) - Shape must be (n_choices, n_items) + contexts_features : tuple of np.ndarray (contexts_features) + a batch of contexts features + Shape must be (n_contexts, n_contexts_features) + contexts_items_features : tuple of np.ndarray (contexts_items_features) + a batch of contexts items features + Shape must be (n_contexts, n_contexts_items_features) + contexts_items_availabilities : np.ndarray + A batch of contexts items availabilities + Shape must be (n_contexts, n_items) choices_batch : np.ndarray Choices - Shape must be (n_choices, ) + Shape must be (n_contexts, ) verbose : int, optional Parametrization of the logging outputs, by default 0 @@ -375,10 +375,10 @@ def compute_utility_from_specification( tf.Tensor Utilities corresponding of shape (n_choices, n_items) """ - _ = choices_batch + _ = choices - num_items = availabilities_batch.shape[1] - num_choices = availabilities_batch.shape[0] + num_items = contexts_items_availabilities.shape[1] + num_choices = contexts_items_availabilities.shape[0] contexts_items_utilities = [] # Items features if self._items_features_names is not None: @@ -397,7 +397,7 @@ def compute_utility_from_specification( [ s_i_u[:k], tf.multiply( - items_batch[i][k, j], + fixed_items_features[i][k, j], self.weights[weight_index][:, q], ), s_i_u[k + 1 :], @@ -409,7 +409,7 @@ def compute_utility_from_specification( [ s_i_u[:idx], tf.multiply( - items_batch[i][idx, j], + fixed_items_features[i][idx, j], self.weights[weight_index][:, q], ), s_i_u[idx + 1 :], @@ -458,9 +458,9 @@ def compute_utility_from_specification( axis=1, ) """ - contexts_batch[i][:, j] + contexts_features[i][:, j] compute = tf.multiply( - contexts_batch[i][:, j], + contexts_features[i][:, j], self.weights[weight_index][:, q], ) s_i_u[k] += compute @@ -482,7 +482,7 @@ def compute_utility_from_specification( ) """ compute = tf.multiply( - contexts_batch[i][:, j], self.weights[weight_index][:, q] + contexts_features[i][:, j], self.weights[weight_index][:, q] ) s_i_u[idx] += compute @@ -516,7 +516,7 @@ def compute_utility_from_specification( s_i_u[:, :k], tf.expand_dims( tf.multiply( - contexts_items_batch[i][:, k, j], + contexts_items_features[i][:, k, j], self.weights[weight_index][:, q], ), axis=-1, @@ -531,7 +531,7 @@ def compute_utility_from_specification( s_i_u[:, :idx], tf.expand_dims( tf.multiply( - contexts_items_batch[i][:, idx, j], + contexts_items_features[i][:, idx, j], self.weights[weight_index][:, q], ), axis=-1, @@ -785,28 +785,34 @@ def instantiate( raise ValueError("No weights instantiated") return weights - def compute_utility( - self, items_batch, contexts_batch, contexts_items_batch, availabilities_batch, choices_batch + def compute_batch_utility( + self, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, ): """Main method to compute the utility of the model. Selects the right method to compute. Parameters ---------- - items_batch : tuple of np.ndarray (items_features) + fixed_items_features : tuple of np.ndarray Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products constant/fixed features. Shape must be (n_items, n_items_features) - contexts_batch : tuple of np.ndarray (contexts_features) - Time-Features - Shape must be (n_choices, n_contexts_features) - contexts_items_batch : tuple of np.ndarray (contexts_items_features) - Time-Item-Features - Shape must be (n_choices, n_contexts_items_features) - availabilities_batch : np.ndarray - Availabilities (contexts_items_availabilities) - Shape must be (n_choices, n_items) + contexts_features : tuple of np.ndarray (contexts_features) + a batch of contexts features + Shape must be (n_contexts, n_contexts_features) + contexts_items_features : tuple of np.ndarray (contexts_items_features) + a batch of contexts items features + Shape must be (n_contexts, n_contexts_items_features) + contexts_items_availabilities : np.ndarray + A batch of contexts items availabilities + Shape must be (n_contexts, n_items) choices_batch : np.ndarray - Choices Shape must be (n_choices, ) + Choices + Shape must be (n_contexts, ) Returns: -------- @@ -814,44 +820,49 @@ def compute_utility( Computed utilities of shape (n_choices, n_items). """ if isinstance(self.params, ModelSpecification): - return self.compute_utility_from_specification( - items_batch, - contexts_batch, - contexts_items_batch, - availabilities_batch, - choices_batch, + return self.compute_batch_utility_from_specification( + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, + choices=choices, ) - return self.compute_utility_from_dict( - items_batch, - contexts_batch, - contexts_items_batch, - availabilities_batch, - choices_batch, + return self.compute_batch_utility_from_dict( + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, + choices=choices, ) - def compute_utility_from_dict( - self, items_batch, contexts_batch, contexts_items_batch, availabilities_batch, choices_batch + def compute_batch_utility_from_dict( + self, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, ): """Computes the utility when the model is constructed from a dictionnary object. Parameters ---------- - items_batch : tuple of np.ndarray (items_features) + fixed_items_features : tuple of np.ndarray Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products constant/fixed features. Shape must be (n_items, n_items_features) - contexts_batch : tuple of np.ndarray (contexts_features) - Time-Features - Shape must be (n_choices, n_contexts_features) - contexts_items_batch : tuple of np.ndarray (contexts_items_features) - Time-Item-Features - Shape must be (n_choices, n_contexts_items_features) - availabilities_batch : np.ndarray - Availabilities (contexts_items_availabilities) - Shape must be (n_choices, n_items) + contexts_features : tuple of np.ndarray (contexts_features) + a batch of contexts features + Shape must be (n_contexts, n_contexts_features) + contexts_items_features : tuple of np.ndarray (contexts_items_features) + a batch of contexts items features + Shape must be (n_contexts, n_contexts_items_features) + contexts_items_availabilities : np.ndarray + A batch of contexts items availabilities + Shape must be (n_contexts, n_items) choices_batch : np.ndarray Choices - Shape must be (n_choices, ) + Shape must be (n_contexts, ) verbose : int, optional Parametrization of the logging outputs, by default 0 @@ -860,14 +871,14 @@ def compute_utility_from_dict( tf.Tensor Utilities corresponding of shape (n_choices, n_items) """ - _, _ = availabilities_batch, choices_batch + _ = choices contexts_items_utilities = [] - if items_batch is not None: - num_items = items_batch[0].shape[0] + if fixed_items_features is not None: + num_items = fixed_items_features[0].shape[0] else: - num_items = contexts_items_batch[0].shape[1] - num_choices = availabilities_batch.shape[0] + num_items = contexts_items_features[0].shape[1] + num_choices = contexts_items_availabilities.shape[0] # Items features for i, feat_tuple in enumerate(self._items_features_names): @@ -876,16 +887,19 @@ def compute_utility_from_dict( weight = self.weights[k] if self.params[feat] == "constant": s_i_u = tf.concat( - [tf.multiply(items_batch[i][:, j], weight)] * num_choices, axis=0 + [tf.multiply(fixed_items_features[i][:, j], weight)] * num_choices, + axis=0, ) elif self.params[feat] == "item": weight = tf.concat([tf.constant([[0.0]]), weight], axis=-1) s_i_u = tf.concat( - [tf.multiply(items_batch[i][:, j], weight)] * num_choices, axis=0 + [tf.multiply(fixed_items_features[i][:, j], weight)] * num_choices, + axis=0, ) elif self.params[feat] == "item-full": s_i_u = tf.concat( - [tf.multiply(items_batch[i][:, j], weight)] * num_choices, axis=0 + [tf.multiply(fixed_items_features[i][:, j], weight)] * num_choices, + axis=0, ) else: raise NotImplementedError(f"Param {self.params[feat]} not implemented") @@ -903,13 +917,13 @@ def compute_utility_from_dict( weight = self.weights[k] if self.params[feat] == "constant": s_i_u = tf.concat( - [tf.multiply(contexts_batch[i][j], weight)] * num_items, axis=-1 + [tf.multiply(contexts_features[i][j], weight)] * num_items, axis=-1 ) elif self.params[feat] == "item": weight = tf.concat([tf.constant([[0.0]]), weight], axis=-1) - s_i_u = tf.tensordot(contexts_batch[i][:, j : j + 1], weight, axes=1) + s_i_u = tf.tensordot(contexts_features[i][:, j : j + 1], weight, axes=1) elif self.params[feat] == "item-full": - s_i_u = tf.tensordot(contexts_batch[i][:, j : j + 1], weight, axes=1) + s_i_u = tf.tensordot(contexts_features[i][:, j : j + 1], weight, axes=1) else: raise NotImplementedError(f"Param {self.params[feat]} not implemented") contexts_items_utilities.append(s_i_u) @@ -925,12 +939,12 @@ def compute_utility_from_dict( if feat in self.params.keys(): weight = self.weights[k] if self.params[feat] == "constant": - s_i_u = tf.multiply(contexts_items_batch[i][:, :, j], weight) + s_i_u = tf.multiply(contexts_items_features[i][:, :, j], weight) elif self.params[feat] == "item": weight = tf.concat([tf.constant([[0.0]]), weight], axis=-1) - s_i_u = tf.multiply(contexts_items_batch[i][:, :, j], weight) + s_i_u = tf.multiply(contexts_items_features[i][:, :, j], weight) elif self.params[feat] == "item-full": - s_i_u = tf.multiply(contexts_items_batch[i][:, :, j], weight) + s_i_u = tf.multiply(contexts_items_features[i][:, :, j], weight) else: raise NotImplementedError(f"Param {self.params[feat]} not implemented") contexts_items_utilities.append(s_i_u) @@ -987,7 +1001,7 @@ def fit(self, choice_dataset, get_report=False, **kwargs): self.report = self.compute_report(choice_dataset) return fit - def _fit_with_lbfgs(self, choice_dataset, n_epochs, tolerance=1e-8, get_report=False): + def _fit_with_lbfgs(self, choice_dataset, epochs=None, tolerance=1e-8, get_report=False): """Specific fit function to estimate the paramters with LBFGS. Parameters @@ -1018,7 +1032,9 @@ def _fit_with_lbfgs(self, choice_dataset, n_epochs, tolerance=1e-8, get_report=F contexts_items_features_names=choice_dataset.contexts_items_features_names, ) self.instantiated = True - fit = super()._fit_with_lbfgs(choice_dataset, n_epochs, tolerance) + if epochs is None: + epochs = self.epochs + fit = super()._fit_with_lbfgs(choice_dataset, epochs, tolerance) if get_report: self.report = self.compute_report(choice_dataset) return fit @@ -1093,7 +1109,7 @@ def get_weights_std(self, dataset): index += _w.shape[1] model.weights = mw for batch in dataset.iter_batch(batch_size=-1): - utilities = model.compute_utility(*batch) + utilities = model.compute_batch_utility(*batch) probabilities = tf.nn.softmax(utilities, axis=-1) loss = tf.keras.losses.CategoricalCrossentropy(reduction="sum")( y_pred=probabilities, @@ -1103,7 +1119,9 @@ def get_weights_std(self, dataset): jacobian = tape_2.jacobian(loss, w) # Compute the Hessian from the Jacobian hessian = tape_1.batch_jacobian(jacobian, w) - return tf.sqrt([tf.linalg.inv(tf.squeeze(hessian))[i][i] for i in range(len(w))]) + return tf.sqrt( + [tf.linalg.inv(tf.squeeze(hessian))[i][i] for i in range(len(tf.squeeze(hessian)))] + ) def clone(self): """Returns a clone of the model.""" From dadf5f4972d1acea808c2ef881c5de5bce577755 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 2 Feb 2024 17:08:25 +0100 Subject: [PATCH 125/767] ENH: latest signature in example --- README.md | 2 +- .../choice_learn_introduction_clogit.ipynb | 36 +++++++++---------- notebooks/custom_model.ipynb | 16 ++++----- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 976714b8..9481432a 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ Choice-Learn requires the following: - pandas (>=1.5) For modelling you need: - TensorFlow (>=2.13) -Finally, an optional requirement used for specific functions is: +Finally, an optional requirement used for report and LBFG-s use is: - tensorflow_probability (>=0.20.1) ## Usage diff --git a/notebooks/choice_learn_introduction_clogit.ipynb b/notebooks/choice_learn_introduction_clogit.ipynb index 51886a9d..0dcc47a5 100644 --- a/notebooks/choice_learn_introduction_clogit.ipynb +++ b/notebooks/choice_learn_introduction_clogit.ipynb @@ -174,7 +174,7 @@ "metadata": {}, "outputs": [], "source": [ - "history = model.fit(dataset, n_epochs=1000)" + "history = model.fit(dataset, epochs=1000, get_report=True)" ] }, { @@ -447,7 +447,7 @@ "metadata": {}, "outputs": [], "source": [ - "history = cmnl.fit(dataset, n_epochs=1000)\n", + "history = cmnl.fit(dataset, epochs=1000)\n", "print(cmnl.weights)" ] }, @@ -469,7 +469,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 1/1 [00:02<00:00, 2.46s/it]" + "100%|██████████| 1/1 [00:02<00:00, 2.41s/it]" ] }, { @@ -499,8 +499,8 @@ " tf.constant([[0.0595089, -0.00678188, -0.00645982, -0.00145029]]),\n", " tf.constant([[0.697311, 1.8437, 3.27381]]),\n", "]\n", - "gt_model = ConditionalMNL(parameters=params, lr=0.01)\n", - "gt_model.fit(dataset, n_epochs=1, batch_size=-1)\n", + "gt_model = ConditionalMNL(parameters=params, lr=0.01, epochs=1, batch_size=-1)\n", + "gt_model.fit(dataset)\n", "\n", "# Here we estimate the negative log-likelihood with these coefficients (also, we obtain same value as in those papers):\n", "gt_model.weights = gt_weights\n", @@ -565,11 +565,11 @@ "outputs": [], "source": [ "cmnl = ConditionalMNL(parameters=params, optimizer=\"Adam\")\n", - "history = cmnl.fit(dataset, n_epochs=2000, batch_size=-1)\n", + "history = cmnl.fit(dataset, epochs=2000, batch_size=-1)\n", "cmnl.optimizer.lr = cmnl.optimizer.lr / 5\n", - "history2 = cmnl.fit(dataset, n_epochs=4000, batch_size=-1)\n", + "history2 = cmnl.fit(dataset, epochs=4000, batch_size=-1)\n", "cmnl.optimizer.lr = cmnl.optimizer.lr / 10\n", - "history3 = cmnl.fit(dataset, n_epochs=20000, batch_size=-1)" + "history3 = cmnl.fit(dataset, epochs=20000, batch_size=-1)" ] }, { @@ -582,14 +582,14 @@ { "data": { "text/plain": [ - "[,\n", - " ,\n", - " ,\n", - " ,\n", + "[,\n", + " ,\n", + " ,\n", + " ,\n", " ,\n", - " ]" + " ]" ] }, "execution_count": null, @@ -611,7 +611,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": null, @@ -653,7 +653,7 @@ " \"intercept\": \"item\"}\n", "\n", "# Instantiation of the model\n", - "cmnl = ConditionalMNL(parameters=params, optimizer=\"lbfgs\")" + "cmnl = ConditionalMNL(parameters=params, optimizer=\"lbfgs\", epochs=1000)" ] }, { @@ -678,7 +678,7 @@ } ], "source": [ - "history = cmnl.fit(dataset, n_epochs=1000)\n", + "history = cmnl.fit(dataset)\n", "print(cmnl.weights)" ] }, @@ -821,7 +821,7 @@ "metadata": {}, "outputs": [], "source": [ - "history = swiss_model.fit(swiss_dataset, n_epochs=10000)" + "history = swiss_model.fit(swiss_dataset, epochs=10000)" ] }, { diff --git a/notebooks/custom_model.ipynb b/notebooks/custom_model.ipynb index 2e929611..9440ef69 100644 --- a/notebooks/custom_model.ipynb +++ b/notebooks/custom_model.ipynb @@ -70,17 +70,17 @@ "transport_df.income = transport_df.income.astype(\"float32\")\n", "\n", "dataset = ChoiceDataset.from_single_df(df=transport_df,\n", - " items_features_columns=[\"oh_air\",\n", + " fixed_items_features_columns=[\"oh_air\",\n", " \"oh_bus\",\n", " \"oh_car\",\n", " \"oh_train\"],\n", - " sessions_features_columns=[\"income\"],\n", - " sessions_items_features_columns=[\"cost\",\n", + " contexts_features_columns=[\"income\"],\n", + " contexts_items_features_columns=[\"cost\",\n", " \"freq\",\n", " \"ovt\",\n", " \"ivt\"],\n", " items_id_column=\"alt\",\n", - " sessions_id_column=\"case\",\n", + " contexts_id_column=\"case\",\n", " choices_column=\"choice\",\n", " choice_mode=\"one_zero\")" ] @@ -93,7 +93,7 @@ "\n", "For our custom model to work, we need to specify:\n", "- Weights initialization in __init__()\n", - "- the utility function in compute_utility()" + "- the utility function in compute_batch_utility()" ] }, { @@ -179,7 +179,7 @@ " self.weights = [beta_inter, beta_freq_cost_ovt, beta_income, beta_ivt]\n", "\n", "\n", - " def compute_utility(self,\n", + " def compute_batch_utility(self,\n", " items_batch,\n", " sessions_batch,\n", " sessions_items_batch,\n", @@ -249,7 +249,7 @@ "outputs": [], "source": [ "model = CustomCanadaConditionalMNL(optimizer=\"lbfgs\")\n", - "history = model.fit(dataset, n_epochs=400)" + "history = model.fit(dataset, epochs=400)" ] }, { @@ -427,7 +427,7 @@ " # Easy with TensorFlow.Layer\n", " self.weights = self.dense_1.trainable_variables + self.dense_2.trainable_variables\n", " \n", - " def compute_utility(self,\n", + " def compute_batch_utility(self,\n", " items_batch,\n", " sessions_batch,\n", " sessions_items_batch,\n", From 68a4ebfbf31c4a641f3311f30bee95cd0d7e2203 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 2 Feb 2024 17:16:51 +0100 Subject: [PATCH 126/767] FIX: add local in requirements --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 3c9de3ac..07c7368e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +-e . numpy==1.24.3 pandas==1.5.3 tensorflow==2.13.0 From 42d5ed3016e3cdcc33ddfcf68a95f8223a84eb90 Mon Sep 17 00:00:00 2001 From: Vincent Auriau Date: Fri, 2 Feb 2024 17:28:44 +0100 Subject: [PATCH 127/767] stop deploy doc on PR --- .github/workflows/deploy_docs.yaml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/deploy_docs.yaml b/.github/workflows/deploy_docs.yaml index 22500072..66b4d8b3 100644 --- a/.github/workflows/deploy_docs.yaml +++ b/.github/workflows/deploy_docs.yaml @@ -4,9 +4,6 @@ on: push: branches: - main - pull_request: - branches: - - main jobs: deploy-docs: @@ -28,4 +25,4 @@ jobs: mkdocs build mkdocs gh-deploy --force - \ No newline at end of file + From 5b15444259e7f7312301c850511e6fe35e5aa6dd Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 2 Feb 2024 18:51:51 +0100 Subject: [PATCH 128/767] ADD: base for MixMNL --- choice_learn/models/base_model.py | 56 ++++++++++- choice_learn/models/conditional_mnl.py | 8 +- choice_learn/models/mix_mnl.py | 0 notebooks/mixture_mnl.ipynb | 126 +++++++++++++++++++++++++ 4 files changed, 183 insertions(+), 7 deletions(-) create mode 100644 choice_learn/models/mix_mnl.py create mode 100644 notebooks/mixture_mnl.ipynb diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index 4808324e..9ad1331c 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -524,7 +524,7 @@ def predict_probas(self, choice_dataset, batch_size=-1): return tf.concat(stacked_probabilities, axis=0) - def evaluate(self, choice_dataset, batch_size=-1): + def evaluate(self, choice_dataset, sample_weight=None, batch_size=-1): """Evaluates the model for each context and each product of a ChoiceDataset. Predicts the probabilities according to the model and computes the Negative-Log-Likelihood @@ -554,6 +554,7 @@ def evaluate(self, choice_dataset, batch_size=-1): contexts_items_features=contexts_items_features, contexts_items_availabilities=contexts_items_availabilities, choices=choices, + sample_weight=sample_weight, ) batch_losses.append(loss) if batch_size != -1: @@ -567,7 +568,7 @@ def evaluate(self, choice_dataset, batch_size=-1): batch_loss = tf.reduce_mean(batch_losses) return batch_loss - def _lbfgs_train_step(self, dataset): + def _lbfgs_train_step(self, dataset, sample_weight=None): """A factory to create a function required by tfp.optimizer.lbfgs_minimize. Parameters @@ -636,7 +637,7 @@ def f(params_1d): # update the parameters in the model assign_new_model_parameters(params_1d) # calculate the loss - loss_value = self.evaluate(dataset, batch_size=-1) + loss_value = self.evaluate(dataset, sample_weight=sample_weight, batch_size=-1) # calculate gradients and convert to 1D tf.Tensor grads = tape.gradient(loss_value, self.weights) @@ -659,7 +660,7 @@ def f(params_1d): f.history = [] return f - def _fit_with_lbfgs(self, dataset, epochs=None, tolerance=1e-8): + def _fit_with_lbfgs(self, dataset, epochs=None, sample_weight=None, tolerance=1e-8): """Fit function for L-BFGS optimizer. Replaces the .fit method when the optimizer is set to L-BFGS. @@ -684,7 +685,7 @@ def _fit_with_lbfgs(self, dataset, epochs=None, tolerance=1e-8): if epochs is None: epochs = self.epochs - func = self._lbfgs_train_step(dataset) + func = self._lbfgs_train_step(dataset, sample_weight=sample_weight) # convert initial model parameters to a 1D tf.Tensor init_params = tf.dynamic_stitch(func.idx, self.weights) @@ -826,3 +827,48 @@ def compute_batch_utility( if self.weights is None: raise ValueError("Model not fitted") return np.stack([np.log(self.weights.numpy())] * len(choices), axis=0) + + +class BaseMixtureModel(object): + def __init__( + self, + latent_classes, + model_class, + model_parameters, + fit_method, + epochs, + ): + self.latent_classes = latent_classes + self.model_parameters = model_parameters + self.model_class = model_class + self.fit_method = fit_method + + self.epochs = epochs + + def instantiate(self): + self.latent_logit = tf.Variable(tf.ones(self.latent_classes)) / self.latent_classes + self.models = [ + self.model_class(**self.model_parameters) for _ in range(self.latent_classes) + ] + + def _em_fit(self, dataset): + for model in self.models: + # model.instantiate() + model.fit(dataset) + for i in tqdm.trange(self.epochs): + predicted_probas = [model.predict_probas(dataset) for model in self.models] + predicted_probas = [ + latent + * tf.gather_nd( + params=proba, + indices=tf.stack([tf.range(0, len(dataset), 1), dataset.choices], axis=1), + ) + for latent, proba in zip(self.latent_logit, predicted_probas) + ] + + weights = predicted_probas / tf.reduce_sum(predicted_probas, axis=0, keepdims=True) + for q in range(self.latent_classes): + print(weights[q].shape) + self.models[q].fit(dataset, sample_weight=weights[q]) + + self.latent_probas = tf.reduce_mean(weights, axis=0) diff --git a/choice_learn/models/conditional_mnl.py b/choice_learn/models/conditional_mnl.py index 5a95b60c..170c8f84 100644 --- a/choice_learn/models/conditional_mnl.py +++ b/choice_learn/models/conditional_mnl.py @@ -1001,7 +1001,9 @@ def fit(self, choice_dataset, get_report=False, **kwargs): self.report = self.compute_report(choice_dataset) return fit - def _fit_with_lbfgs(self, choice_dataset, epochs=None, tolerance=1e-8, get_report=False): + def _fit_with_lbfgs( + self, choice_dataset, epochs=None, sample_weight=None, tolerance=1e-8, get_report=False + ): """Specific fit function to estimate the paramters with LBFGS. Parameters @@ -1034,7 +1036,9 @@ def _fit_with_lbfgs(self, choice_dataset, epochs=None, tolerance=1e-8, get_repor self.instantiated = True if epochs is None: epochs = self.epochs - fit = super()._fit_with_lbfgs(choice_dataset, epochs, tolerance) + fit = super()._fit_with_lbfgs( + dataset=choice_dataset, epochs=epochs, tolerance=tolerance, sample_weight=sample_weight + ) if get_report: self.report = self.compute_report(choice_dataset) return fit diff --git a/choice_learn/models/mix_mnl.py b/choice_learn/models/mix_mnl.py new file mode 100644 index 00000000..e69de29b diff --git a/notebooks/mixture_mnl.ipynb b/notebooks/mixture_mnl.ipynb new file mode 100644 index 00000000..93f22651 --- /dev/null +++ b/notebooks/mixture_mnl.ipynb @@ -0,0 +1,126 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "\n", + "os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"\"\n", + "\n", + "import sys\n", + "from pathlib import Path\n", + "\n", + "sys.path.append(\"../\")\n", + "\n", + "import numpy as np\n", + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from choice_learn.datasets import load_modecanada\n", + "\n", + "transport_df = load_modecanada(as_frame=True)\n", + "\n", + "# Following torch-choice guide:\n", + "transport_df = transport_df.loc[transport_df.noalt == 4]\n", + "\n", + "items = [\"air\", \"bus\", \"car\", \"train\"]\n", + "transport_df.income = transport_df.income.astype(\"float32\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Initialization of the ChoiceDataset\n", + "from choice_learn.data import ChoiceDataset\n", + "dataset = ChoiceDataset.from_single_df(df=transport_df,\n", + " contexts_features_columns=[\"income\"],\n", + " contexts_items_features_columns=[\"cost\", \"freq\", \"ovt\", \"ivt\"],\n", + " items_id_column=\"alt\",\n", + " contexts_id_column=\"case\",\n", + " choices_column=\"choice\",\n", + " choice_mode=\"one_zero\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from choice_learn.models import ConditionalMNL\n", + "from choice_learn.models.base_model import BaseMixtureModel" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hpp = {\n", + " \"parameters\": {\"income\": \"item\",\n", + " \"cost\": \"constant\",\n", + " \"freq\": \"constant\",\n", + " \"ovt\": \"constant\",\n", + " \"ivt\": \"item-full\",\n", + " \"intercept\": \"item\"},\n", + " \"optimizer\": \"lbfgs\",\n", + " \"epochs\": 10,\n", + "}\n", + "mixMNL = BaseMixtureModel(model_class=ConditionalMNL, \n", + " model_parameters=hpp,\n", + " latent_classes=4, epochs=10, fit_method=\"fit\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mixMNL.instantiate()\n", + "mixMNL._em_fit(dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "tf_env", + "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.11.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From ef4c42bd6465287e6279512e125f5f20b5f3aa41 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 6 Feb 2024 11:37:39 +0100 Subject: [PATCH 129/767] small changes on example --- notebooks/rumnet_example.ipynb | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/notebooks/rumnet_example.ipynb b/notebooks/rumnet_example.ipynb index ce18c800..597b5ecd 100644 --- a/notebooks/rumnet_example.ipynb +++ b/notebooks/rumnet_example.ipynb @@ -192,6 +192,9 @@ " \"logmin\": 1e-10,\n", " \"label_smoothing\": 0.02,\n", " \"callbacks\": [],\n", + " \"epochs\": 150,\n", + " \"batch_size\": 128,\n", + " \"tol\": 1e-5,\n", "}" ] }, @@ -217,8 +220,11 @@ " model = RUMnet(**model_args)\n", " model.instantiate()\n", "\n", - " losses = model.fit(train_dataset, n_epochs=5000, batch_size=128)\n", - " test_eval.append(model.evaluate(test_dataset))\n", + " losses = model.fit(train_dataset, val_dataset=test_dataset)\n", + " probas = model.predict_probas(test_dataset)\n", + " eval = tf.keras.losses.CategoricalCrossentropy(from_logits=False)(y_pred=model.predict_probas(test_dataset), y_true=tf.one_hot(test_dataset.choices, 3))\n", + " test_eval.append(eval)\n", + " print(test_eval)\n", "\n", " fit_losses.append(losses)" ] @@ -230,7 +236,8 @@ "outputs": [], "source": [ "for i in range(len(fit_losses)):\n", - " plt.plot(fit_losses[i][\"train_loss\"], label=f\"fold {i}\")\n", + " plt.plot(fit_losses[i][\"train_loss\"], label=f\"fold {i}\", c=[\"r\", \"g\", \"b\", \"cyan\", \"purple\"][i])\n", + " plt.plot(fit_losses[i][\"test_loss\"], c=[\"r\", \"g\", \"b\", \"cyan\", \"purple\"][i])\n", "plt.legend()" ] }, @@ -244,17 +251,8 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [] } ], From bb7a83c99e23f8059f4f84d3de385ac35be22389 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 6 Feb 2024 12:15:11 +0100 Subject: [PATCH 130/767] ADD: Pure NLL + Optimized Loss in model evaluation --- choice_learn/models/base_model.py | 21 ++++++++++++++------- choice_learn/models/rumnet.py | 18 +++++++++++++----- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index 9ad1331c..376b4c55 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -346,7 +346,7 @@ def fit( contexts_items_batch, availabilities_batch, choices_batch, - )[0] + )[0]["optimized_loss"] ) val_logs["val_loss"].append(test_losses[-1]) temps_logs = {k: tf.reduce_mean(v) for k, v in val_logs.items()} @@ -432,11 +432,18 @@ def batch_predict( # Compute loss from probabilities & actual choices # batch_loss = self.loss(probabilities, c_batch, sample_weight=sample_weight) - batch_loss = self.loss( - y_pred=probabilities, - y_true=tf.one_hot(choices, depth=probabilities.shape[1]), - sample_weight=sample_weight, - ) + batch_loss = { + "optimized_loss": self.loss( + y_pred=probabilities, + y_true=tf.one_hot(choices, depth=probabilities.shape[1]), + sample_weight=sample_weight, + ), + "NegativeLogLikelihood": tf.keras.losses.CategoricalCrossentropy()( + y_pred=probabilities, + y_true=tf.one_hot(choices, depth=probabilities.shape[1]), + sample_weight=sample_weight, + ), + } return batch_loss, probabilities def save_model(self, path): @@ -556,7 +563,7 @@ def evaluate(self, choice_dataset, sample_weight=None, batch_size=-1): choices=choices, sample_weight=sample_weight, ) - batch_losses.append(loss) + batch_losses.append(loss["NegativeLogLikelihood"]) if batch_size != -1: last_batch_size = contexts_items_availabilities.shape[0] coefficients = tf.concat( diff --git a/choice_learn/models/rumnet.py b/choice_learn/models/rumnet.py index 09f08fa9..2872bce7 100644 --- a/choice_learn/models/rumnet.py +++ b/choice_learn/models/rumnet.py @@ -1133,9 +1133,17 @@ def batch_predict( probabilities = tf.divide( probabilities, tf.reduce_sum(probabilities, axis=1, keepdims=True) + 1e-5 ) - batch_loss = self.loss( - y_pred=probabilities, - y_true=tf.one_hot(choices, depth=probabilities.shape[1]), - sample_weight=sample_weight, - ) + + batch_loss = { + "optimized_loss": self.loss( + y_pred=probabilities, + y_true=tf.one_hot(choices, depth=probabilities.shape[1]), + sample_weight=sample_weight, + ), + "NegativeLogLikelihood": tf.keras.losses.CategoricalCrossentropy()( + y_pred=probabilities, + y_true=tf.one_hot(choices, depth=probabilities.shape[1]), + sample_weight=sample_weight, + ), + } return batch_loss, probabilities From 4fc9fbebb8b13fdb0d2167b1d2a8d6bc3ef84f14 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 6 Feb 2024 12:15:38 +0100 Subject: [PATCH 131/767] ADD: small modifs --- notebooks/rumnet_example.ipynb | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/notebooks/rumnet_example.ipynb b/notebooks/rumnet_example.ipynb index 597b5ecd..2bad7f12 100644 --- a/notebooks/rumnet_example.ipynb +++ b/notebooks/rumnet_example.ipynb @@ -28,6 +28,7 @@ "import matplotlib.pyplot as plt\n", "import numpy as np\n", "import pandas as pd\n", + "import tensorflow as tf\n", "\n", "from choice_learn.data import ChoiceDataset\n", "from choice_learn.models import RUMnet\n", @@ -192,7 +193,7 @@ " \"logmin\": 1e-10,\n", " \"label_smoothing\": 0.02,\n", " \"callbacks\": [],\n", - " \"epochs\": 150,\n", + " \"epochs\": 15,\n", " \"batch_size\": 128,\n", " \"tol\": 1e-5,\n", "}" @@ -235,12 +236,23 @@ "metadata": {}, "outputs": [], "source": [ + "cmap = plt.cm.coolwarm\n", + "colors = [cmap(j / 4) for j in range(5)]\n", "for i in range(len(fit_losses)):\n", - " plt.plot(fit_losses[i][\"train_loss\"], label=f\"fold {i}\", c=[\"r\", \"g\", \"b\", \"cyan\", \"purple\"][i])\n", - " plt.plot(fit_losses[i][\"test_loss\"], c=[\"r\", \"g\", \"b\", \"cyan\", \"purple\"][i])\n", + " plt.plot(fit_losses[i][\"train_loss\"], c=colors[i], linestyle=\"--\")\n", + " plt.plot(fit_losses[i][\"test_loss\"], label=f\"fold {i}\", c=colors[i])\n", "plt.legend()" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.evaluate(test_dataset)" + ] + }, { "cell_type": "code", "execution_count": null, From bc254737bbd2552a339751f1630ad4e1e8c0e025 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 6 Feb 2024 12:22:29 +0100 Subject: [PATCH 132/767] ENH: from_single_df -> from_single_long_df --- choice_learn/data/choice_dataset.py | 6 +++--- choice_learn/datasets/base.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index 780d1b93..56448da1 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -724,7 +724,7 @@ def from_single_wide_df( choices_column="choice", choice_mode="items_id", ): - """Builds numpy arrays for ChoiceDataset from a single dataframe. + """Builds numpy arrays for ChoiceDataset from a single dataframe in wide format. Parameters ---------- @@ -820,7 +820,7 @@ def from_single_wide_df( ) @classmethod - def from_single_df( + def from_single_long_df( cls, df, fixed_items_features_columns=None, @@ -831,7 +831,7 @@ def from_single_df( choices_column="choice", choice_mode="items_id", ): - """Builds numpy arrays for ChoiceDataset from a single dataframe. + """Builds numpy arrays for ChoiceDataset from a single dataframe in long format. Parameters ---------- diff --git a/choice_learn/datasets/base.py b/choice_learn/datasets/base.py index 6e649634..92b65eab 100644 --- a/choice_learn/datasets/base.py +++ b/choice_learn/datasets/base.py @@ -357,7 +357,7 @@ def load_modecanada( if len(items_features) == 0: items_features = None - return ChoiceDataset.from_single_df( + return ChoiceDataset.from_single_long_df( df=canada_df, fixed_items_features_columns=items_features, contexts_features_columns=session_features, From 03c6255d6a0ecd30380a5afec231861f9ab835b6 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 6 Feb 2024 13:38:47 +0100 Subject: [PATCH 133/767] update notebook with 'long' keyword --- notebooks/choice_learn_introduction_clogit.ipynb | 16 ++++++++-------- notebooks/choice_learn_introduction_data.ipynb | 2 +- notebooks/custom_model.ipynb | 2 +- notebooks/dataset_creation.ipynb | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/notebooks/choice_learn_introduction_clogit.ipynb b/notebooks/choice_learn_introduction_clogit.ipynb index 0dcc47a5..bd20a3e0 100644 --- a/notebooks/choice_learn_introduction_clogit.ipynb +++ b/notebooks/choice_learn_introduction_clogit.ipynb @@ -65,7 +65,7 @@ "source": [ "# Initialization of the ChoiceDataset\n", "from choice_learn.data import ChoiceDataset\n", - "dataset = ChoiceDataset.from_single_df(df=transport_df,\n", + "dataset = ChoiceDataset.from_single_long_df(df=transport_df,\n", " contexts_features_columns=[\"income\"],\n", " contexts_items_features_columns=[\"cost\", \"freq\", \"ovt\", \"ivt\"],\n", " items_id_column=\"alt\",\n", @@ -469,7 +469,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 1/1 [00:02<00:00, 2.41s/it]" + "100%|██████████| 1/1 [00:01<00:00, 2.00s/it]" ] }, { @@ -582,14 +582,14 @@ { "data": { "text/plain": [ - "[,\n", - " ,\n", - " ,\n", - " ,\n", + "[,\n", + " ,\n", + " ,\n", + " ,\n", " ,\n", - " ]" + " ]" ] }, "execution_count": null, diff --git a/notebooks/choice_learn_introduction_data.ipynb b/notebooks/choice_learn_introduction_data.ipynb index 11d92b1d..05c0f692 100644 --- a/notebooks/choice_learn_introduction_data.ipynb +++ b/notebooks/choice_learn_introduction_data.ipynb @@ -279,7 +279,7 @@ "metadata": {}, "outputs": [], "source": [ - "dataset = ChoiceDataset.from_single_df(df=transport_df,\n", + "dataset = ChoiceDataset.from_single_long_df(df=transport_df,\n", " fixed_items_features_columns=[\"is_public\"],\n", " contexts_features_columns=[\"income\", \"urban\", \"dist\"],\n", " contexts_items_features_columns=[\"cost\", \"freq\", \"ovt\", \"ivt\"],\n", diff --git a/notebooks/custom_model.ipynb b/notebooks/custom_model.ipynb index 9440ef69..3cfda8ec 100644 --- a/notebooks/custom_model.ipynb +++ b/notebooks/custom_model.ipynb @@ -69,7 +69,7 @@ "\n", "transport_df.income = transport_df.income.astype(\"float32\")\n", "\n", - "dataset = ChoiceDataset.from_single_df(df=transport_df,\n", + "dataset = ChoiceDataset.from_single_long_df(df=transport_df,\n", " fixed_items_features_columns=[\"oh_air\",\n", " \"oh_bus\",\n", " \"oh_car\",\n", diff --git a/notebooks/dataset_creation.ipynb b/notebooks/dataset_creation.ipynb index 75209981..ea94a78f 100644 --- a/notebooks/dataset_creation.ipynb +++ b/notebooks/dataset_creation.ipynb @@ -238,7 +238,7 @@ } ], "source": [ - "dataset = ChoiceDataset.from_single_df(df=canada_df,\n", + "dataset = ChoiceDataset.from_single_long_df(df=canada_df,\n", " fixed_items_features_columns=[\"is_public\"],\n", " contexts_features_columns=[\"dist\", \"income\", \"urban\"],\n", " contexts_items_features_columns=[\"freq\", \"cost\", \"ivt\", \"ovt\"],\n", @@ -452,7 +452,7 @@ } ], "source": [ - "dataset = ChoiceDataset.from_single_df(df=canada_df,\n", + "dataset = ChoiceDataset.from_single_long_df(df=canada_df,\n", " fixed_items_features_columns=[\"is_public\"],\n", " contexts_features_columns=[\"dist\", \"income\", \"urban\"],\n", " contexts_items_features_columns=[\"freq\", \"cost\", \"ivt\", \"ovt\"],\n", From 49b4eb0ddf241fc1db18c614d910403128be0543 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 6 Feb 2024 14:11:23 +0100 Subject: [PATCH 134/767] small update --- .../choice_learn_introduction_clogit.ipynb | 140 +++++++++--------- 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/notebooks/choice_learn_introduction_clogit.ipynb b/notebooks/choice_learn_introduction_clogit.ipynb index 0dcc47a5..e61c1197 100644 --- a/notebooks/choice_learn_introduction_clogit.ipynb +++ b/notebooks/choice_learn_introduction_clogit.ipynb @@ -211,8 +211,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "The average neg-loglikelihood is: 0.67447394\n", - "The total neg-loglikelihood is: 1874.3630829453468\n" + "The average neg-loglikelihood is: 0.6744666\n", + "The total neg-loglikelihood is: 1874.3427090644836\n" ] } ], @@ -267,25 +267,25 @@ " \n", " 0\n", " beta_inter:0_0\n", - " 0.698367\n", - " 1.280208\n", - " 0.545511\n", - " 5.854024e-01\n", + " 0.698380\n", + " 1.280237\n", + " 0.545508\n", + " 5.854039e-01\n", " \n", " \n", " 1\n", " beta_inter:0_1\n", - " 1.844104\n", - " 0.708454\n", - " 2.602998\n", - " 9.241223e-03\n", + " 1.844129\n", + " 0.708489\n", + " 2.602904\n", + " 9.243727e-03\n", " \n", " \n", " 2\n", " beta_inter:0_2\n", - " 3.274187\n", - " 0.624366\n", - " 5.244018\n", + " 3.274206\n", + " 0.624402\n", + " 5.243744\n", " 1.192093e-07\n", " \n", " \n", @@ -293,7 +293,7 @@ " beta_income:0_0\n", " -0.089087\n", " 0.018347\n", - " -4.855643\n", + " -4.855632\n", " 1.192093e-06\n", " \n", " \n", @@ -301,7 +301,7 @@ " beta_income:0_1\n", " -0.027993\n", " 0.003873\n", - " -7.228673\n", + " -7.228651\n", " 0.000000e+00\n", " \n", " \n", @@ -309,15 +309,15 @@ " beta_income:0_2\n", " -0.038147\n", " 0.004083\n", - " -9.342690\n", + " -9.342653\n", " 0.000000e+00\n", " \n", " \n", " 6\n", " beta_ivt:0_0\n", - " 0.059509\n", + " 0.059510\n", " 0.010073\n", - " 5.907992\n", + " 5.908023\n", " 0.000000e+00\n", " \n", " \n", @@ -325,39 +325,39 @@ " beta_ivt:0_1\n", " -0.006784\n", " 0.004433\n", - " -1.530137\n", - " 1.259828e-01\n", + " -1.530130\n", + " 1.259845e-01\n", " \n", " \n", " 8\n", " beta_ivt:0_2\n", " -0.006460\n", " 0.001898\n", - " -3.403037\n", - " 6.663799e-04\n", + " -3.402944\n", + " 6.666183e-04\n", " \n", " \n", " 9\n", " beta_ivt:0_3\n", " -0.001450\n", " 0.001187\n", - " -1.221401\n", - " 2.219341e-01\n", + " -1.221381\n", + " 2.219417e-01\n", " \n", " \n", " 10\n", " beta_cost:0_0\n", " -0.033339\n", " 0.007095\n", - " -4.698925\n", + " -4.698679\n", " 2.622604e-06\n", " \n", " \n", " 11\n", " beta_freq:0_0\n", - " 0.092529\n", + " 0.092530\n", " 0.005098\n", - " 18.151833\n", + " 18.151777\n", " 0.000000e+00\n", " \n", " \n", @@ -365,7 +365,7 @@ " beta_ovt:0_0\n", " -0.043004\n", " 0.003225\n", - " -13.335643\n", + " -13.335551\n", " 0.000000e+00\n", " \n", " \n", @@ -374,19 +374,19 @@ ], "text/plain": [ " Coefficient Name Coefficient Estimation Std. Err z_value P(.>z)\n", - "0 beta_inter:0_0 0.698367 1.280208 0.545511 5.854024e-01\n", - "1 beta_inter:0_1 1.844104 0.708454 2.602998 9.241223e-03\n", - "2 beta_inter:0_2 3.274187 0.624366 5.244018 1.192093e-07\n", - "3 beta_income:0_0 -0.089087 0.018347 -4.855643 1.192093e-06\n", - "4 beta_income:0_1 -0.027993 0.003873 -7.228673 0.000000e+00\n", - "5 beta_income:0_2 -0.038147 0.004083 -9.342690 0.000000e+00\n", - "6 beta_ivt:0_0 0.059509 0.010073 5.907992 0.000000e+00\n", - "7 beta_ivt:0_1 -0.006784 0.004433 -1.530137 1.259828e-01\n", - "8 beta_ivt:0_2 -0.006460 0.001898 -3.403037 6.663799e-04\n", - "9 beta_ivt:0_3 -0.001450 0.001187 -1.221401 2.219341e-01\n", - "10 beta_cost:0_0 -0.033339 0.007095 -4.698925 2.622604e-06\n", - "11 beta_freq:0_0 0.092529 0.005098 18.151833 0.000000e+00\n", - "12 beta_ovt:0_0 -0.043004 0.003225 -13.335643 0.000000e+00" + "0 beta_inter:0_0 0.698380 1.280237 0.545508 5.854039e-01\n", + "1 beta_inter:0_1 1.844129 0.708489 2.602904 9.243727e-03\n", + "2 beta_inter:0_2 3.274206 0.624402 5.243744 1.192093e-07\n", + "3 beta_income:0_0 -0.089087 0.018347 -4.855632 1.192093e-06\n", + "4 beta_income:0_1 -0.027993 0.003873 -7.228651 0.000000e+00\n", + "5 beta_income:0_2 -0.038147 0.004083 -9.342653 0.000000e+00\n", + "6 beta_ivt:0_0 0.059510 0.010073 5.908023 0.000000e+00\n", + "7 beta_ivt:0_1 -0.006784 0.004433 -1.530130 1.259845e-01\n", + "8 beta_ivt:0_2 -0.006460 0.001898 -3.402944 6.666183e-04\n", + "9 beta_ivt:0_3 -0.001450 0.001187 -1.221381 2.219417e-01\n", + "10 beta_cost:0_0 -0.033339 0.007095 -4.698679 2.622604e-06\n", + "11 beta_freq:0_0 0.092530 0.005098 18.151777 0.000000e+00\n", + "12 beta_ovt:0_0 -0.043004 0.003225 -13.335551 0.000000e+00" ] }, "execution_count": null, @@ -469,14 +469,14 @@ "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 1/1 [00:02<00:00, 2.41s/it]" + "100%|██████████| 1/1 [00:01<00:00, 1.73s/it]" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "'Ground Truth' Negative LogLikelihood: tf.Tensor(1874.3633, shape=(), dtype=float32)\n" + "'Ground Truth' Negative LogLikelihood: tf.Tensor(1874.3427, shape=(), dtype=float32)\n" ] }, { @@ -526,11 +526,11 @@ "output_type": "stream", "text": [ "Purchase probability of each item for the first 5 sessions: tf.Tensor(\n", - "[[0.1906135 0.00353266 0.4053667 0.4004831 ]\n", - " [0.34869286 0.00069682 0.36830992 0.28229675]\n", - " [0.14418365 0.00651285 0.40567666 0.44362238]\n", - " [0.34869286 0.00069682 0.36830992 0.28229675]\n", - " [0.34869286 0.00069682 0.36830992 0.28229675]], shape=(5, 4), dtype=float32)\n" + "[[0.19061361 0.00353295 0.4053689 0.4004805 ]\n", + " [0.3486952 0.00069691 0.36830923 0.28229502]\n", + " [0.14418328 0.00651326 0.40567988 0.44361907]\n", + " [0.3486952 0.00069691 0.36830923 0.28229502]\n", + " [0.3486952 0.00069691 0.36830923 0.28229502]], shape=(5, 4), dtype=float32)\n" ] } ], @@ -582,14 +582,14 @@ { "data": { "text/plain": [ - "[,\n", - " ,\n", - " ,\n", - " ,\n", + "[,\n", + " ,\n", + " ,\n", + " ,\n", " ,\n", - " ]" + " ]" ] }, "execution_count": null, @@ -611,7 +611,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": null, @@ -669,11 +669,11 @@ "text": [ "L-BFGS Opimization finished:\n", "---------------------------------------------------------------\n", - "Number of iterations: 170\n", + "Number of iterations: 190\n", "Algorithm converged before reaching max iterations: True\n", - "[, , , , , ]\n" + "[, , , , , ]\n" ] } ], @@ -834,16 +834,16 @@ { "data": { "text/plain": [ - "[,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " 1:0' shape=(1, 1) dtype=float32, numpy=array([[1.413982]], dtype=float32)>]" + "[,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " 1:0' shape=(1, 1) dtype=float32, numpy=array([[1.4228866]], dtype=float32)>]" ] }, "execution_count": null, @@ -865,7 +865,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": null, From e54af65e1c0522a2ed0d1f4bb1c76c3de2bbec65 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 6 Feb 2024 14:12:55 +0100 Subject: [PATCH 135/767] ADD: changed tests according to new signature --- tests/unit_tests/data/test_choice_dataset.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests/data/test_choice_dataset.py b/tests/unit_tests/data/test_choice_dataset.py index b288cde3..ed2b495f 100644 --- a/tests/unit_tests/data/test_choice_dataset.py +++ b/tests/unit_tests/data/test_choice_dataset.py @@ -267,7 +267,7 @@ def test_from_df(): "choice": [0, 0, 0, 2, 2, 2, 1, 1], } ) - cd_test = ChoiceDataset.from_single_df( + cd_test = ChoiceDataset.from_single_long_df( features_df, fixed_items_features_columns=["items_feat_1", "items_feat_2"], contexts_features_columns=["session_feat_1", "session_feat_2"], @@ -307,7 +307,7 @@ def test_from_df(): "choice": [1, 0, 0, 0, 0, 1, 1, 0], } ) - cd_test = ChoiceDataset.from_single_df( + cd_test = ChoiceDataset.from_single_long_df( features_df, fixed_items_features_columns=["items_feat_1", "items_feat_2"], contexts_features_columns=["session_feat_1", "session_feat_2"], From 310d5dd3609e041e4d81ba598edebcaf71b91367 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 8 Feb 2024 09:59:58 +0100 Subject: [PATCH 136/767] FIX: some typos --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9481432a..dde53c8e 100644 --- a/README.md +++ b/README.md @@ -91,10 +91,12 @@ Choice-Learn requires the following: - Python (>=3.8) - NumPy (>=1.24) - pandas (>=1.5) + For modelling you need: - TensorFlow (>=2.13) -Finally, an optional requirement used for report and LBFG-s use is: -- tensorflow_probability (>=0.20.1) + +Finally, an optional requirement used for report and LBFG-S optimization is: +- TensorFlow Probability (>=0.20.1) ## Usage ```python From dbd4b8f85539dfbd636723fbdadc221bf79d30a6 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 8 Feb 2024 14:21:38 +0100 Subject: [PATCH 137/767] ENH: change some explanation about CD from wide DF --- notebooks/choice_learn_introduction_data.ipynb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/notebooks/choice_learn_introduction_data.ipynb b/notebooks/choice_learn_introduction_data.ipynb index 05c0f692..cfb6ca8f 100644 --- a/notebooks/choice_learn_introduction_data.ipynb +++ b/notebooks/choice_learn_introduction_data.ipynb @@ -320,9 +320,11 @@ "source": [ "The ChoiceDataset is ready !\n", "\n", + "If your DataFrame is in the wide format, you can use the equivalent method *from_single_wide_df*. An example can be found [here](https://github.com/artefactory/choice-learn-private/blob/main/notebooks/dataset_creation.ipynb) on the SwissMetro dataset: \n", + "\n", "You now have three possibilities to continue discovering the choice-learn package:\n", "- You can directly go [here]() to the modelling tutorial if you want to understand how a first simple ConditionMNl would be implementd.\n", - "- You can go [here]() if your dataset is organized differently to see all the different ways to instantiate a ChoiceDataset. In particular it helps if you DataFrame is in the wide format or if it is splitted into several DataFrames.\n", + "- You can go [here]() if your dataset is organized differently to see all the different ways to instantiate a ChoiceDataset. In particular it helps if you data is splitted into several DataFrames or if you have another format of data.\n", "- Or you can continue this current tutorial to better understand the ChoiceDataset machinery and everything there is to know about it.\n", "\n", "Whatever your choice, you can also check [here](#ready-to-use-datasets) the list of open source datasets available directly with the package." From 55a6b7d43c5465b6e70a9e1755b865f5fe1df43d Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Wed, 14 Feb 2024 16:55:14 +0100 Subject: [PATCH 138/767] ADD: AssortmentOptimizer skeleton --- choice_learn/toolbox/assortment_optimizer.py | 61 ++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 choice_learn/toolbox/assortment_optimizer.py diff --git a/choice_learn/toolbox/assortment_optimizer.py b/choice_learn/toolbox/assortment_optimizer.py new file mode 100644 index 00000000..74e037e2 --- /dev/null +++ b/choice_learn/toolbox/assortment_optimizer.py @@ -0,0 +1,61 @@ +"""Tool function for assortment optimization.""" + +import gurobipy as gp + + +class AssortmentOptimizer(object): + """Base class for assortment optimization.""" + + def __init__(self, utilities, assortment_size): + """Initializes the AssortmentOptimizer object. + + Parameters + ---------- + utilities : list-like + List of utilities for each item. + assortment_size : int + maximum size of the requested assortment. + """ + self.utilities = utilities + self.assortment_size = assortment_size + + self.n_items = len(utilities) + + self.solver = self.base_instantiate() + + def base_instantiate(self): + """Base instantiation of the solver. + + Returns: + -------- + gurobipy.Model + solver with basic variables and constraints. + """ + solver = gp.Model("ClusterUTA") + self.binary_z = { + i: solver.addVar(vtype=gp.GRB.BINARY, name=f"z_{i}") for i in range(self.n_items) + } + solver.addConstr( + gp.quicksum(self.binary_z[i] for i in range(self.n_items)) == self.assortment_size + ) + return solver + + def set_objective_function(self): + """Function to define the objective function to maximize with the assortment.""" + pass + + def add_constraint(self): + """Function to add constraints.""" + pass + + def solve(self): + """Function to solve the optimization problem.""" + self.solver.update() + + # -- Résolution -- + self.solver.optimize() + self.status = self.solver.Status + assortment = [] + for i in range(self.n_items): + assortment.append(self.binary_z[i].x) + return assortment From 60dab0d6ef9c8135c707950063635b2b8ce0827d Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 15 Feb 2024 11:57:23 +0100 Subject: [PATCH 139/767] ADD: AssortOptimizer baseclass --- choice_learn/toolbox/assortment_optimizer.py | 71 +++++++++++++++----- 1 file changed, 54 insertions(+), 17 deletions(-) diff --git a/choice_learn/toolbox/assortment_optimizer.py b/choice_learn/toolbox/assortment_optimizer.py index 74e037e2..454eab38 100644 --- a/choice_learn/toolbox/assortment_optimizer.py +++ b/choice_learn/toolbox/assortment_optimizer.py @@ -1,12 +1,14 @@ """Tool function for assortment optimization.""" - import gurobipy as gp +import numpy as np + +"""TODO: clarify outside good integration""" class AssortmentOptimizer(object): """Base class for assortment optimization.""" - def __init__(self, utilities, assortment_size): + def __init__(self, utilities, itemwise_values, assortment_size): """Initializes the AssortmentOptimizer object. Parameters @@ -16,7 +18,13 @@ def __init__(self, utilities, assortment_size): assortment_size : int maximum size of the requested assortment. """ + if len(utilities) != len(itemwise_values): + raise ValueError( + f"You should provide as many utilities as itemwise values.\ + Found {len(utilities)} and {len(itemwise_values)} instead." + ) self.utilities = utilities + self.itemwise_values = itemwise_values self.assortment_size = assortment_size self.n_items = len(utilities) @@ -31,31 +39,60 @@ def base_instantiate(self): gurobipy.Model solver with basic variables and constraints. """ - solver = gp.Model("ClusterUTA") - self.binary_z = { - i: solver.addVar(vtype=gp.GRB.BINARY, name=f"z_{i}") for i in range(self.n_items) - } - solver.addConstr( - gp.quicksum(self.binary_z[i] for i in range(self.n_items)) == self.assortment_size - ) + # Create a new model + solver = gp.Model("Assortment_IP") + solver.ModelSense = -1 + solver.setParam("OutputFlag", False) + + # Create variables + y = {} + + for j in range(self.n_items + 1): + y[j] = solver.addVar( + vtype=gp.GRB.CONTINUOUS, obj=self.itemwise_values[j], name="y_%s" % j + ) + self.y = y + # Integrate new variables + solver.update() + + # Add constraints + for j in range(1, self.n_items + 1): + solver.addConstr(y[j] * self.utilities[0] <= y[0] * self.utilities[j]) + + charnes_cooper = gp.quicksum(y[j] for j in range(self.n_items + 1)) + solver.addConstr(charnes_cooper == 1) + assort_size = gp.quicksum(y[j] for j in range(1, self.n_items + 1)) + solver.addConstr(assort_size == self.assortment_size * y[0]) + + # Integrate constraints + solver.update() return solver - def set_objective_function(self): - """Function to define the objective function to maximize with the assortment.""" - pass + def set_objective_function(self, itemwise_values): + """Function to define the objective function to maximize with the assortment. + + Parameters: + ----------- + itemwise_values : list-like + List of values for each item - total value to be optimized. + """ + raise NotImplementedError def add_constraint(self): """Function to add constraints.""" - pass + raise NotImplementedError def solve(self): """Function to solve the optimization problem.""" self.solver.update() - # -- Résolution -- + # -- Optimize -- self.solver.optimize() self.status = self.solver.Status - assortment = [] - for i in range(self.n_items): - assortment.append(self.binary_z[i].x) + + assortment = np.zeros(self.n_items + 1) + for i in range(self.n_items + 1): + if self.y[i].x > 0: + assortment[i] = 1 + return assortment From 412fba3bb1f62797d36abacda80cdd2a86e25fbd Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 15 Feb 2024 12:36:33 +0100 Subject: [PATCH 140/767] ENH: some doc --- choice_learn/toolbox/assortment_optimizer.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/choice_learn/toolbox/assortment_optimizer.py b/choice_learn/toolbox/assortment_optimizer.py index 454eab38..e53a64d2 100644 --- a/choice_learn/toolbox/assortment_optimizer.py +++ b/choice_learn/toolbox/assortment_optimizer.py @@ -2,7 +2,9 @@ import gurobipy as gp import numpy as np -"""TODO: clarify outside good integration""" +"""TODO: clarify outside good integration +TODO 2: ADD easy integration of additionnal constraints +""" class AssortmentOptimizer(object): @@ -13,8 +15,10 @@ def __init__(self, utilities, itemwise_values, assortment_size): Parameters ---------- - utilities : list-like + utilities : Iterable List of utilities for each item. + itemwise_values: Iterable + List of to-be-optimized values for each item, e.g. prices. assortment_size : int maximum size of the requested assortment. """ @@ -83,7 +87,13 @@ def add_constraint(self): raise NotImplementedError def solve(self): - """Function to solve the optimization problem.""" + """Function to solve the optimization problem. + + Returns: + -------- + np.ndarray: + Array of 0s and 1s, indicating the presence of each item in the optimal assortment. + """ self.solver.update() # -- Optimize -- From e77dc3878f7106143f60f4cab56943b8270a1b9d Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 15 Feb 2024 12:39:19 +0100 Subject: [PATCH 141/767] ENH: baseline models organization --- choice_learn/models/base_model.py | 141 ++++--------------------- choice_learn/models/baseline_models.py | 124 ++++++++++++++++++++++ 2 files changed, 146 insertions(+), 119 deletions(-) create mode 100644 choice_learn/models/baseline_models.py diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index 376b4c55..abf17cef 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -717,126 +717,9 @@ def _fit_with_lbfgs(self, dataset, epochs=None, sample_weight=None, tolerance=1e return func.history -class RandomChoiceModel(ChoiceModel): - """Dumb model that randomly attributes utilities to products.""" - - def __init__(self, **kwargs): - """Initialization of the model.""" - super().__init__(**kwargs) - - def compute_batch_utility( - self, - fixed_items_features, - contexts_features, - contexts_items_features, - contexts_items_availabilities, - choices, - ): - """Computes the random utility for each product of each context. - - Parameters - ---------- - fixed_items_features : tuple of np.ndarray - Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products - constant/fixed features. - Shape must be (n_items, n_items_features) - contexts_features : tuple of np.ndarray (contexts_features) - a batch of contexts features - Shape must be (n_contexts, n_contexts_features) - contexts_items_features : tuple of np.ndarray (contexts_items_features) - a batch of contexts items features - Shape must be (n_contexts, n_contexts_items_features) - contexts_items_availabilities : np.ndarray - A batch of contexts items availabilities - Shape must be (n_contexts, n_items) - choices_batch : np.ndarray - Choices - Shape must be (n_contexts, ) - - Returns: - -------- - tf.Tensor - (n_contexts, n_items) matrix of random utilities - """ - # In order to avoid unused arguments warnings - _ = fixed_items_features, contexts_features, contexts_items_availabilities, choices - return np.squeeze( - np.random.uniform(shape=(contexts_items_features.shape), minval=0, maxval=1) - ) - - def fit(**kwargs): - """Make sure that nothing happens during .fit.""" - _ = kwargs - return {} - - -class DistribMimickingModel(ChoiceModel): - """Dumb class model that mimicks the probabilities. - - It stores the encountered in the train datasets and always returns them - """ - - def __init__(self, **kwargs): - """Initialization of the model.""" - super().__init__(**kwargs) - self.weights = [] - - def fit(self, choice_dataset, **kwargs): - """Computes the choice frequency of each product and defines it as choice probabilities.""" - _ = kwargs - choices = choice_dataset.choices - for i in range(choice_dataset.get_num_items()): - self.weights.append(tf.reduce_sum(tf.cast(choices == i, tf.float32))) - self.weights = tf.stack(self.weights) / len(choices) - - def compute_batch_utility( - self, - fixed_items_features, - contexts_features, - contexts_items_features, - contexts_items_availabilities, - choices, - ): - """Returns utility that is fixed. U = log(P). - - Parameters - ---------- - fixed_items_features : tuple of np.ndarray - Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products - constant/fixed features. - Shape must be (n_items, n_items_features) - contexts_features : tuple of np.ndarray (contexts_features) - a batch of contexts features - Shape must be (n_contexts, n_contexts_features) - contexts_items_features : tuple of np.ndarray (contexts_items_features) - a batch of contexts items features - Shape must be (n_contexts, n_contexts_items_features) - contexts_items_availabilities : np.ndarray - A batch of contexts items availabilities - Shape must be (n_contexts, n_items) - choices_batch : np.ndarray - Choices - Shape must be (n_contexts, ) - - Returns: - -------- - np.ndarray (n_contexts, n_items) - Utilities - - Raises: - ------- - ValueError - If the model has not been fitted cannot evaluate the utility - """ - # In order to avoid unused arguments warnings - _ = fixed_items_features, contexts_features, contexts_items_availabilities - _ = contexts_items_features - if self.weights is None: - raise ValueError("Model not fitted") - return np.stack([np.log(self.weights.numpy())] * len(choices), axis=0) - - class BaseMixtureModel(object): + """Base Class to work with Mixtures of models.""" + def __init__( self, latent_classes, @@ -845,6 +728,21 @@ def __init__( fit_method, epochs, ): + """Instantiation of the model mixture. + + Parameters + ---------- + latent_classes : int + Number of latent classes + model_class : BaseModel + class of models to get a mixture of + model_parameters : dict + hyper-parameters of the models + fit_method : str + Method to estimate the parameters: "EM", "LBFGS", "SGD". + epochs : int + Number of epochs to train the model. + """ self.latent_classes = latent_classes self.model_parameters = model_parameters self.model_class = model_class @@ -853,12 +751,17 @@ def __init__( self.epochs = epochs def instantiate(self): + """Instantiation.""" self.latent_logit = tf.Variable(tf.ones(self.latent_classes)) / self.latent_classes self.models = [ self.model_class(**self.model_parameters) for _ in range(self.latent_classes) ] + if self.fit_method == "EM": + self.fit = self._em_fit + def _em_fit(self, dataset): + """Fit with Expectation-Maximization Algorithm.""" for model in self.models: # model.instantiate() model.fit(dataset) diff --git a/choice_learn/models/baseline_models.py b/choice_learn/models/baseline_models.py new file mode 100644 index 00000000..4a93ebbf --- /dev/null +++ b/choice_learn/models/baseline_models.py @@ -0,0 +1,124 @@ +"""Models to be used as baselines for choice modeling. Nothing smart here.""" +import numpy as np +import tensorflow as tf + +from .base_model import ChoiceModel + + +class RandomChoiceModel(ChoiceModel): + """Dumb model that randomly attributes utilities to products.""" + + def __init__(self, **kwargs): + """Initialization of the model.""" + super().__init__(**kwargs) + + def compute_batch_utility( + self, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, + ): + """Computes the random utility for each product of each context. + + Parameters + ---------- + fixed_items_features : tuple of np.ndarray + Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products + constant/fixed features. + Shape must be (n_items, n_items_features) + contexts_features : tuple of np.ndarray (contexts_features) + a batch of contexts features + Shape must be (n_contexts, n_contexts_features) + contexts_items_features : tuple of np.ndarray (contexts_items_features) + a batch of contexts items features + Shape must be (n_contexts, n_contexts_items_features) + contexts_items_availabilities : np.ndarray + A batch of contexts items availabilities + Shape must be (n_contexts, n_items) + choices_batch : np.ndarray + Choices + Shape must be (n_contexts, ) + + Returns: + -------- + tf.Tensor + (n_contexts, n_items) matrix of random utilities + """ + # In order to avoid unused arguments warnings + _ = fixed_items_features, contexts_features, contexts_items_availabilities, choices + return np.squeeze( + np.random.uniform(shape=(contexts_items_features.shape), minval=0, maxval=1) + ) + + def fit(**kwargs): + """Make sure that nothing happens during .fit.""" + _ = kwargs + return {} + + +class DistribMimickingModel(ChoiceModel): + """Dumb class model that mimicks the probabilities. + + It stores the encountered in the train datasets and always returns them + """ + + def __init__(self, **kwargs): + """Initialization of the model.""" + super().__init__(**kwargs) + self.weights = [] + + def fit(self, choice_dataset, **kwargs): + """Computes the choice frequency of each product and defines it as choice probabilities.""" + _ = kwargs + choices = choice_dataset.choices + for i in range(choice_dataset.get_num_items()): + self.weights.append(tf.reduce_sum(tf.cast(choices == i, tf.float32))) + self.weights = tf.stack(self.weights) / len(choices) + + def compute_batch_utility( + self, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, + ): + """Returns utility that is fixed. U = log(P). + + Parameters + ---------- + fixed_items_features : tuple of np.ndarray + Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products + constant/fixed features. + Shape must be (n_items, n_items_features) + contexts_features : tuple of np.ndarray (contexts_features) + a batch of contexts features + Shape must be (n_contexts, n_contexts_features) + contexts_items_features : tuple of np.ndarray (contexts_items_features) + a batch of contexts items features + Shape must be (n_contexts, n_contexts_items_features) + contexts_items_availabilities : np.ndarray + A batch of contexts items availabilities + Shape must be (n_contexts, n_items) + choices_batch : np.ndarray + Choices + Shape must be (n_contexts, ) + + Returns: + -------- + np.ndarray (n_contexts, n_items) + Utilities + + Raises: + ------- + ValueError + If the model has not been fitted cannot evaluate the utility + """ + # In order to avoid unused arguments warnings + _ = fixed_items_features, contexts_features, contexts_items_availabilities + _ = contexts_items_features + if self.weights is None: + raise ValueError("Model not fitted") + return np.stack([np.log(self.weights.numpy())] * len(choices), axis=0) From ed301d1f7623f856dbfdd792e5c0cbdf77c454c8 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 15 Feb 2024 13:50:00 +0100 Subject: [PATCH 142/767] ADD: n_features getters --- choice_learn/data/choice_dataset.py | 45 +++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index 56448da1..0dd290da 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -1396,3 +1396,48 @@ def filter(self, bool_list): """ indexes = [i for i, keep in enumerate(bool_list) if keep] return self[indexes] + + def get_n_fixed_items_features(self): + """Method to access the number of fixed items features. + + Returns: + ------- + int + number of fixed items features + """ + if self.fixed_items_features is not None: + n_features = 0 + for fixed_features in self.fixed_items_features: + n_features += fixed_features.shape[1] + return n_features + return 0 + + def get_n_contexts_features(self): + """Method to access the number of contexts features. + + Returns: + ------- + int + number of fixed items features + """ + if self.contexts_features is not None: + n_features = 0 + for context_features in self.contexts_features: + n_features += context_features.shape[1] + return n_features + return 0 + + def get_n_contexts_items_features(self): + """Method to access the number of context items features. + + Returns: + ------- + int + number of fixed items features + """ + if self.contexts_items_features is not None: + n_features = 0 + for contexts_items_features in self.contexts_items_features: + n_features += contexts_items_features.shape[1] + return n_features + return 0 From 794759278ca624dd78da0503e9b40c98c3197cf5 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 15 Feb 2024 13:53:32 +0100 Subject: [PATCH 143/767] ADD: Base Linear MNL --- choice_learn/models/mix_mnl.py | 1 + choice_learn/models/simple_mnl.py | 256 ++++++++++++++++++++++++++++++ 2 files changed, 257 insertions(+) create mode 100644 choice_learn/models/simple_mnl.py diff --git a/choice_learn/models/mix_mnl.py b/choice_learn/models/mix_mnl.py index e69de29b..26c75b53 100644 --- a/choice_learn/models/mix_mnl.py +++ b/choice_learn/models/mix_mnl.py @@ -0,0 +1 @@ +"""Implementation of MixMNL. Citation to add.""" diff --git a/choice_learn/models/simple_mnl.py b/choice_learn/models/simple_mnl.py new file mode 100644 index 00000000..981cef38 --- /dev/null +++ b/choice_learn/models/simple_mnl.py @@ -0,0 +1,256 @@ +"""Implementation of the simple linear multinomial logit model. + +It is a multi output logistic regression. +""" + +import pandas as pd +import tensorflow as tf + +from .base_model import ChoiceModel + + +class SimpleMNL(ChoiceModel): + """Simple MNL with one linear coefficient to estimate by feature.""" + + def __init__( + self, + add_exit_choice=False, + optimizer="Adam", + lr=0.001, + **kwargs, + ): + """Initialization of Simple-MNL. + + Parameters: + ----------- + add_exit_choice : bool, optional + Whether or not to normalize the probabilities computation with an exit choice + whose utility would be 1, by default True + optimizer: str + TensorFlow optimizer to be used for estimation + lr: float + Learning Rate to be used with optimizer. + """ + super().__init__(normalize_non_buy=add_exit_choice, optimizer=optimizer, lr=lr, **kwargs) + self.instantiated = False + + def instantiate(self, n_fixed_items_features, n_contexts_features, n_contexts_items_features): + """Instantiate the model from ModelSpecification object. + + Paramters + -------- + n_weights: int + Number of weights to be estimated. Corresponds to the number of features. + + Returns: + -------- + list of tf.Tensor + List of the weights created coresponding to the specification. + """ + weights = [ + tf.Variable( + tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(1, n_feat)), + name="Weights", + ) + for n_feat in [n_fixed_items_features, n_contexts_features, n_contexts_items_features] + ] + self.instantiated = True + return weights + + def compute_batch_utility( + self, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, + ): + """Main method to compute the utility of the model. Selects the right method to compute. + + Parameters + ---------- + fixed_items_features : tuple of np.ndarray + Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products + constant/fixed features. + Shape must be (n_items, n_items_features) + contexts_features : tuple of np.ndarray (contexts_features) + a batch of contexts features + Shape must be (n_contexts, n_contexts_features) + contexts_items_features : tuple of np.ndarray (contexts_items_features) + a batch of contexts items features + Shape must be (n_contexts, n_contexts_items_features) + contexts_items_availabilities : np.ndarray + A batch of contexts items availabilities + Shape must be (n_contexts, n_items) + choices_batch : np.ndarray + Choices + Shape must be (n_contexts, ) + + Returns: + -------- + tf.Tensor + Computed utilities of shape (n_choices, n_items). + """ + _, _ = contexts_items_availabilities, choices + if len(self.weights[0]) > 0: + fixed_items_features = tf.concat(*fixed_items_features, axis=1) + fixed_items_utilities = tf.tensordot(fixed_items_features, self.weights[0], axes=1) + else: + fixed_items_utilities = 0 + + if len(self.weights[1]) > 0: + contexts_features = tf.concat(*contexts_features, axis=1) + contexts_utilities = tf.tensordot(contexts_features, self.weights[1], axes=1) + contexts_utilities = tf.expand_dims(contexts_utilities, axis=0) + else: + contexts_utilities = 0 + + if len(self.weights[2]) > 0: + contexts_items_features = tf.concat([*contexts_items_features], axis=2) + contexts_items_utilities = tf.tensordot(contexts_items_features, self.weights[2]) + else: + contexts_utilities = tf.zeros( + (contexts_utilities.shape[0], fixed_items_utilities.shape[1], 1) + ) + + return fixed_items_utilities + contexts_utilities + contexts_items_utilities + + def fit(self, choice_dataset, get_report=False, **kwargs): + """Main fit function to estimate the paramters. + + Parameters + ---------- + choice_dataset : ChoiceDataset + Choice dataset to use for the estimation. + get_report: bool, optional + Whether or not to compute a report of the estimation, by default False + + Returns: + -------- + ConditionalMNL + With estimated weights. + """ + if not self.instantiated: + # Lazy Instantiation + self.weights = self.instantiate( + n_items_features=choice_dataset.get_n_fixed_items_features(), + n_context_features=choice_dataset.get_n_contexts_features(), + n_contexts_items_features=choice_dataset.get_n_contexts_items_features(), + ) + self.instantiated = True + fit = super().fit(choice_dataset=choice_dataset, **kwargs) + if get_report: + self.report = self.compute_report(choice_dataset) + return fit + + def compute_report(self, dataset): + """Computes a report of the estimated weights. + + Parameters + ---------- + dataset : ChoiceDataset + ChoiceDataset used for the estimation of the weights that will be + used to compute the Std Err of this estimation. + + Returns: + -------- + pandas.DataFrame + A DF with estimation, Std Err, z_value and p_value for each coefficient. + """ + import tensorflow_probability as tfp + + weights_std = self.get_weights_std(dataset) + dist = tfp.distributions.Normal(loc=0.0, scale=1.0) + + names = [] + z_values = [] + estimations = [] + p_z = [] + i = 0 + for weight in self.weights: + for j in range(weight.shape[1]): + names.append(f"{weight.name}_{j}") + estimations.append(weight.numpy()[0][j]) + z_values.append(weight.numpy()[0][j] / weights_std[i].numpy()) + p_z.append(2 * (1 - dist.cdf(tf.math.abs(z_values[-1])).numpy())) + i += 1 + + return pd.DataFrame( + { + "Coefficient Name": names, + "Coefficient Estimation": estimations, + "Std. Err": weights_std.numpy(), + "z_value": z_values, + "P(.>z)": p_z, + }, + ) + + def get_weights_std(self, dataset): + """Approximates Std Err with Hessian matrix. + + Parameters + ---------- + dataset : ChoiceDataset + ChoiceDataset used for the estimation of the weights that will be + used to compute the Std Err of this estimation. + + Returns: + -------- + tf.Tensor + Estimation of the Std Err for the weights. + """ + # Loops of differentiation + with tf.GradientTape() as tape_1: + with tf.GradientTape(persistent=True) as tape_2: + model = self.clone() + w = tf.concat(self.weights, axis=1) + tape_2.watch(w) + tape_1.watch(w) + mw = [] + index = 0 + for _w in self.weights: + mw.append(w[:, index : index + _w.shape[1]]) + index += _w.shape[1] + model.weights = mw + for batch in dataset.iter_batch(batch_size=-1): + utilities = model.compute_batch_utility(*batch) + probabilities = tf.nn.softmax(utilities, axis=-1) + loss = tf.keras.losses.CategoricalCrossentropy(reduction="sum")( + y_pred=probabilities, + y_true=tf.one_hot(dataset.choices, depth=4), + ) + # Compute the Jacobian + jacobian = tape_2.jacobian(loss, w) + # Compute the Hessian from the Jacobian + hessian = tape_1.batch_jacobian(jacobian, w) + return tf.sqrt( + [tf.linalg.inv(tf.squeeze(hessian))[i][i] for i in range(len(tf.squeeze(hessian)))] + ) + + def clone(self): + """Returns a clone of the model.""" + clone = SimpleMNL( + add_exit_choice=self.normalize_non_buy, + optimizer=self.optimizer_name, + ) + if hasattr(self, "history"): + clone.history = self.history + if hasattr(self, "is_fitted"): + clone.is_fitted = self.is_fitted + if hasattr(self, "instantiated"): + clone.instantiated = self.instantiated + clone.loss = self.loss + clone.label_smoothing = self.label_smoothing + if hasattr(self, "report"): + clone.report = self.report + if hasattr(self, "weights"): + clone.weights = self.weights + if hasattr(self, "lr"): + clone.lr = self.lr + if hasattr(self, "_items_features_names"): + clone._items_features_names = self._items_features_names + if hasattr(self, "_contexts_features_names"): + clone._contexts_features_names = self._contexts_features_names + if hasattr(self, "_contexts_items_features_names"): + clone._contexts_items_features_names = self._contexts_items_features_names + return clone From a823f89db235d3add614a7d20f17efdf4357a273 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 15 Feb 2024 16:26:53 +0100 Subject: [PATCH 144/767] FIX: ensure float32 dtype for default availabilities --- choice_learn/data/choice_dataset.py | 8 +++++--- choice_learn/data/indexer.py | 6 ++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index 0dd290da..fdea9c42 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -689,7 +689,7 @@ def _contexts_items_features_df_to_np( sess_df.columns = sess_df.loc[items_id_column] if features is not None: contexts_items_features.append(sess_df[items_index].loc[features].T.values) - contexts_items_availabilities.append(np.ones(len(items_index))) + contexts_items_availabilities.append(np.ones(len(items_index)).astype("float32")) else: sess_feats = [] sess_av = [] @@ -1038,7 +1038,9 @@ def get_choices_batch(self, choices_indexes, features=None): ) if self.contexts_items_availabilities is None: - contexts_items_availabilities = np.ones((len(choices_indexes), self.base_num_items)) + contexts_items_availabilities = np.ones( + (len(choices_indexes), self.base_num_items) + ).astype("float32") else: contexts_items_availabilities = self.contexts_items_availabilities[choices_indexes] # .astype(self._return_types[3]) @@ -1179,7 +1181,7 @@ def get_choices_batch(self, choices_indexes, features=None): ) if self.contexts_items_availabilities is None: - contexts_items_availabilities = np.ones((self.base_num_items)) + contexts_items_availabilities = np.ones((self.base_num_items)).astype("float32") else: contexts_items_availabilities = self.contexts_items_availabilities[choices_indexes] diff --git a/choice_learn/data/indexer.py b/choice_learn/data/indexer.py index ddba5383..29ed0e2d 100644 --- a/choice_learn/data/indexer.py +++ b/choice_learn/data/indexer.py @@ -295,7 +295,7 @@ def __getitem__(self, choices_indexes): if self.choice_dataset.contexts_items_availabilities is None: contexts_items_availabilities = np.ones( (len(choices_indexes), self.choice_dataset.base_num_items) - ) + ).astype("float32") else: if hasattr(self.choice_dataset.contexts_items_availabilities, "batch"): contexts_items_availabilities = ( @@ -440,7 +440,9 @@ def __getitem__(self, choices_indexes): choice = self.choice_dataset.choices[choices_indexes] if self.choice_dataset.contexts_items_availabilities is None: - contexts_items_availabilities = np.ones((self.choice_dataset.base_num_items)) + contexts_items_availabilities = np.ones( + (self.choice_dataset.base_num_items) + ).astype("float32") else: contexts_items_availabilities = self.choice_dataset.contexts_items_availabilities[ choices_indexes From 4906a7ab9cfbc745dbfb3ad392faffc5ed7d5688 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 15 Feb 2024 16:28:30 +0100 Subject: [PATCH 145/767] FIX: iteration over features when is None in compute_utilities --- choice_learn/models/conditional_mnl.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/choice_learn/models/conditional_mnl.py b/choice_learn/models/conditional_mnl.py index 170c8f84..e66e85bf 100644 --- a/choice_learn/models/conditional_mnl.py +++ b/choice_learn/models/conditional_mnl.py @@ -629,16 +629,18 @@ def instantiate( """ # Possibility to stack weights to be faster ???? if items_features_names is None: - items_features_names = [] + items_features_names = [()] if contexts_features_names is None: - contexts_features_names = [] + contexts_features_names = [()] if contexts_items_features_names is None: - contexts_items_features_names = [] + contexts_items_features_names = [()] weights = [] weights_count = 0 self._items_features_names = [] for feat_tuple in items_features_names: tuple_names = [] + if feat_tuple is None: + feat_tuple = () for feat in feat_tuple: if feat in self.params.keys(): if self.params[feat] == "constant": @@ -671,6 +673,8 @@ def instantiate( self._contexts_features_names = [] for feat_tuple in contexts_features_names: + if feat_tuple is None: + feat_tuple = () tuple_names = [] for feat in feat_tuple: if feat in self.params.keys(): @@ -706,6 +710,8 @@ def instantiate( self._contexts_items_features_names = [] for feat_tuple in contexts_items_features_names: + if feat_tuple is None: + feat_tuple = () tuple_names = [] for feat in feat_tuple: if feat in self.params.keys(): From 33b31abc5b17c9a478c7f09382e39c0eef9385fb Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 15 Feb 2024 16:28:54 +0100 Subject: [PATCH 146/767] ADD: Logitstic Regression tutorial notebook --- notebooks/logistic_regression.ipynb | 169 ++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 notebooks/logistic_regression.ipynb diff --git a/notebooks/logistic_regression.ipynb b/notebooks/logistic_regression.ipynb new file mode 100644 index 00000000..9ad2e742 --- /dev/null +++ b/notebooks/logistic_regression.ipynb @@ -0,0 +1,169 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Logistic Regression: 3-class Classifier\n", + "\n", + "The Conditional MNL is a generalization of the multi-class Logistic Regression.\n", + "Here, we recreate the scikit-learn tutorial that can be found [here](https://scikit-learn.org/stable/auto_examples/linear_model/plot_iris_logistic.html#sphx-glr-auto-examples-linear-model-plot-iris-logistic-py)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "\n", + "# Remove GPU use\n", + "os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"\"\n", + "\n", + "import sys\n", + "\n", + "sys.path.append(\"../\")\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "from sklearn import datasets\n", + "from sklearn.inspection import DecisionBoundaryDisplay\n", + "\n", + "from choice_learn.models import ConditionalMNL\n", + "from choice_learn.data import ChoiceDataset" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# import some data to play with\n", + "iris = datasets.load_iris()\n", + "X = iris.data[:, :2] # we only take the first two features.\n", + "Y = iris.target" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We need to create a ChoiceDataset object. Features are contexts_features as they are shared by the three outcomes. The class labels are ''choices''." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset = ChoiceDataset(contexts_features=(X, ),\n", + "contexts_features_names=([\"feat_1\", \"feat_2\"], ),\n", + " fixed_items_features=np.ones((3, 3)),\n", + " choices=Y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the model parametrization, we specify that we want to learn one weight by outcome for each feature: 'feat_1', 'feat_2' and the intercept. This is done with the keyword \"item-full\"." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "parametrization = {\n", + " \"intercept\": \"item-full\",\n", + " \"feat_1\": \"item-full\",\n", + " \"feat_2\": \"item-full\"\n", + "}\n", + "\n", + "# Let's estimate the weights\n", + "model = ConditionalMNL(parameters=parametrization, optimizer=\"lbfgs\")\n", + "hist = model.fit(dataset, epochs=100)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's display the resulting model, just as in the sk-learn tutorial." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "feature_1, feature_2 = np.meshgrid(\n", + " np.linspace(X[:, 0].min() - 0.5, X[:, 0].max() + 0.5),\n", + " np.linspace(X[:, 1].min() - 0.5, X[:, 1].max() + 0.5)\n", + ")\n", + "grid = np.vstack([feature_1.ravel(), feature_2.ravel()]).T\n", + "\n", + "grid_dataset = ChoiceDataset(contexts_features=(grid, ),\n", + "contexts_features_names=([\"feat_1\", \"feat_2\"], ),\n", + " fixed_items_features=np.ones((3, 3)),\n", + " choices=np.ones(len(grid), ))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "y_pred = np.reshape(np.argmax(model.predict_probas(grid_dataset), axis=1), feature_1.shape)\n", + "display = DecisionBoundaryDisplay(\n", + " xx0=feature_1, xx1=feature_2, response=y_pred\n", + ")\n", + "display.plot(plot_method=\"pcolormesh\",\n", + " cmap=plt.cm.Paired,\n", + " shading=\"auto\",\n", + " xlabel=\"Sepal length\",\n", + " ylabel=\"Sepal width\")\n", + "display.ax_.scatter(\n", + " X[:, 0], X[:, 1], c=Y, edgecolor=\"black\", \n", + " cmap=plt.cm.Paired,\n", + ")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It sure looks alike !" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "tf_env", + "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.11.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 96cfb1c40b66a4999174c10d90d60fb7132569b6 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 16 Feb 2024 10:02:18 +0100 Subject: [PATCH 147/767] FIX: evaluation of contexts items features nb --- choice_learn/data/choice_dataset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index fdea9c42..818cb3bb 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -1440,6 +1440,6 @@ def get_n_contexts_items_features(self): if self.contexts_items_features is not None: n_features = 0 for contexts_items_features in self.contexts_items_features: - n_features += contexts_items_features.shape[1] + n_features += contexts_items_features.shape[2] return n_features return 0 From 34c543c2150bee832218671e8265a5abdd928b88 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 16 Feb 2024 10:03:58 +0100 Subject: [PATCH 148/767] ADD: file & base loader for Heating Dataset --- choice_learn/datasets/base.py | 46 ++++++++++++++++++ .../datasets/data/heating_data.csv.gz | Bin 0 -> 33956 bytes 2 files changed, 46 insertions(+) create mode 100644 choice_learn/datasets/data/heating_data.csv.gz diff --git a/choice_learn/datasets/base.py b/choice_learn/datasets/base.py index 92b65eab..9853d24c 100644 --- a/choice_learn/datasets/base.py +++ b/choice_learn/datasets/base.py @@ -367,3 +367,49 @@ def load_modecanada( choices_column=choice_column, choice_mode="one_zero", ) + + +def load_heating( + as_frame=False, + return_desc=False, + to_wide=False, +): + """Load and return the ModeCanada dataset from Koppleman et al. (1993). + + Parameters + ---------- + one_hot_cat_data : bool, optional + Whether to transform categorical data as OneHot, by default False. + add_is_public : bool, optional + Whether to add the is_public feature, by default False. + add_items_one_hot : bool, optional + Whether to add a OneHot encoding of items as items_features, by default False + as_frame : bool, optional + Whether to return the dataset as pd.DataFrame. If not, returned as ChoiceDataset, + by default False. + return_desc : bool, optional + Whether to return the description, by default False. + choice_mode : str, optional, among ["one_zero", "items_id"] + mode indicating how the choice is encoded, by default "one_zero". + split_features : bool, optional + Whether to split features by type in different dataframes, by default False. + to_wide : bool, optional + Whether to return the dataset in wide format, + by default False (an thus retuned in long format). + + Returns: + -------- + ChoiceDataset + Loaded ModeCanada dataset + """ + _ = to_wide + data_file_name = "heating_data.csv.gz" + names, data = load_gzip(data_file_name) + + if return_desc: + # TODO + pass + + if as_frame: + return pd.read_csv(resources.files(DATA_MODULE) / "heating_data.csv.gz") + return None diff --git a/choice_learn/datasets/data/heating_data.csv.gz b/choice_learn/datasets/data/heating_data.csv.gz new file mode 100644 index 0000000000000000000000000000000000000000..5fd53831883b8a3566dea7a0d35768b1be623361 GIT binary patch literal 33956 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�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 literal 0 HcmV?d00001 From 829358cf5ffd17b4fce61cb92932de6753dfc30f Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 16 Feb 2024 10:04:27 +0100 Subject: [PATCH 149/767] FIX: std with nb of features --- choice_learn/models/conditional_mnl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/choice_learn/models/conditional_mnl.py b/choice_learn/models/conditional_mnl.py index e66e85bf..8d40f684 100644 --- a/choice_learn/models/conditional_mnl.py +++ b/choice_learn/models/conditional_mnl.py @@ -1123,7 +1123,7 @@ def get_weights_std(self, dataset): probabilities = tf.nn.softmax(utilities, axis=-1) loss = tf.keras.losses.CategoricalCrossentropy(reduction="sum")( y_pred=probabilities, - y_true=tf.one_hot(dataset.choices, depth=4), + y_true=tf.one_hot(dataset.choices, depth=probabilities.shape[1]), ) # Compute the Jacobian jacobian = tape_2.jacobian(loss, w) From cdbdc7f42c05b15aff4bf077a48f2a34ce15d70e Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 16 Feb 2024 10:05:18 +0100 Subject: [PATCH 150/767] ADD: smarter & functioning simpleMNL --- choice_learn/models/simple_mnl.py | 117 ++++++++++++++++++++++-------- 1 file changed, 87 insertions(+), 30 deletions(-) diff --git a/choice_learn/models/simple_mnl.py b/choice_learn/models/simple_mnl.py index 981cef38..cab20a22 100644 --- a/choice_learn/models/simple_mnl.py +++ b/choice_learn/models/simple_mnl.py @@ -47,15 +47,22 @@ def instantiate(self, n_fixed_items_features, n_contexts_features, n_contexts_it list of tf.Tensor List of the weights created coresponding to the specification. """ - weights = [ - tf.Variable( - tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(1, n_feat)), - name="Weights", - ) - for n_feat in [n_fixed_items_features, n_contexts_features, n_contexts_items_features] - ] + weights = [] + indexes = {} + for n_feat, feat_name in zip( + [n_fixed_items_features, n_contexts_features, n_contexts_items_features], + ["items", "contexts", "contexts_items"], + ): + if n_feat > 0: + weights = [ + tf.Variable( + tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(n_feat,)), + name=f"Weights_{feat_name}", + ) + ] + indexes[feat_name] = len(weights) - 1 self.instantiated = True - return weights + return indexes, weights def compute_batch_utility( self, @@ -92,22 +99,31 @@ def compute_batch_utility( Computed utilities of shape (n_choices, n_items). """ _, _ = contexts_items_availabilities, choices - if len(self.weights[0]) > 0: - fixed_items_features = tf.concat(*fixed_items_features, axis=1) - fixed_items_utilities = tf.tensordot(fixed_items_features, self.weights[0], axes=1) + if "items" in self.indexes.keys(): + if isinstance(fixed_items_features, tuple): + fixed_items_features = tf.concat(*fixed_items_features, axis=1) + fixed_items_utilities = tf.tensordot( + fixed_items_features, self.weights[self.indexes["items"]], axes=1 + ) else: fixed_items_utilities = 0 - if len(self.weights[1]) > 0: - contexts_features = tf.concat(*contexts_features, axis=1) - contexts_utilities = tf.tensordot(contexts_features, self.weights[1], axes=1) + if "contexts" in self.indexes.keys(): + if isinstance(contexts_features, tuple): + contexts_features = tf.concat(*contexts_features, axis=1) + contexts_utilities = tf.tensordot( + contexts_features, self.weights[self.indexes["contexts"]], axes=1 + ) contexts_utilities = tf.expand_dims(contexts_utilities, axis=0) else: contexts_utilities = 0 - if len(self.weights[2]) > 0: - contexts_items_features = tf.concat([*contexts_items_features], axis=2) - contexts_items_utilities = tf.tensordot(contexts_items_features, self.weights[2]) + if "contexts_items" in self.indexes.keys(): + if isinstance(contexts_items_features, tuple): + contexts_items_features = tf.concat([*contexts_items_features], axis=2) + contexts_items_utilities = tf.tensordot( + contexts_items_features, self.weights[self.indexes["contexts_items"]], axes=1 + ) else: contexts_utilities = tf.zeros( (contexts_utilities.shape[0], fixed_items_utilities.shape[1], 1) @@ -132,9 +148,10 @@ def fit(self, choice_dataset, get_report=False, **kwargs): """ if not self.instantiated: # Lazy Instantiation - self.weights = self.instantiate( - n_items_features=choice_dataset.get_n_fixed_items_features(), - n_context_features=choice_dataset.get_n_contexts_features(), + print("Instantiation") + self.indexes, self.weights = self.instantiate( + n_fixed_items_features=choice_dataset.get_n_fixed_items_features(), + n_contexts_features=choice_dataset.get_n_contexts_features(), n_contexts_items_features=choice_dataset.get_n_contexts_items_features(), ) self.instantiated = True @@ -143,6 +160,45 @@ def fit(self, choice_dataset, get_report=False, **kwargs): self.report = self.compute_report(choice_dataset) return fit + def _fit_with_lbfgs( + self, choice_dataset, epochs=None, sample_weight=None, tolerance=1e-8, get_report=False + ): + """Specific fit function to estimate the paramters with LBFGS. + + Parameters + ---------- + choice_dataset : ChoiceDataset + Choice dataset to use for the estimation. + n_epochs : int + Number of epochs to run. + tolerance : float, optional + Tolerance in the research of minimum, by default 1e-8 + get_report: bool, optional + Whether or not to compute a report of the estimation, by default False + + Returns: + -------- + conditionalMNL + self with estimated weights. + """ + if not self.instantiated: + # Lazy Instantiation + print("Instantiation") + self.indexes, self.weights = self.instantiate( + n_fixed_items_features=choice_dataset.get_n_fixed_items_features(), + n_contexts_features=choice_dataset.get_n_contexts_features(), + n_contexts_items_features=choice_dataset.get_n_contexts_items_features(), + ) + self.instantiated = True + if epochs is None: + epochs = self.epochs + fit = super()._fit_with_lbfgs( + dataset=choice_dataset, epochs=epochs, tolerance=tolerance, sample_weight=sample_weight + ) + if get_report: + self.report = self.compute_report(choice_dataset) + return fit + def compute_report(self, dataset): """Computes a report of the estimated weights. @@ -168,10 +224,10 @@ def compute_report(self, dataset): p_z = [] i = 0 for weight in self.weights: - for j in range(weight.shape[1]): + for j in range(weight.shape[0]): names.append(f"{weight.name}_{j}") - estimations.append(weight.numpy()[0][j]) - z_values.append(weight.numpy()[0][j] / weights_std[i].numpy()) + estimations.append(weight.numpy()[j]) + z_values.append(weight.numpy()[j] / weights_std[i].numpy()) p_z.append(2 * (1 - dist.cdf(tf.math.abs(z_values[-1])).numpy())) i += 1 @@ -209,23 +265,22 @@ def get_weights_std(self, dataset): mw = [] index = 0 for _w in self.weights: - mw.append(w[:, index : index + _w.shape[1]]) - index += _w.shape[1] + mw.append(w[index : index + _w.shape[0]]) + index += _w.shape[0] model.weights = mw for batch in dataset.iter_batch(batch_size=-1): utilities = model.compute_batch_utility(*batch) probabilities = tf.nn.softmax(utilities, axis=-1) loss = tf.keras.losses.CategoricalCrossentropy(reduction="sum")( y_pred=probabilities, - y_true=tf.one_hot(dataset.choices, depth=4), + y_true=tf.one_hot(dataset.choices, depth=probabilities.shape[-1]), ) # Compute the Jacobian jacobian = tape_2.jacobian(loss, w) # Compute the Hessian from the Jacobian - hessian = tape_1.batch_jacobian(jacobian, w) - return tf.sqrt( - [tf.linalg.inv(tf.squeeze(hessian))[i][i] for i in range(len(tf.squeeze(hessian)))] - ) + hessian = tape_1.jacobian(jacobian, w) + hessian = tf.linalg.inv(tf.squeeze(hessian)) + return tf.sqrt([hessian[i][i] for i in range(len(tf.squeeze(hessian)))]) def clone(self): """Returns a clone of the model.""" @@ -245,6 +300,8 @@ def clone(self): clone.report = self.report if hasattr(self, "weights"): clone.weights = self.weights + if hasattr(self, "indexes"): + clone.indexes = self.indexes if hasattr(self, "lr"): clone.lr = self.lr if hasattr(self, "_items_features_names"): From fc13a99e426ec8f75e6137c0f52657a32d15e658 Mon Sep 17 00:00:00 2001 From: Luca Serra Date: Fri, 16 Feb 2024 11:35:22 +0100 Subject: [PATCH 151/767] add copy of readme to be able to comment it --- README_review.md | 121 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 README_review.md diff --git a/README_review.md b/README_review.md new file mode 100644 index 00000000..9481432a --- /dev/null +++ b/README_review.md @@ -0,0 +1,121 @@ +
+ +# choice-learn-private + +[![CI status](https://github.com/artefactory/choice-learn-private/actions/workflows/ci.yaml/badge.svg)](https://github.com/artefactory/choice-learn-private/actions/workflows/ci.yaml?query=branch%3Amain) +[![Python Version](https://img.shields.io/badge/python-3.8%20%7C%203.9%20%7C%203.10-blue.svg)]() + +[![Linting , formatting, imports sorting: ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) +[![security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit) +[![Pre-commit](https://img.shields.io/badge/pre--commit-enabled-informational?logo=pre-commit&logoColor=white)](https://github.com/artefactory/choice-learn-private/blob/main/.pre-commit-config.yaml) + +
+ + + +Choice-Learn is a Python package designed to help you build discrete choice models. +The package provides ready to use datasets and different models from the litterature. It also provides a lower level use if you want to customize any model or create your own from scratch. In particular you will find smart datasets handling to limit RAM usage and different structure commons to any choice model. + +Choice-Learn uses NumPy and pandas as data backend engines and TensorFlow for models. + +This repository contains a private version of the package. + +## Table of Contents + +- [choice-learn-private](#choice-learn-private) + - [Introduction - Discrete Choice Modelling](#introduction---discrete-choice-modelling) + - [Table of Contents](#table-of-contents) + - [What's in there ?](#whats-in-there) + - [Getting Started](#getting-started---fast-track) + - [Installation](#installation) + - [Usage](#usage) + - [Documentation](#documentation) + - [Citation](#citation) + +## Introduction - Discrete Choice Modelling + +Discrete choice models aim at explaining or predicting a choice from a set of alternatives. Well known use-cases include analyzing people choice of mean of transport or products purchases in stores. + +If you are new to choice modelling, you can check this [resource](https://www.publichealth.columbia.edu/research/population-health-methods/discrete-choice-model-and-analysis). The different notebooks from the [Getting Started](#getting-started---fast-track) section can also help you understand choice modelling and more importantly help you for your usecase. + +## What's in there ? + +### Data +- Generic dataset handling with the ChoiceDataset class +- Ready-To-Use datasets: + - SwissMetro from Bierlaire et al. (2001) + - ModeCanada from Koppelman et al. (1993) + +### Models +- Ready to use models: + - Conditional MultiNomialLogit, Train, K.; McFadden, D.; Ben-Akiva, M. (1987) + - RUMnet, Aouad A.; Désir A. (2022) [1] +- Ready to use models to be implemented: + - Nested MultiNomialLogit + - MultiNomialLogit with latent variables (MixedLogit) + - TasteNet + - SHOPPER + - Others ... +- Custom modelling is made easy by subclassing the ChoiceModel class + +### Different tools (to come) +- Standardization of evaluation protocols +- Assortment optimization from model +- Interfaces + +## Getting Started - Fast Track + +You can find the following notebooks to help you getting started with the package: +- [Introduction to data management](notebooks/choice_learn_introduction_data.ipynb) +- [Introduction to modelling with the conditional logit model on ModeCanada dataset](notebooks/choice_learn_introduction_clogit.ipynb) +- [Introduction to custom modelling with the ModeCanada dataset](notebooks/custom_model.ipynb) + +## Installation + +### User installation + +To install the required packages in a virtual environment, run the following command: + +** pip-install not possible yet, to come soon** +```bash +pip install choice-learn +``` + +In the mean time you can clone the repository: +```bash +git clone git@github.com:artefactory/choice-learn-private.git +``` + +### Dependencies +Choice-Learn requires the following: +- Python (>=3.8) +- NumPy (>=1.24) +- pandas (>=1.5) +For modelling you need: +- TensorFlow (>=2.13) +Finally, an optional requirement used for report and LBFG-s use is: +- tensorflow_probability (>=0.20.1) + +## Usage +```python +from choice_learn.data import ChoiceDataset +from choice_learn.models import ConditionalMNL, RUMnet +``` + +## Documentation + +A detailed documentation of this project is available [here](https://artefactory.github.io/choice-learn-private/) + +## Citation + +### Contributors + +## References + +### Papers +[1][Representing Random Utility Choice Models with Neural Networks](https://arxiv.org/abs/2207.12877), Aouad A.; Désir A. (2022) + +### Code and Repositories +- [PyLogit](https://github.com/timothyb0912/pylogit) +- [Torch Choice](https://gsbdbi.github.io/torch-choice/) +- [1][RUMnet](https://github.com/antoinedesir/rumnet) From 146c38fc730e65a86dc387dda4622761fbc6e4a2 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 16 Feb 2024 11:52:50 +0100 Subject: [PATCH 152/767] ADD: important illustration --- notebooks/logistic_regression.ipynb | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/notebooks/logistic_regression.ipynb b/notebooks/logistic_regression.ipynb index 9ad2e742..45252ec3 100644 --- a/notebooks/logistic_regression.ipynb +++ b/notebooks/logistic_regression.ipynb @@ -118,8 +118,23 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "keep_output": true + }, + "outputs": [ + { + "data": { + "image/png": "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KioqapxfXl4OhUJR7UaPrytJt9Gng4PWxAYAhvVwRkxyLlQqdRNHRkREDUVvkhtBELBo0SL0798fHTt2rPW8jIwM2NnZVTtmZ2eHyspK5OTk1Dh/9erVkMvlmpuzs3ODx07Nh7mpMXLyS2ttz84vhamJEcRiURNGRUREDUlvkps33ngD0dHR2Llz5wPPFYmqf/DcvbJ273EACAgIQEFBgeaWmpraMAFTszShvycuxGUh/FpGjTZlhQpbD1/FxP6eWn+XiIioedCL5GbevHkIDg7GiRMn4OTkdN9z7e3tkZFR/YMpKysLEokE1tbWNc6XSqWwtLSsdqPH1/h+HujkYY3JKw4gNCpNkxjfzC7E1A8OITmzEG8920PHURIR0aPQ6YYegiBg3rx52LNnD0JCQuDu7v7A+/j5+WH//v3Vjv3xxx/o2bMnjI2NGytUMhASIzEOfDIRE94JxpA3f4OnoxxycymibmTDXGaMX1aOQXcvW12HSUREj0Cnyc3cuXPx008/Yd++fWjRooVmREYul0MmkwGouqyUlpaG7du3A6haGbVhwwYsWrQIc+bMQVhYGL777rs6Xc4iAoA2NhY4/800HItMwe9hiShXqvDiWF88P7w9Wphpn2hMRETNh06Tm02bNgEABg8eXO14YGAgZs2aBQBIT09HSkqKps3d3R0HDx7EwoUL8fXXX8PR0RFffvklJk2a1FRh6w0u8X54YrEII3q5YkQvV12HQkREDUznl6UeZOvWrTWODRo0CBcuXGiEiIiIiKi504sJxUREREQNhckNERERGRQmN0RERGRQmNwQERGRQWFyQ0RERAaFyQ0REREZFCY3REREZFCY3BAREZFBYXJDREREBoXJDRERERkUJjdERERkUJjcEBERkUFhckNEREQGRadVwUm7ZwvW6ToEIiKiZosjN0RERGRQmNwQERGRQWFyQ0RERAaFyQ0REREZFCY3REREZFCY3BAREZFB4VLwJsQl3kRERI2PIzdERERkUJjcEBERkUFhckNEREQGhckNERERGRQmN0RERGRQmNwQERGRQWFyQ0RERAaFyQ0REREZFCY3REREZFCY3BAREZFBYXJDREREBoXJDRERERkUJjdERERkUJjcEBERkUGR6DoAQ/BswTpdh0BEzcSTL4+s03m/bz7SyJEQGS6O3BAREZFBYXJDREREBoXJ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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "keep_output": true + }, + "output_type": "display_data" + } + ], "source": [ "y_pred = np.reshape(np.argmax(model.predict_probas(grid_dataset), axis=1), feature_1.shape)\n", "display = DecisionBoundaryDisplay(\n", From ca1a1f6dd596c6b7fdb2a83b6b716431f514333c Mon Sep 17 00:00:00 2001 From: Emmanuel MALHERBE Date: Fri, 16 Feb 2024 12:04:16 +0100 Subject: [PATCH 153/767] ADD: typo and suggestions for README --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9481432a..b91aaa26 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Choice-Learn is a Python package designed to help you build discrete choice models. -The package provides ready to use datasets and different models from the litterature. It also provides a lower level use if you want to customize any model or create your own from scratch. In particular you will find smart datasets handling to limit RAM usage and different structure commons to any choice model. +The package provides ready-to-use datasets and models from the litterature. It also provides a lower level use if you want to customize any model or create your own from scratch. In particular you will find efficient data handling to limit RAM usage and structure commons to any choice model. Choice-Learn uses NumPy and pandas as data backend engines and TensorFlow for models. @@ -47,10 +47,10 @@ If you are new to choice modelling, you can check this [resource](https://www.pu - ModeCanada from Koppelman et al. (1993) ### Models -- Ready to use models: +- Ready-to-use models: - Conditional MultiNomialLogit, Train, K.; McFadden, D.; Ben-Akiva, M. (1987) - RUMnet, Aouad A.; Désir A. (2022) [1] -- Ready to use models to be implemented: +- (WIP) Ready-to-use models to be implemented: - Nested MultiNomialLogit - MultiNomialLogit with latent variables (MixedLogit) - TasteNet @@ -108,7 +108,13 @@ A detailed documentation of this project is available [here](https://artefactory ## Citation -### Contributors +If you consider this package and any of its feature useful for your research, please cite our paper: + +(WIP - Paper to come) + +### License + +The use of this software is under the MIT (tbc) license, with no limitation of usage, including for commercial applications. ## References From fc6fb506f4e5e7eae7fb481c09bd2e1fe41e24a8 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 16 Feb 2024 12:05:34 +0100 Subject: [PATCH 154/767] ADD: intercept + intercept modes in SimpleMNL --- choice_learn/models/simple_mnl.py | 51 +++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/choice_learn/models/simple_mnl.py b/choice_learn/models/simple_mnl.py index cab20a22..9f5cf7b0 100644 --- a/choice_learn/models/simple_mnl.py +++ b/choice_learn/models/simple_mnl.py @@ -15,6 +15,7 @@ class SimpleMNL(ChoiceModel): def __init__( self, add_exit_choice=False, + intercept=None, optimizer="Adam", lr=0.001, **kwargs, @@ -33,8 +34,11 @@ def __init__( """ super().__init__(normalize_non_buy=add_exit_choice, optimizer=optimizer, lr=lr, **kwargs) self.instantiated = False + self.intercept = intercept - def instantiate(self, n_fixed_items_features, n_contexts_features, n_contexts_items_features): + def instantiate( + self, n_items, n_fixed_items_features, n_contexts_features, n_contexts_items_features + ): """Instantiate the model from ModelSpecification object. Paramters @@ -61,6 +65,34 @@ def instantiate(self, n_fixed_items_features, n_contexts_features, n_contexts_it ) ] indexes[feat_name] = len(weights) - 1 + if self.intercept is None: + print("No intercept in the model") + elif self.intercept == "item": + weights.append( + tf.Variable( + tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(n_items - 1,)), + name="Intercept", + ) + ) + indexes["intercept"] = len(weights) - 1 + elif self.intercept == "item-full": + print("Are you sure you do not want to normalize an intercept to 0?") + weights.append( + tf.Variable( + tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(n_items,)), + name="Intercept", + ) + ) + indexes["intercept"] = len(weights) - 1 + else: + weights.append( + tf.Variable( + tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(1,)), + name="Intercept", + ) + ) + indexes["intercept"] = len(weights) - 1 + self.instantiated = True return indexes, weights @@ -129,7 +161,16 @@ def compute_batch_utility( (contexts_utilities.shape[0], fixed_items_utilities.shape[1], 1) ) - return fixed_items_utilities + contexts_utilities + contexts_items_utilities + if "intercept" in self.indexes.keys(): + intercept = self.weights[self.indexes["intercept"]] + if self.intercept == "item": + intercept = tf.concat([tf.constant([0.0]), intercept], axis=0) + if self.intercept in ["item", "item-full"]: + intercept = tf.expand_dims(intercept, axis=0) + else: + intercept = 0 + + return fixed_items_utilities + contexts_utilities + contexts_items_utilities + intercept def fit(self, choice_dataset, get_report=False, **kwargs): """Main fit function to estimate the paramters. @@ -150,6 +191,7 @@ def fit(self, choice_dataset, get_report=False, **kwargs): # Lazy Instantiation print("Instantiation") self.indexes, self.weights = self.instantiate( + n_items=choice_dataset.get_n_items(), n_fixed_items_features=choice_dataset.get_n_fixed_items_features(), n_contexts_features=choice_dataset.get_n_contexts_features(), n_contexts_items_features=choice_dataset.get_n_contexts_items_features(), @@ -185,6 +227,7 @@ def _fit_with_lbfgs( # Lazy Instantiation print("Instantiation") self.indexes, self.weights = self.instantiate( + n_items=choice_dataset.get_num_items(), n_fixed_items_features=choice_dataset.get_n_fixed_items_features(), n_contexts_features=choice_dataset.get_n_contexts_features(), n_contexts_items_features=choice_dataset.get_n_contexts_items_features(), @@ -259,7 +302,7 @@ def get_weights_std(self, dataset): with tf.GradientTape() as tape_1: with tf.GradientTape(persistent=True) as tape_2: model = self.clone() - w = tf.concat(self.weights, axis=1) + w = tf.concat(self.weights, axis=0) tape_2.watch(w) tape_1.watch(w) mw = [] @@ -302,6 +345,8 @@ def clone(self): clone.weights = self.weights if hasattr(self, "indexes"): clone.indexes = self.indexes + if hasattr(self, "intercept"): + clone.intercept = self.intercept if hasattr(self, "lr"): clone.lr = self.lr if hasattr(self, "_items_features_names"): From cf9ba00443dc6312617b210438ec8517d5835fe7 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 16 Feb 2024 12:06:03 +0100 Subject: [PATCH 155/767] ADD: Example for simple MNL base on mlogit package & Heating Dataset --- notebooks/simple_and_mix_logit.ipynb | 182 +++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 notebooks/simple_and_mix_logit.ipynb diff --git a/notebooks/simple_and_mix_logit.ipynb b/notebooks/simple_and_mix_logit.ipynb new file mode 100644 index 00000000..43ce5a87 --- /dev/null +++ b/notebooks/simple_and_mix_logit.ipynb @@ -0,0 +1,182 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "\n", + "# Remove GPU use\n", + "os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"\"\n", + "\n", + "import sys\n", + "\n", + "sys.path.append(\"../\")\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "from choice_learn.models.simple_mnl import SimpleMNL\n", + "from choice_learn.data import ChoiceDataset\n", + "from choice_learn.datasets.base import load_heating" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's recreate this [tutorial](https://cran.r-project.org/web/packages/mlogit/vignettes/e1mlogit.html) from Kenneth Train and Yves Croissant." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "heating_df = load_heating(as_frame=True)\n", + "\n", + "contexts_features = [\"income\", \"agehed\", \"rooms\"]\n", + "choice = [\"depvar\"]\n", + "contexts_items_features = [\"ic.\", \"oc.\"]\n", + "items = [\"hp\", \"gc\", \"gr\", \"ec\", \"er\"]\n", + "\n", + "choices = np.array([items.index(val) for val in heating_df[choice].to_numpy().ravel()])\n", + "contexts = heating_df[contexts_features].to_numpy()\n", + "contexts_items = np.stack([heating_df[[feat + item for feat in contexts_items_features]].to_numpy() for item in items], axis=1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset = ChoiceDataset(contexts_items_features=contexts_items, choices=choices)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset = ChoiceDataset(contexts_items_features=contexts_items, choices=choices)\n", + "model = SimpleMNL(optimizer=\"lbfgs\")\n", + "history = model.fit(dataset, epochs=100, get_report=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.evaluate(dataset) * len(dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.report" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ratio_contexts_items = []\n", + "for case in range(contexts_items.shape[0]):\n", + " feat = []\n", + " for item in range(contexts_items.shape[1]):\n", + " feat.append([contexts_items[case, item, 0] + contexts_items[case, item, 1] / 0.12])\n", + " ratio_contexts_items.append(feat)\n", + "ratio_contexts_items = np.array(ratio_contexts_items)\n", + "ratio_contexts_items.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ratio_dataset = ChoiceDataset(contexts_items_features=ratio_contexts_items, choices=choices)\n", + "model = SimpleMNL(optimizer=\"lbfgs\")\n", + "history = model.fit(ratio_dataset, epochs=100, get_report=False)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.weights" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.evaluate(ratio_dataset) * len(ratio_dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model = SimpleMNL(optimizer=\"lbfgs\", intercept=\"item\")\n", + "history = model.fit(dataset, epochs=100, get_report=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.report" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "tf_env", + "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.11.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From bd43aa9250054d8e1721e56c20047e5e0e547b91 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 16 Feb 2024 12:40:27 +0100 Subject: [PATCH 156/767] some cleaning --- choice_learn/datasets/base.py | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/choice_learn/datasets/base.py b/choice_learn/datasets/base.py index 9853d24c..7f8722a3 100644 --- a/choice_learn/datasets/base.py +++ b/choice_learn/datasets/base.py @@ -378,21 +378,11 @@ def load_heating( Parameters ---------- - one_hot_cat_data : bool, optional - Whether to transform categorical data as OneHot, by default False. - add_is_public : bool, optional - Whether to add the is_public feature, by default False. - add_items_one_hot : bool, optional - Whether to add a OneHot encoding of items as items_features, by default False as_frame : bool, optional Whether to return the dataset as pd.DataFrame. If not, returned as ChoiceDataset, by default False. return_desc : bool, optional Whether to return the description, by default False. - choice_mode : str, optional, among ["one_zero", "items_id"] - mode indicating how the choice is encoded, by default "one_zero". - split_features : bool, optional - Whether to split features by type in different dataframes, by default False. to_wide : bool, optional Whether to return the dataset in wide format, by default False (an thus retuned in long format). @@ -406,10 +396,29 @@ def load_heating( data_file_name = "heating_data.csv.gz" names, data = load_gzip(data_file_name) + heating_df = pd.read_csv(resources.files(DATA_MODULE) / "heating_data.csv.gz") + if return_desc: # TODO pass if as_frame: - return pd.read_csv(resources.files(DATA_MODULE) / "heating_data.csv.gz") - return None + return heating_df + + contexts_features = ["income", "agehed", "rooms", "region"] + choice = ["depvar"] + contexts_items_features = ["ic.", "oc."] + items = ["gc", "gr", "ec", "er", "hp"] + + choices = np.array([items.index(val) for val in heating_df[choice].to_numpy().ravel()]) + contexts = heating_df[contexts_features].to_numpy() + contexts_items = np.stack( + [ + heating_df[[feat + item for feat in contexts_items_features]].to_numpy() + for item in items + ], + axis=1, + ) + return ChoiceDataset( + contexts_features=contexts, contexts_items_features=contexts_items, choices=choices + ) From 0d59645840d75e465c98bef1e3cf2b4fb5bb1daa Mon Sep 17 00:00:00 2001 From: Emmanuel MALHERBE Date: Fri, 16 Feb 2024 14:01:39 +0100 Subject: [PATCH 157/767] ADD: requirements with python version explicit (took me time to install the environment... hehe) --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index b91aaa26..3ae3bf86 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,10 @@ For modelling you need: Finally, an optional requirement used for report and LBFG-s use is: - tensorflow_probability (>=0.20.1) +Once you have created your conda/pip python==3.9 environment, you can install requirements by: +```bash +pip install choice-learn +``` ## Usage ```python from choice_learn.data import ChoiceDataset From 1eb47ece22ad747dc99a7b8d15daa0eb1e8bc91d Mon Sep 17 00:00:00 2001 From: Emmanuel MALHERBE Date: Fri, 16 Feb 2024 14:25:41 +0100 Subject: [PATCH 158/767] FIX: changed way to locate data module (with os) --- choice_learn/datasets/base.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/choice_learn/datasets/base.py b/choice_learn/datasets/base.py index 92b65eab..99f49571 100644 --- a/choice_learn/datasets/base.py +++ b/choice_learn/datasets/base.py @@ -2,13 +2,15 @@ import csv import gzip from importlib import resources +import os import numpy as np import pandas as pd from choice_learn.data.choice_dataset import ChoiceDataset -DATA_MODULE = "choice_learn.datasets.data" + +DATA_MODULE = os.path.join(os.path.abspath('..'), 'choice_learn', 'datasets', 'data') def load_csv(data_file_name, data_module=DATA_MODULE, encoding="utf-8"): @@ -30,8 +32,7 @@ def load_csv(data_file_name, data_module=DATA_MODULE, encoding="utf-8"): np.ndarray data contained in the csv file """ - data_path = resources.files(data_module) - with (data_path / data_file_name).open("r", encoding=encoding) as csv_file: + with open(os.path.join(data_module, data_file_name), "r", encoding=encoding) as csv_file: data_file = csv.reader(csv_file) names = next(data_file) data = [] @@ -60,8 +61,7 @@ def load_gzip(data_file_name, data_module=DATA_MODULE, encoding="utf-8"): np.ndarray data contained in the csv file """ - data_path = resources.files(data_module) - with (data_path / data_file_name).open("rb") as compressed_file: + with open(os.path.join(data_module, data_file_name), "rb") as compressed_file: compressed_file = gzip.open(compressed_file, mode="rt", encoding=encoding) names = next(compressed_file) names = names.replace("\n", "") From 6789e60cae392c55906fa9f620ca648487d49333 Mon Sep 17 00:00:00 2001 From: Emmanuel MALHERBE Date: Fri, 16 Feb 2024 14:26:22 +0100 Subject: [PATCH 159/767] ADD: remove useless import --- choice_learn/datasets/base.py | 1 - 1 file changed, 1 deletion(-) diff --git a/choice_learn/datasets/base.py b/choice_learn/datasets/base.py index 99f49571..4ac6930d 100644 --- a/choice_learn/datasets/base.py +++ b/choice_learn/datasets/base.py @@ -1,7 +1,6 @@ """Datasets loader.""" import csv import gzip -from importlib import resources import os import numpy as np From dff24d2bd570ed790c294af5418a7835a3d19f50 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 16 Feb 2024 16:38:09 +0100 Subject: [PATCH 160/767] ADD: little explanations --- notebooks/simple_and_mix_logit.ipynb | 31 +++++++++++++++++----------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/notebooks/simple_and_mix_logit.ipynb b/notebooks/simple_and_mix_logit.ipynb index 43ce5a87..3d4860dc 100644 --- a/notebooks/simple_and_mix_logit.ipynb +++ b/notebooks/simple_and_mix_logit.ipynb @@ -27,7 +27,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Let's recreate this [tutorial](https://cran.r-project.org/web/packages/mlogit/vignettes/e1mlogit.html) from Kenneth Train and Yves Croissant." + "Let's recreate this [tutorial](https://cran.r-project.org/web/packages/mlogit/vignettes/e1mlogit.html) by Yves Croissant for the mlogit R package.\n", + "\n", + "It uses the Heating dataset, where we try to predict which heating harware a houseold will chose. The dataset is integrated in the package, you can find information [here]." ] }, { @@ -49,12 +51,10 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "dataset = ChoiceDataset(contexts_items_features=contexts_items, choices=choices)" + "First part estimates a simple MNL without intercept from the 'ic' and 'oc' features. By default, SimpleMNL does not integrate any intercept, but you can precise 'None'." ] }, { @@ -64,7 +64,7 @@ "outputs": [], "source": [ "dataset = ChoiceDataset(contexts_items_features=contexts_items, choices=choices)\n", - "model = SimpleMNL(optimizer=\"lbfgs\")\n", + "model = SimpleMNL(optimizer=\"lbfgs\", intercept=None)\n", "history = model.fit(dataset, epochs=100, get_report=True)" ] }, @@ -74,7 +74,8 @@ "metadata": {}, "outputs": [], "source": [ - "model.evaluate(dataset) * len(dataset)" + "print(\"Estimation Negative LogLikelihood:\",\n", + " model.evaluate(dataset) * len(dataset))" ] }, { @@ -86,6 +87,13 @@ "model.report" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We reach very similar results. The second part is about modelling useing the ic + oc/0.12 ratio. Here is how it can be done:" + ] + }, { "cell_type": "code", "execution_count": null, @@ -119,16 +127,15 @@ "metadata": {}, "outputs": [], "source": [ - "model.weights" + "print(\"Weights:\", model.weights)\n", + "print(\"Estimation Negative LogLikelihood:\", model.evaluate(ratio_dataset) * len(ratio_dataset))" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "model.evaluate(ratio_dataset) * len(ratio_dataset)" + "Finally, to add itemwise intercept for the last part, here is how it can be done:" ] }, { From ff445e4e8743a40a63f15d9a3b786e684cb8286f Mon Sep 17 00:00:00 2001 From: Emmanuel MALHERBE Date: Fri, 16 Feb 2024 18:01:27 +0100 Subject: [PATCH 161/767] ADD : some cosmetics for notebooks (and choicedataset) --- choice_learn/data/choice_dataset.py | 33 +- .../choice_learn_introduction_data.ipynb | 418 ++++++++++++------ 2 files changed, 294 insertions(+), 157 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index 56448da1..72a4b239 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -363,7 +363,6 @@ def _build_features_by_ids(self): indexes and features_by_id of contexts_items_features """ if len(self.features_by_ids) == 0: - print("No features_by_ids given.") return {}, {}, {} if ( @@ -614,6 +613,10 @@ def __len__(self): """ return len(self.choices) + def __str__(self): + template = '''First choice is:\nItems features: {}\nContexts features: {}\nContexts Items features: {}\nContexts Items Availabilities: {}\nContexts Choice: {}''' + return template.format(self.batch[0][0], self.batch[0][1], self.batch[0][2], self.batch[0][3], self.batch[0][4]) + def get_num_items(self): """Method to access the total number of different items. @@ -823,13 +826,13 @@ def from_single_wide_df( def from_single_long_df( cls, df, + choices_column="choice", + items_id_column="item_id", + contexts_id_column="context_id", fixed_items_features_columns=None, contexts_features_columns=None, contexts_items_features_columns=None, - items_id_column="item_id", - contexts_id_column="context_id", - choices_column="choice", - choice_mode="items_id", + choice_format="items_id", ): """Builds numpy arrays for ChoiceDataset from a single dataframe in long format. @@ -837,19 +840,19 @@ def from_single_long_df( ---------- df : pandas.DataFrame dataframe in Long format + choices_column: str, optional + Name of the column containing the choices, default is "choice" + items_id_column: str, optional + Name of the column containing the item ids, default is "items_id" + contexts_id_column: str, optional + Name of the column containing the sessions ids, default is "contexts_id" fixed_items_features_columns : list Columns of the dataframe that are item features, default is None contexts_features_columns : list Columns of the dataframe that are contexts features, default is None contexts_items_features_columns : list Columns of the dataframe that are context-item features, default is None - items_id_column: str, optional - Name of the column containing the item ids, default is "items_id" - contexts_id_column: str, optional - Name of the column containing the sessions ids, default is "contexts_id" - choices_column: str, optional - Name of the column containing the choices, default is "choice" - choice_mode: str, optional + choice_format: str, optional How choice is indicated in df, either "items_name" or "one_zero", default is "items_id" @@ -901,13 +904,13 @@ def from_single_long_df( else None ) - if choice_mode == "items_id": + if choice_format == "items_id": choices = df[[choices_column, contexts_id_column]].drop_duplicates(contexts_id_column) choices = choices.set_index(contexts_id_column) choices = choices.loc[sessions].to_numpy() # items is the value (str) of the item choices = np.squeeze([np.where(items == c)[0] for c in choices]) - elif choice_mode == "one_zero": + elif choice_format == "one_zero": choices = df[[items_id_column, choices_column, contexts_id_column]] choices = choices.loc[choices[choices_column] == 1] choices = choices.set_index(contexts_id_column) @@ -918,7 +921,7 @@ def from_single_long_df( ) else: raise ValueError( - f"choice_mode {choice_mode} not recognized. Must be in ['items_id', 'one_zero']" + f"choice_format {choice_format} not recognized. Must be in ['items_id', 'one_zero']" ) return ChoiceDataset( fixed_items_features=items_features, diff --git a/notebooks/choice_learn_introduction_data.ipynb b/notebooks/choice_learn_introduction_data.ipynb index 05c0f692..32096086 100644 --- a/notebooks/choice_learn_introduction_data.ipynb +++ b/notebooks/choice_learn_introduction_data.ipynb @@ -4,62 +4,69 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Introduction to choice-learn's data management" + "# Introduction to choice-learn's data management" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import os\n", "import sys\n", - "from pathlib import Path\n", - "\n", - "sys.path.append(\"../\")\n", "\n", - "import numpy as np\n", - "import pandas as pd" + "sys.path.append(\"../\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### ChoiceDataset - Getting Started !\n", + "## ChoiceDataset - Getting Started !\n", + "\n", + "In order to estimate a model using the choice-learn API, you will first need to wrap your dataset within a ChoiceDataset.\n", "\n", - "choice-learn package aims at being able to handle large datasets. One of the main idea is to limit as much as possible the usage of memory to save several time the same feature.\n", + "choice-learn ChoiceDataset aims at being able to handle large datasets, typically by limiting the usage of memory to store several times the same feature.\n", "We define two sources of features, the items and the contexts.\n", "\n", "**Items** represent a product, an alternative that can be chosen by the customer at some point.\n", "\n", - "**Contexts** represent the different cases of the dataset. One context corresponds to one choice and regroups every factor that might be different from one choice to another.\n", + "**Contexts** represent the contexts surrounding each choice. One context corresponds to one choice and regroups every factor that might be different from one choice to another.\n", "\n", "\n", - "From these two concepts, we defines 5 different types of data, storing them separatly in order to avoid redundancy in memory:\n", + "From these two concepts, we defines 5 types of data:\n", "\n", "- **choices:** The main information, indicating which item/alternative has been chosen among all availables\n", "- **fixed_items_features:** The items features that never change (e.g. size, color, etc...) over the choices/contexts.\n", - "- **contexts_features:** It represents all the features that might change from one choice to another and that are **common** to all items (e.g. day of week, customer features, etc...)\n", - "- **contexts_items_features:** The features that are function of the item and of the context (e.g. prices change over contexts and are specific to each sold item, etc...)\n", - "\n", + " \n", + " Size=number of items.\n", + "- **contexts_features:** It represents all the features that might change from one choice to another and that are **common** to all items (e.g. day of week, customer features, etc...).\n", + " \n", + " Size=number of choices.\n", + "- **contexts_items_features:** The features that are function of the item and of the context (e.g. prices change over contexts and are specific to each sold item, etc...).\n", + " \n", + " Size=number of choices x number of items\n", "- **contexts_items_availabilities:** For each context it represents whether each item/alternative is proposed to the customer (1.) or not (0.).\n", + " \n", + " Size=number of choices.\n", "\n", "\n", - "In order to estimate a model using the choice-learn API, you will first need to wrap your dataset within a ChoiceDataset. The easiest way to do it is to use a pandas DataFrame, let's see how to do it !" + "The easiest way to do it is to use a pandas DataFrame, let's see how to do it !" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ + "## Hands-on: example from a DataFrame with ModeCanada\n", + "\n", "We will use the ModeCanada [1] dataset for this example. It is provided with the choice-learn package and can loaded as follows:" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": { "keep_output": true }, @@ -182,12 +189,15 @@ "5 3 train 0 83 28.25 50 66 4 70.0 0 2" ] }, - "execution_count": null, + "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "\n", "from choice_learn.data import ChoiceDataset\n", "from choice_learn.datasets import load_modecanada\n", "\n", @@ -225,7 +235,7 @@ "Easy ! It is the alternative whenever the value is one.\n", "\n", "**contexts_features**\n", - "The income, urban and distance (also noalt which is not really a feature) features are the same for all the alternative within a context: they are contexts_features.\n", + "The income, urban and distance (also noalt which is not really a feature) features are the same for all the alternative within a context: they are contexts_features. They are all constant with respect to a case=traveler ID.\n", "\n", "**contexts_items_features**\n", "Ivt, Ovt, cost and freq depends on the alternative and change over the contexts. They are contexts_items_features.\n", @@ -239,13 +249,150 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, - "outputs": [], + "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", + "
casealtchoicedistcostivtovtfreqincomeurbannoaltis_public
11train08328.255066445.0021.0
21car18315.77610045.0020.0
32train08328.255066425.0021.0
42car18315.77610025.0020.0
53train08328.255066470.0021.0
\n", + "
" + ], + "text/plain": [ + " case alt choice dist cost ivt ovt freq income urban noalt \\\n", + "1 1 train 0 83 28.25 50 66 4 45.0 0 2 \n", + "2 1 car 1 83 15.77 61 0 0 45.0 0 2 \n", + "3 2 train 0 83 28.25 50 66 4 25.0 0 2 \n", + "4 2 car 1 83 15.77 61 0 0 25.0 0 2 \n", + "5 3 train 0 83 28.25 50 66 4 70.0 0 2 \n", + "\n", + " is_public \n", + "1 1.0 \n", + "2 0.0 \n", + "3 1.0 \n", + "4 0.0 \n", + "5 1.0 " + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "transport_df = canada_transport_df.copy()\n", "items = [\"air\", \"bus\", \"car\", \"train\"]\n", "\n", + "# Add \"is_public\" feature for transport modes\n", "transport_df[\"is_public\"] = transport_df.apply(lambda row: 0. if row.alt == \"car\" else 1., axis=1)\n", "\n", "# Just some typing\n", @@ -260,46 +407,54 @@ "metadata": {}, "source": [ "Our feature, is_public is 0 for the car and 1 for all other alternatives, seems fine! We can now create our ChoiceDataset !\\\n", - "*Note that you do NOT need each type of feature, here the purpose was to give a complete example.*\n", + "*Note that you do NOT need each type of feature, here the purpose was to give a complete example.*" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Creating a ChoiceDataset from this *single* dataframe\n", "\n", "In order to create the ChoiceDataset from the DataFrame, we need to specify:\n", + "- the column in which the choice is given\n", + "- the column where the item is identified \n", + "- the column where the context is identified\n", "- the columns representing the fixed_items_features\n", "- the columns representing the contexts_features\n", "- the columns representing the contexts_items_features\n", - "- the column where the item is identified \n", - "- the column where the context is identified\n", - "- the column in which the choice is given\n", + "\n", "\n", "For our Canada Transport example, here is how it should be done:" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ - "dataset = ChoiceDataset.from_single_long_df(df=transport_df,\n", - " fixed_items_features_columns=[\"is_public\"],\n", - " contexts_features_columns=[\"income\", \"urban\", \"dist\"],\n", - " contexts_items_features_columns=[\"cost\", \"freq\", \"ovt\", \"ivt\"],\n", - " items_id_column=\"alt\",\n", - " contexts_id_column=\"case\",\n", - " choices_column=\"choice\",\n", - " choice_mode=\"one_zero\")" + "dataset = ChoiceDataset.from_single_long_df(\n", + " df=transport_df,\n", + " choices_column=\"choice\",\n", + " items_id_column=\"alt\",\n", + " contexts_id_column=\"case\",\n", + " fixed_items_features_columns=[\"is_public\"],\n", + " contexts_features_columns=[\"income\", \"urban\", \"dist\"],\n", + " contexts_items_features_columns=[\"cost\", \"freq\", \"ovt\", \"ivt\"],\n", + " choice_format=\"one_zero\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "I have added an argument without any warning, the \"choice_mode\". It only precises how the choice is encoded in the dataframe. Currently two modes are availble:\n", + "Last argument, \"choice_format\", precises how the choice is encoded in the dataframe. Currently two modes are availble:\n", "\n", - "**one_zero:**\n", + " - *one_zero*:\n", "The choice column contains a 0 when the alternative/item is not chosen in the session and a 1 if it is chosen.\n", "This is the case here with Canada Transport.\n", - "\n", - "**item_id:**\n", + " - *item_id*:\n", "The choice column contains the id of the choice during the session. The id corresponds to the values used in the column 'items_id_column'.\n", "In this case of Canada Transport, the dataframe would need to be:\n", "\n", @@ -321,7 +476,7 @@ "The ChoiceDataset is ready !\n", "\n", "You now have three possibilities to continue discovering the choice-learn package:\n", - "- You can directly go [here]() to the modelling tutorial if you want to understand how a first simple ConditionMNl would be implementd.\n", + "- You can directly go [here]() to the modelling tutorial if you want to understand how a first simple ConditionMNL would be implementd.\n", "- You can go [here]() if your dataset is organized differently to see all the different ways to instantiate a ChoiceDataset. In particular it helps if you DataFrame is in the wide format or if it is splitted into several DataFrames.\n", "- Or you can continue this current tutorial to better understand the ChoiceDataset machinery and everything there is to know about it.\n", "\n", @@ -332,26 +487,29 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### ChoiceDataset - Inside the machine\n", + "## Hands-on: example from a NumPy arrays\n", + "\n", + "Let's see an example of ChoiceDataset instantiation from numpy arrays.\n", + "\n", + "Let's consider three *items* whose *features* are: Size, Weight, price, promotion (simply a boolean to indicate whether it is under promotion).\n", + "\n", + "For size and weights, we will store as *fixed items features* as they don't change. For the price and promotion, we will store in the *contexts items features*, since they may change for each context.\n", "\n", - "Let's see an example of ChoiceDataset instantiation from numpy arrays:" + "For the *contexts*, we will consider the customers attributes: Budget and age." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ - "# Let's see an example of ChoiceDataset instantiation\n", - "\n", - "# from choice-learn.data import ChoiceDataset\n", + "# Choices:\n", + "# Customer 1 bought item 1\n", + "# Customer 2 bought item 3\n", + "# Customer 1 bought item 2\n", "\n", - "# Let's consider three items whose features are:\n", - "# - Size\n", - "# - Weight\n", - "# - price\n", - "# - whether is is on promotion or not\n", + "choices = [0, 2, 1]\n", "\n", "fixed_items_features = [\n", " [1, 2], # item 1 [size, weight]\n", @@ -359,42 +517,35 @@ " [1.5, 1.5], # item 3 [size, weight]\n", "]\n", "\n", - "# We have two customers whose features are\n", - "# - Budget\n", - "# - Age\n", - "# Customer 1 bought item 1 at session 1 and item 2 at session 3\n", - "# Customer 2 bought item 3 at session 2\n", - "\n", - "choices = [0, 2, 1]\n", - "contexts_items_availabilities = [\n", - " [1, 1, 1], # All items available at session 1\n", - " [1, 1, 1], # All items available at session 2\n", - " [0, 1, 1], # Item 1 not available at session 3\n", - "]\n", - "\n", "contexts_features = [\n", - " [100, 20], # session 1, customer 1 [budget, age]\n", - " [200, 40], # session 2, customer 2 [budget, age]\n", - " [80, 20], # session 3, customer 1 [budget, age]\n", + " [100, 20], # choice 1, customer 1 [budget, age]\n", + " [200, 40], # choice 2, customer 2 [budget, age]\n", + " [80, 20], # choice 3, customer 1 [budget, age]\n", "]\n", "\n", "contexts_items_features = [\n", " [\n", - " [100, 0], # Session 1, Item 1 [price, promotion]\n", - " [140, 0], # Session 1, Item 2 [price, promotion]\n", - " [200, 0], # Session 1, Item 2 [price, promotion]\n", + " [100, 0], # choice 1, Item 1 [price, promotion]\n", + " [140, 0], # choice 1, Item 2 [price, promotion]\n", + " [200, 0], # choice 1, Item 2 [price, promotion]\n", " ],\n", " [\n", - " [100, 0], # Session 2 Item 1 [price, promotion]\n", - " [120, 1], # Session 2, Item 2 [price, promotion]\n", - " [200, 0], # Session 2, Item 2 [price, promotion]\n", + " [100, 0], # choice 2, Item 1 [price, promotion]\n", + " [120, 1], # choice 2, Item 2 [price, promotion]\n", + " [200, 0], # choice 2, Item 2 [price, promotion]\n", " ],\n", " [\n", - " [100, 0], # Session 3, Item 1 [price, promotion], values do not really matter, but needs to exist for shapes sake\n", - " [120, 1], # Session 3, Item 2 [price, promotion]\n", - " [180, 1], # Session 3, Item 2 [price, promotion]\n", + " [100, 0], # choice 3, Item 1 [price, promotion]\n", + " [120, 1], # choice 3, Item 2 [price, promotion]\n", + " [180, 1], # choice 3, Item 2 [price, promotion]\n", " ],\n", - "]\n" + "]\n", + "\n", + "contexts_items_availabilities = [\n", + " [1, 1, 1], # All items available at choice 1\n", + " [1, 1, 1], # All items available at choice 2\n", + " [0, 1, 1], # Item 1 not available at choice 3\n", + "]" ] }, { @@ -403,23 +554,24 @@ "source": [ "Note that in items_features and contexts_items_features, the features need to be well ordered:\n", "- The features are ordered the same for all items\n", - "- The items are ordered the same for items_features and contexts_items_features, and their index is used in choices:\n", + "- The items are ordered in their index given in choices. This applies in items_features and contexts_items_features\n", "\n", "\n", - "**items_features** = [[feature_1_item_A, feature_2_item_A, ...], [features_1_item_B, feature_2_item_B, ...], ...]\n", + "**items_features** = [[item1_featureA, item1_featureB, ...], [item2_featureA, item2_featureB, ...], ...]\n", "\n", - "**contexts_items_features** = [[[context_1_feature_1_item_A, ...], [context_1_feature_1_item_B, ...]], [[context_2_feature_1_item_A, ...], [context_2_feature_1_item_B, ...]], ...]\n", + "**contexts_items_features** = [[[context1_item1_featureA, ...], [context1_item2_featureA, ...]], [[context2_item1_featureA, ...], [context2_item2_featureA, ...]], ...]\n", "\n", - "**choices** then represent the index of the item: 0 when item_1 is chose, 1 when item_2, etc..., e.g. [0, 0, 2, 1, ...]" + "**choices** then represent the index of the item: 0 when item1 is chose, 1 when item2, etc..., e.g. [0, 0, 2, 1, ...]" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "dataset = ChoiceDataset(\n", + " choices=choices,\n", " fixed_items_features=fixed_items_features,\n", " fixed_items_features_names=[\"size\", \"weight\"], # You can precise the names of the features if you want\n", " contexts_features=contexts_features,\n", @@ -427,13 +579,12 @@ " contexts_items_features=contexts_items_features,\n", " contexts_items_features_names=[\"price\", \"promotion\"], # same, not mandatory\n", " contexts_items_availabilities=contexts_items_availabilities,\n", - " choices=choices,\n", ")" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": { "keep_output": true }, @@ -444,7 +595,7 @@ "(3, 3, 2)" ] }, - "execution_count": null, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -457,13 +608,40 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "ChoiceDataset is indexed by session. You can use [] to subset it.\n", + "ChoiceDataset is indexed by choice. You can use [] to subset it.\n", "It is particularly useful for train/test split:" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Some choices never happen in the dataset: {1, 2}\n", + "First choice is:\n", + "Items features: (array([[1. , 2. ],\n", + " [2. , 4. ],\n", + " [1.5, 1.5]], dtype=float32),)\n", + "Contexts features: (array([100, 20], dtype=int32),)\n", + "Contexts Items features: (array([[100, 0],\n", + " [140, 0],\n", + " [200, 0]], dtype=int32),)\n", + "Contexts Items Availabilities features: [1 1 1]\n", + "Contexts Choices: 0\n" + ] + } + ], + "source": [ + "print(dataset[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 11, "metadata": { "keep_output": true }, @@ -492,7 +670,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "If you want to access the features you can use the .iloc function with sessions indexes \n", + "If you want to access the features you can use the .iloc function with choices indexes \n", "It returns the features in this order:\n", "\n", "- items_features (n_items, n_items_features)\n", @@ -519,7 +697,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "metadata": { "keep_output": true }, @@ -566,7 +744,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "metadata": { "keep_output": true }, @@ -595,23 +773,19 @@ ], "source": [ "# All the features are given for each session, in order to compute utility and NegativeLogLikelihood\n", - "for n_batch, batch in enumerate(dataset.iter_batch(batch_size=1)):\n", - " print(n_batch, batch)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that you will need to use a ChoiceDataset to use the models." + "for i, batch in enumerate(dataset.iter_batch(batch_size=1)):\n", + " print(i, batch)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "**Stacking features**\n", - "If you need to keep a clear distinction between different features, you can use stacking in the ChoiceDataset. For example if we have two kind of items_features and we do not want them to be within the same np.ndarray we can as follow:" + "**Stacking features when building the ChoiceDataset**\n", + "\n", + "If you need to keep a clear distinction between different features, you can use stacking in the ChoiceDataset. In this case, you need to provide the additional features arrays indexed the same. It is possible to stack: *items_features*, *contexts_features*, *contexts_items_features*.\n", + "\n", + "For example if we have two kind of items_features and we do not want them to be within the same np.ndarray we can as follow:" ] }, { @@ -675,34 +849,6 @@ "dataset.batch[0]" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This is possible with:\n", - "- items_features\n", - "- contexts_features\n", - "- contexts_items_features\n", - "As the other should not need any superposition of values." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset = ChoiceDataset(\n", - " fixed_items_features=(fixed_items_features, items_features_2), # Here items_features specified as a tuple of the two features lists\n", - " contexts_features=(contexts_features, contexts_features),\n", - " contexts_items_features=(contexts_items_features, contexts_items_features),\n", - " contexts_items_availabilities=contexts_items_availabilities,\n", - " choices=choices,\n", - ")\n", - "\n", - "dataset.batch[0]" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -1378,23 +1524,11 @@ "[1] Koppelman et al. (1993), *Application and Interpretation of Nested Logit Models of Intercity Mode Choice*\\\n", "[2] Bierlaire, M., Axhausen, K. and Abay, G. (2001), *The Acceptance of Modal Innovation: The Case of SwissMetro*" ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { "kernelspec": { - "display_name": "tf_env", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -1408,9 +1542,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.4" + "version": "3.9.18" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } From a9ceb166f8fdd87e2b7fb141a5fcf22fbb1b59d1 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 16 Feb 2024 18:35:02 +0100 Subject: [PATCH 162/767] commit du we, unfinished business :/ --- choice_learn/datasets/data/train_data.csv.gz | Bin 0 -> 22811 bytes choice_learn/models/base_model.py | 33 ++++++++++++------- choice_learn/models/simple_mnl.py | 6 ++-- 3 files changed, 25 insertions(+), 14 deletions(-) create mode 100644 choice_learn/datasets/data/train_data.csv.gz diff --git a/choice_learn/datasets/data/train_data.csv.gz b/choice_learn/datasets/data/train_data.csv.gz new file mode 100644 index 0000000000000000000000000000000000000000..540f7d326ad59e25f78f1117f4744ab8555155a0 GIT binary patch literal 22811 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 literal 0 HcmV?d00001 diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index abf17cef..c0228b0b 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -722,7 +722,7 @@ class BaseMixtureModel(object): def __init__( self, - latent_classes, + n_latent_classes, model_class, model_parameters, fit_method, @@ -732,7 +732,7 @@ def __init__( Parameters ---------- - latent_classes : int + n_latent_classes : int Number of latent classes model_class : BaseModel class of models to get a mixture of @@ -743,7 +743,7 @@ class of models to get a mixture of epochs : int Number of epochs to train the model. """ - self.latent_classes = latent_classes + self.n_latent_classes = n_latent_classes self.model_parameters = model_parameters self.model_class = model_class self.fit_method = fit_method @@ -752,9 +752,11 @@ class of models to get a mixture of def instantiate(self): """Instantiation.""" - self.latent_logit = tf.Variable(tf.ones(self.latent_classes)) / self.latent_classes + init_logit = tf.random.uniform((self.n_latent_classes,)) + init_logit = init_logit / tf.reduce_sum(init_logit) + self.latent_logits = tf.Variable(init_logit) self.models = [ - self.model_class(**self.model_parameters) for _ in range(self.latent_classes) + self.model_class(**self.model_parameters) for _ in range(self.n_latent_classes) ] if self.fit_method == "EM": @@ -773,12 +775,19 @@ def _em_fit(self, dataset): params=proba, indices=tf.stack([tf.range(0, len(dataset), 1), dataset.choices], axis=1), ) - for latent, proba in zip(self.latent_logit, predicted_probas) + for latent, proba in zip(self.latent_logits, predicted_probas) ] + weights = tf.stack(predicted_probas, axis=0) / tf.reduce_sum( + predicted_probas, axis=0, keepdims=True + ) - weights = predicted_probas / tf.reduce_sum(predicted_probas, axis=0, keepdims=True) - for q in range(self.latent_classes): - print(weights[q].shape) - self.models[q].fit(dataset, sample_weight=weights[q]) - - self.latent_probas = tf.reduce_mean(weights, axis=0) + models = [] + for q in range(self.n_latent_classes): + model = self.model_class(**self.model_parameters) + sample_weight = weights[q, :] + sample_weight = tf.gather(weights, q, axis=0) + model.fit(dataset, sample_weight=sample_weight) + models.append(model) + self.models = models + print(weights[:, :4]) + self.latent_logits = tf.reduce_mean(weights, axis=1) diff --git a/choice_learn/models/simple_mnl.py b/choice_learn/models/simple_mnl.py index 9f5cf7b0..17ad48f5 100644 --- a/choice_learn/models/simple_mnl.py +++ b/choice_learn/models/simple_mnl.py @@ -213,10 +213,12 @@ def _fit_with_lbfgs( Choice dataset to use for the estimation. n_epochs : int Number of epochs to run. + sample_weight: Iterable, optional + list of each sample weight, by default None meaning that all samples have weight 1. tolerance : float, optional - Tolerance in the research of minimum, by default 1e-8 + Tolerance in the research of minimum, by default 1e-8. get_report: bool, optional - Whether or not to compute a report of the estimation, by default False + Whether or not to compute a report of the estimation, by default False. Returns: -------- From 0ed2840d3de393f94c0127e158d35f2cc43c0b72 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 19 Feb 2024 09:47:57 +0100 Subject: [PATCH 163/767] ADD: wip MixMNL notebook --- notebooks/simple_and_mix_logit.ipynb | 242 +++++++++++++++++++++++++++ 1 file changed, 242 insertions(+) diff --git a/notebooks/simple_and_mix_logit.ipynb b/notebooks/simple_and_mix_logit.ipynb index 3d4860dc..4f9b4862 100644 --- a/notebooks/simple_and_mix_logit.ipynb +++ b/notebooks/simple_and_mix_logit.ipynb @@ -157,6 +157,248 @@ "model.report" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from choice_learn.datasets import load_swissmetro\n", + "from choice_learn.models.base_model import BaseMixtureModel" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sm_df = load_swissmetro(as_frame=True)\n", + "sm_df = sm_df.loc[sm_df.CHOICE != 0]\n", + "sm_df.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "[sm_df[[f\"{item}_{feature}\" for feature in [\"CO\", \"TT\"]]] for item in [\"CAR\", \"TRAIN\", \"SM\"]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sm_df.CHOICE" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "contexts_items = np.stack([sm_df[[f\"{item}_{feature}\" for feature in [\"CO\", \"TT\"]]].to_numpy() for item in [\"CAR\", \"TRAIN\", \"SM\"]],\n", + "axis=1)\n", + "contexts_items[:, :, 0] = contexts_items[:, :, 0] / 100\n", + "contexts_items[:, :, 1] = contexts_items[:, :, 1] / 100\n", + "dataset = ChoiceDataset(\n", + " contexts_items_features=contexts_items,\n", + " choices=sm_df.CHOICE.to_numpy()-1\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.unique(dataset.choices)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import tensorflow as tf\n", + "import importlib\n", + "import choice_learn.models.base_model\n", + "importlib.reload(choice_learn.models.base_model)\n", + "\n", + "from choice_learn.models.base_model import BaseMixtureModel" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model = BaseMixtureModel(\n", + " n_latent_classes=2,\n", + " model_class=SimpleMNL,\n", + " model_parameters={\"optimizer\": \"lbfgs\", \"epochs\": 20},\n", + " fit_method=\"EM\",\n", + " epochs=2,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.instantiate()\n", + "model._em_fit(dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.models[0].weights" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.models[1].weights" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.latent_logits" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "predicted_probas = [m.predict_probas(dataset) for m in model.models]\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "predicted_probas" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for latent, proba in zip(model.latent_logits, predicted_probas):\n", + " print(latent, proba[:4])\n", + " print(latent\n", + " * tf.gather_nd(\n", + " params=proba,\n", + " indices=tf.stack([tf.range(0, len(dataset), 1), dataset.choices], axis=1),\n", + " )[:4])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "predicted_probas = [\n", + " latent\n", + " * tf.gather_nd(\n", + " params=proba,\n", + " indices=tf.stack([tf.range(0, len(dataset), 1), dataset.choices], axis=1),\n", + " )\n", + " for latent, proba in zip(model.latent_logits, predicted_probas)\n", + "]\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "predicted_probas" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "weights = predicted_probas / tf.reduce_sum(predicted_probas, axis=0, keepdims=True)\n", + "weights" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for q in range(self.n_latent_classes):\n", + " self.models[q].fit(dataset, sample_weight=weights[q])\n", + "\n", + "self.latent_logits = tf.reduce_mean(weights, axis=1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model = SimpleMNL(optimizer=\"lbfgs\", intercept=\"item\")\n", + "model.fit(dataset, sample_weight=np.random.rand(len(dataset)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.weights" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model = SimpleMNL(optimizer=\"lbfgs\", intercept=\"item\")\n", + "model.fit(dataset)\n", + "model.weights" + ] + }, { "cell_type": "code", "execution_count": null, From 38dab82fde2f155753100bf52ff6dd72a9eb0e71 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 19 Feb 2024 10:05:44 +0100 Subject: [PATCH 164/767] ENH: from Luca's remarks round 1 --- README.md | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 9481432a..930a1775 100644 --- a/README.md +++ b/README.md @@ -43,18 +43,18 @@ If you are new to choice modelling, you can check this [resource](https://www.pu ### Data - Generic dataset handling with the ChoiceDataset class - Ready-To-Use datasets: - - SwissMetro from Bierlaire et al. (2001) - - ModeCanada from Koppelman et al. (1993) + - [SwissMetro](./choice_learn/datasets/data/swissmetro.csv.gz) from Bierlaire et al. (2001) [[2]](#citation) + - [ModeCanada](./choice_learn/datasets/data/ModeCanada.csv.gz) from Koppelman et al. (1993) [[3]](#citation) ### Models -- Ready to use models: - - Conditional MultiNomialLogit, Train, K.; McFadden, D.; Ben-Akiva, M. (1987) - - RUMnet, Aouad A.; Désir A. (2022) [1] -- Ready to use models to be implemented: +- Ready-to-use models: + - Conditional MultiNomialLogit, Train, K.; McFadden, D.; Ben-Akiva, M. (1987) [[4]](#citation) + - RUMnet, Aouad A.; Désir A. (2022) [[1]](#citation) +- Ready-to-use models to be implemented: - Nested MultiNomialLogit - MultiNomialLogit with latent variables (MixedLogit) - - TasteNet - - SHOPPER + - [TasteNet](https://arxiv.org/abs/2002.00922) + - [SHOPPER](https://projecteuclid.org/journals/annals-of-applied-statistics/volume-14/issue-1/SHOPPER--A-probabilistic-model-of-consumer-choice-with-substitutes/10.1214/19-AOAS1265.full) - Others ... - Custom modelling is made easy by subclassing the ChoiceModel class @@ -113,7 +113,10 @@ A detailed documentation of this project is available [here](https://artefactory ## References ### Papers -[1][Representing Random Utility Choice Models with Neural Networks](https://arxiv.org/abs/2207.12877), Aouad A.; Désir A. (2022) +[1][Representing Random Utility Choice Models with Neural Networks](https://arxiv.org/abs/2207.12877), Aouad, A.; Désir, A. (2022)\ +[2][The Acceptance of Model Innovation: The Case of Swissmetro](https://www.researchgate.net/publication/37456549_The_acceptance_of_modal_innovation_The_case_of_Swissmetro), Bierlaire, M.; Axhausen, K., W.; Abay, G. (2001)\ +[3][Applications and Interpretation of Nested Logit Models of Intercity Mode Choice](https://trid.trb.org/view/385097), Forinash, C., V.; Koppelman, F., S. (1993) +[4][The Demand for Local Telephone Service: A Fully Discrete Model of Residential Calling Patterns and Service Choices](https://www.jstor.org/stable/2555538), Train K., E.; McFadden, D., L.; Moshe, B. (1987) ### Code and Repositories - [PyLogit](https://github.com/timothyb0912/pylogit) From a126bc420d9de4d5a95b22393ef543083a21f58c Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 19 Feb 2024 10:17:56 +0100 Subject: [PATCH 165/767] ENH: ReadMe --- README.md | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 930a1775..005b18f6 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,40 @@ Finally, an optional requirement used for report and LBFG-s use is: ```python from choice_learn.data import ChoiceDataset from choice_learn.models import ConditionalMNL, RUMnet + +# Instantiation of a ChoiceDataset from a pandas.DataFrame +# Onl need to specify how the file is encoded: +dataset = ChoiceDataset.from_single_long_df(df=transport_df, + items_id_column="alt", + contexts_id_column="case", + choices_column="choice", + contexts_features_columns=["income"], + contexts_items_features_columns=["cost", "freq", "ovt", "ivt"], + choice_format="item_id") + +# Initialization of the model +model = ConditionalMNL(optimizer="lbfgs") + +# Creation of the different weights: + + +# add_coefficients adds one coefficient for each specified item_index +# intercept, and income are added for each item except the first one that needs to be zeroed +model.add_coefficients(coefficient_name="beta_inter", feature_name="intercept", items_indexes=[1, 2, 3]) +model.add_coefficients(coefficient_name="beta_income", feature_name="income", items_indexes=[1, 2, 3]) + +# ivt is added for each item: +model.add_coefficients(coefficient_name="beta_ivt", feature_name="ivt", items_indexes=[0, 1, 2, 3]) + +# shared_coefficient add one coefficient that is used for all items specified in the items_indexes: +# Here, cost, freq and ovt coefficients are shared between all items +model.add_shared_coefficient(coefficient_name="beta_cost", feature_name="cost", items_indexes=[0, 1, 2, 3]) +model.add_shared_coefficient(coefficient_name="beta_freq", feature_name="freq", items_indexes=[0, 1, 2, 3]) +model.add_shared_coefficient(coefficient_name="beta_ovt", feature_name="ovt", items_indexes=[0, 1, 2, 3]) + +history = model.fit(dataset, epochs=1000, get_report=True) +print("The average neg-loglikelihood is:", model.evaluate(dataset).numpy()) +print(model.report) ``` ## Documentation @@ -115,10 +149,12 @@ A detailed documentation of this project is available [here](https://artefactory ### Papers [1][Representing Random Utility Choice Models with Neural Networks](https://arxiv.org/abs/2207.12877), Aouad, A.; Désir, A. (2022)\ [2][The Acceptance of Model Innovation: The Case of Swissmetro](https://www.researchgate.net/publication/37456549_The_acceptance_of_modal_innovation_The_case_of_Swissmetro), Bierlaire, M.; Axhausen, K., W.; Abay, G. (2001)\ -[3][Applications and Interpretation of Nested Logit Models of Intercity Mode Choice](https://trid.trb.org/view/385097), Forinash, C., V.; Koppelman, F., S. (1993) -[4][The Demand for Local Telephone Service: A Fully Discrete Model of Residential Calling Patterns and Service Choices](https://www.jstor.org/stable/2555538), Train K., E.; McFadden, D., L.; Moshe, B. (1987) +[3][Applications and Interpretation of Nested Logit Models of Intercity Mode Choice](https://trid.trb.org/view/385097), Forinash, C., V.; Koppelman, F., S. (1993)\ +[4][The Demand for Local Telephone Service: A Fully Discrete Model of Residential Calling Patterns and Service Choices](https://www.jstor.org/stable/2555538), Train K., E.; McFadden, D., L.; Moshe, B. (1987)\ ### Code and Repositories -- [PyLogit](https://github.com/timothyb0912/pylogit) -- [Torch Choice](https://gsbdbi.github.io/torch-choice/) - [1][RUMnet](https://github.com/antoinedesir/rumnet) +- [PyLogit](https://github.com/timothyb0912/pylogit) +- [Torch Choice](https://gsbdbi.github.io/torch-choice) +- [BioGeme](https://github.com/michelbierlaire/biogeme) +- [mlogit](https://github.com/cran/mlogit) From 6ede510164add1758372ae43c478c9fa945fdcd4 Mon Sep 17 00:00:00 2001 From: Emmanuel MALHERBE Date: Mon, 19 Feb 2024 10:40:31 +0100 Subject: [PATCH 166/767] ADD: precommit fixes --- README.md | 2 +- .../choice_learn_introduction_data.ipynb | 188 ++---------------- tests/unit_tests/data/test_choice_dataset.py | 4 +- 3 files changed, 21 insertions(+), 173 deletions(-) diff --git a/README.md b/README.md index 3ae3bf86..ce54f68f 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,7 @@ If you consider this package and any of its feature useful for your research, pl ### License -The use of this software is under the MIT (tbc) license, with no limitation of usage, including for commercial applications. +The use of this software is under the MIT (tbc) license, with no limitation of usage, including for commercial applications. ## References diff --git a/notebooks/choice_learn_introduction_data.ipynb b/notebooks/choice_learn_introduction_data.ipynb index 32096086..9ffd374e 100644 --- a/notebooks/choice_learn_introduction_data.ipynb +++ b/notebooks/choice_learn_introduction_data.ipynb @@ -9,7 +9,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -21,7 +21,9 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "jp-MarkdownHeadingCollapsed": true + }, "source": [ "## ChoiceDataset - Getting Started !\n", "\n", @@ -66,7 +68,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": { "keep_output": true }, @@ -189,7 +191,7 @@ "5 3 train 0 83 28.25 50 66 4 70.0 0 2" ] }, - "execution_count": 2, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -249,145 +251,9 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "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", - "
casealtchoicedistcostivtovtfreqincomeurbannoaltis_public
11train08328.255066445.0021.0
21car18315.77610045.0020.0
32train08328.255066425.0021.0
42car18315.77610025.0020.0
53train08328.255066470.0021.0
\n", - "
" - ], - "text/plain": [ - " case alt choice dist cost ivt ovt freq income urban noalt \\\n", - "1 1 train 0 83 28.25 50 66 4 45.0 0 2 \n", - "2 1 car 1 83 15.77 61 0 0 45.0 0 2 \n", - "3 2 train 0 83 28.25 50 66 4 25.0 0 2 \n", - "4 2 car 1 83 15.77 61 0 0 25.0 0 2 \n", - "5 3 train 0 83 28.25 50 66 4 70.0 0 2 \n", - "\n", - " is_public \n", - "1 1.0 \n", - "2 0.0 \n", - "3 1.0 \n", - "4 0.0 \n", - "5 1.0 " - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "transport_df = canada_transport_df.copy()\n", "items = [\"air\", \"bus\", \"car\", \"train\"]\n", @@ -430,7 +296,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -500,7 +366,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -566,7 +432,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -584,7 +450,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": { "keep_output": true }, @@ -595,7 +461,7 @@ "(3, 3, 2)" ] }, - "execution_count": 7, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -614,34 +480,16 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Some choices never happen in the dataset: {1, 2}\n", - "First choice is:\n", - "Items features: (array([[1. , 2. ],\n", - " [2. , 4. ],\n", - " [1.5, 1.5]], dtype=float32),)\n", - "Contexts features: (array([100, 20], dtype=int32),)\n", - "Contexts Items features: (array([[100, 0],\n", - " [140, 0],\n", - " [200, 0]], dtype=int32),)\n", - "Contexts Items Availabilities features: [1 1 1]\n", - "Contexts Choices: 0\n" - ] - } - ], + "outputs": [], "source": [ "print(dataset[0])" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": { "keep_output": true }, @@ -697,7 +545,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": { "keep_output": true }, @@ -744,7 +592,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": { "keep_output": true }, diff --git a/tests/unit_tests/data/test_choice_dataset.py b/tests/unit_tests/data/test_choice_dataset.py index ed2b495f..3b52297a 100644 --- a/tests/unit_tests/data/test_choice_dataset.py +++ b/tests/unit_tests/data/test_choice_dataset.py @@ -272,7 +272,7 @@ def test_from_df(): fixed_items_features_columns=["items_feat_1", "items_feat_2"], contexts_features_columns=["session_feat_1", "session_feat_2"], contexts_items_features_columns=["session_item_feat_1", "session_item_feat_2"], - choice_mode="items_id", + choice_format="items_id", ) ground_truth_cd = ChoiceDataset( fixed_items_features=fixed_items_features, @@ -312,7 +312,7 @@ def test_from_df(): fixed_items_features_columns=["items_feat_1", "items_feat_2"], contexts_features_columns=["session_feat_1", "session_feat_2"], contexts_items_features_columns=["session_item_feat_1", "session_item_feat_2"], - choice_mode="one_zero", + choice_format="one_zero", ) ground_truth_cd = ChoiceDataset( fixed_items_features=fixed_items_features, From 055c773017f4977e034acddd6319ccbc00a2c780 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 19 Feb 2024 16:28:58 +0100 Subject: [PATCH 167/767] ENH: consitency in nummber & subset fix --- choice_learn/data/choice_dataset.py | 84 +++++++++++++++++++---------- 1 file changed, 55 insertions(+), 29 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index 818cb3bb..8e2c1779 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -614,7 +614,7 @@ def __len__(self): """ return len(self.choices) - def get_num_items(self): + def get_n_items(self): """Method to access the total number of different items. Returns: @@ -624,7 +624,7 @@ def get_num_items(self): """ return self.base_num_items - def get_num_choices(self): + def get_n_choices(self): """Method to access the total number of different choices. Redundant with __len__ method. @@ -940,7 +940,7 @@ def summary(self): print("%=====================================================================%") print("%%% Summary of the dataset:") print("%=====================================================================%") - print("Number of items:", self.get_num_items()) + print("Number of items:", self.get_n_items()) print( "Number of choices:", len(self), @@ -1301,41 +1301,67 @@ def __getitem__(self, choices_indexes): elif isinstance(choices_indexes, slice): return self.__getitem__(list(range(*choices_indexes.indices(len(self.choices))))) - if self.fixed_items_features[0] is None: - fixed_items_features = None - else: + try: + if self.fixed_items_features[0] is None: + fixed_items_features = None + else: + fixed_items_features = self.fixed_items_features + except TypeError: fixed_items_features = self.fixed_items_features - if self.contexts_features[0] is None: + + try: + if self.contexts_features[0] is None: + contexts_features = None + else: + contexts_features = tuple( + self.contexts_features[i][choices_indexes] + for i in range(len(self.contexts_features)) + ) + except TypeError: contexts_features = None - else: - contexts_features = tuple( - self.contexts_features[i][choices_indexes] - for i in range(len(self.contexts_features)) - ) - if self.contexts_items_features[0] is None: + + try: + if self.contexts_items_features[0] is None: + contexts_items_features = None + else: + contexts_items_features = tuple( + self.contexts_items_features[i][choices_indexes] + for i in range(len(self.contexts_items_features)) + ) + except TypeError: contexts_items_features = None - else: - contexts_items_features = tuple( - self.contexts_items_features[i][choices_indexes] - for i in range(len(self.contexts_items_features)) - ) - if self.fixed_items_features_names[0] is None: + + try: + if self.fixed_items_features_names[0] is None: + fixed_items_features_names = None + else: + fixed_items_features_names = self.fixed_items_features_names + except TypeError: fixed_items_features_names = None - else: - fixed_items_features_names = self.fixed_items_features_names - if self.contexts_features_names[0] is None: + try: + if self.contexts_features_names[0] is None: + contexts_features_names = None + else: + contexts_features_names = self.contexts_features_names + except TypeError: contexts_features_names = None - else: - contexts_features_names = self.contexts_features_names - if self.contexts_items_features_names[0] is None: + try: + if self.contexts_items_features_names[0] is None: + contexts_items_features_names = None + else: + contexts_items_features_names = self.contexts_items_features_names + except TypeError: contexts_items_features_names = None - else: - contexts_items_features_names = self.contexts_items_features_names + + try: + contexts_items_availabilities = self.contexts_items_availabilities[choices_indexes] + except TypeError: + contexts_items_availabilities = None return ChoiceDataset( fixed_items_features=fixed_items_features, contexts_features=contexts_features, contexts_items_features=contexts_items_features, - contexts_items_availabilities=self.contexts_items_availabilities[choices_indexes], + contexts_items_availabilities=contexts_items_availabilities, choices=[self.choices[i] for i in choices_indexes], fixed_items_features_names=fixed_items_features_names, contexts_features_names=contexts_features_names, @@ -1393,7 +1419,7 @@ def filter(self, bool_list): Parameters ---------- bool_list : list of boolean - list of booleans of length self.get_num_sessions() to filter sessions. + list of booleans of length self.get_n_contexts() to filter contexts. True to keep, False to discard. """ indexes = [i for i, keep in enumerate(bool_list) if keep] From dc6f745a37b6098293f55f172f61c5cbfbf9847f Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 19 Feb 2024 18:47:56 +0100 Subject: [PATCH 168/767] ENH: new Mixture archi --- choice_learn/models/base_model.py | 141 +++++++++++++++++++++++------- choice_learn/models/simple_mnl.py | 2 +- 2 files changed, 110 insertions(+), 33 deletions(-) diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index c0228b0b..65a9f82f 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -531,7 +531,7 @@ def predict_probas(self, choice_dataset, batch_size=-1): return tf.concat(stacked_probabilities, axis=0) - def evaluate(self, choice_dataset, sample_weight=None, batch_size=-1): + def evaluate(self, choice_dataset, sample_weight=None, batch_size=-1, mode="eval"): """Evaluates the model for each context and each product of a ChoiceDataset. Predicts the probabilities according to the model and computes the Negative-Log-Likelihood @@ -563,7 +563,10 @@ def evaluate(self, choice_dataset, sample_weight=None, batch_size=-1): choices=choices, sample_weight=sample_weight, ) - batch_losses.append(loss["NegativeLogLikelihood"]) + if mode == "eval": + batch_losses.append(loss["NegativeLogLikelihood"]) + elif mode == "optim": + batch_losses.append(loss["optimized_loss"]) if batch_size != -1: last_batch_size = contexts_items_availabilities.shape[0] coefficients = tf.concat( @@ -644,7 +647,9 @@ def f(params_1d): # update the parameters in the model assign_new_model_parameters(params_1d) # calculate the loss - loss_value = self.evaluate(dataset, sample_weight=sample_weight, batch_size=-1) + loss_value = self.evaluate( + dataset, sample_weight=sample_weight, batch_size=-1, mode="optim" + ) # calculate gradients and convert to 1D tf.Tensor grads = tape.gradient(loss_value, self.weights) @@ -744,7 +749,16 @@ class of models to get a mixture of Number of epochs to train the model. """ self.n_latent_classes = n_latent_classes - self.model_parameters = model_parameters + if isinstance(model_parameters, list): + if not len(model_parameters) == n_latent_classes: + raise ValueError( + """If you specify a list of hyper-parameters, it means that you want to use\ + different hyper-parameters for each latent class. In this case, the length\ + of the list must be equal to the number of latent classes.""" + ) + self.model_parameters = model_parameters + else: + self.model_parameters = [model_parameters] * n_latent_classes self.model_class = model_class self.fit_method = fit_method @@ -754,40 +768,103 @@ def instantiate(self): """Instantiation.""" init_logit = tf.random.uniform((self.n_latent_classes,)) init_logit = init_logit / tf.reduce_sum(init_logit) - self.latent_logits = tf.Variable(init_logit) - self.models = [ - self.model_class(**self.model_parameters) for _ in range(self.n_latent_classes) - ] + self.latent_logits = init_logit + self.models = [self.model_class(**mp) for mp in self.model_parameters] if self.fit_method == "EM": self.fit = self._em_fit + self.minf = np.log(1e-3) + + def _nothing(self, inputs): + """_summary_. + + Parameters + ---------- + inputs : _type_ + _description_ + + Returns: + -------- + _type_ + _description_ + """ + latent_probas = tf.clip_by_value( + self.latent_logits - tf.reduce_max(self.latent_logits), self.minf, 0 + ) + latent_probas = tf.math.exp(latent_probas) + # latent_probas = tf.math.abs(self.logit_latent_probas) # alternative implementation + latent_probas = latent_probas / tf.reduce_sum(latent_probas) + proba_list = [] + avail = inputs[4] + for q in range(self.n_latent_classes): + combined = self.models[q].compute_batch_utility(*inputs) + combined = tf.clip_by_value( + combined - tf.reduce_max(combined, axis=1, keepdims=True), self.minf, 0 + ) + combined = tf.keras.layers.Activation(activation=tf.nn.softmax)(combined) + # combined = tf.keras.layers.Softmax()(combined) + combined = combined * avail + combined = latent_probas[q] * tf.math.divide( + combined, tf.reduce_sum(combined, axis=1, keepdims=True) + ) + combined = tf.expand_dims(combined, -1) + proba_list.append(combined) + # print(combined.get_shape()) # it is useful to print the shape of tensors for debugging + + proba_final = tf.keras.layers.Concatenate(axis=2)(proba_list) + return tf.math.reduce_sum(proba_final, axis=2, keepdims=False) + + def _expectation(self, dataset): + predicted_probas = [model.predict_probas(dataset) for model in self.models] + if np.sum(np.isnan(predicted_probas)) > 0: + print("Nan in probas") + predicted_probas = [ + latent + * tf.gather_nd( + params=proba, + indices=tf.stack([tf.range(0, len(dataset), 1), dataset.choices], axis=1), + ) + for latent, proba in zip(self.latent_logits, predicted_probas) + ] + + # E-step + ###### FILL THE CODE BELOW TO ESTIMATE DETERMINE THE WEIGHTS (weights = xxx) + predicted_probas = np.stack(predicted_probas, axis=1) + 1e-10 + + return predicted_probas / np.sum(predicted_probas, axis=1, keepdims=True) + + def _maximization(self, dataset): + """_summary_. + + Parameters + ---------- + dataset : _type_ + _description_ + + Returns: + -------- + _type_ + _description_ + """ + self.models = [self.model_class(**mp) for mp in self.model_parameters] + # M-step: MNL estimation + for q in range(self.n_latent_classes): + self.models[q].fit(dataset, sample_weight=self.weights[:, q], tolerance=1e-6) + + # M-step: latent probability estimation + latent_probas = np.sum(self.weights, axis=0) + + return latent_probas / np.sum(latent_probas) def _em_fit(self, dataset): """Fit with Expectation-Maximization Algorithm.""" + hist_logits = [] + # Initialization for model in self.models: # model.instantiate() - model.fit(dataset) + model.fit(dataset, sample_weight=np.random.rand(len(dataset))) for i in tqdm.trange(self.epochs): - predicted_probas = [model.predict_probas(dataset) for model in self.models] - predicted_probas = [ - latent - * tf.gather_nd( - params=proba, - indices=tf.stack([tf.range(0, len(dataset), 1), dataset.choices], axis=1), - ) - for latent, proba in zip(self.latent_logits, predicted_probas) - ] - weights = tf.stack(predicted_probas, axis=0) / tf.reduce_sum( - predicted_probas, axis=0, keepdims=True - ) - - models = [] - for q in range(self.n_latent_classes): - model = self.model_class(**self.model_parameters) - sample_weight = weights[q, :] - sample_weight = tf.gather(weights, q, axis=0) - model.fit(dataset, sample_weight=sample_weight) - models.append(model) - self.models = models - print(weights[:, :4]) - self.latent_logits = tf.reduce_mean(weights, axis=1) + self.weights = self._expectation(dataset) + self.latent_logits = self._maximization(dataset) + hist_logits.append(self.latent_logits) + return hist_logits diff --git a/choice_learn/models/simple_mnl.py b/choice_learn/models/simple_mnl.py index 17ad48f5..a8225ccf 100644 --- a/choice_learn/models/simple_mnl.py +++ b/choice_learn/models/simple_mnl.py @@ -229,7 +229,7 @@ def _fit_with_lbfgs( # Lazy Instantiation print("Instantiation") self.indexes, self.weights = self.instantiate( - n_items=choice_dataset.get_num_items(), + n_items=choice_dataset.get_n_items(), n_fixed_items_features=choice_dataset.get_n_fixed_items_features(), n_contexts_features=choice_dataset.get_n_contexts_features(), n_contexts_items_features=choice_dataset.get_n_contexts_items_features(), From cec7ed32c068870b8e5b2037b5f3a5c581fc0021 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 19 Feb 2024 19:25:35 +0100 Subject: [PATCH 169/767] ADD: tolerance argument for lbfgs optim --- choice_learn/models/base_model.py | 34 +++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index 65a9f82f..85db1b74 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -20,6 +20,7 @@ def __init__( label_smoothing=0.0, normalize_non_buy=False, optimizer="Adam", + tolerance=1e-8, callbacks=None, lr=0.001, epochs=1, @@ -38,6 +39,15 @@ def __init__( normalization,by default True callbacks : list of tf.kera callbacks, optional List of callbacks to add to model.fit, by default None and only add History + optimizer : str, optional + Name of the tf.keras.optimizers to be used, by default "Adam" + tolerance : float, optional + Tolerance for the L-BFGS optimizer if applied, by default 1e-8 + lr: float, optional + Learning rate for the optimizer if applied, by default 0.001 + epochs: int, optional + (Max) Number of epochs to train the model, by default 1 + batch_size: int, optional """ self.is_fitted = False self.normalize_non_buy = normalize_non_buy @@ -69,6 +79,7 @@ def __init__( self.epochs = epochs self.batch_size = batch_size + self.tolerance = tolerance @abstractmethod def compute_batch_utility( @@ -585,6 +596,8 @@ def _lbfgs_train_step(self, dataset, sample_weight=None): ---------- dataset: ChoiceDataset Dataset on which to estimate the paramters. + sample_weight: np.ndarray, optional + Sample weights to apply, by default None Returns: -------- @@ -672,7 +685,7 @@ def f(params_1d): f.history = [] return f - def _fit_with_lbfgs(self, dataset, epochs=None, sample_weight=None, tolerance=1e-8): + def _fit_with_lbfgs(self, dataset, epochs=None, sample_weight=None): """Fit function for L-BFGS optimizer. Replaces the .fit method when the optimizer is set to L-BFGS. @@ -681,10 +694,10 @@ def _fit_with_lbfgs(self, dataset, epochs=None, sample_weight=None, tolerance=1e ---------- dataset : ChoiceDataset Dataset to be used for coefficients estimations - n_epochs : int + epochs : int Maximum number of epochs allowed to reach minimum - tolerance : float, optional - Maximum tolerance accepted, by default 1e-8 + sample_weight : np.ndarray, optional + Sample weights to apply, by default None Returns: -------- @@ -707,7 +720,7 @@ def _fit_with_lbfgs(self, dataset, epochs=None, sample_weight=None, tolerance=1e value_and_gradients_function=func, initial_position=init_params, max_iterations=epochs, - tolerance=tolerance, + tolerance=self.tolerance, f_absolute_tolerance=-1, f_relative_tolerance=-1, ) @@ -830,8 +843,9 @@ def _expectation(self, dataset): # E-step ###### FILL THE CODE BELOW TO ESTIMATE DETERMINE THE WEIGHTS (weights = xxx) predicted_probas = np.stack(predicted_probas, axis=1) + 1e-10 + loss = np.sum(np.log(np.sum(predicted_probas, axis=1))) - return predicted_probas / np.sum(predicted_probas, axis=1, keepdims=True) + return predicted_probas / np.sum(predicted_probas, axis=1, keepdims=True), loss def _maximization(self, dataset): """_summary_. @@ -849,7 +863,7 @@ def _maximization(self, dataset): self.models = [self.model_class(**mp) for mp in self.model_parameters] # M-step: MNL estimation for q in range(self.n_latent_classes): - self.models[q].fit(dataset, sample_weight=self.weights[:, q], tolerance=1e-6) + self.models[q].fit(dataset, sample_weight=self.weights[:, q], tolerance=1e-4) # M-step: latent probability estimation latent_probas = np.sum(self.weights, axis=0) @@ -859,12 +873,14 @@ def _maximization(self, dataset): def _em_fit(self, dataset): """Fit with Expectation-Maximization Algorithm.""" hist_logits = [] + hist_loss = [] # Initialization for model in self.models: # model.instantiate() model.fit(dataset, sample_weight=np.random.rand(len(dataset))) for i in tqdm.trange(self.epochs): - self.weights = self._expectation(dataset) + self.weights, loss = self._expectation(dataset) self.latent_logits = self._maximization(dataset) hist_logits.append(self.latent_logits) - return hist_logits + hist_loss.append(loss) + return hist_logits, hist_loss From aeb0ec7129b5bce418d9bd6fda5863714bd0b350 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 19 Feb 2024 19:28:20 +0100 Subject: [PATCH 170/767] ADD: verbosity --- choice_learn/models/base_model.py | 44 +++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index 85db1b74..8f9b3384 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -685,7 +685,7 @@ def f(params_1d): f.history = [] return f - def _fit_with_lbfgs(self, dataset, epochs=None, sample_weight=None): + def _fit_with_lbfgs(self, dataset, epochs=None, sample_weight=None, verbose=0): """Fit function for L-BFGS optimizer. Replaces the .fit method when the optimizer is set to L-BFGS. @@ -698,6 +698,8 @@ def _fit_with_lbfgs(self, dataset, epochs=None, sample_weight=None): Maximum number of epochs allowed to reach minimum sample_weight : np.ndarray, optional Sample weights to apply, by default None + verbose : int, optional + print level, for debugging, by default 0 Returns: -------- @@ -728,10 +730,11 @@ def _fit_with_lbfgs(self, dataset, epochs=None, sample_weight=None): # after training, the final optimized parameters are still in results.position # so we have to manually put them back to the model func.assign_new_model_parameters(results.position) - print("L-BFGS Opimization finished:") - print("---------------------------------------------------------------") - print("Number of iterations:", results[2].numpy()) - print("Algorithm converged before reaching max iterations:", results[0].numpy()) + if verbose > 0: + print("L-BFGS Opimization finished:") + print("---------------------------------------------------------------") + print("Number of iterations:", results[2].numpy()) + print("Algorithm converged before reaching max iterations:", results[0].numpy()) return func.history @@ -847,13 +850,15 @@ def _expectation(self, dataset): return predicted_probas / np.sum(predicted_probas, axis=1, keepdims=True), loss - def _maximization(self, dataset): + def _maximization(self, dataset, verbose=0): """_summary_. Parameters ---------- dataset : _type_ _description_ + verbose : int, optional + print level, for debugging, by default 0 Returns: -------- @@ -863,24 +868,41 @@ def _maximization(self, dataset): self.models = [self.model_class(**mp) for mp in self.model_parameters] # M-step: MNL estimation for q in range(self.n_latent_classes): - self.models[q].fit(dataset, sample_weight=self.weights[:, q], tolerance=1e-4) + self.models[q].fit( + dataset, sample_weight=self.weights[:, q], tolerance=1e-4, verbose=verbose + ) # M-step: latent probability estimation latent_probas = np.sum(self.weights, axis=0) return latent_probas / np.sum(latent_probas) - def _em_fit(self, dataset): - """Fit with Expectation-Maximization Algorithm.""" + def _em_fit(self, dataset, verbose=0): + """Fit with Expectation-Maximization Algorithm. + + Parameters + ---------- + dataset: ChoiceDataset + Dataset to be used for coefficients estimations + verbose : int, optional + print level, for debugging, by default 0 + + Returns: + -------- + list + List of logits for each latent class + list + List of losses at each epoch + """ hist_logits = [] hist_loss = [] # Initialization for model in self.models: # model.instantiate() - model.fit(dataset, sample_weight=np.random.rand(len(dataset))) + model.fit(dataset, sample_weight=np.random.rand(len(dataset)), verbose=verbose) for i in tqdm.trange(self.epochs): self.weights, loss = self._expectation(dataset) - self.latent_logits = self._maximization(dataset) + self.latent_logits = self._maximization(dataset, verbose=verbose) hist_logits.append(self.latent_logits) hist_loss.append(loss) return hist_logits, hist_loss From fcf75255027088e93da8d7822d7bd2a827ae3564 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Mon, 19 Feb 2024 20:03:04 +0100 Subject: [PATCH 171/767] FIX: kwargs, tolerance & other arguments --- choice_learn/models/base_model.py | 7 ++++--- choice_learn/models/conditional_mnl.py | 14 ++++++++++++-- choice_learn/models/simple_mnl.py | 6 ++---- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index 8f9b3384..26ed35b8 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -868,9 +868,7 @@ def _maximization(self, dataset, verbose=0): self.models = [self.model_class(**mp) for mp in self.model_parameters] # M-step: MNL estimation for q in range(self.n_latent_classes): - self.models[q].fit( - dataset, sample_weight=self.weights[:, q], tolerance=1e-4, verbose=verbose - ) + self.models[q].fit(dataset, sample_weight=self.weights[:, q], verbose=verbose) # M-step: latent probability estimation latent_probas = np.sum(self.weights, axis=0) @@ -905,4 +903,7 @@ def _em_fit(self, dataset, verbose=0): self.latent_logits = self._maximization(dataset, verbose=verbose) hist_logits.append(self.latent_logits) hist_loss.append(loss) + if np.sum(np.isnan(self.latent_logits)) > 0: + print("Nan in logits") + break return hist_logits, hist_loss diff --git a/choice_learn/models/conditional_mnl.py b/choice_learn/models/conditional_mnl.py index 8d40f684..9987f179 100644 --- a/choice_learn/models/conditional_mnl.py +++ b/choice_learn/models/conditional_mnl.py @@ -1008,7 +1008,13 @@ def fit(self, choice_dataset, get_report=False, **kwargs): return fit def _fit_with_lbfgs( - self, choice_dataset, epochs=None, sample_weight=None, tolerance=1e-8, get_report=False + self, + choice_dataset, + epochs=None, + sample_weight=None, + tolerance=1e-8, + get_report=False, + **kwargs, ): """Specific fit function to estimate the paramters with LBFGS. @@ -1043,7 +1049,11 @@ def _fit_with_lbfgs( if epochs is None: epochs = self.epochs fit = super()._fit_with_lbfgs( - dataset=choice_dataset, epochs=epochs, tolerance=tolerance, sample_weight=sample_weight + dataset=choice_dataset, + epochs=epochs, + tolerance=tolerance, + sample_weight=sample_weight, + **kwargs, ) if get_report: self.report = self.compute_report(choice_dataset) diff --git a/choice_learn/models/simple_mnl.py b/choice_learn/models/simple_mnl.py index a8225ccf..34415c7c 100644 --- a/choice_learn/models/simple_mnl.py +++ b/choice_learn/models/simple_mnl.py @@ -203,7 +203,7 @@ def fit(self, choice_dataset, get_report=False, **kwargs): return fit def _fit_with_lbfgs( - self, choice_dataset, epochs=None, sample_weight=None, tolerance=1e-8, get_report=False + self, choice_dataset, epochs=None, sample_weight=None, get_report=False, **kwargs ): """Specific fit function to estimate the paramters with LBFGS. @@ -215,8 +215,6 @@ def _fit_with_lbfgs( Number of epochs to run. sample_weight: Iterable, optional list of each sample weight, by default None meaning that all samples have weight 1. - tolerance : float, optional - Tolerance in the research of minimum, by default 1e-8. get_report: bool, optional Whether or not to compute a report of the estimation, by default False. @@ -238,7 +236,7 @@ def _fit_with_lbfgs( if epochs is None: epochs = self.epochs fit = super()._fit_with_lbfgs( - dataset=choice_dataset, epochs=epochs, tolerance=tolerance, sample_weight=sample_weight + dataset=choice_dataset, epochs=epochs, sample_weight=sample_weight, **kwargs ) if get_report: self.report = self.compute_report(choice_dataset) From 65fbbe0f086b6bdb232e6313a3e2cad8636182dc Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 20 Feb 2024 17:25:26 +0100 Subject: [PATCH 172/767] WIP: notebooks --- notebooks/mixture_mnl.ipynb | 368 +++++++++++++++++++++++--- notebooks/simple_and_mix_logit.ipynb | 377 +++++++++++++++++++++++++-- 2 files changed, 688 insertions(+), 57 deletions(-) diff --git a/notebooks/mixture_mnl.ipynb b/notebooks/mixture_mnl.ipynb index 93f22651..cbc48d62 100644 --- a/notebooks/mixture_mnl.ipynb +++ b/notebooks/mixture_mnl.ipynb @@ -15,6 +15,7 @@ "\n", "sys.path.append(\"../\")\n", "\n", + "import matplotlib.pyplot as plt\n", "import numpy as np\n", "import pandas as pd" ] @@ -25,15 +26,25 @@ "metadata": {}, "outputs": [], "source": [ - "from choice_learn.datasets import load_modecanada\n", - "\n", - "transport_df = load_modecanada(as_frame=True)\n", - "\n", - "# Following torch-choice guide:\n", - "transport_df = transport_df.loc[transport_df.noalt == 4]\n", - "\n", - "items = [\"air\", \"bus\", \"car\", \"train\"]\n", - "transport_df.income = transport_df.income.astype(\"float32\")" + "df = pd.read_csv(\"../../../electricity_r_data_long.csv\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df.choice = df.choice.astype(int)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df[[\"pf\", 'cl', \"loc\", \"wk\", \"tod\", \"seas\"]] = df[[\"pf\", 'cl', \"loc\", \"wk\", \"tod\", \"seas\"]].astype(float)" ] }, { @@ -42,15 +53,62 @@ "metadata": {}, "outputs": [], "source": [ - "# Initialization of the ChoiceDataset\n", "from choice_learn.data import ChoiceDataset\n", - "dataset = ChoiceDataset.from_single_df(df=transport_df,\n", - " contexts_features_columns=[\"income\"],\n", - " contexts_items_features_columns=[\"cost\", \"freq\", \"ovt\", \"ivt\"],\n", - " items_id_column=\"alt\",\n", - " contexts_id_column=\"case\",\n", - " choices_column=\"choice\",\n", - " choice_mode=\"one_zero\")" + "\n", + "dataset = ChoiceDataset.from_single_long_df(df=df,\n", + "contexts_items_features_columns=[\"pf\", \"cl\", \"loc\", \"wk\", \"tod\", \"seas\"],\n", + "items_id_column=\"alt\",\n", + "contexts_id_column=\"chid\",\n", + "choice_mode=\"one_zero\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from choice_learn.models.simple_mnl import SimpleMNL" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model = SimpleMNL(optimizer=\"lbfgs\", epochs=100, tolerance=1e-4)\n", + "h = model.fit(dataset, sample_weight=www)\n", + "h[-1]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import tensorflow as tf\n", + "model.weights = tf.constant([[-0.622498214, -0.108463198, 1.46465945, 1.02686298, -5.48458862, -5.86176395]])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bigP = model.predict_probas(dataset).numpy()\n", + "p = [(bigP[i][dataset.choices[i]]) for i in range(len(dataset))]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.min(p)" ] }, { @@ -69,19 +127,19 @@ "metadata": {}, "outputs": [], "source": [ - "hpp = {\n", - " \"parameters\": {\"income\": \"item\",\n", - " \"cost\": \"constant\",\n", - " \"freq\": \"constant\",\n", - " \"ovt\": \"constant\",\n", - " \"ivt\": \"item-full\",\n", - " \"intercept\": \"item\"},\n", - " \"optimizer\": \"lbfgs\",\n", - " \"epochs\": 10,\n", - "}\n", - "mixMNL = BaseMixtureModel(model_class=ConditionalMNL, \n", - " model_parameters=hpp,\n", - " latent_classes=4, epochs=10, fit_method=\"fit\")" + "mix = BaseMixtureModel(model_class=SimpleMNL,\n", + " model_parameters={\"optimizer\": \"lbfgs\", \"epochs\": 100, \"tolerance\": 1e-2},\n", + " n_latent_classes=3, epochs=200, fit_method=\"em\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mix.instantiate()\n", + "h1, h2 = mix._em_fit(dataset)" ] }, { @@ -90,10 +148,254 @@ "metadata": {}, "outputs": [], "source": [ - "mixMNL.instantiate()\n", - "mixMNL._em_fit(dataset)" + "(mix.models[0].weights,\n", + "mix.models[1].weights,\n", + "mix.models[2].weights)" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mix.weights" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mix.latent_logits" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "h2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.plot(h2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "len(dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "w1 = [-0.436786, -0.024613, 2.510545, 1.649299, -2.726110, -3.720022]\n", + "w2 = [-0.711346, -0.534724, 0.632174, 0.558454, -5.994899, -5.855283]\n", + "w3 = [-0.785066, -0.055608, 1.559850, 1.219109, -8.866931, -8.332032]\n", + "\n", + "lp = [np.exp(0), np.exp(-0.515807), np.exp(0.152700)]\n", + "lp = np.array(lp) / np.sum(lp)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mmm = [SimpleMNL(optimizer=\"lbfgs\", epochs=100, tolerance=1e-4) for _ in range(3)]\n", + "for _ in mmm:\n", + " _.fit(dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mmm[0].weights = tf.constant(w1)\n", + "mmm[1].weights = tf.constant(w2)\n", + "mmm[2].weights = tf.constant(w3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "probas = [_.predict_probas(dataset).numpy() for _ in mmm]\n", + "c_probas = []\n", + "for prob in probas:\n", + " prob = [prob[i][dataset.choices[i]] for i in range(len(dataset))]\n", + " c_probas.append(prob)\n", + "\n", + "class_logits = [0, -0.515807, 0.152700]\n", + "class_p = [np.exp(l) for l in class_logits]\n", + "class_p = np.array(class_p) / np.sum(class_p)\n", + "c_probas = np.sum([np.array(c_probas[i]) * class_p[i] for i in range(3)], axis=0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.sum(np.log(c_probas))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class_p" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.exp(0), np.exp(-0.515807), np.exp(0.152700)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "probas" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "xxx = dataset.contexts_items_features[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "p1 = np.exp(np.dot(xxx, w1)) / np.sum(np.exp(np.dot(xxx, w1)), axis=1, keepdims=True)\n", + "p2 = np.exp(np.dot(xxx, w2)) / np.sum(np.exp(np.dot(xxx, w2)), axis=1, keepdims=True)\n", + "p3 = np.exp(np.dot(xxx, w3)) / np.sum(np.exp(np.dot(xxx, w3)), axis=1, keepdims=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "p = np.sum([lp[0] * p1, lp[1] * p2, lp[2] * p3], axis=0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nll = [np.log(p[i][z]) for i, z in zip(range(len(p)), dataset.choices)]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.sum(nll)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import tensorflow as tf\n", + "\n", + "tf.keras.metrics.categorical_crossentropy(tf.one_hot(dataset.choices, 4), p)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "tf.reduce_sum(tf.keras.metrics.categorical_crossentropy(tf.one_hot(dataset.choices, 4), p))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nll[:4]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.log(.1), p[0], np.log(p[0][3])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": null, @@ -104,7 +406,7 @@ ], "metadata": { "kernelspec": { - "display_name": "tf_env", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, diff --git a/notebooks/simple_and_mix_logit.ipynb b/notebooks/simple_and_mix_logit.ipynb index 4f9b4862..e4c1cafd 100644 --- a/notebooks/simple_and_mix_logit.ipynb +++ b/notebooks/simple_and_mix_logit.ipynb @@ -184,7 +184,15 @@ "metadata": {}, "outputs": [], "source": [ - "[sm_df[[f\"{item}_{feature}\" for feature in [\"CO\", \"TT\"]]] for item in [\"CAR\", \"TRAIN\", \"SM\"]]" + "contexts_items = np.stack([sm_df[[f\"{item}_{feature}\" for feature in [\"CO\", \"TT\"]]].to_numpy() for item in [\"CAR\", \"TRAIN\", \"SM\"]],\n", + "axis=1)\n", + "contexts_items[:, :, 0] = contexts_items[:, :, 0] / 100\n", + "contexts_items[:, :, 1] = contexts_items[:, :, 1] / 100\n", + "dataset = ChoiceDataset(\n", + " contexts_items_features=(contexts_items, ),\n", + " choices=sm_df.CHOICE.to_numpy()-1,\n", + " contexts_items_features_names=([\"CO\", \"TT\"], ),\n", + ")" ] }, { @@ -193,7 +201,7 @@ "metadata": {}, "outputs": [], "source": [ - "sm_df.CHOICE" + "np.unique(dataset.choices), len(dataset)" ] }, { @@ -202,14 +210,13 @@ "metadata": {}, "outputs": [], "source": [ - "contexts_items = np.stack([sm_df[[f\"{item}_{feature}\" for feature in [\"CO\", \"TT\"]]].to_numpy() for item in [\"CAR\", \"TRAIN\", \"SM\"]],\n", - "axis=1)\n", - "contexts_items[:, :, 0] = contexts_items[:, :, 0] / 100\n", - "contexts_items[:, :, 1] = contexts_items[:, :, 1] / 100\n", - "dataset = ChoiceDataset(\n", - " contexts_items_features=contexts_items,\n", - " choices=sm_df.CHOICE.to_numpy()-1\n", - ")" + "import tensorflow as tf\n", + "import importlib\n", + "import choice_learn.models.base_model\n", + "importlib.reload(choice_learn.models.base_model)\n", + "\n", + "from choice_learn.models.base_model import BaseMixtureModel\n", + "from choice_learn.models.conditional_mnl import ConditionalMNL" ] }, { @@ -218,7 +225,8 @@ "metadata": {}, "outputs": [], "source": [ - "np.unique(dataset.choices)" + "spec = {\"CO\": \"constant\", \"TT\": \"item\", \"intercept\": \"item-full\"}\n", + "spec2 = {\"CO\": \"constant\", \"intercept\": \"item-full\"}" ] }, { @@ -227,12 +235,14 @@ "metadata": {}, "outputs": [], "source": [ - "import tensorflow as tf\n", - "import importlib\n", - "import choice_learn.models.base_model\n", - "importlib.reload(choice_learn.models.base_model)\n", - "\n", - "from choice_learn.models.base_model import BaseMixtureModel" + "model = BaseMixtureModel(\n", + " n_latent_classes=4,\n", + " model_class=ConditionalMNL,\n", + " model_parameters={\"optimizer\": \"lbfgs\", \"epochs\": 100,\"parameters\": spec},\n", + " fit_method=\"EM\",\n", + " epochs=10,\n", + ")\n", + "model.instantiate()" ] }, { @@ -241,15 +251,303 @@ "metadata": {}, "outputs": [], "source": [ - "model = BaseMixtureModel(\n", - " n_latent_classes=2,\n", - " model_class=SimpleMNL,\n", - " model_parameters={\"optimizer\": \"lbfgs\", \"epochs\": 20},\n", - " fit_method=\"EM\",\n", - " epochs=2,\n", - ")" + "type(dataset.contexts_items_features)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model._em_fit(dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "tf.multiply(dataset.contexts_items_features[0][:, :, 0], model.models[0].weights[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.models[1].fit(dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset.contexts_items_features[0].shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.models[0].weights" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.latent_logits" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.models[1].weights" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.models[0].weights" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.models[0].predict_probas(dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.models[1].predict_probas(dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "w = model._expectation(dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.sum(w, axis=0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.weights[:10]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hist = model._em_fit(dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.latent_logits" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.weights" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.plot(np.array(hist)[:, 0])\n", + "plt.plot(np.array(hist)[:, 1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.models[0].weights, model.models[1].weights" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.weights, model.latent_logits, l" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.latent_logits = l\n", + "w = model._expectation(dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "w.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "w" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model = SimpleMNL(optimizer=\"lbfgs\", intercept=None)\n", + "model.fit(dataset, sample_weight=np.concatenate([[1.], [.0]*(len(dataset)-1)]))" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.predict_probas(dataset)[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model = SimpleMNL(optimizer=\"lbfgs\", intercept=None)\n", + "model.fit(dataset, sample_weight=np.concatenate([[0.], [.1]*(len(dataset)-1)]))\n", + "model.weights" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.predict_probas(dataset)[:10], np.min(model.predict_probas(dataset)), np.max(model.predict_probas(dataset))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model = SimpleMNL(optimizer=\"lbfgs\", intercept=None)\n", + "model.fit(dataset)\n", + "model.predict_probas(dataset)[:10]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": null, @@ -399,6 +697,37 @@ "model.weights" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "predicted_probas = np.array([[[.1, .1, .8], [.5, .4, .1]], [[.2, .3, .5], [.3, .3, .4]]])\n", + "latent_probas = [.3, .7]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "predicted_probas = np.concatenate([latent_probas[q]*predicted_probas[q][np.arange(2), [1, 2]].reshape((-1,1)) for q in range(2)], axis = 1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(predicted_probas)\n", + "weights = predicted_probas/np.sum(predicted_probas,axis = 1,keepdims=True)\n", + "print(weights)" + ] + }, { "cell_type": "code", "execution_count": null, From 472d3c49deb6bb5b9c5ea3dc56c81002c845f722 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 20 Feb 2024 17:37:23 +0100 Subject: [PATCH 173/767] CHANGE: allow os.path use --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f4693f3b..258ba107 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ select = [ "PTH", "PD", ] # See: https://beta.ruff.rs/docs/rules/ -ignore = ["D203", "D213", "ANN101", "ANN102", "ANN204", "ANN001", "ANN202", "ANN201", "ANN206", "ANN003"] +ignore = ["D203", "D213", "ANN101", "ANN102", "ANN204", "ANN001", "ANN202", "ANN201", "ANN206", "ANN003", "PTH100", "PTH118", "PTH123"] line-length = 100 target-version = "py310" exclude = [ From f2392b2329baaefb2f31411a7215fbcf9b2b906d Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 20 Feb 2024 17:37:31 +0100 Subject: [PATCH 174/767] ENH: completed renaming choice-mode -> choice_format --- choice_learn/data/choice_dataset.py | 20 ++++++++++++++----- choice_learn/datasets/base.py | 13 ++++++------ .../choice_learn_introduction_clogit.ipynb | 2 +- notebooks/custom_model.ipynb | 2 +- notebooks/dataset_creation.ipynb | 10 +++++----- 5 files changed, 28 insertions(+), 19 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index 72a4b239..232a7c8b 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -614,8 +614,18 @@ def __len__(self): return len(self.choices) def __str__(self): - template = '''First choice is:\nItems features: {}\nContexts features: {}\nContexts Items features: {}\nContexts Items Availabilities: {}\nContexts Choice: {}''' - return template.format(self.batch[0][0], self.batch[0][1], self.batch[0][2], self.batch[0][3], self.batch[0][4]) + """Retursn short representation of ChoiceDataset. + + Returns: + -------- + str + short representation of ChoiceDataset + """ + template = """First choice is:\nItems features: {}\nContexts features: {}\n\ + Contexts Items features: {}\nContexts Items Availabilities: {}\nContexts Choice: {}""" + return template.format( + self.batch[0][0], self.batch[0][1], self.batch[0][2], self.batch[0][3], self.batch[0][4] + ) def get_num_items(self): """Method to access the total number of different items. @@ -725,7 +735,7 @@ def from_single_wide_df( contexts_items_features_suffixes=None, contexts_items_availabilities_suffix=None, choices_column="choice", - choice_mode="items_id", + choice_format="items_id", ): """Builds numpy arrays for ChoiceDataset from a single dataframe in wide format. @@ -745,7 +755,7 @@ def from_single_wide_df( Suffixes of the columns of the dataframe that are context-item availabilities, choice_column: str, optional Name of the column containing the choices, default is "choice" - choice_mode: str, optional + choice_format: str, optional How choice is indicated in df, either "items_name" or "items_index", default is "items_id" @@ -810,7 +820,7 @@ def from_single_wide_df( contexts_items_availabilities = None choices = df[choices_column] - if choice_mode == "items_id": + if choice_format == "items_id": choices = np.squeeze([np.where(items_id == c)[0] for c in choices]) return ChoiceDataset( diff --git a/choice_learn/datasets/base.py b/choice_learn/datasets/base.py index 4ac6930d..3c0f189a 100644 --- a/choice_learn/datasets/base.py +++ b/choice_learn/datasets/base.py @@ -8,8 +8,7 @@ from choice_learn.data.choice_dataset import ChoiceDataset - -DATA_MODULE = os.path.join(os.path.abspath('..'), 'choice_learn', 'datasets', 'data') +DATA_MODULE = os.path.join(os.path.abspath(".."), "choice_learn", "datasets", "data") def load_csv(data_file_name, data_module=DATA_MODULE, encoding="utf-8"): @@ -195,7 +194,7 @@ def load_modecanada( add_is_public=False, as_frame=False, return_desc=False, - choice_mode="one_zero", + choice_format="one_zero", split_features=False, to_wide=False, ): @@ -214,8 +213,8 @@ def load_modecanada( by default False. return_desc : bool, optional Whether to return the description, by default False. - choice_mode : str, optional, among ["one_zero", "items_id"] - mode indicating how the choice is encoded, by default "one_zero". + choice_format : str, optional, among ["one_zero", "items_id"] + format indicating how the choice is encoded, by default "one_zero". split_features : bool, optional Whether to split features by type in different dataframes, by default False. to_wide : bool, optional @@ -270,7 +269,7 @@ def load_modecanada( for col in canada_df.columns: canada_df[col] = pd.to_numeric(canada_df[col], errors="ignore") - if choice_mode == "items_id": + if choice_format == "items_id": # We need to transform how the choice is encoded to add the chosen item id named_choice = [0] * len(canada_df) for n_row, row in canada_df.iterrows(): @@ -364,5 +363,5 @@ def load_modecanada( items_id_column="alt", contexts_id_column="case", choices_column=choice_column, - choice_mode="one_zero", + choice_format="one_zero", ) diff --git a/notebooks/choice_learn_introduction_clogit.ipynb b/notebooks/choice_learn_introduction_clogit.ipynb index bd20a3e0..5773a4ab 100644 --- a/notebooks/choice_learn_introduction_clogit.ipynb +++ b/notebooks/choice_learn_introduction_clogit.ipynb @@ -71,7 +71,7 @@ " items_id_column=\"alt\",\n", " contexts_id_column=\"case\",\n", " choices_column=\"choice\",\n", - " choice_mode=\"one_zero\")" + " choice_format=\"one_zero\")" ] }, { diff --git a/notebooks/custom_model.ipynb b/notebooks/custom_model.ipynb index 3cfda8ec..606c1caf 100644 --- a/notebooks/custom_model.ipynb +++ b/notebooks/custom_model.ipynb @@ -82,7 +82,7 @@ " items_id_column=\"alt\",\n", " contexts_id_column=\"case\",\n", " choices_column=\"choice\",\n", - " choice_mode=\"one_zero\")" + " choice_format=\"one_zero\")" ] }, { diff --git a/notebooks/dataset_creation.ipynb b/notebooks/dataset_creation.ipynb index ea94a78f..5423c436 100644 --- a/notebooks/dataset_creation.ipynb +++ b/notebooks/dataset_creation.ipynb @@ -246,7 +246,7 @@ " contexts_id_column=\"case\",\n", " choices_column=\"choice\",\n", " # the choice columns indicates if the item is chosen (1) or not (0)\n", - " choice_mode=\"one_zero\",\n", + " choice_format=\"one_zero\",\n", " )\n", "print(dataset.summary())" ] @@ -402,7 +402,7 @@ } ], "source": [ - "canada_df = load_modecanada(as_frame=True, add_is_public=True, choice_mode=\"items_id\")\n", + "canada_df = load_modecanada(as_frame=True, add_is_public=True, choice_format=\"items_id\")\n", "canada_df.head()" ] }, @@ -411,7 +411,7 @@ "metadata": {}, "source": [ "This time, the choice is not given by ones and zeros but actually names for each context which alternative (item) has been chosen.\n", - "The ChoiceDataset handles this case easily, by specifying 'choice_mode=\"items_id\"'." + "The ChoiceDataset handles this case easily, by specifying 'choice_format=\"items_id\"'." ] }, { @@ -460,7 +460,7 @@ " contexts_id_column=\"case\",\n", " choices_column=\"choice\",\n", " # the choice columns indicates the id of the chosen item\n", - " choice_mode=\"items_id\",\n", + " choice_format=\"items_id\",\n", " )\n", "print(dataset.summary())" ] @@ -503,7 +503,7 @@ " contexts_items_features_suffixes=[\"CO\", \"TT\", \"HE\", \"SEATS\"],\n", " contexts_items_availabilities_suffix=\"AV\", # [\"TRAIN_AV\", \"SM_AV\", \"CAR_AV\"] also works\n", " choices_column=\"CHOICE\",\n", - " choice_mode=\"item_index\",\n", + " choice_format=\"item_index\",\n", ")" ] }, From 0a568df66ab54023bc610483284ec123b587ef19 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Tue, 20 Feb 2024 18:25:17 +0100 Subject: [PATCH 175/767] minor change --- choice_learn/data/choice_dataset.py | 5 +++-- notebooks/choice_learn_introduction_data.ipynb | 7 ++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/choice_learn/data/choice_dataset.py b/choice_learn/data/choice_dataset.py index 232a7c8b..2d3a519f 100644 --- a/choice_learn/data/choice_dataset.py +++ b/choice_learn/data/choice_dataset.py @@ -621,8 +621,9 @@ def __str__(self): str short representation of ChoiceDataset """ - template = """First choice is:\nItems features: {}\nContexts features: {}\n\ - Contexts Items features: {}\nContexts Items Availabilities: {}\nContexts Choice: {}""" + template = """First choice is:\nItems features: {}\nContexts features: {}\n + Contexts Items features: {}\nContexts Items Availabilities: {}\n + Contexts Choice: {}""" return template.format( self.batch[0][0], self.batch[0][1], self.batch[0][2], self.batch[0][3], self.batch[0][4] ) diff --git a/notebooks/choice_learn_introduction_data.ipynb b/notebooks/choice_learn_introduction_data.ipynb index 9ffd374e..aa0b3deb 100644 --- a/notebooks/choice_learn_introduction_data.ipynb +++ b/notebooks/choice_learn_introduction_data.ipynb @@ -498,9 +498,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "No features_by_ids given.\n", "Some choices never happen in the dataset: {1}\n", - "No features_by_ids given.\n", "Some choices never happen in the dataset: {0, 2}\n", "Train Dataset length: 2 Test Dataset lenght: 1\n" ] @@ -743,8 +741,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Usual Supermakerket Features Shape: (18, 2)\n", - "No features_by_ids given.\n" + "Usual Supermakerket Features Shape: (18, 2)\n" ] } ], @@ -1390,7 +1387,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.18" + "version": "3.11.4" } }, "nbformat": 4, From 79fba5eec9b9156558559075d0055e100c388724 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 22 Feb 2024 12:25:14 +0100 Subject: [PATCH 176/767] ADD: LBFGS working opti of Mixture --- choice_learn/models/base_model.py | 343 +++++++++++++++++++++++++++++- 1 file changed, 340 insertions(+), 3 deletions(-) diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index 26ed35b8..0e97466d 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -738,7 +738,7 @@ def _fit_with_lbfgs(self, dataset, epochs=None, sample_weight=None, verbose=0): return func.history -class BaseMixtureModel(object): +class BaseMixtureModel(object): # TODO: should inherit ChoiceModel ? """Base Class to work with Mixtures of models.""" def __init__( @@ -779,11 +779,16 @@ class of models to get a mixture of self.fit_method = fit_method self.epochs = epochs + self.normalize_non_buy = False + + self.loss = tf_ops.CustomCategoricalCrossEntropy(from_logits=False, label_smoothing=0) def instantiate(self): """Instantiation.""" - init_logit = tf.random.uniform((self.n_latent_classes,)) - init_logit = init_logit / tf.reduce_sum(init_logit) + init_logit = tf.Variable( + tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(self.n_latent_classes - 1,)), + name="Latent-Logits", + ) self.latent_logits = init_logit self.models = [self.model_class(**mp) for mp in self.model_parameters] @@ -791,6 +796,338 @@ def instantiate(self): self.fit = self._em_fit self.minf = np.log(1e-3) + @tf.function + def batch_predict( + self, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, + sample_weight=None, + ): + """Function that represents one prediction (Probas + Loss) for one batch of a ChoiceDataset. + + Parameters + ---------- + fixed_items_features : tuple of np.ndarray + Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products + constant/fixed features. + Shape must be (n_items, n_items_features) + contexts_features : tuple of np.ndarray (contexts_features) + a batch of contexts features + Shape must be (n_contexts, n_contexts_features) + contexts_items_features : tuple of np.ndarray (contexts_items_features) + a batch of contexts items features + Shape must be (n_contexts, n_contexts_items_features) + contexts_items_availabilities : np.ndarray + A batch of contexts items availabilities + Shape must be (n_contexts, n_items) + choices_batch : np.ndarray + Choices + Shape must be (n_contexts, ) + sample_weight : np.ndarray, optional + List samples weights to apply during the gradient descent to the batch elements, + by default None + + Returns: + -------- + tf.Tensor (1, ) + Value of NegativeLogLikelihood loss for the batch + tf.Tensor (batch_size, n_items) + Probabilities for each product to be chosen for each context + """ + # Compute utilities from features + utilities = self.compute_batch_utility( + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, + ) + latent_probabilities = tf.concat( + [[tf.constant(1.0)], tf.math.exp(self.latent_logits)], axis=0 + ) + latent_probabilities = latent_probabilities / tf.reduce_sum(latent_probabilities) + # Compute probabilities from utilities & availabilties + probabilities = [] + for i, class_utilities in enumerate(utilities): + class_probabilities = tf_ops.softmax_with_availabilities( + contexts_items_logits=class_utilities, + contexts_items_availabilities=contexts_items_availabilities, + normalize_exit=self.normalize_non_buy, + axis=-1, + ) + probabilities.append(class_probabilities * latent_probabilities[i]) + probabilities = tf.reduce_sum(probabilities, axis=0) + tf.print("Probas", probabilities[:4]) + + # Compute loss from probabilities & actual choices + # batch_loss = self.loss(probabilities, c_batch, sample_weight=sample_weight) + batch_loss = { + "optimized_loss": self.loss( + y_pred=probabilities, + y_true=tf.one_hot(choices, depth=probabilities.shape[1]), + sample_weight=sample_weight, + ), + "NegativeLogLikelihood": tf.keras.losses.CategoricalCrossentropy()( + y_pred=probabilities, + y_true=tf.one_hot(choices, depth=probabilities.shape[1]), + sample_weight=sample_weight, + ), + } + tf.print(batch_loss) + return batch_loss, probabilities + + def compute_batch_utility( + self, + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, + ): + """_summary_. + + Parameters + ---------- + args : _type_ + _description_ + + Returns: + -------- + _type_ + _description_ + """ + utilities = [] + for model in self.models: + utilities.append( + model.compute_batch_utility( + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, + ) + ) + return utilities + + def evaluate(self, choice_dataset, sample_weight=None, batch_size=-1, mode="eval"): + """Evaluates the model for each context and each product of a ChoiceDataset. + + Predicts the probabilities according to the model and computes the Negative-Log-Likelihood + loss from the actual choices. + + Parameters + ---------- + choice_dataset : ChoiceDataset + Dataset on which to apply to prediction + + Returns: + -------- + np.ndarray (n_contexts, n_items) + Choice probabilties for each context and each product + """ + batch_losses = [] + for ( + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, + ) in choice_dataset.iter_batch(batch_size=batch_size): + loss, _ = self.batch_predict( + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, + choices=choices, + sample_weight=sample_weight, + ) + if mode == "eval": + batch_losses.append(loss["NegativeLogLikelihood"]) + elif mode == "optim": + batch_losses.append(loss["optimized_loss"]) + if batch_size != -1: + last_batch_size = contexts_items_availabilities.shape[0] + coefficients = tf.concat( + [tf.ones(len(batch_losses) - 1) * batch_size, [last_batch_size]], axis=0 + ) + batch_losses = tf.multiply(batch_losses, coefficients) + batch_loss = tf.reduce_sum(batch_losses) / len(choice_dataset) + else: + batch_loss = tf.reduce_mean(batch_losses) + return batch_loss + + def _lbfgs_train_step(self, dataset, sample_weight=None): + """A factory to create a function required by tfp.optimizer.lbfgs_minimize. + + Parameters + ---------- + dataset: ChoiceDataset + Dataset on which to estimate the paramters. + sample_weight: np.ndarray, optional + Sample weights to apply, by default None + + Returns: + -------- + function + with the signature: + loss_value, gradients = f(model_parameters). + """ + # obtain the shapes of all trainable parameters in the model + weights = [] + w_to_model = [] + w_to_model_indexes = [] + for i, model in enumerate(self.models): + for j, w in enumerate(model.weights): + weights.append(w) + w_to_model.append(i) + w_to_model_indexes.append(j) + weights.append(self.latent_logits) + w_to_model.append(-1) + w_to_model_indexes.append(-1) + shapes = tf.shape_n(weights) + n_tensors = len(shapes) + + # we'll use tf.dynamic_stitch and tf.dynamic_partition later, so we need to + # prepare required information first + count = 0 + idx = [] # stitch indices + part = [] # partition indices + + for i, shape in enumerate(shapes): + n = np.product(shape) + idx.append(tf.reshape(tf.range(count, count + n, dtype=tf.int32), shape)) + part.extend([i] * n) + count += n + + part = tf.constant(part) + + @tf.function + def assign_new_model_parameters(params_1d): + """A function updating the model's parameters with a 1D tf.Tensor. + + Pararmeters + ----------- + params_1d: tf.Tensor + a 1D tf.Tensor representing the model's trainable parameters. + """ + params = tf.dynamic_partition(params_1d, part, n_tensors) + for i, (shape, param) in enumerate(zip(shapes, params)): + if w_to_model[i] != -1: + self.models[w_to_model[i]].weights[w_to_model_indexes[j]].assign( + tf.reshape(param, shape) + ) + else: + self.latent_logits.assign(tf.reshape(param, shape)) + + # now create a function that will be returned by this factory + @tf.function + def f(params_1d): + """A function that can be used by tfp.optimizer.lbfgs_minimize. + + This function is created by function_factory. + + Parameters + ---------- + params_1d: tf.Tensor + a 1D tf.Tensor. + + Returns: + -------- + tf.Tensor + A scalar loss and the gradients w.r.t. the `params_1d`. + tf.Tensor + A 1D tf.Tensor representing the gradients w.r.t. the `params_1d`. + """ + # use GradientTape so that we can calculate the gradient of loss w.r.t. parameters + with tf.GradientTape() as tape: + # update the parameters in the model + assign_new_model_parameters(params_1d) + # calculate the loss + loss_value = self.evaluate( + dataset, sample_weight=sample_weight, batch_size=-1, mode="optim" + ) + + # calculate gradients and convert to 1D tf.Tensor + grads = tape.gradient(loss_value, weights) + grads = tf.dynamic_stitch(idx, grads) + + # print out iteration & loss + f.iter.assign_add(1) + + # store loss value so we can retrieve later + tf.py_function(f.history.append, inp=[loss_value], Tout=[]) + + return loss_value, grads + + # store these information as members so we can use them outside the scope + f.iter = tf.Variable(0) + f.idx = idx + f.part = part + f.shapes = shapes + f.assign_new_model_parameters = assign_new_model_parameters + f.history = [] + return f + + def _fit_with_lbfgs(self, dataset, epochs=None, sample_weight=None, verbose=0): + """Fit function for L-BFGS optimizer. + + Replaces the .fit method when the optimizer is set to L-BFGS. + + Parameters + ---------- + dataset : ChoiceDataset + Dataset to be used for coefficients estimations + epochs : int + Maximum number of epochs allowed to reach minimum + sample_weight : np.ndarray, optional + Sample weights to apply, by default None + verbose : int, optional + print level, for debugging, by default 0 + + Returns: + -------- + dict + Fit history + """ + # Only import tensorflow_probability if LBFGS optimizer is used, avoid unnecessary + # dependency + import tensorflow_probability as tfp + + if epochs is None: + epochs = self.epochs + func = self._lbfgs_train_step(dataset, sample_weight=sample_weight) + + # convert initial model parameters to a 1D tf.Tensor + init = [] + for model in self.models: + for w in model.weights: + init.append(w) + init.append(self.latent_logits) + init_params = tf.dynamic_stitch(func.idx, init) + + # train the model with L-BFGS solver + results = tfp.optimizer.lbfgs_minimize( + value_and_gradients_function=func, + initial_position=init_params, + max_iterations=epochs, + tolerance=self.tolerance, + f_absolute_tolerance=-1, + f_relative_tolerance=-1, + ) + + # after training, the final optimized parameters are still in results.position + # so we have to manually put them back to the model + func.assign_new_model_parameters(results.position) + if verbose > 0: + print("L-BFGS Opimization finished:") + print("---------------------------------------------------------------") + print("Number of iterations:", results[2].numpy()) + print("Algorithm converged before reaching max iterations:", results[0].numpy()) + return func.history + def _nothing(self, inputs): """_summary_. From 604a9da5d2f4f60ef2324bd60ebdf3adceef515e Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 22 Feb 2024 12:32:29 +0100 Subject: [PATCH 177/767] ENH: organization of BaseLatentClass --- choice_learn/models/base_model.py | 55 ++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index 0e97466d..ea83f975 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -738,7 +738,7 @@ def _fit_with_lbfgs(self, dataset, epochs=None, sample_weight=None, verbose=0): return func.history -class BaseMixtureModel(object): # TODO: should inherit ChoiceModel ? +class BaseLatentClassModel(object): # TODO: should inherit ChoiceModel ? """Base Class to work with Mixtures of models.""" def __init__( @@ -748,6 +748,9 @@ def __init__( model_parameters, fit_method, epochs, + optimizer=None, + add_exit_choice=False, + tolerance=1e-6, ): """Instantiation of the model mixture. @@ -760,9 +763,15 @@ class of models to get a mixture of model_parameters : dict hyper-parameters of the models fit_method : str - Method to estimate the parameters: "EM", "LBFGS", "SGD". + Method to estimate the parameters: "EM", "MLE". epochs : int Number of epochs to train the model. + optimizer: str, optional + Name of the tf.keras.optimizers to be used if one is used, by default None + add_exit_choice : bool, optional + Whether or not to add an exit choice, by default False + tolerance: float, optional + Tolerance for the L-BFGS optimizer if applied, by default 1e-6 """ self.n_latent_classes = n_latent_classes if isinstance(model_parameters, list): @@ -779,7 +788,9 @@ class of models to get a mixture of self.fit_method = fit_method self.epochs = epochs - self.normalize_non_buy = False + self.add_exit_choice = add_exit_choice + self.tolerance = tolerance + self.optimizer = optimizer self.loss = tf_ops.CustomCategoricalCrossEntropy(from_logits=False, label_smoothing=0) @@ -792,9 +803,12 @@ def instantiate(self): self.latent_logits = init_logit self.models = [self.model_class(**mp) for mp in self.model_parameters] - if self.fit_method == "EM": + if self.fit_method.lower() == "em": self.fit = self._em_fit self.minf = np.log(1e-3) + elif self.fit_method.lower() == "mle": + if self.optimizer.lower() == "lbfgs" or self.optimizer.lower() == "l-bfgs": + self.fit = self._fit_with_lbfgs @tf.function def batch_predict( @@ -859,8 +873,8 @@ def batch_predict( axis=-1, ) probabilities.append(class_probabilities * latent_probabilities[i]) + # Summing over the latent classes probabilities = tf.reduce_sum(probabilities, axis=0) - tf.print("Probas", probabilities[:4]) # Compute loss from probabilities & actual choices # batch_loss = self.loss(probabilities, c_batch, sample_weight=sample_weight) @@ -876,7 +890,6 @@ def batch_predict( sample_weight=sample_weight, ), } - tf.print(batch_loss) return batch_loss, probabilities def compute_batch_utility( @@ -887,19 +900,39 @@ def compute_batch_utility( contexts_items_availabilities, choices, ): - """_summary_. + """Latent class computation of utility. + + It computes the utility for each of the latent models and stores them in a list. Parameters ---------- - args : _type_ - _description_ + fixed_items_features : tuple of np.ndarray + Fixed-Item-Features: formatting from ChoiceDataset: a matrix representing the products + constant/fixed features. + Shape must be (n_items, n_items_features) + contexts_features : tuple of np.ndarray (contexts_features) + a batch of contexts features + Shape must be (n_contexts, n_contexts_features) + contexts_items_features : tuple of np.ndarray (contexts_items_features) + a batch of contexts items features + Shape must be (n_contexts, n_contexts_items_features) + contexts_items_availabilities : np.ndarray + A batch of contexts items availabilities + Shape must be (n_contexts, n_items) + choices_batch : np.ndarray + Choices + Shape must be (n_contexts, ) Returns: -------- - _type_ - _description_ + list of np.ndarray + List of: + Utility of each product for each context. + Shape must be (n_contexts, n_items) + for each of the latent models. """ utilities = [] + # Iterates over latent models for model in self.models: utilities.append( model.compute_batch_utility( From 63ebf41ab222b7147ac77b0c9bdf1a8d7d25974f Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 22 Feb 2024 13:24:19 +0100 Subject: [PATCH 178/767] ENH: small improvements --- choice_learn/models/mix_mnl.py | 1 - choice_learn/models/simple_mnl.py | 14 +++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) delete mode 100644 choice_learn/models/mix_mnl.py diff --git a/choice_learn/models/mix_mnl.py b/choice_learn/models/mix_mnl.py deleted file mode 100644 index 26c75b53..00000000 --- a/choice_learn/models/mix_mnl.py +++ /dev/null @@ -1 +0,0 @@ -"""Implementation of MixMNL. Citation to add.""" diff --git a/choice_learn/models/simple_mnl.py b/choice_learn/models/simple_mnl.py index 34415c7c..bfaaf601 100644 --- a/choice_learn/models/simple_mnl.py +++ b/choice_learn/models/simple_mnl.py @@ -41,10 +41,18 @@ def instantiate( ): """Instantiate the model from ModelSpecification object. - Paramters + Parameters -------- - n_weights: int - Number of weights to be estimated. Corresponds to the number of features. + Parameters + ---------- + n_items : int + Number of items/aternatives to consider. + n_fixed_items_features : int + Number of fixed items features. + n_contexts_features : int + Number of contexts features + n_contexts_items_features : int + Number of contexts items features Returns: -------- From c3ac90e7db4a9fd72da1856549e8f10157fcbe2e Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 22 Feb 2024 13:25:13 +0100 Subject: [PATCH 179/767] ADD: specific class for LatentClass simple MNL --- choice_learn/models/latent_class_mnl.py | 104 ++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 choice_learn/models/latent_class_mnl.py diff --git a/choice_learn/models/latent_class_mnl.py b/choice_learn/models/latent_class_mnl.py new file mode 100644 index 00000000..5a2a98c5 --- /dev/null +++ b/choice_learn/models/latent_class_mnl.py @@ -0,0 +1,104 @@ +"""Latent Class MNL models.""" + +import tensorflow as tf + +from .base_model import BaseLatentClassModel +from .simple_mnl import SimpleMNL + + +class LatentClassSimpleMNL(BaseLatentClassModel): + """Latent Class for SimpleMNL.""" + + def __init__( + self, + n_latent_classes, + fit_method, + epochs, + add_exit_choice=False, + tolerance=1e-6, + intercept=None, + optimizer="Adam", + lr=0.001, + **kwargs, + ): + """Initialization. + + Parameters + ---------- + n_latent_classes : int + Number of latent classes. + fit_method : str + Method to be used to estimate the model. + epochs : int + Number of epochs + add_exit_choice : bool, optional + Whether to normalize probabilities with exit choice, by default False + tolerance : float, optional + LBFG-S tolerance, by default 1e-6 + intercept : str, optional + Type of intercept to include in the SimpleMNL. + Must be in (None, 'item', 'item-full', 'constant'), by default None + optimizer : str, optional + tf.keras.optimizers to be used, by default "Adam" + lr : float, optional + Learning rate to use for optimizer if relevant, by default 0.001 + """ + self.n_latent_classes = n_latent_classes + self.fit_method = fit_method + self.epochs = epochs + self.add_exit_choice = add_exit_choice + self.tolerance = tolerance + self.intercept = intercept + self.optimizer = optimizer + self.lr = lr + + model_params = { + "add_exit_choice": self.add_exit_choice, + "intercept": self.intercept, + "optimizer": self.optimizer, + "tolerance": self.tolerance, + "lr": self.lr, + "epochs": self.epochs, + } + + super().__init__(model_class=SimpleMNL, model_params=model_params, **kwargs) + + def instantiate_latent_models( + self, n_items, n_fixed_items_features, n_contexts_features, n_contexts_items_features + ): + """Instantiation of the Latent Models that are SimpleMNLs. + + Parameters + ---------- + n_items : int + Number of items/aternatives to consider. + n_fixed_items_features : int + Number of fixed items features. + n_contexts_features : int + Number of contexts features + n_contexts_items_features : int + Number of contexts items features + """ + for model in self.models: + model.indexes, model.weights = model.instantiate( + n_items, n_fixed_items_features, n_contexts_features, n_contexts_items_features + ) + model.instantiated = True + + def instantiate( + self, n_items, n_fixed_items_features, n_contexts_features, n_contexts_items_features + ): + """Instantiation of the Latent Class MNL model.""" + self.latent_logits = tf.Variable( + tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(self.n_latent_classes - 1,)), + name="Latent-Logits", + ) + + self.models = [self.model_class(**mp) for mp in self.model_parameters] + + self.instantiate_latent_models( + n_items=n_items, + n_fixed_items_features=n_fixed_items_features, + n_contexts_features=n_contexts_features, + n_contexts_items_features=n_contexts_items_features, + ) From c86a05e20908eeb02a7cea6dad822d2f1b7d9194 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 22 Feb 2024 14:13:09 +0100 Subject: [PATCH 180/767] ADD: Idea for LatentClassConditionalMNL --- choice_learn/models/latent_class_mnl.py | 174 ++++++++++++++++++++++++ 1 file changed, 174 insertions(+) diff --git a/choice_learn/models/latent_class_mnl.py b/choice_learn/models/latent_class_mnl.py index 5a2a98c5..3bb19a65 100644 --- a/choice_learn/models/latent_class_mnl.py +++ b/choice_learn/models/latent_class_mnl.py @@ -3,6 +3,7 @@ import tensorflow as tf from .base_model import BaseLatentClassModel +from .conditrional_logit import ConditionalMNL, ModelSpecification from .simple_mnl import SimpleMNL @@ -102,3 +103,176 @@ def instantiate( n_contexts_features=n_contexts_features, n_contexts_items_features=n_contexts_items_features, ) + + +class LatentClassConditionalMNL(BaseLatentClassModel): + """Latent Class for ConditionalMNL.""" + + def __init__( + self, + n_latent_classes, + fit_method, + parameters=None, + epochs=1, + add_exit_choice=False, + tolerance=1e-6, + optimizer="Adam", + lr=0.001, + **kwargs, + ): + """Initialization. + + Parameters + ---------- + n_latent_classes : int + Number of latent classes. + fit_method : str + Method to be used to estimate the model. + parameters : dict or ModelSpecification + Dictionnary containing the parametrization of the model. + The dictionnary must have the following structure: + {feature_name_1: mode_1, feature_name_2: mode_2, ...} + mode must be among "constant", "item", "item-full" for now + (same specifications as torch-choice). + epochs : int + Number of epochs + add_exit_choice : bool, optional + Whether to normalize probabilities with exit choice, by default False + tolerance : float, optional + LBFG-S tolerance, by default 1e-6 + optimizer : str, optional + tf.keras.optimizers to be used, by default "Adam" + lr : float, optional + Learning rate to use for optimizer if relevant, by default 0.001 + """ + self.n_latent_classes = n_latent_classes + self.fit_method = fit_method + self.parameters = parameters + self.epochs = epochs + self.add_exit_choice = add_exit_choice + self.tolerance = tolerance + self.optimizer = optimizer + self.lr = lr + + model_params = { + "params": self.parameters, + "add_exit_choice": self.add_exit_choice, + "optimizer": self.optimizer, + "tolerance": self.tolerance, + "lr": self.lr, + "epochs": self.epochs, + } + + super().__init__(model_class=ConditionalMNL, model_params=model_params, **kwargs) + + def instantiate_latent_models( + self, n_items, n_fixed_items_features, n_contexts_features, n_contexts_items_features + ): + """Instantiation of the Latent Models that are SimpleMNLs. + + Parameters + ---------- + n_items : int + Number of items/aternatives to consider. + n_fixed_items_features : int + Number of fixed items features. + n_contexts_features : int + Number of contexts features + n_contexts_items_features : int + Number of contexts items features + """ + for model in self.models: + model.indexes, model.weights = model.instantiate( + n_items, n_fixed_items_features, n_contexts_features, n_contexts_items_features + ) + model.instantiated = True + + def instantiate( + self, n_items, n_fixed_items_features, n_contexts_features, n_contexts_items_features + ): + """Instantiation of the Latent Class MNL model.""" + self.latent_logits = tf.Variable( + tf.random_normal_initializer(0.0, 0.02, seed=42)(shape=(self.n_latent_classes - 1,)), + name="Latent-Logits", + ) + + self.models = [self.model_class(**mp) for mp in self.model_parameters] + + self.instantiate_latent_models( + n_items=n_items, + n_fixed_items_features=n_fixed_items_features, + n_contexts_features=n_contexts_features, + n_contexts_items_features=n_contexts_items_features, + ) + + def add_coefficients( + self, coefficient_name, feature_name, items_indexes=None, items_names=None + ): + """Adds a coefficient to the model throught the specification of the utility. + + Parameters + ---------- + coefficient_name : str + Name given to the coefficient. + feature_name : str + features name to which the coefficient is associated. It should work with + the names given. + in the ChoiceDataset that will be used for parameters estimation. + items_indexes : list of int, optional + list of items indexes (in the ChoiceDataset) for which we need to add a coefficient, + by default None + items_names : list of str, optional + list of items names (in the ChoiceDataset) for which we need to add a coefficient, + by default None + + Raises: + ------- + ValueError + When names or indexes are both not specified. + """ + if self.params is None: + self.params = ModelSpecification() + elif not isinstance(self.params, ModelSpecification): + raise ValueError("Cannot add coefficient on top of a dict instantiation.") + self.params.add_coefficients( + coefficient_name=coefficient_name, + feature_name=feature_name, + items_indexes=items_indexes, + items_names=items_names, + ) + + def add_shared_coefficient( + self, coefficient_name, feature_name, items_indexes=None, items_names=None + ): + """Adds a single, shared coefficient to the model throught the specification of the utility. + + Parameters + ---------- + coefficient_name : str + Name given to the coefficient. + feature_name : str + features name to which the coefficient is associated. It should work with + the names given. + in the ChoiceDataset that will be used for parameters estimation. + items_indexes : list of int, optional + list of items indexes (in the ChoiceDataset) for which the coefficient will be used, + by default None + items_names : list of str, optional + list of items names (in the ChoiceDataset) for which the coefficient will be used, + by default None + + Raises: + ------- + ValueError + When names or indexes are both not specified. + """ + if self.params is None: + self.params = ModelSpecification() + elif not isinstance(self.params, ModelSpecification): + raise ValueError("Cannot add shared coefficient on top of a dict instantiation.") + self.params.add_shared_coefficient( + coefficient_name=coefficient_name, + feature_name=feature_name, + items_indexes=items_indexes, + items_names=items_names, + ) From b150eac8de3c3a6c28d570e7c22c243566e64edd Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 22 Feb 2024 15:18:00 +0100 Subject: [PATCH 181/767] ADD: LatentClassMNL ok with _fit_lbfgs --- choice_learn/models/base_model.py | 6 ++++- choice_learn/models/latent_class_mnl.py | 34 ++++++++++++++----------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index ea83f975..59bc36db 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -751,6 +751,7 @@ def __init__( optimizer=None, add_exit_choice=False, tolerance=1e-6, + lr=0.001, ): """Instantiation of the model mixture. @@ -772,6 +773,8 @@ class of models to get a mixture of Whether or not to add an exit choice, by default False tolerance: float, optional Tolerance for the L-BFGS optimizer if applied, by default 1e-6 + lr: float, optional + Learning rate for the optimizer if applied, by default 0.001 """ self.n_latent_classes = n_latent_classes if isinstance(model_parameters, list): @@ -791,6 +794,7 @@ class of models to get a mixture of self.add_exit_choice = add_exit_choice self.tolerance = tolerance self.optimizer = optimizer + self.lr = lr self.loss = tf_ops.CustomCategoricalCrossEntropy(from_logits=False, label_smoothing=0) @@ -869,7 +873,7 @@ def batch_predict( class_probabilities = tf_ops.softmax_with_availabilities( contexts_items_logits=class_utilities, contexts_items_availabilities=contexts_items_availabilities, - normalize_exit=self.normalize_non_buy, + normalize_exit=self.add_exit_choice, axis=-1, ) probabilities.append(class_probabilities * latent_probabilities[i]) diff --git a/choice_learn/models/latent_class_mnl.py b/choice_learn/models/latent_class_mnl.py index 3bb19a65..76caee00 100644 --- a/choice_learn/models/latent_class_mnl.py +++ b/choice_learn/models/latent_class_mnl.py @@ -3,7 +3,7 @@ import tensorflow as tf from .base_model import BaseLatentClassModel -from .conditrional_logit import ConditionalMNL, ModelSpecification +from .conditional_mnl import ConditionalMNL, ModelSpecification from .simple_mnl import SimpleMNL @@ -45,24 +45,28 @@ def __init__( Learning rate to use for optimizer if relevant, by default 0.001 """ self.n_latent_classes = n_latent_classes - self.fit_method = fit_method - self.epochs = epochs - self.add_exit_choice = add_exit_choice - self.tolerance = tolerance self.intercept = intercept - self.optimizer = optimizer - self.lr = lr - model_params = { - "add_exit_choice": self.add_exit_choice, - "intercept": self.intercept, - "optimizer": self.optimizer, - "tolerance": self.tolerance, - "lr": self.lr, - "epochs": self.epochs, + "add_exit_choice": add_exit_choice, + "intercept": intercept, + "optimizer": optimizer, + "tolerance": tolerance, + "lr": lr, + "epochs": epochs, } - super().__init__(model_class=SimpleMNL, model_params=model_params, **kwargs) + super().__init__( + model_class=SimpleMNL, + model_parameters=model_params, + n_latent_classes=n_latent_classes, + fit_method=fit_method, + epochs=epochs, + add_exit_choice=add_exit_choice, + tolerance=tolerance, + optimizer=optimizer, + lr=lr, + **kwargs, + ) def instantiate_latent_models( self, n_items, n_fixed_items_features, n_contexts_features, n_contexts_items_features From 117a44c4443c75c1a3a421f50ecd70d35f7e0fe4 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 22 Feb 2024 15:18:17 +0100 Subject: [PATCH 182/767] WIP notebook --- notebooks/mixture_mnl.ipynb | 653 +++++++++++++++++++++++++++++++++++- 1 file changed, 648 insertions(+), 5 deletions(-) diff --git a/notebooks/mixture_mnl.ipynb b/notebooks/mixture_mnl.ipynb index cbc48d62..40ef3694 100644 --- a/notebooks/mixture_mnl.ipynb +++ b/notebooks/mixture_mnl.ipynb @@ -17,7 +17,9 @@ "\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", - "import pandas as pd" + "import pandas as pd\n", + "\n", + "import tensorflow as tf" ] }, { @@ -68,7 +70,308 @@ "metadata": {}, "outputs": [], "source": [ - "from choice_learn.models.simple_mnl import SimpleMNL" + "from choice_learn.models.simple_mnl import SimpleMNL\n", + "from choice_learn.models.base_model import BaseLatentClassModel\n", + "from choice_learn.models.latent_class_mnl import LatentClassSimpleMNL" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lc_model = LatentClassSimpleMNL(n_latent_classes=2, fit_method=\"em\", optimizer=\"lbfgs\", epochs=100)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lc_model.instantiate(dataset.get_n_items(),\n", + "dataset.get_n_fixed_items_features(),\n", + " dataset.get_n_contexts_features(),\n", + " dataset.get_n_contexts_items_features())\n", + "lc_model._fit_with_lbfgs(dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lc_model.latent_logits, lc_model.models[0].weights, lc_model.models[1].weights" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "smnl = SimpleMNL(optimizer=\"lbfgs\", intercept=\"item\")\n", + "smnl.fit(dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mm = BaseMixtureModel(model_class=SimpleMNL, model_parameters={\"add_exit_choice\": False}, n_latent_classes=2, fit_method=\"em\", epochs=2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mm = BaseMixtureModel(model_class=SimpleMNL, model_parameters={\"add_exit_choice\": False}, n_latent_classes=2, fit_method=\"em\", epochs=2)\n", + "mm.instantiate()\n", + "print(mm.latent_logits)\n", + "mm.models[0].fit(dataset, epochs=1)\n", + "mm.models[1].fit(dataset, epochs=1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mm.tolerance = 1e-2\n", + "h = mm._fit_with_lbfgs(dataset[:25], epochs=100, verbose=1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mm.evaluate(dataset[:25]) * 25 " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mm.models[1].weights" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mm.models[0].weights" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mm.latent_logits" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mm2 = BaseMixtureModel(model_class=SimpleMNL, model_parameters={\"add_exit_choice\": False}, n_latent_classes=2, fit_method=\"em\", epochs=2)\n", + "mm2.instantiate()\n", + "print(mm2.latent_logits)\n", + "mm2.models[0].fit(dataset, epochs=1)\n", + "mm2.models[1].fit(dataset, epochs=1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mm2.models[0].weights\n", + "w1 = [-1.97818, 1.25229, 18.59170, 17.22774, -9.46991, -6.34042]\n", + "w2 = [-1.47861, -0.56208, 2.48494, 2.18748, -14.88065, -20.46972 ]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mm2.latent_logits = tf.constant([0.08077])\n", + "mm2.models[0].weights = [tf.constant([-1.97818, 1.25229, 18.59170, 17.22774, -9.46991, -6.34042])]\n", + "mm2.models[1].weights = [tf.constant([-1.47861, -0.56208, 2.48494, 2.18748, -14.88065, -20.46972 ])]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mm2.evaluate(dataset[:25]) * 25" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for batch in dataset[:25].iter_batch(batch_size=-1):\n", + " c, d = mm2.batch_predict(*batch)\n", + " e, f = mm.batch_predict(*batch)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "d = [d[i][dataset.choices[i]] for i in range(25)]\n", + "f = [f[i][dataset.choices[i]] for i in range(25)]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.sum(d), np.sum(f)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.plot(d, label=\"gmnl\")\n", + "plt.plot(f, label=\"mine\")\n", + "plt.legend()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "PPP1 = []\n", + "PPP2 = []\n", + "for i in range(25):\n", + " print(dataset.choices[i], d[i], d[i][dataset.choices[i]])\n", + " PPP1.append(d[i][dataset.choices[i]])\n", + " PPP2.append(d[i][dataset.choices[i]])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.sum(np.log(PPP1)), np.sum(np.log(PPP))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mm.weights = tf.concat([mm.models[0].weights, mm.models[1].weights, mm.latent_logits], axis=0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mm.tolerance = 1e-2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mm.tolerance = 1e-2\n", + "mm._fit_with_lbfgs(dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mm.evaluate(dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "_f" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "_" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "_2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "_f = [p[0]*_[i] + p[1]*_2[i] for i in range(4)]" ] }, { @@ -129,7 +432,7 @@ "source": [ "mix = BaseMixtureModel(model_class=SimpleMNL,\n", " model_parameters={\"optimizer\": \"lbfgs\", \"epochs\": 100, \"tolerance\": 1e-2},\n", - " n_latent_classes=3, epochs=200, fit_method=\"em\")" + " n_latent_classes=2, epochs=20, fit_method=\"em\")" ] }, { @@ -139,7 +442,130 @@ "outputs": [], "source": [ "mix.instantiate()\n", - "h1, h2 = mix._em_fit(dataset)" + "h1, h2 = mix._em_fit(dataset[:750])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.plot(h2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "(mix.models[0].weights,\n", + "mix.models[1].weights)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "xxx.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "w1 = [-0.4458, -0.1847, 1.2144, 0.9641, -3.2184, -3.4865]\n", + "w2 = [-0.8431, -0.1242, 1.6445, 1.4139, 1.4139, -9.2647]\n", + "p = [np.exp(0), np.exp(-0.2200)]\n", + "p = [p[i] / np.sum(p) for i in range(2)]\n", + "xxx = dataset.contexts_items_features[0][:750]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "p3 = []\n", + "for i in range(len(xxx)):\n", + " c = []\n", + " for j in range(4):\n", + " c.append(np.sum(xxx[i][j] * w1))\n", + " p3.append(np.array(c) / np.sum(c))\n", + "p4 = []\n", + "for i in range(len(xxx)):\n", + " c = []\n", + " for j in range(4):\n", + " c.append(np.sum(xxx[i][j] * w2))\n", + " p4.append(np.array(c) / np.sum(c))\n", + "\n", + "ppp = p[0] * np.stack(p3) + p[1] * np.stack(p4)\n", + "ppp = [ppp[i][dataset.choices[i]] for i in range(750)]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ppp = p[0] * np.stack(p3) + p[1] * np.stack(p4)\n", + "ppp = [ppp[i][dataset.choices[i]] for i in range(750)]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.sum(np.log(ppp))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "p3[0], p1[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "p1 = np.exp(np.dot(xxx, w1)) / np.sum(np.exp(np.dot(xxx, w1)), axis=1, keepdims=True)\n", + "p2 = np.exp(np.dot(xxx, w2)) / np.sum(np.exp(np.dot(xxx, w2)), axis=1, keepdims=True)\n", + "\n", + "ppp = p[0] * p1 + p[1] * p2\n", + "ppp = [ppp[i][dataset.choices[i]] for i in range(750)]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.sum(np.log(ppp))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.log(np.e)" ] }, { @@ -394,7 +820,224 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "np." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.sum([3.167765e-01, 0.2059867040, 0.0000233475, 4.772135e-01])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "w1 = [-1.97818, 1.25229, 18.59170, 17.22774, -9.46991, -6.34042]\n", + "w2 = [-1.47861, -0.56208, 2.48494, 2.18748, -14.88065, -20.46972 ]\n", + "p = [np.exp(0), np.exp(0.08077)]\n", + "p = [p[i] / np.sum(p) for i in range(2)]\n", + "xxx = dataset.contexts_items_features[0][:750]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "p3 = []\n", + "for i in range(len(xxx)):\n", + " c = []\n", + " for j in range(4):\n", + " c.append(np.sum(np.exp(xxx[i][j] * w1)))\n", + " p3.append(np.array(c) / np.sum(c))\n", + "p4 = []\n", + "for i in range(len(xxx)):\n", + " c = []\n", + " for j in range(4):\n", + " c.append(np.sum(np.exp(xxx[i][j] * w2)))\n", + " p4.append(np.array(c) / np.sum(c))\n", + "\n", + "ppp = p[0] * np.stack(p3) + p[1] * np.stack(p4)\n", + "ppp = [ppp[i][dataset.choices[i]] for i in range(750)]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "p[0] * np.stack(p3) + p[1] * np.stack(p4)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.sum(np.log(ppp))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "p3[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "p4[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "_ = []\n", + "for i in range(4):\n", + " a = np.exp(np.sum(xxx[0][i] * w2)) / (np.exp(np.sum(xxx[0][0] * w2)) + np.exp(np.sum(xxx[0][1] * w2)) + np.exp(np.sum(xxx[0][2] * w2)) + np.exp(np.sum(xxx[0][3] * w2)))\n", + " _.append(a)\n", + "_2 = []\n", + "for i in range(4):\n", + " a = np.exp(np.sum(xxx[0][i] * w1)) / (np.exp(np.sum(xxx[0][0] * w1)) + np.exp(np.sum(xxx[0][1] * w1)) + np.exp(np.sum(xxx[0][2] * w1)) + np.exp(np.sum(xxx[0][3] * w1)))\n", + " _2.append(a)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "_f = [p[0]*_[i] + p[1]*_2[i] for i in range(4)]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "rp = [3.167765e-01, 0.2059867040, 0.0000233475, 4.772135e-01]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "_2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.plot(rp)\n", + "plt.plot(_f)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.exp(np.sum(xxx[0][3] * w1)) / (np.exp(np.sum(xxx[0][0] * w1)) + np.exp(np.sum(xxx[0][1] * w1)) + np.exp(np.sum(xxx[0][2] * w1)) + np.exp(np.sum(xxx[0][3] * w1)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "p[0] * 0.2467418414436882 + p[1] * 0.9990703988722798" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.exp(np.sum(xxx[0][3] * w1)) / (np.exp(np.sum(xxx[0][0] * w1)) + np.exp(np.sum(xxx[0][1] * w1)) + np.exp(np.sum(xxx[0][2] * w1)) + np.exp(np.sum(xxx[0][3] * w1)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.exp(np.sum(xxx[0][0] * w1))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.exp(np.sum(xxx[0][3] * w1)) / np" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.exp(np.sum(xxx[0][2] * w2))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.exp(np.sum(xxx[0][3] * w2))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "p3[0]" + ] }, { "cell_type": "code", From dfb9f351850487cc849dab6e56a68df50bfa5863 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 22 Feb 2024 15:21:06 +0100 Subject: [PATCH 183/767] ENH: from Luca's suggestions, round 3 ! --- README_review.md | 121 ----------------------------------------------- 1 file changed, 121 deletions(-) delete mode 100644 README_review.md diff --git a/README_review.md b/README_review.md deleted file mode 100644 index 9481432a..00000000 --- a/README_review.md +++ /dev/null @@ -1,121 +0,0 @@ -
- -# choice-learn-private - -[![CI status](https://github.com/artefactory/choice-learn-private/actions/workflows/ci.yaml/badge.svg)](https://github.com/artefactory/choice-learn-private/actions/workflows/ci.yaml?query=branch%3Amain) -[![Python Version](https://img.shields.io/badge/python-3.8%20%7C%203.9%20%7C%203.10-blue.svg)]() - -[![Linting , formatting, imports sorting: ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) -[![security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit) -[![Pre-commit](https://img.shields.io/badge/pre--commit-enabled-informational?logo=pre-commit&logoColor=white)](https://github.com/artefactory/choice-learn-private/blob/main/.pre-commit-config.yaml) - -
- - - -Choice-Learn is a Python package designed to help you build discrete choice models. -The package provides ready to use datasets and different models from the litterature. It also provides a lower level use if you want to customize any model or create your own from scratch. In particular you will find smart datasets handling to limit RAM usage and different structure commons to any choice model. - -Choice-Learn uses NumPy and pandas as data backend engines and TensorFlow for models. - -This repository contains a private version of the package. - -## Table of Contents - -- [choice-learn-private](#choice-learn-private) - - [Introduction - Discrete Choice Modelling](#introduction---discrete-choice-modelling) - - [Table of Contents](#table-of-contents) - - [What's in there ?](#whats-in-there) - - [Getting Started](#getting-started---fast-track) - - [Installation](#installation) - - [Usage](#usage) - - [Documentation](#documentation) - - [Citation](#citation) - -## Introduction - Discrete Choice Modelling - -Discrete choice models aim at explaining or predicting a choice from a set of alternatives. Well known use-cases include analyzing people choice of mean of transport or products purchases in stores. - -If you are new to choice modelling, you can check this [resource](https://www.publichealth.columbia.edu/research/population-health-methods/discrete-choice-model-and-analysis). The different notebooks from the [Getting Started](#getting-started---fast-track) section can also help you understand choice modelling and more importantly help you for your usecase. - -## What's in there ? - -### Data -- Generic dataset handling with the ChoiceDataset class -- Ready-To-Use datasets: - - SwissMetro from Bierlaire et al. (2001) - - ModeCanada from Koppelman et al. (1993) - -### Models -- Ready to use models: - - Conditional MultiNomialLogit, Train, K.; McFadden, D.; Ben-Akiva, M. (1987) - - RUMnet, Aouad A.; Désir A. (2022) [1] -- Ready to use models to be implemented: - - Nested MultiNomialLogit - - MultiNomialLogit with latent variables (MixedLogit) - - TasteNet - - SHOPPER - - Others ... -- Custom modelling is made easy by subclassing the ChoiceModel class - -### Different tools (to come) -- Standardization of evaluation protocols -- Assortment optimization from model -- Interfaces - -## Getting Started - Fast Track - -You can find the following notebooks to help you getting started with the package: -- [Introduction to data management](notebooks/choice_learn_introduction_data.ipynb) -- [Introduction to modelling with the conditional logit model on ModeCanada dataset](notebooks/choice_learn_introduction_clogit.ipynb) -- [Introduction to custom modelling with the ModeCanada dataset](notebooks/custom_model.ipynb) - -## Installation - -### User installation - -To install the required packages in a virtual environment, run the following command: - -** pip-install not possible yet, to come soon** -```bash -pip install choice-learn -``` - -In the mean time you can clone the repository: -```bash -git clone git@github.com:artefactory/choice-learn-private.git -``` - -### Dependencies -Choice-Learn requires the following: -- Python (>=3.8) -- NumPy (>=1.24) -- pandas (>=1.5) -For modelling you need: -- TensorFlow (>=2.13) -Finally, an optional requirement used for report and LBFG-s use is: -- tensorflow_probability (>=0.20.1) - -## Usage -```python -from choice_learn.data import ChoiceDataset -from choice_learn.models import ConditionalMNL, RUMnet -``` - -## Documentation - -A detailed documentation of this project is available [here](https://artefactory.github.io/choice-learn-private/) - -## Citation - -### Contributors - -## References - -### Papers -[1][Representing Random Utility Choice Models with Neural Networks](https://arxiv.org/abs/2207.12877), Aouad A.; Désir A. (2022) - -### Code and Repositories -- [PyLogit](https://github.com/timothyb0912/pylogit) -- [Torch Choice](https://gsbdbi.github.io/torch-choice/) -- [1][RUMnet](https://github.com/antoinedesir/rumnet) From 224d359dfd91ed8fff5664289c9713a8faa3a9b8 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 22 Feb 2024 19:33:04 +0100 Subject: [PATCH 184/767] ENH: clean Simple MNL - comparison with mlogit notebook --- notebooks/simple_and_mix_logit.ipynb | 760 --------------------------- notebooks/simple_mnl_mlogit.ipynb | 196 +++++++ 2 files changed, 196 insertions(+), 760 deletions(-) delete mode 100644 notebooks/simple_and_mix_logit.ipynb create mode 100644 notebooks/simple_mnl_mlogit.ipynb diff --git a/notebooks/simple_and_mix_logit.ipynb b/notebooks/simple_and_mix_logit.ipynb deleted file mode 100644 index e4c1cafd..00000000 --- a/notebooks/simple_and_mix_logit.ipynb +++ /dev/null @@ -1,760 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "\n", - "# Remove GPU use\n", - "os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"\"\n", - "\n", - "import sys\n", - "\n", - "sys.path.append(\"../\")\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "\n", - "from choice_learn.models.simple_mnl import SimpleMNL\n", - "from choice_learn.data import ChoiceDataset\n", - "from choice_learn.datasets.base import load_heating" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's recreate this [tutorial](https://cran.r-project.org/web/packages/mlogit/vignettes/e1mlogit.html) by Yves Croissant for the mlogit R package.\n", - "\n", - "It uses the Heating dataset, where we try to predict which heating harware a houseold will chose. The dataset is integrated in the package, you can find information [here]." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "heating_df = load_heating(as_frame=True)\n", - "\n", - "contexts_features = [\"income\", \"agehed\", \"rooms\"]\n", - "choice = [\"depvar\"]\n", - "contexts_items_features = [\"ic.\", \"oc.\"]\n", - "items = [\"hp\", \"gc\", \"gr\", \"ec\", \"er\"]\n", - "\n", - "choices = np.array([items.index(val) for val in heating_df[choice].to_numpy().ravel()])\n", - "contexts = heating_df[contexts_features].to_numpy()\n", - "contexts_items = np.stack([heating_df[[feat + item for feat in contexts_items_features]].to_numpy() for item in items], axis=1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "First part estimates a simple MNL without intercept from the 'ic' and 'oc' features. By default, SimpleMNL does not integrate any intercept, but you can precise 'None'." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset = ChoiceDataset(contexts_items_features=contexts_items, choices=choices)\n", - "model = SimpleMNL(optimizer=\"lbfgs\", intercept=None)\n", - "history = model.fit(dataset, epochs=100, get_report=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"Estimation Negative LogLikelihood:\",\n", - " model.evaluate(dataset) * len(dataset))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model.report" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We reach very similar results. The second part is about modelling useing the ic + oc/0.12 ratio. Here is how it can be done:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ratio_contexts_items = []\n", - "for case in range(contexts_items.shape[0]):\n", - " feat = []\n", - " for item in range(contexts_items.shape[1]):\n", - " feat.append([contexts_items[case, item, 0] + contexts_items[case, item, 1] / 0.12])\n", - " ratio_contexts_items.append(feat)\n", - "ratio_contexts_items = np.array(ratio_contexts_items)\n", - "ratio_contexts_items.shape" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ratio_dataset = ChoiceDataset(contexts_items_features=ratio_contexts_items, choices=choices)\n", - "model = SimpleMNL(optimizer=\"lbfgs\")\n", - "history = model.fit(ratio_dataset, epochs=100, get_report=False)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"Weights:\", model.weights)\n", - "print(\"Estimation Negative LogLikelihood:\", model.evaluate(ratio_dataset) * len(ratio_dataset))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally, to add itemwise intercept for the last part, here is how it can be done:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model = SimpleMNL(optimizer=\"lbfgs\", intercept=\"item\")\n", - "history = model.fit(dataset, epochs=100, get_report=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model.report" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from choice_learn.datasets import load_swissmetro\n", - "from choice_learn.models.base_model import BaseMixtureModel" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "sm_df = load_swissmetro(as_frame=True)\n", - "sm_df = sm_df.loc[sm_df.CHOICE != 0]\n", - "sm_df.head()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "contexts_items = np.stack([sm_df[[f\"{item}_{feature}\" for feature in [\"CO\", \"TT\"]]].to_numpy() for item in [\"CAR\", \"TRAIN\", \"SM\"]],\n", - "axis=1)\n", - "contexts_items[:, :, 0] = contexts_items[:, :, 0] / 100\n", - "contexts_items[:, :, 1] = contexts_items[:, :, 1] / 100\n", - "dataset = ChoiceDataset(\n", - " contexts_items_features=(contexts_items, ),\n", - " choices=sm_df.CHOICE.to_numpy()-1,\n", - " contexts_items_features_names=([\"CO\", \"TT\"], ),\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "np.unique(dataset.choices), len(dataset)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import tensorflow as tf\n", - "import importlib\n", - "import choice_learn.models.base_model\n", - "importlib.reload(choice_learn.models.base_model)\n", - "\n", - "from choice_learn.models.base_model import BaseMixtureModel\n", - "from choice_learn.models.conditional_mnl import ConditionalMNL" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "spec = {\"CO\": \"constant\", \"TT\": \"item\", \"intercept\": \"item-full\"}\n", - "spec2 = {\"CO\": \"constant\", \"intercept\": \"item-full\"}" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model = BaseMixtureModel(\n", - " n_latent_classes=4,\n", - " model_class=ConditionalMNL,\n", - " model_parameters={\"optimizer\": \"lbfgs\", \"epochs\": 100,\"parameters\": spec},\n", - " fit_method=\"EM\",\n", - " epochs=10,\n", - ")\n", - "model.instantiate()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "type(dataset.contexts_items_features)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model._em_fit(dataset)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "tf.multiply(dataset.contexts_items_features[0][:, :, 0], model.models[0].weights[0])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model.models[1].fit(dataset)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset.contexts_items_features[0].shape" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model.models[0].weights" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model.latent_logits" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model.models[1].weights" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model.models[0].weights" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model.models[0].predict_probas(dataset)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model.models[1].predict_probas(dataset)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "w = model._expectation(dataset)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "np.sum(w, axis=0)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model.weights[:10]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "hist = model._em_fit(dataset)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model.latent_logits" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model.weights" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "plt.plot(np.array(hist)[:, 0])\n", - "plt.plot(np.array(hist)[:, 1])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model.models[0].weights, model.models[1].weights" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model.weights, model.latent_logits, l" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "a" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model.latent_logits = l\n", - "w = model._expectation(dataset)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "w.shape" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "w" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model = SimpleMNL(optimizer=\"lbfgs\", intercept=None)\n", - "model.fit(dataset, sample_weight=np.concatenate([[1.], [.0]*(len(dataset)-1)]))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model.predict_probas(dataset)[0]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model = SimpleMNL(optimizer=\"lbfgs\", intercept=None)\n", - "model.fit(dataset, sample_weight=np.concatenate([[0.], [.1]*(len(dataset)-1)]))\n", - "model.weights" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model.predict_probas(dataset)[:10], np.min(model.predict_probas(dataset)), np.max(model.predict_probas(dataset))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model = SimpleMNL(optimizer=\"lbfgs\", intercept=None)\n", - "model.fit(dataset)\n", - "model.predict_probas(dataset)[:10]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model.instantiate()\n", - "model._em_fit(dataset)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model.models[0].weights" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model.models[1].weights" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model.latent_logits" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "predicted_probas = [m.predict_probas(dataset) for m in model.models]\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "predicted_probas" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for latent, proba in zip(model.latent_logits, predicted_probas):\n", - " print(latent, proba[:4])\n", - " print(latent\n", - " * tf.gather_nd(\n", - " params=proba,\n", - " indices=tf.stack([tf.range(0, len(dataset), 1), dataset.choices], axis=1),\n", - " )[:4])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "predicted_probas = [\n", - " latent\n", - " * tf.gather_nd(\n", - " params=proba,\n", - " indices=tf.stack([tf.range(0, len(dataset), 1), dataset.choices], axis=1),\n", - " )\n", - " for latent, proba in zip(model.latent_logits, predicted_probas)\n", - "]\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "predicted_probas" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "weights = predicted_probas / tf.reduce_sum(predicted_probas, axis=0, keepdims=True)\n", - "weights" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for q in range(self.n_latent_classes):\n", - " self.models[q].fit(dataset, sample_weight=weights[q])\n", - "\n", - "self.latent_logits = tf.reduce_mean(weights, axis=1)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model = SimpleMNL(optimizer=\"lbfgs\", intercept=\"item\")\n", - "model.fit(dataset, sample_weight=np.random.rand(len(dataset)))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model.weights" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model = SimpleMNL(optimizer=\"lbfgs\", intercept=\"item\")\n", - "model.fit(dataset)\n", - "model.weights" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "predicted_probas = np.array([[[.1, .1, .8], [.5, .4, .1]], [[.2, .3, .5], [.3, .3, .4]]])\n", - "latent_probas = [.3, .7]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "predicted_probas = np.concatenate([latent_probas[q]*predicted_probas[q][np.arange(2), [1, 2]].reshape((-1,1)) for q in range(2)], axis = 1)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(predicted_probas)\n", - "weights = predicted_probas/np.sum(predicted_probas,axis = 1,keepdims=True)\n", - "print(weights)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "tf_env", - "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.11.4" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/notebooks/simple_mnl_mlogit.ipynb b/notebooks/simple_mnl_mlogit.ipynb new file mode 100644 index 00000000..e298dc3f --- /dev/null +++ b/notebooks/simple_mnl_mlogit.ipynb @@ -0,0 +1,196 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Simple MNL: Comparison with R's mlogit package" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "\n", + "# Remove GPU use\n", + "os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"\"\n", + "\n", + "import sys\n", + "\n", + "sys.path.append(\"../\")\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "from choice_learn.models.simple_mnl import SimpleMNL\n", + "from choice_learn.data import ChoiceDataset\n", + "from choice_learn.datasets.base import load_heating" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's recreate this [tutorial](https://cran.r-project.org/web/packages/mlogit/vignettes/e1mlogit.html) by Yves Croissant for the mlogit R package.\n", + "\n", + "It uses the Heating dataset, where we try to predict which heating harware a houseold will chose. The dataset is integrated in the package, you can find information [here]." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "heating_df = load_heating(as_frame=True)\n", + "\n", + "contexts_features = [\"income\", \"agehed\", \"rooms\"]\n", + "choice = [\"depvar\"]\n", + "contexts_items_features = [\"ic.\", \"oc.\"]\n", + "items = [\"hp\", \"gc\", \"gr\", \"ec\", \"er\"]\n", + "\n", + "choices = np.array([items.index(val) for val in heating_df[choice].to_numpy().ravel()])\n", + "contexts = heating_df[contexts_features].to_numpy()\n", + "contexts_items = np.stack([heating_df[[feat + item for feat in contexts_items_features]].to_numpy() for item in items], axis=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First part estimates a simple MNL without intercept from the 'ic' and 'oc' features. By default, SimpleMNL does not integrate any intercept, but you can precise 'None'." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset = ChoiceDataset(contexts_items_features=contexts_items, choices=choices)\n", + "model = SimpleMNL(optimizer=\"lbfgs\", intercept=None)\n", + "history = model.fit(dataset, epochs=100, get_report=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\"Estimation Negative LogLikelihood:\",\n", + " model.evaluate(dataset) * len(dataset))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.report" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We reach very similar results. The second part is about modelling useing the ic + oc/0.12 ratio. Here is how it can be done:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ratio_contexts_items = []\n", + "for case in range(contexts_items.shape[0]):\n", + " feat = []\n", + " for item in range(contexts_items.shape[1]):\n", + " feat.append([contexts_items[case, item, 0] + contexts_items[case, item, 1] / 0.12])\n", + " ratio_contexts_items.append(feat)\n", + "ratio_contexts_items = np.array(ratio_contexts_items)\n", + "ratio_contexts_items.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ratio_dataset = ChoiceDataset(contexts_items_features=ratio_contexts_items, choices=choices)\n", + "model = SimpleMNL(optimizer=\"lbfgs\")\n", + "history = model.fit(ratio_dataset, epochs=100, get_report=False)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\"Weights:\", model.weights)\n", + "print(\"Estimation Negative LogLikelihood:\", model.evaluate(ratio_dataset) * len(ratio_dataset))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, to add itemwise intercept for the last part, here is how it can be done:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model = SimpleMNL(optimizer=\"lbfgs\", intercept=\"item\")\n", + "history = model.fit(dataset, epochs=100, get_report=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.report" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "tf_env", + "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.1.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From d8546258c1eec99a75e70b8a2418a9572901818a Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 23 Feb 2024 10:13:33 +0100 Subject: [PATCH 185/767] ADD: base loader for electricity dataset --- choice_learn/datasets/__init__.py | 7 +-- choice_learn/datasets/base.py | 51 +++++++++++++++++- choice_learn/datasets/data/electricity.csv.gz | Bin 0 -> 76428 bytes 3 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 choice_learn/datasets/data/electricity.csv.gz diff --git a/choice_learn/datasets/__init__.py b/choice_learn/datasets/__init__.py index a16bf199..8a7ec3f4 100644 --- a/choice_learn/datasets/__init__.py +++ b/choice_learn/datasets/__init__.py @@ -1,8 +1,5 @@ """Init file for datasets module.""" -from .base import load_modecanada, load_swissmetro +from .base import load_electricity, load_heating, load_modecanada, load_swissmetro -__all__ = [ - "load_modecanada", - "load_swissmetro", -] +__all__ = ["load_modecanada", "load_swissmetro", "load_electricity", "load_heating"] diff --git a/choice_learn/datasets/base.py b/choice_learn/datasets/base.py index 7f8722a3..9fff22f2 100644 --- a/choice_learn/datasets/base.py +++ b/choice_learn/datasets/base.py @@ -374,7 +374,7 @@ def load_heating( return_desc=False, to_wide=False, ): - """Load and return the ModeCanada dataset from Koppleman et al. (1993). + """Load and return the Heating dataset from Koppleman et al. (1993). Parameters ---------- @@ -422,3 +422,52 @@ def load_heating( return ChoiceDataset( contexts_features=contexts, contexts_items_features=contexts_items, choices=choices ) + + +def load_electricity( + as_frame=False, + return_desc=False, + to_wide=False, +): + """Load and return the Electricity dataset from Koppleman et al. (1993). + + Parameters + ---------- + as_frame : bool, optional + Whether to return the dataset as pd.DataFrame. If not, returned as ChoiceDataset, + by default False. + return_desc : bool, optional + Whether to return the description, by default False. + to_wide : bool, optional + Whether to return the dataset in wide format, + by default False (an thus retuned in long format). + + Returns: + -------- + ChoiceDataset + Loaded ModeCanada dataset + """ + _ = to_wide + data_file_name = "electricity.csv.gz" + names, data = load_gzip(data_file_name) + + elec_df = pd.read_csv(resources.files(DATA_MODULE) / data_file_name) + elec_df.choice = elec_df.choice.astype(int) + elec_df[["pf", "cl", "loc", "wk", "tod", "seas"]] = elec_df[ + ["pf", "cl", "loc", "wk", "tod", "seas"] + ].astype(float) + + if return_desc: + # TODO + pass + + if as_frame: + return elec_df + + return ChoiceDataset.from_single_long_df( + df=elec_df, + contexts_items_features_columns=["pf", "cl", "loc", "wk", "tod", "seas"], + items_id_column="alt", + contexts_id_column="chid", + choice_mode="one_zero", + ) diff --git a/choice_learn/datasets/data/electricity.csv.gz b/choice_learn/datasets/data/electricity.csv.gz new file mode 100644 index 0000000000000000000000000000000000000000..da0a7ee14b8687c7ac9f28395d70ab5a0121eb12 GIT binary patch literal 76428 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

F4oR%|{#STpFd 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 H{q_F<=eLK6 literal 0 HcmV?d00001 From 8bf0459a33c8051d26a37a1c51e3bcdd8980d1a9 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 23 Feb 2024 10:25:21 +0100 Subject: [PATCH 186/767] ADD: working Latent Class MLE fit for simpleMNL --- choice_learn/models/base_model.py | 39 ++++++++++++++++++++----- choice_learn/models/latent_class_mnl.py | 17 +++++++++++ 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index 59bc36db..56e820b5 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -797,6 +797,7 @@ class of models to get a mixture of self.lr = lr self.loss = tf_ops.CustomCategoricalCrossEntropy(from_logits=False, label_smoothing=0) + self.instantiated = False def instantiate(self): """Instantiation.""" @@ -807,13 +808,6 @@ def instantiate(self): self.latent_logits = init_logit self.models = [self.model_class(**mp) for mp in self.model_parameters] - if self.fit_method.lower() == "em": - self.fit = self._em_fit - self.minf = np.log(1e-3) - elif self.fit_method.lower() == "mle": - if self.optimizer.lower() == "lbfgs" or self.optimizer.lower() == "l-bfgs": - self.fit = self._fit_with_lbfgs - @tf.function def batch_predict( self, @@ -949,6 +943,37 @@ def compute_batch_utility( ) return utilities + def fit(self, dataset, sample_weight=None, verbose=0): + """Fit the model on a ChoiceDataset. + + Parameters + ---------- + dataset : ChoiceDataset + Dataset to be used for coefficients estimations + sample_weight : np.ndarray, optional + sample weights to apply, by default None + verbose : int, optional + print level, for debugging, by default 0 + + Returns: + -------- + dict + Fit history + """ + if self.fit_method.lower() == "em": + self.minf = np.log(1e-3) + return self._em_fit(dataset=dataset, sample_weight=sample_weight, verbose=verbose) + + if self.fit_method.lower() == "mle": + if self.optimizer.lower() == "lbfgs" or self.optimizer.lower() == "l-bfgs": + return self._fit_with_lbfgs( + dataset=dataset, sample_weight=sample_weight, verbose=verbose + ) + + return self._fit_normal(dataset=dataset, sample_weight=sample_weight, verbose=verbose) + + raise ValueError(f"Fit method not implemented: {self.fit_method}") + def evaluate(self, choice_dataset, sample_weight=None, batch_size=-1, mode="eval"): """Evaluates the model for each context and each product of a ChoiceDataset. diff --git a/choice_learn/models/latent_class_mnl.py b/choice_learn/models/latent_class_mnl.py index 76caee00..d439ae1c 100644 --- a/choice_learn/models/latent_class_mnl.py +++ b/choice_learn/models/latent_class_mnl.py @@ -108,6 +108,23 @@ def instantiate( n_contexts_items_features=n_contexts_items_features, ) + def fit(self, dataset, **kwargs): + """Fit the model to the dataset. + + Parameters + ---------- + dataset : ChoiceDataset + Dataset to fit the model to. + """ + if not self.instantiated: + self.instantiate( + n_items=dataset.get_n_items(), + n_fixed_items_features=dataset.get_n_fixed_items_features(), + n_contexts_features=dataset.get_n_contexts_features(), + n_contexts_items_features=dataset.get_n_contexts_items_features(), + ) + super().fit(dataset, **kwargs) + class LatentClassConditionalMNL(BaseLatentClassModel): """Latent Class for ConditionalMNL.""" From d61515e2301dd7fe8287c14d69fef9f42fb36dca Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Sat, 24 Feb 2024 21:14:25 +0100 Subject: [PATCH 187/767] updated example --- choice_learn/models/base_model.py | 3 + notebooks/mixture_mnl.ipynb | 276 ++---------------------------- notebooks/rumnet_example.ipynb | 14 +- 3 files changed, 15 insertions(+), 278 deletions(-) diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index 56e820b5..7d772567 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -1190,6 +1190,9 @@ def _fit_with_lbfgs(self, dataset, epochs=None, sample_weight=None, verbose=0): print("Algorithm converged before reaching max iterations:", results[0].numpy()) return func.history + def _gd_train_step(self, dataset, sample_weight=None): + pass + def _nothing(self, inputs): """_summary_. diff --git a/notebooks/mixture_mnl.ipynb b/notebooks/mixture_mnl.ipynb index 40ef3694..7ba2cf0b 100644 --- a/notebooks/mixture_mnl.ipynb +++ b/notebooks/mixture_mnl.ipynb @@ -28,7 +28,8 @@ "metadata": {}, "outputs": [], "source": [ - "df = pd.read_csv(\"../../../electricity_r_data_long.csv\")" + "from choice_learn.datasets import load_electricity\n", + "elec_dataset = load_electricity(as_frame=False)" ] }, { @@ -37,31 +38,9 @@ "metadata": {}, "outputs": [], "source": [ - "df.choice = df.choice.astype(int)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "df[[\"pf\", 'cl', \"loc\", \"wk\", \"tod\", \"seas\"]] = df[[\"pf\", 'cl', \"loc\", \"wk\", \"tod\", \"seas\"]].astype(float)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from choice_learn.data import ChoiceDataset\n", - "\n", - "dataset = ChoiceDataset.from_single_long_df(df=df,\n", - "contexts_items_features_columns=[\"pf\", \"cl\", \"loc\", \"wk\", \"tod\", \"seas\"],\n", - "items_id_column=\"alt\",\n", - "contexts_id_column=\"chid\",\n", - "choice_mode=\"one_zero\")" + "from choice_learn.models.simple_mnl import SimpleMNL\n", + "from choice_learn.models.base_model import BaseLatentClassModel\n", + "from choice_learn.models.latent_class_mnl import LatentClassSimpleMNL" ] }, { @@ -70,9 +49,7 @@ "metadata": {}, "outputs": [], "source": [ - "from choice_learn.models.simple_mnl import SimpleMNL\n", - "from choice_learn.models.base_model import BaseLatentClassModel\n", - "from choice_learn.models.latent_class_mnl import LatentClassSimpleMNL" + "lc_model = LatentClassSimpleMNL(n_latent_classes=3, fit_method=\"mle\", optimizer=\"lbfgs\", epochs=100, tolerance=1e-8)" ] }, { @@ -81,7 +58,7 @@ "metadata": {}, "outputs": [], "source": [ - "lc_model = LatentClassSimpleMNL(n_latent_classes=2, fit_method=\"em\", optimizer=\"lbfgs\", epochs=100)" + "lc_model.fit(elec_dataset)" ] }, { @@ -90,11 +67,7 @@ "metadata": {}, "outputs": [], "source": [ - "lc_model.instantiate(dataset.get_n_items(),\n", - "dataset.get_n_fixed_items_features(),\n", - " dataset.get_n_contexts_features(),\n", - " dataset.get_n_contexts_items_features())\n", - "lc_model._fit_with_lbfgs(dataset)" + "lc_model.latent_logits, lc_model.models[0].weights, lc_model.models[1].weights, lc_model.models[2].weights" ] }, { @@ -103,7 +76,7 @@ "metadata": {}, "outputs": [], "source": [ - "lc_model.latent_logits, lc_model.models[0].weights, lc_model.models[1].weights" + "plt.plot(hist)" ] }, { @@ -112,8 +85,7 @@ "metadata": {}, "outputs": [], "source": [ - "smnl = SimpleMNL(optimizer=\"lbfgs\", intercept=\"item\")\n", - "smnl.fit(dataset)" + "lc_model.evaluate(elec_dataset) * len(elec_dataset)" ] }, { @@ -189,9 +161,7 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [ - "a" - ] + "source": [] }, { "cell_type": "code", @@ -815,230 +785,6 @@ "outputs": [], "source": [] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "np." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "np.sum([3.167765e-01, 0.2059867040, 0.0000233475, 4.772135e-01])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "w1 = [-1.97818, 1.25229, 18.59170, 17.22774, -9.46991, -6.34042]\n", - "w2 = [-1.47861, -0.56208, 2.48494, 2.18748, -14.88065, -20.46972 ]\n", - "p = [np.exp(0), np.exp(0.08077)]\n", - "p = [p[i] / np.sum(p) for i in range(2)]\n", - "xxx = dataset.contexts_items_features[0][:750]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "p3 = []\n", - "for i in range(len(xxx)):\n", - " c = []\n", - " for j in range(4):\n", - " c.append(np.sum(np.exp(xxx[i][j] * w1)))\n", - " p3.append(np.array(c) / np.sum(c))\n", - "p4 = []\n", - "for i in range(len(xxx)):\n", - " c = []\n", - " for j in range(4):\n", - " c.append(np.sum(np.exp(xxx[i][j] * w2)))\n", - " p4.append(np.array(c) / np.sum(c))\n", - "\n", - "ppp = p[0] * np.stack(p3) + p[1] * np.stack(p4)\n", - "ppp = [ppp[i][dataset.choices[i]] for i in range(750)]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "p[0] * np.stack(p3) + p[1] * np.stack(p4)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "np.sum(np.log(ppp))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "p3[0]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "p4[0]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "_ = []\n", - "for i in range(4):\n", - " a = np.exp(np.sum(xxx[0][i] * w2)) / (np.exp(np.sum(xxx[0][0] * w2)) + np.exp(np.sum(xxx[0][1] * w2)) + np.exp(np.sum(xxx[0][2] * w2)) + np.exp(np.sum(xxx[0][3] * w2)))\n", - " _.append(a)\n", - "_2 = []\n", - "for i in range(4):\n", - " a = np.exp(np.sum(xxx[0][i] * w1)) / (np.exp(np.sum(xxx[0][0] * w1)) + np.exp(np.sum(xxx[0][1] * w1)) + np.exp(np.sum(xxx[0][2] * w1)) + np.exp(np.sum(xxx[0][3] * w1)))\n", - " _2.append(a)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "_f = [p[0]*_[i] + p[1]*_2[i] for i in range(4)]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "rp = [3.167765e-01, 0.2059867040, 0.0000233475, 4.772135e-01]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "_2" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "plt.plot(rp)\n", - "plt.plot(_f)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "np.exp(np.sum(xxx[0][3] * w1)) / (np.exp(np.sum(xxx[0][0] * w1)) + np.exp(np.sum(xxx[0][1] * w1)) + np.exp(np.sum(xxx[0][2] * w1)) + np.exp(np.sum(xxx[0][3] * w1)))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "p[0] * 0.2467418414436882 + p[1] * 0.9990703988722798" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "np.exp(np.sum(xxx[0][3] * w1)) / (np.exp(np.sum(xxx[0][0] * w1)) + np.exp(np.sum(xxx[0][1] * w1)) + np.exp(np.sum(xxx[0][2] * w1)) + np.exp(np.sum(xxx[0][3] * w1)))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "np.exp(np.sum(xxx[0][0] * w1))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "np.exp(np.sum(xxx[0][3] * w1)) / np" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "np.exp(np.sum(xxx[0][2] * w2))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "np.exp(np.sum(xxx[0][3] * w2))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "p3[0]" - ] - }, { "cell_type": "code", "execution_count": null, diff --git a/notebooks/rumnet_example.ipynb b/notebooks/rumnet_example.ipynb index 2bad7f12..0bbd6693 100644 --- a/notebooks/rumnet_example.ipynb +++ b/notebooks/rumnet_example.ipynb @@ -270,21 +270,9 @@ ], "metadata": { "kernelspec": { - "display_name": "tf_env", + "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.11.4" } }, "nbformat": 4, From 945543f5c440fedbeb9f7c9424246c74dcadc254 Mon Sep 17 00:00:00 2001 From: VincentAURIAU Date: Sat, 24 Feb 2024 14:52:06 +0100 Subject: [PATCH 188/767] ADD: small modifs --- choice_learn/datasets/base.py | 4 ++-- choice_learn/models/base_model.py | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/choice_learn/datasets/base.py b/choice_learn/datasets/base.py index 9fff22f2..ae524b89 100644 --- a/choice_learn/datasets/base.py +++ b/choice_learn/datasets/base.py @@ -390,7 +390,7 @@ def load_heating( Returns: -------- ChoiceDataset - Loaded ModeCanada dataset + Loaded Heating dataset """ _ = to_wide data_file_name = "heating_data.csv.gz" @@ -445,7 +445,7 @@ def load_electricity( Returns: -------- ChoiceDataset - Loaded ModeCanada dataset + Loaded Electricity dataset """ _ = to_wide data_file_name = "electricity.csv.gz" diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index 7d772567..fb9dc1e4 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -962,6 +962,7 @@ def fit(self, dataset, sample_weight=None, verbose=0): """ if self.fit_method.lower() == "em": self.minf = np.log(1e-3) + print("Expectation-Maximization estimation algorithm not well implemented yet.") return self._em_fit(dataset=dataset, sample_weight=sample_weight, verbose=verbose) if self.fit_method.lower() == "mle": From b94d891ee31e209087b6d2c286e4c82fad8dcd8f Mon Sep 17 00:00:00 2001 From: VincentAURIAU Date: Sat, 24 Feb 2024 14:53:27 +0100 Subject: [PATCH 189/767] ADD: better instantiation of LatentClassConditionalMNL --- choice_learn/models/latent_class_mnl.py | 65 +++++++++++++++++++------ 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/choice_learn/models/latent_class_mnl.py b/choice_learn/models/latent_class_mnl.py index d439ae1c..e097364d 100644 --- a/choice_learn/models/latent_class_mnl.py +++ b/choice_learn/models/latent_class_mnl.py @@ -187,7 +187,11 @@ def __init__( super().__init__(model_class=ConditionalMNL, model_params=model_params, **kwargs) def instantiate_latent_models( - self, n_items, n_fixed_items_features, n_contexts_features, n_contexts_items_features + self, + n_items, + items_features_names, + contexts_features_names, + contexts_items_features_names, ): """Instantiation of the Latent Models that are SimpleMNLs. @@ -195,21 +199,33 @@ def instantiate_latent_models( ---------- n_items : int Number of items/aternatives to consider. - n_fixed_items_features : int - Number of fixed items features. - n_contexts_features : int - Number of contexts features - n_contexts_items_features : int - Number of contexts items features + items_features_names: str, + Names of fixed_items_features + contexts_features_names: str, + Names of contexts features + contexts_items_features_names: str, + Names of contexts items features """ - for model in self.models: - model.indexes, model.weights = model.instantiate( - n_items, n_fixed_items_features, n_contexts_features, n_contexts_items_features - ) - model.instantiated = True + if isinstance(self.params, ModelSpecification): + for model in self.models: + model.params = self.params + model.instantiate_from_specifications() + else: + for model in self.models: + model.params = self.params + model.indexes, model.weights = model.instantiate( + num_items=n_items, items_features_names=items_features_names, + contexts_features_names=contexts_features_names, + contexts_items_features_names=contexts_items_features_names + ) + model.instantiated = True def instantiate( - self, n_items, n_fixed_items_features, n_contexts_features, n_contexts_items_features + self, + n_items, + items_features_names, + contexts_features_names, + contexts_items_features_names, ): """Instantiation of the Latent Class MNL model.""" self.latent_logits = tf.Variable( @@ -221,9 +237,9 @@ def instantiate( self.instantiate_latent_models( n_items=n_items, - n_fixed_items_features=n_fixed_items_features, - n_contexts_features=n_contexts_features, - n_contexts_items_features=n_contexts_items_features, + items_features_names=items_features_names, + contexts_features_names=contexts_features_names, + contexts_items_features_names=contexts_items_features_names, ) def add_coefficients( @@ -297,3 +313,20 @@ def add_shared_coefficient( items_indexes=items_indexes, items_names=items_names, ) + + def fit(self, dataset, **kwargs): + """Fit the model to the dataset. + + Parameters + ---------- + dataset : ChoiceDataset + Dataset to fit the model to. + """ + if not self.instantiated: + self.instantiate( + n_items=dataset.get_n_items(), + n_fixed_items_features=dataset.get_n_fixed_items_features(), + n_contexts_features=dataset.get_n_contexts_features(), + n_contexts_items_features=dataset.get_n_contexts_items_features(), + ) + super().fit(dataset, **kwargs) \ No newline at end of file From 59e75a14428ec1d71a57c826b25e577794385372 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 29 Feb 2024 22:55:18 +0100 Subject: [PATCH 190/767] merging enhancements from different branches --- choice_learn/models/latent_class_mnl.py | 36 ++++++++++-- notebooks/mixture_mnl.ipynb | 78 ++++++++++++++++++++++++- 2 files changed, 109 insertions(+), 5 deletions(-) diff --git a/choice_learn/models/latent_class_mnl.py b/choice_learn/models/latent_class_mnl.py index d439ae1c..20c1e755 100644 --- a/choice_learn/models/latent_class_mnl.py +++ b/choice_learn/models/latent_class_mnl.py @@ -123,7 +123,7 @@ def fit(self, dataset, **kwargs): n_contexts_features=dataset.get_n_contexts_features(), n_contexts_items_features=dataset.get_n_contexts_items_features(), ) - super().fit(dataset, **kwargs) + return super().fit(dataset, **kwargs) class LatentClassConditionalMNL(BaseLatentClassModel): @@ -168,7 +168,7 @@ def __init__( """ self.n_latent_classes = n_latent_classes self.fit_method = fit_method - self.parameters = parameters + self.params = parameters self.epochs = epochs self.add_exit_choice = add_exit_choice self.tolerance = tolerance @@ -176,7 +176,7 @@ def __init__( self.lr = lr model_params = { - "params": self.parameters, + "params": self.params, "add_exit_choice": self.add_exit_choice, "optimizer": self.optimizer, "tolerance": self.tolerance, @@ -184,7 +184,18 @@ def __init__( "epochs": self.epochs, } - super().__init__(model_class=ConditionalMNL, model_params=model_params, **kwargs) + super().__init__( + model_class=ConditionalMNL, + model_parameters=model_params, + n_latent_classes=n_latent_classes, + fit_method=fit_method, + epochs=epochs, + add_exit_choice=add_exit_choice, + tolerance=tolerance, + optimizer=optimizer, + lr=lr, + **kwargs, + ) def instantiate_latent_models( self, n_items, n_fixed_items_features, n_contexts_features, n_contexts_items_features @@ -297,3 +308,20 @@ def add_shared_coefficient( items_indexes=items_indexes, items_names=items_names, ) + + def fit(self, dataset, **kwargs): + """Fit the model to the dataset. + + Parameters + ---------- + dataset : ChoiceDataset + Dataset to fit the model to. + """ + if not self.instantiated: + self.instantiate( + n_items=dataset.get_n_items(), + n_fixed_items_features=dataset.get_n_fixed_items_features(), + n_contexts_features=dataset.get_n_contexts_features(), + n_contexts_items_features=dataset.get_n_contexts_items_features(), + ) + return super().fit(dataset, **kwargs) diff --git a/notebooks/mixture_mnl.ipynb b/notebooks/mixture_mnl.ipynb index 7ba2cf0b..0ef808e7 100644 --- a/notebooks/mixture_mnl.ipynb +++ b/notebooks/mixture_mnl.ipynb @@ -58,7 +58,7 @@ "metadata": {}, "outputs": [], "source": [ - "lc_model.fit(elec_dataset)" + "hist = lc_model.fit(elec_dataset)" ] }, { @@ -88,6 +88,82 @@ "lc_model.evaluate(elec_dataset) * len(elec_dataset)" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from choice_learn.models.latent_class_mnl import LatentClassConditionalMNL" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lc_model_2 = LatentClassConditionalMNL(n_latent_classes=3, fit_method=\"mle\", optimizer=\"lbfgs\", epochs=100, tolerance=1e-8)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "elec_dataset.summary()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lc_model_2.add_shared_coefficient(coefficient_name=\"pf\",\n", + " feature_name=\"pf\",\n", + " items_indexes=[0, 1, 2, 3])\n", + "lc_model_2.add_shared_coefficient(coefficient_name=\"cl\",\n", + " feature_name=\"cl\",\n", + "items_indexes=[0, 1, 2, 3])\n", + "lc_model_2.add_shared_coefficient(coefficient_name=\"loc\",\n", + " feature_name=\"loc\",\n", + " items_indexes=[0, 1, 2, 3])\n", + "lc_model_2.add_shared_coefficient(coefficient_name=\"wk\",\n", + "feature_name=\"wk\",\n", + "items_indexes=[0, 1, 2, 3])\n", + "lc_model_2.add_shared_coefficient(coefficient_name=\"tod\",\n", + " feature_name=\"tod\",\n", + " items_indexes=[0, 1, 2, 3])\n", + "lc_model_2.add_shared_coefficient(coefficient_name=\"seas\",\n", + " feature_name=\"seas\",\n", + " items_indexes=[0, 1, 2, 3])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lc_model_2.fit(elec_dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": null, From 19484fee969315532977385b54e9479354665bac Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Thu, 29 Feb 2024 23:17:01 +0100 Subject: [PATCH 191/767] ADD: basic working LC-ConditionalMNL --- choice_learn/models/latent_class_mnl.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/choice_learn/models/latent_class_mnl.py b/choice_learn/models/latent_class_mnl.py index 09d28e05..4c6fad8c 100644 --- a/choice_learn/models/latent_class_mnl.py +++ b/choice_learn/models/latent_class_mnl.py @@ -176,7 +176,7 @@ def __init__( self.lr = lr model_params = { - "params": self.params, + "parameters": self.params, "add_exit_choice": self.add_exit_choice, "optimizer": self.optimizer, "tolerance": self.tolerance, @@ -220,7 +220,11 @@ def instantiate_latent_models( if isinstance(self.params, ModelSpecification): for model in self.models: model.params = self.params - model.instantiate_from_specifications() + model.weights = model.instantiate_from_specifications() + + model._items_features_names = items_features_names + model._contexts_features_names = contexts_features_names + model._contexts_items_features_names = contexts_items_features_names else: for model in self.models: model.params = self.params @@ -337,8 +341,8 @@ def fit(self, dataset, **kwargs): if not self.instantiated: self.instantiate( n_items=dataset.get_n_items(), - n_fixed_items_features=dataset.get_n_fixed_items_features(), - n_contexts_features=dataset.get_n_contexts_features(), - n_contexts_items_features=dataset.get_n_contexts_items_features(), + items_features_names=dataset.fixed_items_features_names, + contexts_features_names=dataset.contexts_features_names, + contexts_items_features_names=dataset.contexts_items_features_names, ) return super().fit(dataset, **kwargs) From 3b44749ead1e51bca1b84455d68e5c4dd38e2461 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 1 Mar 2024 14:33:12 +0100 Subject: [PATCH 192/767] FIX/ADD: small fixes & additions in Base LatentClass model --- choice_learn/models/base_model.py | 60 ++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/choice_learn/models/base_model.py b/choice_learn/models/base_model.py index fb9dc1e4..b281be28 100644 --- a/choice_learn/models/base_model.py +++ b/choice_learn/models/base_model.py @@ -808,7 +808,7 @@ def instantiate(self): self.latent_logits = init_logit self.models = [self.model_class(**mp) for mp in self.model_parameters] - @tf.function + # @tf.function def batch_predict( self, fixed_items_features, @@ -857,6 +857,7 @@ def batch_predict( contexts_items_availabilities, choices, ) + latent_probabilities = tf.concat( [[tf.constant(1.0)], tf.math.exp(self.latent_logits)], axis=0 ) @@ -932,15 +933,14 @@ def compute_batch_utility( utilities = [] # Iterates over latent models for model in self.models: - utilities.append( - model.compute_batch_utility( - fixed_items_features, - contexts_features, - contexts_items_features, - contexts_items_availabilities, - choices, - ) + model_utilities = model.compute_batch_utility( + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, + choices=choices, ) + utilities.append(model_utilities) return utilities def fit(self, dataset, sample_weight=None, verbose=0): @@ -1079,7 +1079,7 @@ def assign_new_model_parameters(params_1d): params = tf.dynamic_partition(params_1d, part, n_tensors) for i, (shape, param) in enumerate(zip(shapes, params)): if w_to_model[i] != -1: - self.models[w_to_model[i]].weights[w_to_model_indexes[j]].assign( + self.models[w_to_model[i]].weights[w_to_model_indexes[i]].assign( tf.reshape(param, shape) ) else: @@ -1112,7 +1112,6 @@ def f(params_1d): loss_value = self.evaluate( dataset, sample_weight=sample_weight, batch_size=-1, mode="optim" ) - # calculate gradients and convert to 1D tf.Tensor grads = tape.gradient(loss_value, weights) grads = tf.dynamic_stitch(idx, grads) @@ -1176,9 +1175,10 @@ def _fit_with_lbfgs(self, dataset, epochs=None, sample_weight=None, verbose=0): value_and_gradients_function=func, initial_position=init_params, max_iterations=epochs, - tolerance=self.tolerance, - f_absolute_tolerance=-1, + tolerance=-1, + f_absolute_tolerance=self.tolerance, f_relative_tolerance=-1, + x_tolerance=-1, ) # after training, the final optimized parameters are still in results.position @@ -1310,3 +1310,37 @@ def _em_fit(self, dataset, verbose=0): print("Nan in logits") break return hist_logits, hist_loss + + def predict_probas(self, choice_dataset, batch_size=-1): + """Predicts the choice probabilities for each context and each product of a ChoiceDataset. + + Parameters + ---------- + choice_dataset : ChoiceDataset + Dataset on which to apply to prediction + batch_size : int, optional + Batch size to use for the prediction, by default -1 + + Returns: + -------- + np.ndarray (n_contexts, n_items) + Choice probabilties for each context and each product + """ + stacked_probabilities = [] + for ( + fixed_items_features, + contexts_features, + contexts_items_features, + contexts_items_availabilities, + choices, + ) in choice_dataset.iter_batch(batch_size=batch_size): + _, probabilities = self.batch_predict( + fixed_items_features=fixed_items_features, + contexts_features=contexts_features, + contexts_items_features=contexts_items_features, + contexts_items_availabilities=contexts_items_availabilities, + choices=choices, + ) + stacked_probabilities.append(probabilities) + + return tf.concat(stacked_probabilities, axis=0) From e3b2fd053842c4ea38dfc8bf4a14c0f1f33de521 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 1 Mar 2024 14:34:04 +0100 Subject: [PATCH 193/767] FIX: Conditional MNL latent class avoids superposition of instantiations --- choice_learn/models/conditional_mnl.py | 3 +-- choice_learn/models/latent_class_mnl.py | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/choice_learn/models/conditional_mnl.py b/choice_learn/models/conditional_mnl.py index 9987f179..beb7ff9d 100644 --- a/choice_learn/models/conditional_mnl.py +++ b/choice_learn/models/conditional_mnl.py @@ -826,6 +826,7 @@ def compute_batch_utility( Computed utilities of shape (n_choices, n_items). """ if isinstance(self.params, ModelSpecification): + print("Using specification") return self.compute_batch_utility_from_specification( fixed_items_features=fixed_items_features, contexts_features=contexts_features, @@ -1012,7 +1013,6 @@ def _fit_with_lbfgs( choice_dataset, epochs=None, sample_weight=None, - tolerance=1e-8, get_report=False, **kwargs, ): @@ -1051,7 +1051,6 @@ def _fit_with_lbfgs( fit = super()._fit_with_lbfgs( dataset=choice_dataset, epochs=epochs, - tolerance=tolerance, sample_weight=sample_weight, **kwargs, ) diff --git a/choice_learn/models/latent_class_mnl.py b/choice_learn/models/latent_class_mnl.py index 4c6fad8c..94561ff6 100644 --- a/choice_learn/models/latent_class_mnl.py +++ b/choice_learn/models/latent_class_mnl.py @@ -1,4 +1,5 @@ """Latent Class MNL models.""" +import copy import tensorflow as tf @@ -219,7 +220,7 @@ def instantiate_latent_models( """ if isinstance(self.params, ModelSpecification): for model in self.models: - model.params = self.params + model.params = copy.deepcopy(self.params) model.weights = model.instantiate_from_specifications() model._items_features_names = items_features_names From dccd23a044d9fe3054a1207e8eaab415420628ab Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 1 Mar 2024 14:34:21 +0100 Subject: [PATCH 194/767] update notebook --- notebooks/mixture_mnl.ipynb | 86 ++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 45 deletions(-) diff --git a/notebooks/mixture_mnl.ipynb b/notebooks/mixture_mnl.ipynb index 0ef808e7..ac02c7cf 100644 --- a/notebooks/mixture_mnl.ipynb +++ b/notebooks/mixture_mnl.ipynb @@ -49,7 +49,7 @@ "metadata": {}, "outputs": [], "source": [ - "lc_model = LatentClassSimpleMNL(n_latent_classes=3, fit_method=\"mle\", optimizer=\"lbfgs\", epochs=100, tolerance=1e-8)" + "lc_model = LatentClassSimpleMNL(n_latent_classes=3, fit_method=\"mle\", optimizer=\"lbfgs\", epochs=1000, tolerance=1e-10)" ] }, { @@ -58,7 +58,7 @@ "metadata": {}, "outputs": [], "source": [ - "hist = lc_model.fit(elec_dataset)" + "hist = lc_model.fit(elec_dataset, verbose=1)" ] }, { @@ -103,16 +103,7 @@ "metadata": {}, "outputs": [], "source": [ - "lc_model_2 = LatentClassConditionalMNL(n_latent_classes=3, fit_method=\"mle\", optimizer=\"lbfgs\", epochs=100, tolerance=1e-8)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "elec_dataset.summary()" + "lc_model_2 = LatentClassConditionalMNL(n_latent_classes=3, fit_method=\"mle\", optimizer=\"lbfgs\", epochs=1000, tolerance=1e-12)" ] }, { @@ -126,13 +117,13 @@ " items_indexes=[0, 1, 2, 3])\n", "lc_model_2.add_shared_coefficient(coefficient_name=\"cl\",\n", " feature_name=\"cl\",\n", - "items_indexes=[0, 1, 2, 3])\n", + " items_indexes=[0, 1, 2, 3])\n", "lc_model_2.add_shared_coefficient(coefficient_name=\"loc\",\n", " feature_name=\"loc\",\n", " items_indexes=[0, 1, 2, 3])\n", "lc_model_2.add_shared_coefficient(coefficient_name=\"wk\",\n", - "feature_name=\"wk\",\n", - "items_indexes=[0, 1, 2, 3])\n", + " feature_name=\"wk\",\n", + " items_indexes=[0, 1, 2, 3])\n", "lc_model_2.add_shared_coefficient(coefficient_name=\"tod\",\n", " feature_name=\"tod\",\n", " items_indexes=[0, 1, 2, 3])\n", @@ -147,7 +138,7 @@ "metadata": {}, "outputs": [], "source": [ - "lc_model_2.fit(elec_dataset)" + "hist2 = lc_model_2.fit(elec_dataset, verbose=1)" ] }, { @@ -155,14 +146,46 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "lc_model_2.evaluate(elec_dataset)*len(elec_dataset)" + ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "plt.plot(hist2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lc_model.latent_logits, lc_model_2.latent_logits" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lc_model.predict_probas(elec_dataset[:4])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for batch in elec_dataset[:4].iter_batch(batch_size=-1): \n", + " _ = lc_model.compute_batch_utility(*batch)" + ] }, { "cell_type": "code", @@ -384,33 +407,6 @@ "mm.evaluate(dataset)" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "_f" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "_" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "_2" - ] - }, { "cell_type": "code", "execution_count": null, From 1cb77cab7c47ff97a7a783cb22821a16b41ea7be Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Fri, 1 Mar 2024 18:51:09 +0100 Subject: [PATCH 195/767] ADD: TaFeng Grocery Dataset --- choice_learn/datasets/data/ta_feng.csv.zip | Bin 0 -> 14172990 bytes choice_learn/datasets/examples.py | 87 +++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 choice_learn/datasets/data/ta_feng.csv.zip create mode 100644 choice_learn/datasets/examples.py diff --git a/choice_learn/datasets/data/ta_feng.csv.zip b/choice_learn/datasets/data/ta_feng.csv.zip new file mode 100644 index 0000000000000000000000000000000000000000..7a2550536b39cfd374ffa1a8fb81484e42feb08a GIT binary patch literal 14172990 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�!7-eh2xe^kgR_!pCLn{`TSRTG)j-xRrS z<&!&sR8Qeh6K-us6W2(lQU|SeJDyAE^7jxUEV1U2dRkflHHMR~ZuD@#rK`f@7?hdv zot7;as3Xrs#Fo1g8X|oYfbs z#ShEOE_X9mQ{S_0b!pANx4ziMH$kSBax4pbWP9xAu%tB>-ryzWNX6(2kyPjxScKs* z+*5)dgNk7*!Aoc$6pu>GdmHvKNabYzs2!cp1sHg`9sLXh@y8ENBZaLam{?$%Uuwms zGZ-@iY~5+KJ8Pg}9t@xh@(%A;jVG7%R_cha4}e4hO?a=7z+c7=Ue_inJPskuf$>ta~?tX4co7No&F(Mwf@ z6uZAcTbFKm4)3)q2LX=yTI^J1W75ga)gyTL`R`_z#>w(1bxI&8AJtCs4RQtu!;^Fx zA~Z*P2?-SL2s>bv?Kj~&^p&Q3E;W<9PFLFSoPt$~1XpN#(iSYV*wStFDEZLRL@D_Q zVxVf((x-d7q)|nHIov!yixZeg3R1z?LbdX5vf4ri%N$_R3M(K#Qi@u_XoC@4hrHW0?kn$LLgCD>1Ap`Jd{xNH!6op z?yclnmnOHZqH+Q+^-Y2!*L4sKo~0N|bW4m=Pv3`H9*5>jTMn&Vwl&!CmXEZ=|~P>_Vp69z~L=r z(wROYIRbgWpNAZpiz?hv0-6!JNz}r#nTfT%KIno&&f#m{#ylRNkcj~}%Z-^>SZ|ux zA=ENTmsWq?vnJTSPZMg=jN=Bal-wyY7-G2RtmjRH`{8waP$&(w(9pg-#L#&Ktx

    t-Y(Ir4xl+DHz6 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 z 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

    ~c<{*gxb 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

    u0th4YIw;| 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�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

    VWc-VpqMNiDmSvT8fkOLvJL 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�Md-NqYI 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�m!U8eo9IP6WG}xXow;@TggASX$ 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

    pQxe7>|$)rS@1I`e~fGVg=qR0w%KLpnx~}Q z4(|}UwP^~$JaDq{zjY(;>KIh}>_}PkZE+HPxpchLu8Qcycbmnmpi5Vlg2B&! zzf`)O_HN1Wg?5RXh6u%ElRO;Wg3I~MkKOX(2Vwd&(ASjHz4H=H4K|iq0(yF@9|}8b z%^k1bI4*VpP833jFfpU#WWTt?B9OX35e;^^C5a}BW)8&3WgXoqm>bwqn)Q_usjil^mVyLbwBMS-3-V7B0Nu}oVZ2yxbH z$0_r7?6=`=+WQbk>IU$NwTY1E#JS0zc{ zt;ij@YV=oGf=W)58N)eVTFvxOhprnr(^Q}4+`o8Tn{}-jh%~ui@E1l&cI2yEi^&nz z!0C^zlNjzz5p7DyaUE@+-gy0rne4A!GL^rdtjRfqjS{dH{biovqv~y0EKnxGt`KF+ z#Y8-i*0X@sEwJy~XnI2rffre=JbizE;YX~1aS5faNXd_TCnAM zha#JrD?oZmL)>WvJ&U^vOZIjWZV2{a!{&ND{3dr;>ko{zVF{P~k!-S=%FQ=<`tNARyN;hqNBRUC+@B9j(p-T_iCkE~mI96G8Ta{*BRrqjbe3Z4B$XE4+3d8-ioz7TtAowF6xj?WG$TM1?Rc_U z9?7>Z?~n-Q>X^gc38s_Pm8;J~(R&N*=kgkEU8@%@8)jL_qvmCq+!?*IH*5laCsq(d z7%i8!MRBvPURxi7o$Aa+0Fk-o$*rN$c?za@0PcM@Yo^?R5s5GU_bnBn!tgVjrdA)l zzb9t-H~4IsdH(xzxWDa!lwMdz+rQEc_>EHA)f6=+FG8zwJ(F^=Ns>4nx|41#S}HEv zdVdbu>!cqfq4a^6ZOSbnQGHLy40YHkT4`)19jn{gcFt9RdYK&2m(OO0mU+4Ok773y zzmAhGQ2@W=yPtfQ8S-tpaq4$aAj|6OruCNu%**s|Htslyql@ScG}9|2pyCbHY*9bG zR#&7F-QSV)M1lrt6uTly=Wy*zGX0QYZkxB`$JzenC5{MQwpn_pecH^*Iase#-&_h1 zfJE<5txAZ@UYImbQrVrADzns^W1m$xJaY5i*yS#%5_gNN(;8Z;b3BU0iOX5gRjcFWgeqpI)y^h~DR5-F zv>MNSq!Ir$@%JNnt6gJ(E~t_o68)uJ%(RH(3^4p}-pL8l)~}U*$iSk;Y@CPUk?`PO zLDfoH7Q95n$9SFn(%$Wv{qn+guOa7t_f7@FIEY8l)iN6DtVt_=h8`Ib8DKZQDCMTi zOIzWM=P6QzAxcIEO1ZuX{Hw7YYN;PUt;JHexFjbip8)x@OFreCs9fy^31D?mY`cEC5YQXWy^B+4g-pOf?>vL$rT`+$ze8;Sc!SKBoG04 zjsV9!9=@^=(g=O3m-rd)o8=uHyO z4Jl-A;TILcOe(pUx)yy(5!jra5e*DoAzW@&AZbXKMy{G%7r%CBoRubVFOJTBmcAYN zNdU(mHj3{RNL?)+m=k`9g^PH)D1XAa07F2$zw}L>n1!&5biU7W6OqW@M#K7pz0o6f z`*x-ZWxi+WrT$35lhp$MJx6?i$mWdKqrox>qL+rAhDcFR<#^LeS4-Kf z;#o$tc3LB;)-I@gLZqh_klr*3doEphbg0d;+}_$p*_{#qSw8<+-_b^L$eXt@Waz+X zRP-H^iE-X#f#M5(N_b^up;RSzjie?V)xM#>+S3du6g_d43eH{7VWY~JZTnQyEn#)xeF(y;r(=JMIQ3%3NuGaI|I}(v9Jg&hZ$d5J5S z^Z7G+!+J~LXSw%ih@fsDYiJqdgdC8DY6igFN-x(?3CCa+&>`dQ%a#J#@sZl)%& zjUM*uEM-)(SNO!TqIVJ2&=kE9$-<`^4Eo{%Kl_HNV_lhiC-jQ4r0?QdVMc z;o98v@&p!T`b2; z)mY}UnQoY2it1fvw@NQkqr7o{V8a$(W#`oIkY%V#@4^@3EoI#(OmL#p`ut>1cmv$u zMSzvWoJGKSt!C3T=cxdW!S+tgoa>9Zy_9u(5~i%P{_*$Mzk=sU>J$j@_}}=b*4NMk zMUifoWp;W`P<1_|NiT?TmWtKKPg~$(Rw+qRvEv-zvtzU&>3X*ln;R&-*ST5XRK3wQ z$7Tnay`+(9uerFL_r~d4vx+ux=P8DX`l!RukyBpk1f|xekiGb zD%1}w+Y)F?I$rY(Zd{bvm9JaKY_JnCwj{0l6~1d}zLlFOH))OWy{q;#Xvpr|Xy=61#63Hvvw27C|s zfp;UM9s=~bW%7M&sc>P|rLOi@*APNqpHL%Y32}*K^A`W$lxt>ZXj-j^-w3=`O`R*F z8nX8aI?<-2Z*ZMqQ#6R9m)X&v#9{wLiHWX;?bVLMgGcH!&Q{ecePc~a$eVeUI=#ST zEikT0Ev92Ji6oB3LjcT>GYCT3f0!tXs`385RFxrpw02V*y2Zw$=-jNdCZ;*BSJcY8 ztu`SpVLw^wlG@P%b!wR8)V=0iTbmK471$Mlka6v_P}o!LFD|D%v$wDt;^_j#h4-cp z)s-z@%&w{2p?ntS=!20*9;D7`#+YOoJSY@Za=$8J{-JWsmvZaIlC=8WM_X}BJD5!-c*WYP-$nqQ}uo}Ldbv2)Q5&Wo>zH@GSaY3}s zx(oa&t7|^itipL4POBn$PjYgt&Sj^HZk~1o5YupMR9*Kf#4St;kfG6p086t=S>A6$6}RJ1><9(aB)WIz!d2qZX_?5zw3U-;?#%l*7GWqyBxZc~giLa8Y?;qU$Hv zTK`^tWx#{y@~Z>6`^L6ifE^L9NtGj?ClOBAy_a16hgC=NxmHN5caH5_N*!D18I$Oy z8)}kbsv{;5)xM$uxACH;WD1^SY(xgZD@CH0&YL0}zCQcwe z_YJwbA5mfHfoV@L`aCQC)x!GnG2COV(o#2@FVDa-ML>^UqeX0#{3iavzBRYc_t74p z`HPqXo^L1Tc!;?zeyHvK;U2F`tGZ~;I`ukjQq>h#QkvS#fUIqmGR?CA`_m--Lg}Lk zqGI>ujAqzGq{c{Isd{-C!%)G?zgqTB`sCp8BYYvRP``*vaT z^qh2DhJD2s}_)Lf`BJMHgbYc1EUowcvznt)r6<;H^I7&o0U`3rxwAQo5^ zt%aWcULLZ(vLm7Tk`KQTcnZeorwkt)IW$@s(mp-k1G^|CKy{*b-kN{KIKKlsT+W!i zX>O3*HK!~M&8<3|vvHKWb8b$xAxkkg8|`|{hf19lNnWdJEe4x(k^zz@8Zw|+<)|z+ z8L#mof>8~s(yKn*m8~ubK-}=sOhL-dF>qOw|B>cjBJGkDVJUnKyT&J8b=S9ZBHsn8 zand3px@(B+zpt?A+9vBDOvYo-W&;1k;}>dG`JZqm1dpW7Je|7vY|n!4dAfIHm`U`d zVOmzIa+ty;`MZ>js@2A`pw579G@c;69qi$wtxwIXCk)oebi@+wI)c|?xlsU|ALyRf zj;`kKy4eYHR5BNg$?#qz>Cc~laB7rrY~LTo8@k3RRFd)K^-g^X&x2{m?!H30oU29V zEO(k=Rvn19%_dGjQ$gIJ%z){m-+vWH?UVA;Qz=rLeQpM4nsj+$KzOPN≤P=oP7{ zi7{HikC)%|3@NQWQ}mBxglFJy8aU;8R3cHTU%S=68V>{LR^+hiBQi5EZ^`=Jxst^^hhgLQGNcn1@K4hl zPD!UguwyvVr~(m2QJU-+h5Km!b7#^8lO#;&ToEDcT{VHtI8;R=_jeWU47luM%wmrK(=s=du_`UwGbA(>4D#N< ze=`xHFO2fCoLQYMnsMinh5lq%<1$T3-Sxw(SCE`$>xPNp-?Mw{!ktL$ze9id!=aiL za>HDTR|O$kAMXdWMn1d69FNUFwIX-*IhdRbxuXcb3THX}I;Pd>gqi(u;yPZ-p#`bc zKkZZ|ix4Z?Qr%QJ&)AvVT2b|1oG3^bOtR%GhFZK?z1<6^wmn*0S3LFxHt;@XRKh zhFufe{YT8fQ1?X`CL(~F(*~-g&-2}1g- zRQ9;labBWH!-BiP%Yd$w&u@45K<)}vGt^+aZq2@rmpPOpBud|e2QKaB_41o|89O(M z-OT9HVmBJ=D!nx0#ZAr&gmta*5gI3K*G|RPL!7JuR+xlnP&3a`HiSwigaP!9zvI8F zG2OhQ3Fci7i#@)u-$U{AnjA=-e}AvcB57uBR`Ae%>1J8f8xZlbKyqgQq^{E8iMa;^ zck|yYoUF{C)Sl+_-*^-&cri+aEC;MOt?tXwy4FYIu|o;iJP8@MezVpW^aGmNWykQH zT0x!MR|Bg1+mqBV$gDY9Q%g)f{lFBjS{6e!n+cR`h8Ca;|KAYIQ?b^R|IgZ$Wyy{z z$-TsPeTY$F{~K$}9UPF1$k2WLPS@>Qm5~Ia&u(^OwVAKp7yR=6EE++v^$0hohm4j( zR`}|h&bHoEM5djD9S5F_=#}_xv{Brr(oX9qF}Ju|>3-jg8vuFijM}*_i*J~j^S+_1 zKR!l7Cb(bXl!UW08{nw+c6gd4_;#x8iDg6q6QI4?c-nA8S*VID;kk3kV*SvG0-5Qo z%%T}~%*otQMem4SOm=eWg3VIz+5OM}XXR+chhZ`JYH&2UemAX0vynrY`!zu6c)hzU-;2y<7DN0jrp`bkJ|g7f#KBQ3E*V#GFA%p$H@ zv~{o`0zk3SBAwLRIU3L5Aqpqv;`2y#HzF)%*`br=mH>(}+2iWdi=uym8_g`MPK zpz!SwgJ(hZ^V2H}I4;n%wAp!0Td_3UmRsSN%o9mKOaMQMvG(#{M_Nw~HX9d$m@y}f zx>oyM9@qnvzRj#YY3ORbG^W95G8FOPrR)0cEKdF%+b!_*%H)CU(* z>|$6sU#LDrE3y3A9SQZ1z&zFb7pg_&m{x@&QPEH9==H)FX<;jcbfBqK&U1XjSHzKK zD`A#`cS>%tC5WD-2(Y9ErKt8Vup>>bkybq-F#i%VslH*9tNZNblj|kDRfwQFZ^>G@ zNYrEcMmBFNt(Oge^!zwMC|&J zDy&j^aoxgf1Ot6D1T*F|-}Ua9F5ROcT)}RL&W&12*_Svw)ixTh(USMBrs#_^{hP9n zKGX9$HLSU2^ZnHQ4F1yVat2)5`1&rI1=`-b>Ul`<+|RC_&0qFZxJPiC&t( zGG~Qf8rF}hty^W=EYL}rmZ$Vg^`=PZY7HR@14?&rs(*8o4CKqwI6^i60L=gDrkOTw`HTMZ}^eo zPsq!c^&TulUwz0cJ>SG4)6vnFkIN+8mQDC5;Z%CKzQk!rB!XPOc|Uq zj7qCGD5x?&EhMb*DyALI;I#blnb-fLIfzzyrBhMn9w52Sd?YC_41R=z@HuAsexa=& zjbl=`oWoeDc)v8i=aa%@&W1E9S}j+2h5`d~s$alw2Kws1k*~LvA{;EwUbYJ>#oU;O zgjOfT7G3vk3mFq^cAn<


    =BQz4XTS@AC~ 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 z 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� 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%0A}z2RWzE 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℘(7%)g5aElko$mCb2rA`% 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%0DU^m`Nw6S`0qC_hoTeSfV1g5Xi7zg@cc0e( zEN?yQ7w$tQlK4b`$kda3AMKL<)KkghvTZ$;Z~y@7k1dm&)aV+KbuxRSI)Wr*6~_au ziVjv#urlARJ^K#d*KVyC$EpKFJgUJ>LZf?#>!kJPFgB!+)|u=O(}jeY{2s2km95od zJmQ(6_ZGEPAZZpF<*3w>{cpyjP&3AoM}x2YAYv#YG=yod_Y4KYGBbA|S$u^#nx<`t zF^=yJltPxgKhU=*ziqfi{p&6h;pb*<1^X+~^ApH zJs+0cwh5_0q>OkQ<@4L-2E{{lg23@}mUZ8Va6|M#&T6$8az6yj>;U;t)H^u_W2IL| z)c)z)%pQ^DJlafknGDqw4J7eJp27Dg>Q6{}c_WJq7oWBXqm+dS(pi{Vq%I3LZR&pD zimDE-YU?^uKghgse{g5DS>*u&`@?gpr(Iob{83eCyZ;kXjC0C@Yt6zt7Th-w6f=u9 zf_P%r_3_TGx}O7X01$pUOMu3PIptvXRhnMr39uN;67-A6AooMkNaQW)5Py>#kZQ00 z?nL|Qv!w~7>lp{Bf89t;Wx?FYv!)vQLr_u)Kp@hN0OUQ;|R z_CzEv|RTV}@kwyub^scV<(kn8>ar?Gi=pwvE3#{%0a~x4Fx;ook zA)69K!4(=i`|Xgc#%iijm?G(d1(y<8^)|1=U1G^wEK&n&?4r5ch(ebD#Wo@zY>`ZO zz<;|QgZaOMVf1}g4^&>^qoCt!V38fgQRi%gO4%nR);mI7lO?Ai?S4T{DSthZq zs!w+2`Ig<Ng-6%}QfFB3jwRh^}=;HxT2(|M4IcVaVY0{5u@EA_(n9?g6 z+0^*U`bp*nkOPUxS`0Q6qnd6JC(m1GUdyy-S^Jd;sly{Y0St!zO4X<0^HRPd3bVh) zbpQ_4Phc04)n@3pu$+?O7JG7a!PKrne4dR)%C>q*rjC8LWu7A)mp+0=h)CJ8MdqGS>eVfy zht<+hM^!GjV5!reBNN(81q04&bTmx6ha8^I^Qo(cztkh004W+6 zBU)KS;wJe>zLnz75kI7qde*%<$0r<_0qT@>t&f>yfdQHZ8x5+v;u@Kk{5tDHgaSGi zICs0ZKXidc3E8~vkKmcU3`2Npkgj|_Sf_-+VAXd-W2`qtB{AX5%v_`xP8vjk9<{c* z1MqmxSt4TJ@p{#(j%nSl@9x3tM}n^S(_8Wt^w(^`Ykn{7OnhTqeY@B$v$0{jKboWI9+ zPjY?gKBBQ4#Y$Ghwry=e_;l$<`NO53E(?)Q@5yk+g~8$_>d>aQBe8fhy<1-`thm0` z@S<|P+K#y_)C7}6v12WecFw2~w@j}G;sf|Ce9)Q2)%R>JZIL}w*-twicz;{xZ(9bAOFs+Cn|&mbvY^bp*sQiW zxgFzuY_(=p^_{poWy+#$dChl&xsLg8NgZ32Y-u>9>RlxkL`At6{35C4P}n z%jV1))Z|k6crZVQcL9edI9q*gvIb%#0f}>g+_C6D8n6$j#ZJd)-PR)MgIzTcKgZ|X zez_iRcI{?xA(q$XrUqAFc0+X}wN`xB;>9aNDbdHaCTNh$I|X4&U2N~-Q0Tmh;)Id< z0M`bqSN1qBZ|1muIWuSeuDKBpx41zPBzdqzB~=0ofc(~N z04C{Np04+NKk|79;imkCTsHiH8O{4jwh8MW3~W;i?22o+X!cWq2_E`$xx7b&QaG)8 zL|g2LX?3QeAo8!p`rfhc$-h$-cCwlq7y`3)|HtS|aCMWHwhsf7_@RhrS2X5lpb=aV zpiy_#rvizEDZ#VnUQbLt4mdwlJnJ8>U#Mbq^;@1r(j$DQK`UZ<*K2g@n`d$HXijdf z?mTJ_4q4ew@8Rq$6fz8JJj*C0kBZ$akZ6K)jy2wRw z14=!iw(LBMrAkHa)83gKMZD#&;7Ha(9jd;K_Z+I!Cp{Y>w_J=}Vg<35fcIglEPR%qH` z1oO^8odA$N03+K<<-b`#DuuWJ{QiT{yW?Z_Gh$HzN^MbV0)MGle%2582k*3=XYw7d zUIx@MCRRFw5SZ-7(|YKKP&XD%P16kch%A)$QC8n$9_*iXtsGu=Z4G@`gzQ2|8e-K0 z^JRNIU{9TMuzj+)`dzyebHt>Z6w%YnG zNPW-xVCaStCWgLD{A!8cT#n&KMlbZ*qbn`Hcr8OgVpzrEt*yZ->QSpxg?$`dY5G!W zp~Y2gJrOJ6hzIbQcjr8LIc&j53^Vs!XsA6C|4B;ie$yy zirp7z2}pGUBsKoeodf==LVlqW9_0)z#(;tu2=ZViuY5HV9HlzdqDCKxObvDi2&6uo@fPw+!n7h*30&=F}^-1j{2i|AFiHv5}2448h zwiOkSo$d6DgK1N&-2vG8f$Z?py=~2R=FIP!@7_|@n#diL;enCZywF`=NZ)(73qEI+`pOHXq=8h+*wAJ?%-3~if`BI zrN#WK4&>Q5Y31VL6ATDqKbYkq{vZJT%pwY|<;OaiRCTS*#g)f@&_WBOXJ$iuiZpcX zQi>#*hKnG+8Vf5{=`1OMTbXT~JT=rgkJ!2f4t=3Bw{mDawf$?$*2-i`HYV%Bo6Vu->^b+yV(R13-`nnv{>X(jBWa5 z>Ufb$B3r`1nY?4f&>tnM$pty!fR%~xK-wDIG_%Q)Y~I}A!t8^ZbWJ8cy8SlTeSFYQfhe|OiKrBG(QlBcRXe&G4x{kn{DJ& zbb$k0=a#}H-J_OLTN%=4_5=s>|MhqX@I5V1;ZY)~Rg$uGTJOnf$Tk3^k5WDcc>4u3 zAsRv3?0_A0!0zq)rhYQZw@SU!>;I8&-Jqi|&IvP|TV{s^psM$!V2+Q{uOG-UQCckF z|5-{#oafbd?5Lu{jZ%1}CSWHIb>r*+jSN1x^35Fj_8&_ueL29DaWZuB@dtK zb~)07ADy;?#d46D!TQ1 z?1;{{o%V2Tihx_SxoOELt#wXXr2i;4|49(N>8nJZUiREzw~oW6Cktk4jWH}tpt{LN zZfY44w9zHX9^eNH$L#pkr&{y+2okDKOCL;&VOSK)!x}qg{W;YZb_I{t27l&}#KE?l z^nIdsYnod-&)!caj6w>^Ew4#@DHan3TX%f@_l(9285FCSf_vO;NOgah;-uir?$3?} z*5;h5?$0*Vl(%`ti4@IGBXn|ENGE*NVyD(#t&)2wV|CIU>&C9>i#f?~*#0u_o7o7X zTPuUpyMdPDD-^Po;#Hux?lHIDUK74l26-BOzfJB)>ej5@Sq#HW0O1O3(*ejS`B!q? za#fI|n0O9Z_f7=gS1Ka)B4-c|r^@(#M{ujVmJ*#w#B3req+6{9@%i zJKB}|jdO04!D?S6)1znJcBA%7A_00={shdfUJH=HUMpZ(7GRp!f1R12&T|Cpibm{c z^-bn5(!Qt7uexm@{R%2XL}H%$vRLO!m6w^=MX@DpL>G8$S{h8TNq!kc5=?5+?zx|K z&T*)>I05oVa>)m)sgn24(q22>gy0M{MCpmcNVzmX1{P-95$Q~qx4My1)}{(ymZ{rD z;wW#}HRdEAK#XC__6e#{$tuVaI&`M-ri|g&q4nLB3jp5K!RiGMV%&5Qw}aMj*OAUd zHZK0=KT;E9yG%I+HGFBC>)r|sUH&#d{sh%~+c=ep{S;;rIZmy;R#(&=IjS{ceuDgX zMpN9LQg~v0gDoB|i`DDHB9WdQX|F^T`ZC{k_I)(7UjkbDWljXZfN6`?il-s!XH@1R zR(LPW2YD0|>&yT6H1P~tUr9s_tAnv=S3?Bvb7nj8YCl`zf*=y|!1F%&o>K>dJ(Gfkm-!+8atxPN7BzYH-)Q-qW(JCRnb8}iC#}zTQ+=6-{`g{MZO?!p z6{|@coHdMVXoFmhx*wNc2J3tF6CrMiz;(a^*GiN)b!t|l4%VqTkOH;97(0vi*HW9m zDm|}j&CsE_6&uOF!*7#-?v6YB3rF(rmEwMwYC&pL0Jz#8mqNI@#ISVU^tlp*b$i`$OE2K${E&27)1xElj z_z0zI0W%ru4g2_Xi~=cSDtN8C{%Bt2QuU+(nrCcsn(TRw_l_|s~zVF&ZE-kwj$;7IBkt_Ck#69}mZwMWxPjr(5 z8Ecan!41=Ek?Rw;^{o(g^R?eI@`h#t!Hy2)lKt=FwMq&y;EphOE(Djrs~bE<8tX4) zFjUB|kFxs%c9if30P1LNk5~LBGq=WDi98*D=1BT`|=pMo@N^yi|*doxlmquh)OK`0Xty zU#+u=^HXiT^Ye>#Gc}&L;Oy3dIYfS)^age5?*fc%C*dq{TFxFO(%~j|jI%JfiP}^m zYhi$?>&zIK`qe7kAIYD|b%J$S)xJqHeFL=f`T&XOv}<-ftPU=r(e9k;b#ydR-%&lR zW62EO#I{@x)FvI;+Afj^UrN!`kvqn3-Ac_6w#6qT$$~iE;SH>L*8t_DL}fO&N65Ox z0jukTo;;roF|PS!47_L;KYTQU11!A_r<3KI-BH}Rx8=HSe9JfYMF{3T|cgV@RzyKsAf@|h1X5DOq?Wj zoZ<#PkR}gUHNYDVZj<1Ovto9)Bp_I9?j0bQMGXr+?uHQ~tBhaW4mEs$su@jqYY2g? zuo`5g%v(RB)Go>(!#L@3C}_ZsmVd(~77O!Ufb|y%;O8;#XnSV0#CXqqPQi-nogD`2^) zD%S#uzqnRIA%`J{;8MRMB0E^!32>jqUAa?|^kC-4QQ$gGI*AHh+NGshyPC_kUn?g7km-RoW$HL?W2d;!3v8_5$ zq!7H-&1!a#v2<)ob!OYUT7Iydr}8GvlAoF zjKzQfUg7YW%escu0-yQ4g^TTv0O1=tboJV& zxxJwwmEjg3|n&{ zK!YwX!Ory7@pM?SQUi3vpW3lDPjRp+h0ao6*4a-~B6XBcK>Va>uq7e*eKYvp4PCiS z0AAk3t(sempt_ofd8taD9%>Uu;W(x8+uPJ+&WxgJLq)$Nq^e}7qT7-ydjy$qsb=er z;|frL@%DgGG^WxQ$bTXU5l(}b^`g20la_C)6rMrTk?Ymi z2kUD-PQ^fe=-*Piz^RJM>#Dc7OG{C5%skyOwLjd)G(4*wy(Dpz zO_)s%G)%+!6bC~lPWB5T?mP)!RLwh-tM-M;h7ee>Hw^d5gk=)U@yRw-p+jB*t-(sJ zbn7UB#tMWT<_3wuP9!C24@d$2Pd4-0z+`_sw#dET+DBK78=sbfp- z890NM*5S5iSeHCR7{n??K1M5a)-?2-W-n-@bY=8q$QvO0b)~2+m$x*_XtO?xh(!Yf zQThZTWB2^X-h%SyiHgm^EU2AHBq+Zl;r_mze>;>#NTtM~Iw30~5~29?ntu|fCev_j7KFv>kQ z<}7L)kMOj9e!CpiQg!JW*!PxX><=mx%iL@GI0FUPWCdMw0VJXW?O7jZe*;mRibSIE zd-QMb8f1;AlOiq5mc!5>HAD5}Sn>XwB8BCRa!`CXM5I(@S4*;VEwDw%sFz%eR{PEo zADaW^o}Ul47<&%nA|rIQi};~4Ol`48FVPRT4IxK8f_vHXRG=0j0IIEkYnOQg_QlDjrap|Dc;PiFH`co^_>pj4w>Th`Ctg;cRLj5>~#TB0_ppnQ4El( zFq%Z<@OALU*k}G@CgJ zJoaI?q(K9)G{gqkeJ(ar?v-#^9b7}UAoBxf@T?TfF>5kOk`O?iQThWp2^A=;=WjE& zu~aicj*&Om8zI1KUqBI?di&|IUiGQ!8a~5Mmy369_U%M{k6-o;e*wwYWjQjNLGVWV zLN(4w8_N0HUqNvI=;SZc&5E%|1u(^SpDWw(3S&=O%R*(B8Hhb{5NTOxvjmI1eW^wC z0~c65Wk=R2Nt8T|HYCZ&Z&yj;k7T9jGAxPn2Nbj3%3@?W|JU2$f8kOr8Kp6=hYFl? zwL*UwojKfct~9%P<+x;SCKuAIqYqJzb_sV_YG>?wCX)+;BDR&QQZHc__SSn_=ZMb& zfy9PWT~98@rkDjG*KRzQ6D?t(wKKeWEQSOZ0MVtG8w;*k7@=hV#iJf{jb4#l7fOK2 z?XjChgGo#&d zuc)N>N5kgCncVRudr}Q#lT#ovvT;W`(zA4}m&YXVN|*Y&g8ITDK;+J`&hHHh)*<7I zmw|rEYGZX3qn1bhe8=Kc8lwQMgB4wylsr`kr;^OQ9)-tDhReS@^~ZC+wk)T7Fj;ER zAI}}*^`#1oZEnCq-i^AL zc0<@wmHp?Lg`*F>i75HWN?xn3mCr5YbHXjv20QB4p+Kcy4&@mO%x%0<66r|@hq|-{ zW{)p=iPXVR!-LA(5Eo;?LPkEf;iLy5Ry)w{h`NTPwdjq6)JR8l-2s~|T1D&~jrN@9 z=hqET0dk<{6%jzGm(GeC)fwfYgZER!$pxw!>Iz6t_I0YmLEl0yt+4JHf|{_Cs&QK7 zau|NC(uFWv98};kza~MJ0UvKdeSp`SH?i|L=7`&w1=-0Ax403OTf=SYvWq}}I!2kP zW|@xfoV3=(6S9ikXqH>pn3NEf6r1R$rkkBYwqlBgHh~2lY8PEi_6q`gv9>D+M=T^_$TazA%jDn$?*+F1&gwhs|yCRO@Ap%@z;U#B#vR zGzqtRssc5tqG+)vk2vB*K%)z(nS?T0YQyo_F=0+xjEc>!wLE;ToWExlMBC&ckqpu$ z-7g60)WIgx-+>gHG2#Ueb|?(;9epATd%U|EHZPc{Xl8GNiAG?y1cS4nl79H z{(kV^Q$jTK^-xua^{FlIfaP9C(p0fbyoKkEoK+nJOMU&JrrNvyw1po1PsL0*t{r{C$IE8qu7*>5*O76c$^5Ef)}Dc z2YDB)wEx{nJc^lNF}4A>sQMSUx#+Y18y%4jcb$x;@Td269@n*$xvZ4!5?ZW!-a!Dg z({B$(CYe7!i(i8E!S|@=ip1{clAcyIIij+%Xl8_jD=dgdO_toq_QE-(m$h^tBx*%R zZF-!w3@%T%$m{l8f@;w3Z%gE`ih;8Q5Z2817N0!4>u5Lh{t6uhl#nu{*%p6HDQumRd2UDLO+p;apVk6xIOob{V~#eSlSVKcQ`*CNcNG!%n; zkWoN^;!#bi?Y23%e=d$dV~f#|mBQ+iTeSf3AmH5R1~_}M&aM7VJZEN{f6V=xN9bY` z2Z1wr-27%yS_SB~I#~8%07omc(0D2->)w&!k|GOx2)iN+S0Brn)i!=KXEwnh5fw<7 zu3*%H`w~EVmr#$+As?Zx9CEghZifwuzI$FSZsK001tL=fNmF!DeQ2>guY84qA50b?B~! z&kqz9Oq&{dtaA#ZuvihizZz_~^co9HgL6g96`EK?~_sUMKQ zYa446L=OC;D#5Wx6yjP>bu9I^Vkx-{K*-bvYQg*K{AQ6qRj=>m0AN6$zwHnF$Qw-{ zbIba5cuueqCbA~^AnO&4;G~kc!5v)emZv`a?dq~3jC z@?bF7>`b-ilh|v(jySwZ#)YUu66lzMwsIG!Dtq#77X!hCqKu+`^oN5k7oBsdTa)s6 z)_jpsX1gjrS;t)92?}l8n0`f8sNoN0Hs@eKqT{C=%=TfS{CB~W-I-W%_@c^8$|}Y8 z#Hol;j3_%gCY-hJMiqwNTsJ@T)giSQhL<2FI{_5*Rd*=2)6JfT#oh0263`H5n2y`5 z$(AYk7dP}BjWe{K8Es%3i++?ei0yEGJ6^{tuPZo!h-9nPEDZB(H!Q-lK>E1n_HX)e zsjI4P&}dYXjU#^0RnC~#3nH6?iFFZzOwC!h%_1q{2eEi@os}5tB)4fcgW$yn*<5iD z+>2k`9l^95Kwl?nfYG1VpS?T&nlVS$Pp>s3T-3Jae=C^Yx}(<+Rn^vKzU`mFc|B2 z+bHv+C;ZT*PT;>D)Bkwy*g6o_C~*u4l^rc+Ucw6 zl@_H+xuyNWC?*q}b-?!x&qHJbl}Sg8401e-hmTvQwLN`q5<(~F36dW6)7-j%^L7}q z01FMQ?0s&n|AIC!Urmy)jw$$z+HfVp-a1DJ#Ou~P7rLW{_CGXzS4kce1a(2FnKD;E zB}dWoXm!Oe63U5co*!x?KQHhtq8Qbydfh{93%9^=i33AUv)wf1HwgnfM3wzX1_N1* zm~D%SA(iK+WnJ&2zaN3+-vT{;;6<)|mNQcRky|C(GT0-Di;A6Ye{?Jo_wjHlzuR!t z8@j5r9PDZuAR{ExRV-Wz5JkLP{3)h*T+IXF?ry9=MJfq7?zuY z+Yp|gH}nj<$^i^@Yeo8KK(XJt^&s|JbY;1A_E4wQUV=aJnsu~FuQ~9htv_~8w7Ake zM*|A-xddudtO*C2ZaAvHeD{cg<{BB@PYQ?HKBQ`KSX>S*E|y7eJ~JUGK{7qdFpnq= zSNNioWSxOMhz+j=i8chgBiqiJ4ZgG|ZIRY4xNVDcr5qtXg_3}Jb#Yn1>e3EaRw|!o zAVeI;PZX%!d$jcWl1dzy%PPiMYc+>xQx?#+PV8UuafCrMKu!|48?dEGBt_8C!Ce@Z zh3d@|n_XeVAN}VsW&|c>x0P1LaW- zAjhhE>aCRU^XpN?)DEGu#aP3M)`E~IyIiC2dL+=l&w;@NJhg294pgPcYDcNonS)|3 zwo0wSV~_w_Uff>-yqnQ}ilJ_$+KeDKlcZ~*kje#GuK`Q~;uif>aQLQmx#Kb@J_h`! zHrTdJX9Ef7duaw_M{VBSA@N>XJ5098do~=3Gi> zCUE0iEf3V8pZ$qy2$_|B(3YPtYHwn_90)<1t)_Q_L4Tr@67#viTD zkArR3c{mZv4|pj*IWHf#EmyP8Y2xtzQ~CS{*+72?h&acF7W?+S@8OO0vO`V^VN6ux zR29)?upOoL96uE$>YafbZ=*dM6i`3MiM?=KDA_Q^5zp$NUUyd3jn%P2hVp7NE7g&L zkdxhzYZA0+mSrRNmdvQJfF&cIpT)`KbV-_H3!OTGAC1{Onk6GULILk{gP(pFGDdoe z&}j05a8QeR!Z&B2{wN$Xp~Q*GI;-xjC@s=~;VzhUqT(JFTd!vYpafiRv*+b=6z=yb z*MfvQVyL6)5o`#P#8vZ;74KEMKi@4j2w8pc+8TTX*v)OIt<&OAo`6Aa*0*t52uf0& z5FHuXq!+ zY7Mb4;*|~+-AgRI%8`aV)3iFOzD?udR~fWA_P;#kj|j9j80@tAKJ(}v(09OY+8#l5 zsUrdFmlb}fFHOYR8_tbEQz}{@jMiW^I@#NdF@`1V|1Zgsoz&Q&tjQsWMj)4C1I#mG zrdPEPB4}(!(XaB|krPcQ{}w^KMouOr@Huc{@K=;b2+5=MBdCLc#@w>MYmxLES>pu4 z2n=*{^h}5l`O}h*#p&}TLC!N5O&Joj-nP&`a+x1-Wj4PThT&Lq{~PKuT|*bnn9j$GL3f>NaIutzD#BE_+rhO5+b4qxIceI&;f0`i4wZ zDYl)^DtFPbHf+riYbPD0^Q7b&bu#I6RnsQJwa=DnQO%K97UFFX_s&)|B8Xbsetv$Q zq~38PBIFPMIJq>TzNum(2g*|}+X^FmRLu^0py9ZlvIr{FI?$__toFGdrSBR|WNUqM zKVlmWpa)1Q8*4-(v>+?p5eoYa*RDJn`5MCay-6;u(b8%xBfVtrK#Qd#NkqJpAefu` zf}#7bB*bEXqanFZPvpM)W;`jbyk2$^s2WUNB&pHN5=@}ekWW11TW{Y-Go%L}?HYh( z_xEFgbc~$sP9VLLyzVt5ulI^Rp|+$-o^Lnq>c-mvs0|k{b8Qt~B<9bz?%vv$5!f}W zMm@;%`2&;qhu8I{EX^9Xi)UPU}m4>bf*N1KC z2XnnD8|IO2S*!$*uTKsGhIoy7Y|Wbx19O{Ynz9mz)qA{>E=$h#iRWnUJY0!vv@%Z) z0j3dFT$I;5*p@(W+_riU^|Yc`Bl<*MJ74}tx9p3&@ktXpgf$TV=;o^IFl!p}2noqI zwPX0lsOJ_9e=h!)EQQNP6QX%?HoFb$`J;R8R6IKwOah1(yK&)ApMHI%bDf297ROQH zCK8)Oop*#-R;vY{{({;%%p8%;W6X64rBn0Go#oM|g%L70>p~WB^9qHD|?8)WNhaM$nj>06$GUE_x7B&oo)pjgQCuPLxM%x&uZ&}sv?yw^CS_FpB~b?9qZ5hQx-@xRBCW&u6^>q^&V}dS&y{g?xP1B!l0k! zw%C79HNRSvD2?p$LN6q1Gvq=W!qBRp>NkSc%sdX|0%B#v8{E^W$}YuI_44X^lNeyB zv%i^ta+#2UYwyUP0|-N`6WXA%Prci%fIJCMbA3{duMiPhMTWeEWUyV$TCPH(PVF2W zC7LxLGu!i$!}=Dd0U?>{I(A*YZHw3mSLoiZLsBR~TCm$-TfU=eC57zSygrELGH?zM zUC-m$V_G}4JT7iusr+C)8+92<3A>in{(YPbEU$VaX_eLTJHLpZH|WbEX1n&S{xLd) zOqI9TI;H;RxUOQiBpps`ZQ|q;w00<(KZ}0J1DUXWAhpGQd3Qu80kLv9ttF+gD;}2n zAuol&R-@LEL|~_go%l!2jq(STL1fR~z|pDUSS@#ygV(_gtwQm+X;Hx6*)9YY(iQDI zHL$=s^gnx6PNDNHgSiGO=534BVVrfk>4C-ViQyVqjb@mT!8Xj~k6KQzY%(g1WX`PK z>0Pl+lDU;C-vj&#Lwr*SPOe%tzS415#d952wawx=*Pmz|{Y8cXN1?o-{{xKCZqJ_P zaT>rVJM(yl$!OTFxEiRM^4=u4fZZpjZiu-=ELqN8|CX^zn>@-cBB7y+d78mfIi*zs=>iL z`n>8p0R?Km9eM%SOD|Vmq?+#~>d}gcP%Z*|ATc;z|0%hG_e8sY5HN}L0iOl+`190Q zN*dOWJoW`ED-A;d71&S(x9k})li%g_>~%_uVzCkm@nSC$+t~RjVMsKm)X>q)WQ7VR zgI%$M65bL|Rn zc(NSwf#CRhqV4iNSgXg0ijE?V&j*0e0X_yQ<}Gw9<`9|Lj-GoCXKFL%X||P!@PqAI zj;)L6Ud(URo46g&QN|7(+7l(_OKd=vOHfWwD*DX83Rf*Qm&0tt1;75{TJ`|v=!mnUXg8Zdinj%67vYQfIUN{AD}O|#f!b@Fx36>dr>7SwSq zJMk8g*zyZh>oUrt8Pk~^eguokdC2XOd8sNtXyEL~R~v~zR-RWKMhjE>3bh@d$m`vs zbS+Ffk!*~dg~%Re0#!HhdP?jVMqUdU7s0(s~0w-CDi{gQAOSRL55pH#&9H@1xb!TN)^ZZSTW@l-`83=6Y!u zbi-HuO~UwZp(u;Rufx{E#fUjuRY!wRW;TnbWIuS+W_?bOx4KmPVEg8-V{y{|#iiKQ zgWX|(wDnr|<3*z`@K8_js#mL63VuWcS{uGvqxg4nV8jJ`lNGZ7raBZwdj-_MlY?Lo zVsGlf`kqNWSZeN~+;Y(lBvAe)<+14U>V6xN${V=LdP+IW&ua2FWvRXDDkL)v6p@S^ z!dd+=H4N@jd*nG4fG}GfuU7c6=J}1?IA=U?&GJ;)v_o+Nrk$EB54@wP&(Dc2&s}5s z7L#NZoBX-24eHV*GDrbi7cIk9sA8drFk0D!mm*7~0zn_xRe==o(N28Su9RhN+(Zt= zo|Sx#L~&5ieW@l{U28vw_!K9~+WNJ4nQ6}m0*KdL75pYUVBkwt#WTM2Q?Cy0w{}zg zd#vO=t#&saLpTnwo?88YdMqr!w1;T#G$)Wv^})vp5J8;5z=ZfwT4jDe)n$T4El}6) zuCt6XZMFKy{J@+ii zhnzzhYFLPXTS%d_KvMu5>S4E61Q)RY|9A}eEy>3sXysD5Es{l+PuPyHH5MX6sfbN>t5ojbCDJJ#{m1H)Q+&4@B-KB;0(K{~(aw zkTU!gJtyIzDz;RA-y)E^jJW(b+mGj_Np;3+7!4!f`gfB73*fp~1jPASEb+_M2?oyf zv_nkximnd`9FKg>HqU;>a4bOTQxLt+?BksA338xW)BnQ_K|}n(9U|UHD@s1?2CJtZ z7k5-vm;H$OA?AwSo!o5@iBvH8f!?n&`!7xE5*%ui9$JV`8M+gURN0;f4}hL0(4?ws z;#xu;(-L6Tix{a#RclMBLz9t{-|ecSAf7|Nx%za78Ca!XVz{WzaoS}3gMUwk%JpvO zu{~muW}sddf(w@gHr4!~Xzb{x5Lx?xEtvcvMM3C#Z||uc{*?VBSw{IqcpOz{9ObmA zKxrX{=i`J`ksj;JbE!!JzpFdU1Z*#hl?ZN*GtRMUMCq!9X~?v#B!KkIJ3tQ=8kHG0 z7YnEw%PPvmxn?+~;j9YmY0036rP1`L;*&9LFu5Zn!nRxLf_zfY!0rbQlbCoHlev2` z_-^f@L>^LP}KDkBSn58Q}}}Fbu6gcbE$%= z_4BIka`IO$-il`R(h+5PW#FDptF=&+HL_vgYF7-nk_KkOW(N?AStSgIUKU$zdnD8A zKiOc4wDa0iPr>`eXj^PbEt~)%vK!pEUJXkMmr*WlIeZo_f30CWAYlEhn5XDK*YdHT zTCG@&OiO^i$oYn0GBi-E!x{s;vL28+ir_>>zo?GsN*>8a^qI)3!$)Ltfs(y$dbfYt zx9dXb^6NhqRhjnf1fEBiaT*LHxo9aq8pg9lqAWn;(eQL!BeAOa6jJB}@MV$Ek7tEU z`O*9haMlAC(imS=F);GjPzv#`wwosFls~Y^A;3N>z%@M3&lJI=s@u$o*&$Y9Yjr$g zK=;8?y}Y2n?XOgM!>HlL8LVBaw?v^C&<^T|qn_yC+vWw@VHTGEux(qq!BG!@s4ZGe zWtct`j8Gb>yGI~0b=~5BD%zr_`U+bmU0B<*Ug}e}=)E$-(jT$b#*hARx zcuG96FB4IApUi#HVqA7{!MZAT?Y%h0KT4;bFnILBaflpGLhS=3SZ);?EEmn4JxXI1 zJ}&4%D?CHh>n4&N=aKhwr$WGG^~XAF!wC&kCREpy7W zMu&=4L`d6UyCmJd(rGT^2YgJ`X@@D8V>24CLZ?8_WXT*OeJkY|-e6B0P809evRY_st-o&u|xVt_HP}Ha*RLh8U z>}*10e!__oN=-kkdR?%4POplEcx08Ow+!xIh1(Rc{ETU~oYxYy>2rTKakSx!vEk?ZD(4y0yWeP z%}8b~cjcl%vZU}Lw_rmjRZP-{b)Dzs&7=$xE{hCntG;-pvl?!KZ1;~o$1cdpAE)sKku<{Q5j(cUZRE6P79J&rGGHMhaUIY2b78%1Sn{^3uv^)VR>n64FQRZ(rHx$`ut z7ktTJHnZNp5Dmq?id{6I4WM!naOLB({HdfF^sxFz+QhTC$?k#ibbhsM{cbdf+rdb( z+qUXdp2rPINnX@d&!FE97>U&Yuyjd#4$OI^T+>1#C0m4QOmt<{qewQGe2}H~ucI8g zaS!VhYNctajAoO*X<{>T&}d5IzSu*!xL1y`n;mL^)4Rs0!*@9*Imvbm#7a2zb*`}m z;c}2S4@rB$d7mPaB2t--Ive>pY5y||_fiAbbd*MPS&wK+MH|x}S8Wu~YeArfDn;e% z<0BexLms}>?lLXCYD7()!QWUwWw38e825%pyZb){lv(wET0~twcMv;1pIMnb=lc(L zOpQuIUyFwAq)4GGkLLYxmHA>!f?IP{P>2BpIeIqo5qU4HUa2~Iid*}Lm)`spH^BaO z{)*H#OV{Yb>`vO23Dh1u`)i_w&}<*`&CrcELEPSECek(`KrsZG)_5}H(u~~bYe-ui zObTwqO2I1)QeJMQEecwfKb#j{W*4;5Z0&&8(}vn&3vWomk+(9Lfvo6tq=9iRzsoL% zud3gPmL{3Uu2HIn$|93q|4q3#b~Plj_Sm!g)%d6_wC?YzXdJ^vlU3{r3T0*(>|}!h zz-YD~nZ0qKMSV1dig(B2hd^>rZN7#{pZpnaz|7&xnGV=3b612S+p3x;Q@6OR42sPd zt(H(vH&$bM)Tzs_1-50oRbs!pA@nhw&+eN2lotU{pf>E>6WpT?R;sS+*P1`3wMwj+ zVV6Pv#aFL-JLV~8vjklSd}e8o6|%dJ&`=z(pm#}75! zaQ)@C2ozBdxxif)t0P6LN0u*Up#--f9iIRP(BX1M=f(>adCQ7-wp8uI_l%`FQP-%E z5ts;8NdEyHA>FsKVp5 z!CLDC3n#du5U0!3R)Ar^n5AKoD!4{q3c21P*JuTvS=y{-kpy9`YNdOts8wT&`HUOB z_8I4;J}bP?WJazge@Vy>Oxq>T_QJnB()z591*&m8(rz-Kw+h87c6&8EL5S(MRPs~v zYCdA9K9vCuHkx1dO1JW($B3#cavVxR*QX}m$Jn^5-@d@+{VNV1f+CFQ#*Lm0FkYjO z#^4%6AhF8TJ)Qi6Tg>_n_S|B7?Wg52^}kO+Z#$wXEQK6lzNp)>rcOmI)q*Nlwz(-6 zBMVYgF?xgQ$6&(f(*{FO7=D`TgK5SwempZ65}{qU4B%aN=yuT_=PUsw&bRJ8e&fCD3=4j%F-+u&D!!v?ztrGa5=9CW^z(L)8hairqgm;{t z5&lwnKdGs;KZZp=2jB~ZA>Fjx*0VVHI|gCrexT4fp#q=5fuH*It7;2M!g^~vG6@H& zUlhQXGAb+dBg{DkxzpmbO&J6gFixr_OCGjEyUeV9G z{nLORt6nbw5T1|aN-Ef_V2O(lLN0aR*xsFovK6iomI31p@Ske7)X}W#^V*4l4d?d} zM=n8Tk2<-2s%n=qs}T7dk#!4(+7rsxyAhO9RNoP0c%+ru{Kko9QIR5*WFyY2@4F4SFxYY)VK>Dc>ifISDgf-YYUG9h zvpdJ3%4h7e6A5sLI@wnIqt}?wO@j|tWzMqHi?&+gRnNZC&j zEe!84Hmcj(EA_)~P@5@?K&WzZv2wu8o&5zkr5a@Q05Jb&-{(+%DED#B{06mvSu*S> z2cgGwZ6Zw;A=^JJ2Yu=+gJl91)lcPK>l{)Z+tK+1Ss zZtxsyA6t>vRC;&LNXv2&1)*!lu)g$y$cqf}0Wv2B{=VPS{eRr~2hZJv7eV=&Zt zB}m&5=h72p#VH#|wR>@ja~}ZdBJ!7K8+wTD9~QbLV@;(Q$B~)(O8E91_Bg8$9{6w_J8|sS$-!I_f`g@nJWFqoo)^;}m zXo+P>219X2oS)|uA@9ob)1=cII&_bTKl3{Ln?OdUYIB*DTx1wgJ78%v?K9rGRq!F+ES2KBso2$YbL4 z^tl}+NE)iEmMtT|Ua@?y3%2mL{udndow2;QKbI&2ySU8}V*L?sxR-SkF_2(gYtB~| ziqEm)nG=DdXQaoVO>i;9s*HzK32Covq{w5}(a;X>mdCwF#gA;i3QC5iv*T-;>K;Rq z+v`S+tqMbOrW>~8NhNDgCi@Y+!>AWY#_VzKEMM0srmx)PhtBK^$@X`8o@p2E0nH8B zB}zQdo731-8mrcvNcTf%*Y3{n_@DsgarG(qfoXTFS^iJ%fT@%&N)HS7;#|jLSR6rJC1Lx ztx2E&6#6!jDAS81A9H<6TJ?J`AxZ7_$8>7hjNI9%LhWSM`|bg_DK=dVZcOno;V$j%(acRK33U%{G&%|QvB2DJ*bf_UB04A{GD$^6rcwcv=g@)!Tm98 zvs|%WBP~?C7eXxPBOuZ>2UINv#?!V5ZQ@kz%_Dl{2Bg0_EVKhVA9)c;Q^=|N7}eAd zX#MV^Y0j5bbeAKusrg^}B+iKR@aq;R{YAysOMV3z>L%HK8f?S0G4-~gxlKxqy7Jrh zA;b&#d9TMUd&D(ciMecnEPzqf)~VfS6#MQk&>n&mQvbKCRHR!tiTMY-lQK&Wd!Q3& zkrzI!k-%3ooH_gAFp5J_NxgtMq*r@j1;J!@xx`? z#F`9m0h|R0(80aw+a`mtR*-rC8iZa8f5kKveW1ORa{2nz4QiV)m$oF-G`=1!4c~*@ zqdEVOLH-{A)mLmxc^Kh$$KVZ-@wgQd%Q=eqdFryW(Ef(4dA6C+b(g~E2UMOVR@Qu7 z8k`~x2wl_7RfO`7zH~<8y`k>#bE>^DHd|rRHkboA17!|hlTySO8j&G+R7`Lmz|(v^ zu7AC+-6U0@DT0ijAE8X(LP^fJ**)4~aKA+nzk))ziK0&OPE5}7T+CsD08`2lyE~_n9KEP+Z zdyAar-4BFs)%{6gC%qoUmg0w<8QHD6W5rU8YTS~T!rrM3LA~v2uby^gRm@Nv!lNYZ zRwZ(yZ~g%SYk!UUXiSSGLXMU3;I1?4e-!ttj7!lvs#vV4+L*GL3nb@GpW~l$^q-Hx zc1*QyBFIBKN*({`yWjAE(-*ZSc#Z911c(sC-}-Rs`LOiShEE;A8T6GXlg_Q;sJ=^j3!A7uE@+z;G)WXZVG*IddwRTiW48LD@hcobW(SP=J?2Gthj&XZ-H0lPGfiqcV#<2&Z>G!=5IfK}H}D8{ zyioqE*I%T~y;NtE%cI$-8p|@wtG5TS`u2M2j(ebAm-E*DrkKwM0B&U_F6Wr+xyRhf zMJcOys$Q8~0xRN@dy8A&HVpM;g8S0%hHsVn?3I38l5}roWu^BYgVTo6Pr%FXQo6e; zP&J0}rVIf0q-tZ|pOqTCfl0RwPo`Y8E{(n*e%t`ZAHWH12azMdo6sQ8hLeglrsz3b z_WYtepoS5#X+tGF^{<4{*JiF4q2*rF^K@;nN8{LyikMto39*FNsz~9?+D!wHA{_VB z=C!TjI@77eZ!g~XaEWh*(nvG1S^|wW633?ZZuP+fv@VCNXwPjhx#f(~VSi_T*!@$G zjb22(58+sC?-If};?%7Lhbdm$Oxelz4t zDaKIsRF^{Z$)RQOR@phtjuC7AO%P_3M*6dWm~3PSRWq~3-@js4IMV}t&~Xr^XkL#+ zPU;8KJhvqz`CwKwWJ5V%ws)!e8?vzv?o%1+f_?9RkMFyl(ozg&{{fpO+E5>KQHZ03 z;WDdky5hN{GlnH&*}V(BPOt(FD^=Jcqm=8~KzvU9dZ+_EoB^$B$r`!8yd372XS#LX zpT`*oC#VW?GP5mJ=A$j~EYTDT#yr@OR$;mjh?tps%BaYgMpO}9nj^&gwDy>GU~g#A zf7v!)Z62+PeVBfKB_Bx4<6Z2pz0qd;6@wO2b^?|}-qNV%X0M@4)b+@+7QnGcOumk_ zWpzrtcVkVtF)wSm)CL>son^IdKWyS2x|qDpeIjGQn~Q!fRZBYJQ$X@M*Ep5rWfU7% z(Px*e84|4Cd*3T!<`78Vig(^}z3t92=^cWbKxvxnP9w)sH9^F4((YY+L{FAM4DF)A zKRtjQ*Y{kPRAmMdh`B%XedHBTnX0Vsl|+4J9W8e%f7=X}&T7XmPDZ~SgX<$ZG%|a& zS6>F=$Y|iVC9_t4TdKQ=%EMu;;a8amO6XH1rot4*x*YxwS;W3h4FIyIen~#;^@J>% zUIE5BOayuD1!slE8@~I+jKRiL1vNk%6>*4^#%%X(ZYQtu_yDJ?g^D)Pc%}O<}EmTUxs` zx_{z%oUu*$WoP8rZ3A|J?DdMDhDd)q0>R2bTB(aR?RR2C&WOCr6L^efctui{6rpe0 z)knKZumEgSOj}AO02J(F zTCE9k>wTyf5FSF63}Ifaw?}0W31loT{jx42(RBJ z?AOM2rNyr-wzK6ajn?H`07>8nnYIR=uFnViO&|e%!7X$XQ|=4h8LHDWhy%@PmVKeg zJxaHUs=8KU=^9Y5w?y(0Hk;-_)hnTo2W_F^9( z9OX99yhCt(gmeAiSlVL~ZZ_@f0(?|rm)Q-nHICXm;Mf*C<2IVU&GPx~TQuf^eU(ng z4cmRuev|=?C;&3p1c))Kve%N>ypVY?p+MYAi^ zbomqO8R8SAGd4B7Y+p^x63|g9{1kOXh`-4s$hmljAsnMsxFNP${GQjp&a z3{`5sXTI|;ir_w+w}7i2!1eJmF_=V>!B!E2X_IZwY_3kj65nXs6{aq(s(p_W(ZxQP z$R5@;xNYdj_LNZ4m_tc@@3p^-+AQ(Xs`-1X>mV{!r>P8xTs@|Pg!O^4u&_6_f{DnfAU^FGzF~cD?wAtORre zH#XdTWGSojWWrI@1yh>Uo>Cz3e*N96y(FefMC_&)7Z@8DI;p0%{en981EWKOa+Ini zs(Es2!1zU(aL)6E06EGn8$II+`w=L;d%dy@&|$$qL$;(^U1qh&4@Pj4ssSy#v~r&R zwoG0H=B+ut*`Q$jwL2ysp%^Kfj^!y4dB#hb{%(+Beol;v zQS&Gu@JnS#J_U)PPi6HLx;X+klq>C=4~*IujbF!Ik{k<$vN_#3(J45G^~qWJ zqS{h~5oq@`|14~vxV-W7T1wqAvA2TY{ygW7WsD`^OA0wzQen^2{m}3O@J&rxkm@M8 zwk?uhpRmQYwXQbNn|3VF(k8j>t|3cY>LoIqYHit|m4*}{)}Gx%XfyI^5!*dl?f%XhdV5EfYGo~O9VHm)^&gM$#ioST8@#P1 zkQgg3{&?>eF(XF0 z6r56ps;??Wf8**?9G_d|G|=c%WyjsDNL;4OUY$o2sm$uwhb~%iMB_* zm3DQIWk!i0eZI_hclI6j`?K3SOtmJhHke$IdZV@Gipme)=csKgaX{N`TV4+-hI#Cs zpA&cy9oq1z+F+-O5z4`swejm=hqM3%^4$ndpfSx>t3S!)>J89>yPLuF>?{~hRa;CQ z&qxKrLzRwhzG)&G6yCC3Dssi!OkZ4LV!&BAObs}OuI58a{5%_WTzeJh@5%+GZ6j?j zTAc-C>M=M5zxU^R<%F=5s(G%gzRrx65pTs@Wg{}{Qm=eN-)qLwCi42yLh|#wU7M@( zTFQ7N+QlX2us@t!_r@f0Tfygrp9zT@VeVL~n44s36WhY8XN`?9{I# zXW(07D|51@R3k#^evr^_(Oq}P@HvdoazWZ3A2yO$gl)AA?=hRrwJpFB1eiGnHN^0J zFsl;T4)*4jNG?b%xD+lw(m<^RoaR9(ZM+NS&Wp$CwSihxy;Kt60+Feu^IQ+XUTJ#^ z^-+MP?y|R_C&~<)>cvXh<8>1sDlCy4sorT-3ZrRzi#UUdf~Z307HA8G#)1wi3~oyG zMIY%^+LM>m1cFNt#!7K#TsNT=ZTk28~p#n_< z@!=#1(R~h=sv#A|duoOyYw6!GEz59SsMQOC{`motA+ncxL-iuf?$xJSk6Ecll>)3Q z;HUD5awcu2e3ZLdKRM8#u8acJHnY$`XIZ{09)}XVE*t^Bw5nqEih)U>GX1OHT)5tY z%u$6VLm=ne@vz2w>@K+^t!(CzYU4IldVDl>&|X^ZTE{&*x24=``N1kwPk^Jn?ivrL z==IqNmL@uwRpj9#YBSId-wfW>*D#7^op<+`qc#5RU;?-N@xNTR9p!sQUrm=rM?gHp z4ZLLSvZj5nXw;O8^sK*feYk{*sX>V)0TmYcys8Pcl;2N@$0poDI8ewu3N5w2kr~cC zn)Zyzeh;!+g;tJp=64DWERymJ#;wpmE?F_r=Jw8-FU2d!=9=XpYau;Kkh?7I`IBfn zeMk()Bm8^B@p=lk2XxErA_m4(Os|bk+<8aolw@xO?uXFEq8$ydqsP%V<|RMZ9>c(r%3- zftWKJx=Lu6*feR=Fy3PJyNU|zj~2*0vM}GjDlxRR9m`HZj?~0(;+YZRyy@lYu9eqTzd#I zvs64dT>9OW(aPsXu;e9#5w7|9aygQY_#CX%S0nMCRUII**u79-cwF%qw71&5$Vv!z zbDMLKQo)%AHtx29Glsg1^q8ApdUxtSDTI+D)s)uratK%KQ$|XEfl7S|QuIrvQk-dm z(oCnDnK0E3O05Tw<+|X|EHE+G-tre~JAjx(7moBWHKimTtdC_wbL;1V58#TNE_OAw z>)Htd0Vsd@Kh~}!+m%#F?nUE2pa}?KQu|+4Vea5SgrO_x!NZ8KwYbw^wnrl^p(SIDgW#rIeu#7;CN0x`hUr`Bl}85?1~MOBJ4Yx~ z+8c`IUlhWdD>9LsDQB_kkx753cl)_YkXTBW;*Fr?PgiKCMyo3vhgL>b&_`>Mj&gqw z);#=)hSAJ-yUqAZxdhDCeaALzq{^_KtB0Fxt=n^W&o*p5B+|<(8}s_ZY^ZAHIA<4T zdiz~xwSztT=C!a7t9#rGC#kExd2<&P2HJHP?ZS5wed_A@0*-GQK+3zuk6o%M^>BEA zaT9XCyiz8?iZR1krHw4*Zi#or0Js;G2eJO#pM2~r#B+I7 z-y~4cwY=6x$6?1PBopns{D9q7$Q!28u`Rpp4iWzEG7^U0d$zdEaKPMpW%l-VeP;KW!?m5f6sZJtBX>93cMKrF^&4DqRBYAJc|-a|XGS=>9d4<8Djw-<5?T5z-ywj7B9l5GiFD zEDHyaaPiycLe5{CI8!|X`N|vc&u}RO;5DfGq>tsbxf>gD++U0r4-~sZE}F?RfC8km zda{>Wr6aQ(H}-~+csMb9F9`C%Nv2fA%k;J~?fgxsY^kl&>B1-qHS6YD-=HOnJdkNcz7+e_RicNLA)tjQ#aHK_or zdnJ11G8?jy?a)9eH~dJ&$Yn04mYXS<#rPC9NJAEB~=}D&tTuG{Sf%@^8u67&5L{!G(IR??V5_3l%gYkT1(FD( zJs7O|LlB(ZBN<9VFFqy5T1~rIxlDS>UMXnwCjJMl?;!gR_IO3vU4j72ow7!>me^*X zy?^S^8L80~0Prq{0NUZ;^Y3B%}PPYmi9b!1r4 z4a?>Rzv+a4y)9HRAwp)-4T?>tzVx*99PI(XwyYJoec$v%KX>>@LH~fp*%qIiE}e^q zV0O&#-qGSx|Ff!o45(p0f`LD5;ZQIX>UBpYj+G9haQbZL}~c(E4=&j$hw7vA>Vc73eI!)$xkK z&{Vc0cn3nS^C2wN3SH*L0IUu-+B3Gs%nm5sk7AL=v~`Z!bbK#+p>?D)%!gpE!7qnU zQZuhv(sH=Uz_dZxk$I2eYp|EF7nC!u5V&StKhzy{R~1F4g7)1A&wTe@MCuN*RyhbQ z<8^H3-f$b5E%PB7$5yiWfkG=ehXGs#dNUR!huMvJR z+CtEv4e8(ccGtGCis(jT#gR+Eb}YJzE%P|Sm1gzwuVp}Z_d%WMf48-^$mD8=!$iXW z>N+iqqINq`e*ul=iw`*zsflrfd#ZO~+Em^P@%VOxxxEM<#RQlckVhm@E+cCW)XsP_AmBR4ed0Cj=__AnS16_-Td^eW=e7FXxP&X)lfHk|e^q zgkhsoM+$%~SHZ0u;bF~2&|1~3Xx_JC$;ng3uuw0S#F0ovp$6)nJh02}&l%m`o2aJc z1sy(=WQietEVMxEZ1`o5qNJWm6O$puFzj6sY_w*i9+u~8?QT3!kZ_mR!5A;i)>mFK zR1A}E7yBep6hfIw35^SUBh13f<7H6Yn=~t3dX)4 zj2tIQ(!?=&p!)a*i4sBE+BaYJmx06~AbrhYtTxWkP7+YefY)r}B=K2J4wB14b>0nH zTD&8$&B?{lmE$LSNoQ(}%8%4dY&hY9g92@A*0R_|%&pxqyW@iOjThT0CDTytpjjkf zV|$~l)+E|lr3wPluFuVF=2mrMkw<$gP@QBgj^GqH-98vT$NbQp|MRz%#@MGeF^U;m zL79(&4W^}e%qifem9S5lzj7SaxJ?7S0GE!H6Uhn8`e`z}<>>=&Cm~HWcwgnq*#T^% z546eAPE*)Hd<%xFohIi>V@{w7m?ef?+`qC^Oc7V*lxJl(9@QwoEdXCYpuYvJ!?tUh zM`MQC&YkT|XKD;dSi$#gYZrj&;W{^&x50vgX%$-*m>?G0m&Mbh${aB_w zPs?Bm&RHGF3iKK!!*i%NTw;S>6~F=efo><%W8Bdi5e5R;H(9vaC3xyBIeNwntRQSTkBwht-XM z5GGAaokDd@VB=Jl35S0}x9%v*~TPfn95Em#cedaZDdf zipe?tD?tX9W%j!Pp%xB5NKo|I(}Jgbo{Q)6v2y1Hgrt^YbyTiui>5Ss>%{7yG(fb! zKq}$7z|EJJ*MGdaDtJ+^r;6@NN#wgd^kirOZrPa;oCsE%p|5~Fsa*889${B&uY)3p zfSd2%uNuT^+YCH zwmc^3VID@p4!q;d-Qa7KYay4{Q5g0TSaII2x<(H`?ho;?>+hV(@pCf~Mth{dIVHWe z?N=mjDt~ApyiBQWH5a~P#&yHxM4Mt(0SDX zTG(+5v+nY4>XOO0OavhSdCV5a^qjgG)QB@i)K>n$$b~m`!eM=z00}gn+!p7cr8?)K zR_ndQ{p*=+ByA5h$_XUIf4vz&Izh@`ct(x+{QEWYrCL-X8P@(LRGZ)zQ8odev0k&( zui3Wnej9jP^xTP6h5@dfQj+G)z(@<8i`uzrnjpGj4` zK9Lu_8gFt8oY}^fNiHqSmLPjYf(YLZ1`xKeu)EqlvsO!F$Li;kF&=5(X8dNbpA6BA zFMf*Kxx!MU8t9bzW8bkvq2Wu(KOd29Lny7{tkU7*$>aKTmmU{?j0;8<2`xcyWDo zo@UtMJb{Q|yM}49Tx_+{vN+eTonzO9t&OEr94t0njSaoG&sbGIPGKMLgLOnN+Lwcw zFL1)e)ohZCbLjLweo=GnZ9UQJa?bpeD5>+vvf-fm;caW*6TeiAkq?q?^S{Npkpa`^ zrV?_=h12YX$u(ALRb3E`m_1@8cm1j0`eMF0{RENU=cN!n#J}qoBv+fYZipdkNHrtN z(p)%rOz8nL_#5ol0r2hD!|eWE8NjJgzKO>n_+KM)?2Y;I z&^99xgK0xE!#~(U2z!FYYgrq*He+u4reCd9|!MRWxX=d9t8vg|;xjpzT<<{nUU}gjH#8pq)djn!o zUpRa|SiECL0xz)-rn~&yG;ua&;W6uk8>&TJYM-2nHnweB`gM(NR;%;Chml?DuS$`# z%2$Kkiqu9Kz^-H#G!pqHJVd4=Cf~NrA3(E;1Mfkxp~*5Y)J`NeGmDfeb=P%GZS(k1 zKAzc>XAEK6W`2{r$445*Wrfo>JJQnu1& zcfcjOhHyLkWqO)4SGd%VxNA}ly&<(GUh9Vo+CL!7Lq?b}AfE%aQ*ZKLL%SD=PoLjkjIyT+nr* zdeeC%1(17;}jEUmS2y?zmgL)BU_>?~wG{GZh@H1LCbO z^L+92_S^gWLyy>Y-+o!@Tf%tXrUqjRRSi89s7-(55O##|Ys+dq(_*?$mr3bJ0l0)e zz7`+S%H%Oxg0(w!Gt0)2RRT&)q}$Ew+ie;Ca?e`18O%)xlBo29JTmE~h8Y>G`fd_q z{kjdG`5X0hE;VpNBlKtr1o~AK$4J+@_Brwj4mAKCk_g3N4Xx7&_K~zlw*i$1jCjlS zoRY#@J;A?ot8PS9<8_(bmG?pkpgEhgIo|NNrJ1M-BG(2J70zJqC`y-L+4RS$387>@ zJVs)^=qB|(BcDhLEhwz#TUomUkPM@PB>)8La-%H9%kPqM*LVESOO#$ZDB5USX!(2= z*I)>45Gv|aRnZvHe&a92Op}O*ejO_q0VgQFQ@4M`y_@=b>qGIQY)y0|kZ#l%}Wyvt`PWj%(JR&)1#`8p@p(eq%UoDF31fZVsaeSRk@0ZLmF9;I^DX zJt5$LxPr5qJa|px@eC7(?Rom}Sro0zO;*d!)C2YN^{5nH@VSLGW3b+~xb7EcD!13^ za6Tf#k?(@dJ#F2f7%8to_|nE&AUuTYtSk4R1_;ZP^7x&tgLoPO^_NUK5v02`Wq-uO#nGN;;bhoO0t-xVR z-O}BDpAHU)9WQ>G88pgTBwmXHS$3WnJ>)90HsAW>w65@Bq>j2m#MdFcY&iY=bFer3 z@k?u#au}C^gN$Eicsl`fh~)aZ#vgCq6%zP;cKQ*@$F?QDeH6A0bhxyc+kPV*E(x zL$jcwR^?Mhw$0N*+gN`Iq1yH+WU-Q66;+;jGFAVpk-9*5-^=b&h;~avy0M_ehI=^m zfW0WwV6{u9<_#m$fZkJfUpFjg*8nsv38ryd=5(Od`{}`)K3Hi=NvI_#!Pb~XVV2~+ zncHB*Lq89oE5>o+$H%)ro8s90vnqx7T5KZ*rd&dMjSsuwubfr-e3`S~*E|5bwc1cg zoyh9a;S;Y%T1Y1mph5fQOG7nF0dG$74lQz2zw2CNBQGjU*E9Y~uGlRL&n^1YN@!OT zW{P{jZKCw=^NW@Pm4Ly5x5Yjw1i7s3tsoxz0rk{#0j55CGzK($)t6jYHAMMMh zh{d3ICDtinm#}I(5gD|=9KR-+v?Zd*re<*zF`!w?`-TZQ20wx_M+BZ>P=I87LdR$3d0OA2zv#8V2=SZ@|UEw$tX6}7Br9CnuSJJF2SuFg4#b~g_j`}gcTAx*~_G?@umvb?YiUOg8 z&-`;OWtB=tP%Q2B`S*e^94gSeT|AZL690%CWBpJb#Ie&dE!3mlANt!+hym!At1WYn zO#6u(*Mh)aef4UpG}6+gc;-1UZo1E})g0`*Ko2#+rA3rUT+q_Rdw`5AWd8+}HnK?e#R%byH^}(vR z68Ln{RQQO-qiFapoEj2%bds%V0d%lkpUM}KkQO}sqWGrwOxhe#(OgrEBh9hV&zsxv zTdT^Ol(PPksF_oQrWKy<$TZQv=5O64dKMe3i>Tw!!BF_BYVzi`__?xBF54(_*)@`( zUPfEo{)6WUz+b0D_0PhJNl_sUX$cN7Z3^*f6XdCU<%%H&3E8EP#sZS+I($SlN8p&W zl!x9=6(myR4E&X@M7P{qZwR3C=q5YPoCM~?*4obLIUq>72~;OR%t~zEcKw27+Q-$wxw%-w{>G_&f{q#LJ(v`)J1+hY>BD>dwk2 zx6GA*04YybVOD!+yErAlXUmkIG#~)5O?>X(Tde?@TS#(QejESl;x$#Bs_qV7-ZVQ) zL6pP}itv#AR}ttaLK){&M+r&~q6F!Us=~?4-Snd7?vCXe(#SxgU}B}Lxds)Y^1TkQUe zk~Xjb$$P&waQreDx^5No_l8IKz)qVQ4z*H&6>Q(VC`KJ#R2sIjw;qtF4Y?u=6_A7Jh_{ruYZgc&bIwH?5_xIrZwElhj@Ta>{vt{%xsO zU2ZTjk4DIQgH<-R&TWI$4x8CcC2hc>h^?Wvxdqfx*ut#1sob%8+8*iu{t6Vqo-#I{ z8e830D7st_87meDR9lkhfp@UoU4edzy6DkyrU|6Gfcz2wNuHDFq1PXnIoeUDqp9p* zh56OCK8Tw!$0rmw{TShNF#|~LdkUBOdAHX|1{-NA8H~xZGt*+WU((3_1A<>kPt|`P zAYk}BHPb+9%!KYg9+Q$N~hJw<}3&Q z!MX)X6;(2~HL4IpD}6%ca3~tymTBQEhQK^o6t*;jemwT{`Cz-MT0Lrc?Ihv# z1{?lU`{l!HYX=Gl{7?*DRZL6IBvG!0XC@}3pVWH2D4_$Sj;TdBt;SR!~eP? z>t$b{#Xo)U_xN&hA=q$R42Kf|B7D`28AyEssVqm}JLPfBw4Izjci!c4oGz<%dw~=K zd=Z0~rq$ZSFW$Rrb?E@UBKi?Zuc8A9(SiJ@K?+iQ;-z3& z?)ANvrPrBO<6JMdZ|nOXFH=uBCAF*WnW?{s#aO)pY~?cVS-Wcw2;_JT%n&iP0xQgT zPqaKmucWik65YGb!up}=-CU1t6BqW7Pn@tCN@{x|N2=X}EbUvp#>3CH>9ks`?8`=r zqm)bA;W^-nM2C)QLpu$4V8-IMFplbauF&Y2%?bFO3x% zaASAjV1O2dVlaC~4)^;mkW0ry7YH7QWvXOvNX@T69EjEMVHQF}`6l+~3R)IrZDunZ zKM%HHnVn+`V5GQk`1Z0?J&?Q0!vU-DEZuk6DnqrHg52C47fG0dJ7QCwW(BHa$|T4; zxX${>b)#GoT!=Q9ND`K6K@vz28dgbu4_HSyetnrT}m+0F{@?gj3x$IL=7OGXnLEMh0vnb>*a@0pP${+@yv z2A$RaXk2)6J7%x@H~^+TW#Qz+XiNruVZ`oO3gN01hR#j1J5-8i_SiSEr(e#%)y;_F zsQzn#x}h(Uq8L%p;D$g^ zOvwX8=Gu(*md6X9sB#5Zcfd8U{@O0~$Z+7Gm3>%i{?I6=C|2&vZ>|5JMi|L8BUh~iPM)`4&raNkp_!v>EW zq4x)3%_~6OJZ3hv?52D)`w>GZ!gpZdg`IYp)2mV!fP}=WA1i*G>_~Tndlr~EN;=SS zXK$-rIaVaL!F~TVPQNkff6MW`^QoEvs6JJSqh&^ZoL>!QGi!vfb_h{-_G7)wl!Adc zh^on7IWB+XHdvkB-a{Vcjne!J7qbnfoXzAkHw>p|XMC!IomJ3Z7Xq1Wuw7k%+p$R_ zj@Si}fLf(&$Wgm0EF`oXscjU?wEHcoLdf%ox=vtUWyWjho-Q+?0G_U==)wem*OaR zkFE&MxP_heFe_W{(Kq!Mr15jW=!#t*nA||U5UEc}y>x0cuPVKeTr%a~p)|7_0`6Z7 z5cP1LbNg+u4HNwg93X7o)l?s?XiAZEeJ*c>1HG$bDT&96X~StXCaaIxxO;92=1Mn8 zZnQ91tei9RHPA3CPjP*rbH8I_=sEhm4NZU$4chac&!U#5rKC=>{y*aglj;^)tGY>w z;&4Q*TuzGqB%}Y*^VE1cvrab=Yd6T~0A*3loMOqsT^18uz)B+XK?`O za;Pi}RU8L%hH6($k=qwPN8Hf5+?)6CO#5Zi%olNlHV?rQj6*A3*fOSq9nKTLC*d|~ zZ?uYwh%PVb!H_qKUnM{gXy#C0fyX;YUG3!qU3Nw3SLIxTD*8YhEH)15Z!MlF=;__` z=r7{vjmg{+bNUuA+DL0?IXDwXJ8Lq|;bF9LyUX(Miq%B>c6W-|`T$Q!8)lFMneVN& z@2ugG^Fc#~^tr`U9jj7I%Qx5LIaCQLFUa0cH>lGBB-=MFCW&<4==ELVJdz(heD1<> zPZ7IwI8e=Mp*APxOtfRrs!6icjZ^yfeWMO@s^3_igU$H^0kmtJPx9)q0(#qe1SnZGA(Ek z8nE|qp_(w2YOU+HyxP@e-spx$8@8=wBhDg#UiRcw%QK@sXZk|(&{&9|9Ty%(8%*Rb zi&pIT+Vgnqh*KQF;ygRV$+}}fAwM2*@DcTZ>*!lzSzZ7}WiQ~36+Rc^Be5Q%v$*=U zbaTDM(T z;^w#Q+STCy7~9++nhM^9?*4IP{jfcvi>{Hzn331koH-Cxg5@zZm_~-#ln(w>?YBV( z7R#;=HdD;Xdd2!-<#`8sV_yGzO4ngZoe905BaEOi36{z$4Hf-wN745ip#c+G2U-;A zO;yNSK#)^YxUv_rGt4Khvh^TMmm@X=A_T;7tCMGnL?jO*G_HDZ!3J*96&IuVW5<()Kb`bf|kXwg=g zB72vmoK9Zt1Mv9+7A|%S*KsJ#{GD#%hpPGWxU>ym6c)JueA}LJWoPE`9$g>%p$?3` z(i`4Rf2ok&uJO@}WR@Lek1L_W@kMT&ggaatFS!B3QLzGpB9vmUhb=lt!q93ReKC|RuNDp~eW;=#T}0`1 zJ%y;IgYkFCBHxv+R9#j^ ziF3q4p>cRc|FbwO4#+^68{4xDllD|l2f{jps;$6RJ3k35oU6|I(wV!+%40IR(N|_o zA4;1MSglhv6>=+3zSS7m-F4L*!t1hZM#BstgKZ7c-b+|r-BCBFO`*iKdmHjIFX{wO z9^SuI!L@P)R$;KAxp%EIuHW2nX(+%|N`_{ha^+fl!aO|m zOvsELg%oQBD7n+jhHbDqmeic3e|P;kJ;YB{$JObNQuW6aV2k{?yV{Z`YxTl{?u~eKu*$bg?P%$yJio3R+>jRvxj7~J0Ti|mD5xm zoac1?zgUl`f?CLtZTGFW16TzilyUWynmMvIfJ16^m$}K!=+XB}niE3Fh@-XPv>Aii z2B%-p(QMar%FWaO250GdX;*%MKEwtMwscJ`T_-4V5L~D>Gp~6ciV(<$^Sy2v?o^JJ zrPT0?Blc7Y)$5(3XG2?#f|V-JufrRhpE@wK8>Y&Em1%O^TZrtVue4s4Bc_3URbDhM z0Tj3_e&$ZbN^u#G^ZMj8oIvhvedGR^eT#p%x7EgpXIvhEY`c^ZbepA`(DfTf_G4G* z{f4I9E}FPT)xI>ju`dGK4mLtx8<=hqH`xyN%dTw)!>{+aFFp*B)^|;$7SZNgUUl0w zl=8+>HGVKNROKVFrgn_)KP|I9!J?!u_eX$I_I`6whJ=#0%WP!)V8Qo#P?s3|V_p+0 zkoYH6+1c}K6pzn&p|4P54-bfR0?{~dK;#cJXBV4sc8?=}-{FoV)1^HHtED#sE;*Q> zWhB=Xq>9|yjUHHn5?)&0{2)`(XUxhH!0G&Eogd?-R27VnVXa8G|My{%SExo(x&&7kBFei=^wz=&1CrT7F7 z$7gV@MtB&(TR*9~*~E_VQ15dnr-i-iL-%T5CG^a6(XHMOGfAtJRstc9sfJ%3bzlH3 zJg`H zS|gj3OcVRLmh`31&+%(%>w(TJK3m`V6_RdHHN{!8F$L%;J*oR`yf!m={gk>A{4D=8AXpVtWim~3*4NErORljXMWPcr6h~;&|{>M8b ztHO@+uKj~sAXr0UvM&LcsmlSD399=nU>M{#1Fe{gSCYg2=Qb|5&}Xw(Zv|0zUQ|E2 z?RQUVLuGG}(BKyihYV&&ep*nOKi+> zq53`W$_A4?HiqW3j&zFbc>TLEx}Vss?)eH6Ym!Vce6h|rr&EAp>Y~{R66j`mhO64U z63+@BT*tA8PBtb@OWCY?ab0OEzr>5`r>1e;B2N1;u)bw&8OF8mJ z@;Rmis`+)^5-Lp>PZ-+hHw0^Y8%*jtSo_OaO&wkr=;r{DI0QLaZIt#elJ{8+I?Xsf zf-uAAMxP*_SiiU$x;nnvwiS-M&Fs)`!cR)(yCdC3LFS;9j6nD*QyG{Hn5p}@BX>s^ zL~0|(9I9}312J5qj)6o_wi)AHy_9_Up+BCo(p_OeD_CN$OStH2}$WtB(>`cI_2s^YcH?H0A%{40Duoh>KqOO zyWjQXf#g=5`-kmubK7B;w!wBbu0K;y3;dsLqU{og0~B(q@+u54BS}?8f~1XXf$}&! z>VS_H%|XlO=!V2c()kz%mA<8AULGRSoILotE{)z+k(1#$7((`uM@g;4G#4O$MA*1n$iZA8L6vW)H+ z-2@`8o?6t0jOy0c|88+Q$VT~PG_*S)fV!;I#PuJ|B}MwO4yCiZ)vt_5^(iq#;5Oc` zFVRzHNY?`OGmdn`O5qz!h~{f7X5O_kod;1Wvkslv!|<2NhU$olin&Q?Vkh^}k`Q!F z_@r{Op4^Udsj2_S{oMOUM^DYYe{>AzfKqVI?)#*t`Ww{_Qr$**3F2ks=R$L}V|3e| zc1)iefW7M5Q;4UR2sSCNeC`@hP-Zi$#lsAV3%LiBJVa;KvIul$VeMx2t{RmZSE#3w zJy>@iU5o9OA@K$T11nY5$g3lx)yJt_`>%&GShp(-DI`ZvE?Kqt)G8%~kjVyv?9PUj zd^X+p+^%$~6n%tF@Yow!5a5}r;}9Fo3dYnZ=S7wp&TxtO@NnJDF#y+^;tRf1b||(@ zp!(f6(6mj`((S6xBY6X|MYA5Av_TJ`2+F1#qC?N&DZM>H3No|Toz2#;Y7neOY_lK3 z+NL}|&a0ZS=W}9D2V1q7=uWwh$9Jpj0pd!v{nD}H1)ndRxF4+ka@AbGBw`D%d;fW*Q ztF}J1B=Xtc*X@l{ik_p@)wHAsc}i99uzRsID5HU=^#RD9;mh+=q*cihnpM1bP_q;J z2m9VUSZpw^H%n+XT?DE9aF+Pd&|661n8^waaMFs<(IuEb^H3(>C zq=CCrW_B;S8kPUZp~ndfP(Hy7Wpot^V*V{E_d!F*tVymT3r3@f9xar0!*Ol4S+Ro@ z=~!5FBiHMQX>4|0#I=%-4_JHo7G|0OhrmsP>1GLVkwmL7tiZv#%OWo#9hq~7{&bny zJs$e#avMPxm1sm@RG}hCntSJ$*9ih}5qbDxHG+y#M)aGj?rWG|xY?f?s~S$gk-7yG zHfqFyN$D?w4JpH`rj5D7_*G_`ZFX!10&}3mEXN=o?_8oR8o??#=0c|K0hqS*`lrMO ztJ@;>;;t$O0;7ImJPtFnwVQxNgAz_m&VcKo`IL{Q9PE>nRhSrB8$N+2cZ7_|e5oZ`|2XSfCpAsPW&-Jcd;F^I< z>xZhqRwO9rVNK6V^}So=?ANViR9D8v$ButQ{AI@^?cucd>tTepC+ft^!!=i*0e`9I zMFn^9r92-4tLn3*YE>VRl4n&Zate>G+i3AeFh;ue@A8)-q{25dGt_by0FhO1QXfp6 zPhug1+pvMXuct6SdekP={WUy}z2CpPZac?9MWjxSn2!e{G}r5K-*9`o5UK7p5D|?w zuXSZ#^b`U&I)3wdwoerfs49E-C_yxW%u0LmdK z$az5+iWF;$?%#D>FNpZ0C&hS2U@J*X=oUS?WVjm4AfTRqY><~OcLpItdZ7R#&; zrw#(~gO2)!mayw&3O4ckN7=)?&{E0*p=h_w>}EuRs~Rs;9rTNy=$q?thy{`(_betwaZ49>(RQzDgb$BuSGs7*Uj0KRdqZ#aezuHv z*(uzt&we>qq&qmq^~$UcB;EhMi)%lmfCKF-{4A-%m@@lE_xW2P_+tik3D zCTu^;D$P!yubW!dc1GSw#KBT$3HfQS>kgP##6}O|ie~W|Y1hXoeW5L(qmD%iha|ka82?f+|Q3DP8{h4eam)#6No>P!(aG z7W7PY<-RQs-r&_rV?nzfmlysF)w8PHJa=6E*SszQI&4u3xT4Z=D^!8tR~{ zP&3)xL?jWA`*H_2WiF+0?NTwPUNnBN@(IwQ%rbIHu{5g)xEmfgTU~xMeyQ@!?5t50 z0ZBBK^o1%xHH(*CDKrGFy%odBPg%l-=eE;~%iFjRRnKBTjj9mkzE8W4%B!l$R8Y35 ztq$%|c@?zY@)?!?9>eTCv-Yt5Vv6-Gn>bPuAyzQBDGU2WBfKRQ&V6QHc+rO8Avc#i z`7h9AhV7x>LI#V-#J&DU6rY(2N{klF(~#T&Yka8FQow@$f=3H-QsZ5#P5R4V4j}C( zQG0W_2#PyG$(AA1Y!X8l*wCCjUE7gnQHke0y=i9>$Ght(x$8H)&nUS2_|Dh=x(;RM zd7imZcrG!4st?X?MF?cvA69?S#0O%h5on%W zy##G*W$9dU{i$=9+bX24*OOxkj!ANQoc^J|;QyaWo}jP3Cf;iO^9-KNu-el2Gsk8*|LY$ z>Yqn4HOJ2cWt|Kb6qc;~+88O%j)1e*kV^VFM z4|~*7+hUJ0Z5NN!%AoF^_7C7BC~}staTgkP`(xKB^+4TK@;R9sum6qu_-ST9NLT*( z2WqW_`EvnDN3j&EnCZ+yh=}&diQQ49zBjx7xt^)VUVe z%$p`n-)?|cYGvLR@h0Hs_KYZMEKh$97RpQhA?hg=7B|_M-QquKRFOrSsxg-d-tteT z&>Qkp!*{qOwc1dL)SP&2qD|ZL>`afwccuAv{90)FSn{R-0O`oh?det6xcHw>N^v0% zRKA}DoHjan#3jI|OAkDQ-F~^MjNuQr6 zwJ*ThQ9-Zf)#a+gj_S>G1US{GX9zJ@j%leV`ll;budlwWyXp7fNV2(YIg*g<(jxeq zZvSO!TiqTfH!qd5fUmOab`3cZ>XkaR>V=YrIy*p$?;W&%`qcyyqY>FqAPP!}mrqE% z>8fLmmMPIzfpyKh>avL_y>;a-W~p={p5_9{*D`$i9rxI5Nor@tVa0H{-CrW!@=B(o z`Lg+)?$Y@Ok>fE}b4VtBuTyQM_f_bk88?=x?ncIB_S&9Vs@X9RS|~O2$(+3wK_OT% zpi|d=icz|7y#BX0i{wy646~>;8r(#NESDF4Ps4kw10nLz-12BYbXjE z9w;@$Wu44R+Yy-6xv7M>;Cv-v`Y;KpMGyp9am#Oq6jysuN0P2>w{{yOh6}ZEN4;x+ z#Vzb~1V12?REB;$Gx%wv$_9Q~@`l%=Q4QjzUFT8cu5Gcjr5(QhU%zQevO|X2$)GUB zb>NfWU;7)_s!xjJ?|-v!-^82V3pDncHa3DERY`!G##ojClDA3G8S7PCaA$3q=5f0` zTmqRkqpp3o^KG0%>fER9AC2eu&nM-ED2nfw%`8#SXfG&~|Mb*Da1$hy2}a%} zEI|-$8zLcBca$?}l=NXfn#CtPL{&WY+qUH)+VEb_%@AL(qF1e$bEYQ3gjTP2S#SNL~HVvlpKqhF= z-!xoT`aJXD{;P|&GdA34>VlgHA!+S{+B6&)1rEyB{nP)SOV)A;l8$pdAb-eGb2`a^ zZmRSAXf{Askndi%YGQdYlrt4jcM=l0caYqhvXru794HYVRR~0Veap=iforCaprbh> zr&p(poGIGKGkKy@OlRTsd#gpO$Wm8sF*$m4QxrjU0nr9;dv?6&^#I9`)8y=$wak66 z3q(XwETcZJ2D?O}Cg@AQ#DaU>%J>b|vK4Yo)Vv$Rs+u~7rd{vsg^+8Vr3(2PsOAZw zN5{Mm7X;qp89ronVOCeFg+i2yC^r(^b~l#UeV@7U)%rNu{qU`QQ0PT)TdvVHChwKF zKOV`7rK?QB4U?T4Sf{(+a@_I3HSXfGjPReIQ}ny7^oxj!QvV><3wyxq>@}7&Hpe;*0WrPmLr=UQ1fVGbjU)*n<0uoC_Z&_pDfTl1c|r` zB4GV(DkK_ZJe4qnY6|4bzu>2y+gNaItL185u{gf0TVYp_go5$* z(3|%e&0A68xAM(kgLo`my3Bsn+O=UCZ^xhd%QJYZ38vC&xg*%V)CSy=3B4-0=wR@d#nSBup<0SbwkvD3(Ickt{V@m&*)ifd%f!SGB{f1#HGk1dD$o(WUy0zko!g%;O77$$_u5K zsNXjk>vO_EDer6V3gYxa4$j0IKF5l=cI<^SVt~T`j=J8y5ey*u$V~yQkMy@1gS{2r z%O9cwe*3{Y*wo+WYCisEGrTERXzg9)y6V%bVkDWSZ=rc+&{R#So#Z57)ReOV5LDr5 z9-lmG#!UeH!ae#sfGFoia104iE3Fi^{lF&h50r3%0cSj8A0t+Hl*VvrYZxZ^qUR zXWB@jJ4KLEty0f+)ON?-N3`OfVrN0Ui77)kKg%v+PcV56m+Cqk@$dZ(LuVgCSzzeeu@ zMx>4h00l9~O@54U^NEm#8)frK_d?8%9fA9!G(BtV`sj-!!G)mu3ZHt`xpzU7LdveG zLRlm}!Kj7Mz{r7*rhqOAcur?;su9r~Y@t{X3E71qz!mN|PDYU&01L~+Y8E{o=r&Q? z(H)+6Ss87m> z7QpbNn{hLYG*fjYxwUmWyzQHYO{pvN#-v~Ja={zUcBPH+(d4e z8f6-jgr(&)TgCjokC-IjQ+dNIQTva$2-OrTOU3)N%}~!pC!x%g0~7ZZ!snlftXoff%B3_Hx=jsFb3+e&rR}j7jrY-(9vS2n#GJRE41bswTHTNEFANmoxHz? z_c+SS)7p{9)^{4(dNEazxqW(aKe@}7Rz_=!7FnM4DCs~Z%`()A&~klq>6UsRbP^nX z&t^MQA)z3vsLNQU@+ivh`Y3}zA z!Y&EWnf+mSt8%~>wNejtRv!52>K7c{A@xQ4Cb`88qM1pP&4akt2Br2Jx)HL6tXm+R zjT(B52mW+H-cosYGX$3xu}_PE$R}9I%%01Bh;(0<8LojRCL6+91pp&+O*5O>Un~V6 zP7yGD`eXIy?i{LNgOL1-ynW6>FP@(`%|xold}!>}T#r`P-U94cfD?UD%r)Jj7NIuv zn#IWE7ImBVfN6$1+y>i)wNRp^cmC$({-^ijr@{Pts`vg*gMcb|8hSmm(r+16D{D9l?o%$u{zOR!r( zn0NUm^JlDV1zh#Byd1tqSNDP&TirF|_thjf(WvmRWj)W3>?mETTb2Rg@cQG?XPoDJ z-E6QsgJ>C*v0{jjg0FX+$n7kf(RFM2Vx@|^WzNlL-V1}M%}iWMhLMn~!F`hV{?jen zoMxI+hcTZ8eCk~iX_HO)crX%n_SSEHb@BIHCue4t{-_*2 z_b%~hA-4=lr{IlIKuf-O`IzP*U$fM}gK7{FA)j*X(ux|zocXIn4cYz&Hd}qaS*x3# zwGq^6!++ZcKsJ2pzx8$R5W=N$vfs6EUE(Tqv+a_A>_z?X5RPMhRCAPUgnQ~+G25f) zL9je&J-FL*cluME(MDHWM|J~JR_zcXicp&8SqV1etjRUS^d8s}qHn19-jm0-3sPNZ z1nhI{gJ~#)mDz51t_kSAKIPZ{8Z;0Cm^ja*HPALQF|(1jYA2e6{yAL3GnF|<^5XGm zin1m>E4BKI4?w^SBVw-$rQJsHEV>K-4yg2og?@DPxFX1fT~8?mG?|$&daH=PL!Oy# zM}K%k(6bG;JA&<=&1Q4BN_|$Rffi}Fh4dRCpWT{ zmxEgC8`t{!KORh4AN$>n5a-7zgO_{9Z14?#yp%GyHkeR!x?Hdd@#99Jvc>0o~`gwyQMj-Q$nBFh`V zuNHEixhgB=9DEk?b^W6LV-{;j&RAp@qkcZJT7R!wL~umioS^5%v1M_yWt<1yudRhu z|3ou9R*>dDrzNp@6C62e=)8^9vaW%;ER@&&VPPR?&>yE}a_H2m{C>nx{cp8A?!3Y! zRhIuj?0>7J+*IiWnLyBLm`#AAMqSBlb_6++Prj9 zIHvGYa^K|L^}!al4%96@=4PdK=t~YNwbfLU)iMBev}9=G-CdrI2%8g@qEY7DWXy9~ zM*-ID>ux11F<3<#j@DzSd9?8H8s~RjmB58$p#^jmaVvj3GdRL6#gVJ{tdFajIl1jx zBZOrH5eZ;;tD%O!AOIDEz*PhrA%_rhWwjEXH9Xz6#jb&<%NCkm{0KI?HtT>oRz_Fy z=rC*@yY8FeR6jvFirF`X{51(RfEQz=va7MghF- z-a-vTT{8YrlRJ94^@%t>$lEHW$5jAZ44I^0)%Zu-kC}`tU^QL6cBjKx$BO`elrtGY%Rjc9-DA-;D-gPgB_jH(FCO78h&%|->3{bl1G z5w%Syc&ZK5jKXzNKhXp29+JN|+a0O>1wJCDMIU$x2MNA>o@$&0cKztu7Ottrze$ye zqC0^IJqI|ZWvW?S$F=V@PF?;;0si^Ua&9pefRBB zaY521Wf{7!K@p3e)X@exlXMDFwQoZx<%wX>&7N# z8T(s9?Ge277$|5JeV02j>tT8#0Tqg&Oto_+53?Fv$NU1;)Iez#UPwsRH`pqCi9#|S z#Kv>6TE+y)JOyC_oacYS)MD?%DV+^51)$}5nEMU1=>b0km7ELp1(PTBAf z)+*r-Z*I4xB=cNGkg6e0u~)UHi2noHkLk_LLdDMOHcOGp3TJqCT18HYkn4WjsOFqb zt+#glg={-tj&NwtIEfRQv2g-R|NNVA{>oPa>%9+lGeYZX|Jt>zSKk6l5D+spwX5c#;S;HdxjE zBD?QBaC1Fm728M-7&5MeaoBsRT05N2D2bl}w!pW7${47R_*JH)_SEba6b%O;UZH;4 zU^_N-kZ~Tjj^SpMYNv)s$m&>wD6R`N)h|T13ocmUdZmZX!TNo4M1YeccS%z1g~ zXK~58Pl`Vz-)u*zYzmCgaKmo#;CeJE;vtu0IQf4Pln5gsQmG8+=e8Jx5BII)}YkQfq$6Pl;b`6;tUB(9(CaSi~!mMRTRDHli@Xsy94GU(anj z*sdX1RppD{vk))6XOHBvT@OS^0C=~m--vDllc&= zDqPDDTq0BB+(a`|x7na)88pRGnYrn1rWxA##F}JQV%TZV01`*#qxHKOFr*Rjh z*(Qe$Cg$>j7-P8+##9yY9BhwQ zJs@0y^lCMDVEof~dC5XOA`N0XG|9HaY^NIM93|f%LJ;4oi4aCLfa<)wnnHF(hQ$Xe zmTYaLVu3MaOW=hnQ6P`I;7mW|EJdrmmP|dGR7S!_8jk8m`8P|%4-OLRC4bL=5OiYJi_^J{Pb!`%WpjbFO~zT zk|>{{nE9?HUo40QjtM!Oy)%Y{58&bY%vwW8B#}%(tf8`qBmZK)YPu4abC*<~TNY6_ zot(2mIk`(0Ep^G7QF%QoaN4D9lvR4SfGYz%}RBRQnPA*YjqoxSHTcUvzIG~Dx@2Fc?st8DpIqvznE>V8Y9iCM=!8J2^ zt7|1Q6GMR5exTKB!nl@D0m!~YV}05brLl`$El53_*>bOz@Vg%-jImGO5D4WtW|rdUbKOl z>bFAU42`+yA-xs30cFszIL^8w{Y7b^9P3OzszZoDUW*AS2C^>Fqp14zKUP3F3m+8B zKkt7s&qt^RK&L&xDkSbh9fA!R=v>&~HLGsy*IN*&T(=?4Guy=gswLF7OZ^Pm^te}c zp9ZGq!F>Jba+Dp@;AYsiPI`TJum7bv2Z!`QkTN=ELtn`C4!Tx>>Qz*)q4NwZ3Ps>v$Q^ zLpb5C2pUWk6>1w$-K7sCm4Ng^zaiRh#QgR*EUMja52Em*RkLce+c6WNS}&qlUM7Ux zWNIiYQ8Bz0v51%w*u*)uw2@*+XhOxaP*^=G5ki}|xek|MCkz?{*?-!!E+od&Vl+q8r+dlHi=dPvV9?$>l8iV?Oni13(U_y3 zgF^SQmr$(^#uf8v0(-t_TN2x3td{PoKI%C#l%iGG6WGv9`Q<=i*H#S`+LmelnuIzw z1dVu}!34O1XP5=4F(4A;C=n{?_2^RMF<1Ff+K;DD+wfXUsVG3uR+HoOJ?N?=V+Rws zRg5N0i>Av3NnpCHmb%la@pUk_E4bETKeIMqJ z{uXIJ!mDqihmS}HjE^?l8tGVejhgWb>|ym6HND;j(>1eLbtzZY9=Io?LQ^anKnzDV zjf`(+U5^__Y60?rkgWDX=?}DNsZ12h=JJZQ+*evMV%38xR)e8r+k81=elFC{nP(JG zy9RHEe^f*=b@1-0^$Q~AUrILG9*Nrls%$Cbm=W#1w`H6l#>MAir+ze_BtdwLZdOh9 zJqJUplLTE?-(Yc%GYW#85`@V2ip@p>oAok976JHWneS4U-O)oGn8Z3PHlZ%x!EE~2 zGYz-vYo12LNBXpy4MP?Q8sRWof0I2QNl}PN7kqY(CSKUETFyRIKENu)EyXAf;Vo^T`fEU%K5 zWh$OrBzyLT_~-e~%gDdURc63U>C)D}8>h&e%!B!j|8;RI{^P~)LpO-c(M`=v)k{K0 zQ&-4a^icFxi_f*-+V|I_HUb>8%bHHNU}EJulm>P!4wM{MJI^ZB5JC@zWhEje6P>aN z&-u9n{=rJj62`}w#7uhK`JnXnn122k=ECFd?v4e(aSAi*rqoe6FR80`<}jcx?!z5JjO;4KD%+ zn&j%5L|S{CVwagWa2#ycf(Cv53;xvej8O})wuGlBCPQXi@0WfPetxrSKe?Sphzi{E z=q3AMp}Xue(kOjqPFV9s2337Vrh+%4%?Z?0X2w}nW`!L90Q?>!{kF&*K`h)uxwL38 zL}7>18UgiCYwI7sd_ z$l;kJ!lS|;A59WBUI!NkxE2;cd^;3%$Ku&wQ|3QI?>TE6)i6A}w^zQ>(+EXLjX4%k zl;|LxRcH^&NnDL>4U8=6i70i8TJ4nju51O?kE{l5X`n%i=xyjTlOK%Sn6p)%saaJ> zki}#Hcx?z_Jm&kVi|;MR9Uu2k&#AgEaY-CaPF;6R5Q2%`+ji|ZSfK<`n(yo6G}&Na zg2}<$&2H0@8@qW-;#s#F3$poRjv**sJh`zSC_5!Z4}O?al5Tj;Y)b_bNBjUhL12-3 zH93n<7ozG)^;1Y=qa<=#e$&u+>)HS`Tdf)pHCD8 zDEXX&O6>%~6h14`h~}*5MMVsGNn2X6$pMqg;k-9;4t2oDI?HheS?4X#GIv_IQ~-=? zSs4w6vZT=_r%2YB`?cMzb5|dGk2!)B$-rXtfwI9iF=;Peg9b&6adA_6`GSCLmU{ul#P?EiI&KLC%7-`fg zZUx4MB+>s^bN4pS{GbT7JoAn10lZ@)C+9Kirel_%2A-+o~uTVfbQsBN`z+qk;@BGdr`>x<7dW;AKt<@T%X>a!=Ay6O~Zd)_lZHG11VWJyFh>`BT*1sk(nTwki@1U5^* zxN;JO`TbipF#L2SpbnP4Qt#=@wFbhXJae6!R$Js?a})2FX}`00Qn?{uOqY%Y)aB~Ko#wJ=L3U)yZ)1S} zVrOB6lmoeY{TIqhaD~&TI6qo~oO#<@_YAY^XIhOhM7V}~AU^`#xKq2Y9)*FB=4PT+ z+X4YjQw{hii#WXrtc`L$q-c&&*&vud7nPRo89ko^@ko536L`ST$`2;l4oI45opz+7 z;8}`Gj$o0nT@5PAla+h^KcIlDzD>DAfZwpWr`l=M#!isoEk+c63t+h&L^RW-yDpl! zxE>~U^-D$g{|R9qq|HmXZBYR8Oc%GE5Q*1{*~LUrCYuHgtU(I!+_ zulw~NyaPjv>a+QLowGNJ;}!6u)#ISSfKy4gZi?z2b#3vg$ewgPX)-0*eMCIirA?JbuyI-6o*Ug#Ri=+8XmcTd_d6-oe>h zS|LYg8v$kd=|z%L-L#rRe`2J|vt&8w?X$cIGe4R$cd03)aHB+k{)?X0>h)-W=B=mI zyHV{aek^YfU@F zIVen=y(6tRHE>An+c1da6C^|ggtuMw`nQK5odSWp(7C)DVSoVGpEk1w(fG08z}hHx zul}V<1SUQ5)o8GYZc$^CF{C{Hj<3Wqs_rsl#aU6y3~;^mvI@TYCRYA%KKmokk{C`sMXaLFk0!N<^e&> zB_j165P$;hw+< zALw!A0%oHRSF+Tt67vKS{Ma&{6P|<67pfW6^zqz8A-5AN@>S&RlZ`=|NuR?2o zS_YlQ+P19o-&av>58(WCZ7L zA1v$io<>8}l6f|eCNs53BA2QVa#K7&f@!QVV@Id#r)%ralyW2YmYD@z>lcHK_6K|z zkLqfJNrdbq5nWJuh~xCnkLyFfan-JvRFYV&yC#Xd@zql`ss^bfT2)HJxVnNhb#vSXUui36D}U zr^jHvs_dv@dyR9t#0@UE36%|ie+jmV8@L@2dXxy4`A?-NDeZ$CCEg*=})*~#R2-n98 zO+A4&Md$4ZnnU*-3^4ifIv>~8QhOyMBoKo&!Krf{7!SjnUAr{`IfGSOb>}n~;*PAV zbUK1g>L9-%)`1vG<+;%7%6{RtYC*d&sk{1h;KI$2KRQ6SXP+1>1fpJAXYM`_mFSMn+m*y(i1u(maRN zH7;pT6KX2ck%jK)l-*)+R8!7tS(_Y7GatxO&kx9+tI-eSxwYUPM z-$sZ!^2vD{?0}B9BC0KM)4NkJ2?rwkV<1|zqI$M*QA$&%xlJKrn_GZvh-S{n9|%R* z8-VqDnap5kXk{|=C0u1G51l-ruCgF4kEsPmt-!!G?yCE7BR)KIIE9FkjSG^u674Q0 zq2h$h4sB4%R{z8>`=B30UshdR^Y^&2fqGK?9&k_gWrb0;) zDs7+-`6awQ#bVo9m%bc{Ew=tIVnT$oS<;WLttIt$BIjhnL@o-mACMu!m)@#aeZ$?8 zb8y#*+=}?i`c1M_Cg`>lknNp5l$$T zTM4^HsY{PWHF#FJ(fQSUamKK_=Z0RDp_}SicgpZ1>ULj01L@!QZD&HbdhVD0)-was zZLdQnH#)^d*c@cA4aG5LW;!}u)#D9^q0lP47UMmQ`ILj|gDo}KbJzdrTI;yiq42%z zf@F6RJ~z?R-4l%9EdkGEpPfWkm<17i;*c~8ado|~LzYXB;$#-YRn{_WeOM=e;M$2+ z)qxt%!wMF?QXqL|vO>ivFVdJ;53mEC=*%%BKYUclNfzRxUV!DrtZzUqN8hlJtDl5o zuVG&9;!)K`&JvceUU7|-&1r-qXLUhdO;AcrPGC`=)9NMffN8lGc`9HUT1Wcil6>x; z=4OE!4Y4qxySp3TSRwNvoM${|l`zcmzEUrdH|MO{T-Dn%f`Qa>;QXgI#T>i^*;O$+ zHW-@4*+M@>o|*>p2(QQ#*0{L8p>m*suD>Xaq!N?itge_=z&^y<4KmidKA74o^md#f z&H~q-XY6_}<^z0KhXo0O6u(5G_XIIyDK;O^s#n!Z1x-~>_Cl||hR3!YAO#eQY;_lW z%X-6UKBM@$rJq4iAbBQ=PSE$vr?3=LE~SR`{ErdSR);(jLB2^Vm||}0^#OKG8&2Jm zM18>xfov}qs!BelV3${0Vi_q`eO1diQ`F%WT9MxfeK11Tg-Y9~X4~Q^2<+w2)(9`5 z?%7noF5=6VkFUtmN-F7KcbKE4=~Cv`?>LXAyiO|ccAc`{;-7OT#?Lb;8St~P`|Fpr z&FjR`M+%1$PLZwiYNteQ#*Ed?!`6Lsii6We+So(6EMSEBu`BUO&aht60Ik_& zwuI71n(s|E^YdQkd7Kgy>{c;*#f5TLR~kDTndH?l(a9fZ9lR{Ovq9v)W#UoTQVh~_ zSCr*;z^d-X4FW;it+aM|pMwEbl00_b`*<+eCBVXmMd~%`!FZ3iXu!Wv1%Qp|SbAfd zZbEr&mf2Tt01au?73{ZHkCZ`|Zjeyt%lk3Lf!o2y;^rjzL_q)m>3#F?G@IkeZ9B@D z#2I*YPiwU;M3IxeQW;D`y7X?KJ4HtN4+=1Mw{{9Qmn!?RkJms-lpo}xRSQcibN+*w z!RI^|^t!fTzXT*d;Wv|ufrj1G1`~-y$O1j6O;7#H2gmvKYEPifGoPa^cGrKslR`__ zy4qXlogG(JL;#BkSKC-z1x=&<8|_BDf+etWAk!@9JCd7~xHoP5i_n1EajJp#S$+T8ClIRT zyRg~VGH3TXNo2V{0kyE`<4j(9d2gOhm=rs5SqW*XKA5bxe7sB`n4H~LKhdm)H}RUU z2ANre2_|;Ig8L_lAc^M*If%qsjX7CEtz@vPnwkgk)k*sI#uY=lHTF3ADztH$`8*?{ z%-v9H-$zk`@BivoxE!1}#;FHKTR_MEf zg}3W*t1lYwfT;E=vCc)cKb@%s2?AfREA&OKNP8du6AFlrX{(~Sc`NkU91{w`FTGxO zWehhDET}nIQ;=M9;xoQWk0=^UL)B?%<)Y z9(N;Vu1id)Dl8i7fK~67QUOGqq>L8Bvh_t3_uL zSAH-(1&9+7Ja=Zw$zep`Bt~;(<$kcf^=iXtYGrLF#>{eCCPE#kd{)qW-2?n&IuxyJ z;dum0>;xsS=mPEM*|>;F4aF8qX@psotY{R(^|Dp6)H4+&>3GPsV@O=#^Bf=qTG7eS zKCiQtRzEzmexlhIVd^$cCIzr37Z-S|3bpV@gZL+}AOrq)HnA+xzEX7qTd(VawqW++ zkzE$s@Dc0KcW_o;9Uq3#-%TuyPBUb;J)>tB<=_GUSC7@o^&}0)%3@N!(n7!Bdj-(A zZXjxjZlue!eu6atZurgMP&K;)87^3ZHkf*$WZSNEsH!5xdR^|~!_JKodaoCW7VK>J zBo{;1ea4joOm?kfcm#DuA>rp(!COpxD|Y~#^9i%F@0tusk25u4@aTzHy-+`4c#9#+ z+AwoCPyNLF4t{%7JFcRqK4*7!1kir~YQ~#WhTrva04$*2 zwgik=NZVBzvyk7Ws?<$h-b`~TuUrby0~u~Rw{B1!h94L#wy7$LIE|tBOM(QewI)IH zHW*4BV7r;qs6hp0NbXlUuqpu_1i{o_yu3lC@b;`NtzSlve2(+-ailRcD8mS?01+%1 z;3tGJ6>RcjOLM*>yO|m5Q>iN`!3xTiv7WgZ8;&M72GjiWkqnwb?k)r3sEg13sf(XB zt{=@19Xsu-Sd8r4h*AhJ!YB`sEoHZN`%pO}rwBMbuZz02S$j3st&3C06djaV_OcD9 z#w1HYa8^|K#YbD`iN5!sd1jGb_ycj!T&cHhX@^)k7{u+aR!l6(0NTYsCuT>i=69Jb zwRWI0Y>}4JXuW{kaSeB|>|jQIkUHGZR-%-|P=kSm67V)VH5aarr#A<8oWNu^Z7fTb z%ge;LuN%B7WqpfN-X;Jk)@vS4X4fc0h#22xyTY)UBjm1YF>owHQvfMj ziFE7lKp?C92!cz9mB7Sp5!L5y^SCOlbU?OFK1VbRw1-HeJ?)3$+*qn*JJg;rdIX-( z)|ty_mfn&9?8y53I8Hb~XO6>S5QmAvQXHVdT6Rn}W>+aMgNdGGgS|rtp4{3h5qvAn zl8cK!6atXH2j(31hZxpj7!1vN%XFibJgIA(|nVWbtV>g zIt6~r(-15nIjWoti z*p(4=4j0ifKl$EgwceJRvrT{q4minv*)A|uX?B-aH1;_HZTA^q7VsJ*t# zAl%?Px^cAHVVJ^*vCFQIwEm7|c8Z_|@xyWVUel?vL@@fS#jE%axK69Jcx?b-C+u6e z%<$^l%(QKScE>dUm`AhH=v8d^Bj>6G$(~h%F=@@iy`20J&>AhC8!ZSbUBCEP(=z*M ziX5r;(v~UfXCalNzS4uu?1ux`lRsyhnfPn|G}}!dE34K+!Y0qAgXx(zS`vJGqzp|p z1aXQYWk=p7M}LYCYzU3TF))>iI@v11`zc7^hXEA6;GhY8B=>@ zGK1NJRfW$z5<1_9eX0R{da`j+l_J_Cpxp~4qQU%d?LK!Tx|^ynQYm!rjMIPvcr2t2 zIgMsEt#4)&X*+UD(spX+u(q8}gMk5dal`*9hO~?RFT){DbDY_*vUotk3Q*kEY5CFqa;0>zEQ@t%;Svgje0XplaBCTN`Yv?U4FXwOX1v zs2j2k?`{}lFwfdxO8vx0()L6Te%5~<5{PX%j_%0st*IXWO|&JUb*bKpQXJoU?ZV(J z0J8Lzth|4h8>$w5(Xx!&P-*xcxNN>yN6@ZTMnDk4e3Z9-Abd-Ep;5qIUej?VIw0i= zRR0Bw66`;C3?rH?9s#WuxKdn1Wfzam4;LI2P-Ud&vRM8nOVI6a2g-RS>4rRvw`Zj_ zTFmDCoNV24xEdiRliO38sSQ%9LaUpLaNj7wksow0F58@Y5E5wv_p4nu%0J5kA&X># zHRhc5fytifd!hOd#k0rje^2T0y-CAa<+mbS_CRCCY}Y`9ROVe(vPoagYq5*2Jc3fzuDcCNat!E#rXwofoJ27ZB7$3g-q=FO;qPZ}1j3zbM zfo_T!CakMo_c+=Rz2 zfc(bywJ!phnu*G=hH{O*5XZvu9C+e&MRV!3zl&ok2!E1g2^2#JjpAbe(~1+;T*WlEBB+TJ`IrPQH!AIaFSEs zkm&t1FIr*vlZQ}`Ge-$Qyr@9ikHr!c$DzR)oz|MgUB#ofSdWTFMp?Sy#YRlgtfHfu z^$q-62E*qVW722YEAK}JR~?l6#VT=>-4m_0uI;NBMY}B4sa~S^ax>edB^@+LAc!?`hHe4Q0>S8MG+GSJ!O#p)gKe80cv` z66QBNeBXCIx+-Ip+u?PS8GblG1;M(>eiU^=GFFJK$^C!kg6~w*R>h$G(nN2@d?_>3 zZ7{5>ov2g3&BHG4mT$A#nQ7s3v99$|d0j2ISe5VyaPBmE6|QSdogjwI|+su|?X(%Ru*1o!bA#)7J$8$433VFNwR8VHr=e8#)jpck(%45=_4tBW_ zqE~W2VpLtBl@_j+5J1iQU`Q$=R6cqT6#b6}ib_=Vy7uBcgi#8n(j{Nb!dO+tD~H7` zcl)>QJU+f{Cfg1~5OdWQrC4f7-VLK%-^@(f>G7{ulnB5Xu3{RhapsiI@7qs3*eE7Q z3|alrD3qo~Igwl}R2muy#6x;anyTJ4A2gvaie26)b1tr?H%PfOQ^jJN++Y%yg>D&R zWAltlxssntX4F?{hlnb4V z0xiuN;J;~UA+xTimAosUl>esp_M3U#YnIB<#pK@V1K-GS1=@p}0uylBLIx#6+piVD z|D%iXsN=D4aEn_Lk-N2%fATCOl$UPH{B5Ys_HVnYJ5Y=t>JvOiv%MvjDVjO2Qc2p4UJ?H)C2if zK+M508~B-OD)+&^?F`w_^L-7vO8mLhiuQ3ySuV# z#u4rlZ5&5IML}`%F_j~G{bj-TeCoY@WlP7xq&rT^|F9>j&7}XRfwUrE8n|e@E-oM?1)^ZIW*xZ<_QKb6xC&Z` z_ta*G;A_nF?e?Xv)Ial6<+R75nDL*ldgG7^IQsR#N9BYl7F9!{d{$+d3d|9i-88WG z^68kXv5tc65^QwLiD<$Y9vtR!Y zCiRXdcSt47td55GqInK#I5HWMbCX_=ll&7?nq_Y{gvBP0E+HYgN|`c!D$tqv1w3(b z%XY#|G>z;V3;R?%P442o3~F=_p=2h+5zdy2$A&6EzI_p$IvOqYHM!x4i-w?h42Nq# z*t0M~lT>P!5=t`B%cvP)`RI!(=x?sAbzHr>wmWug-&6bbAnVw53H4HTzrG>mQw@D7 z6yzfhuxiu{M%^~O2FuGNFDIj&5t0OXEW!Kfi1(5{#K#K(?l3E}59Mtp?@d{Vk|lPD}<|asndndlMJr zn$)$0K}f4{UTQ{Dxh7b0&B{`W0Y93!G)F|_hcBmMwLW7amN-9SeOTqRHzlf@dJEx7 zYW=UZ@YsN+4HN_P7!{c+*+@<7A@SQ6dF@KKCbFYMl=YfDzBRKlaH{4A*C<~9#mPc! z?fie%t}MZkR7u`N-|vGZfQb8F>|yTUK!l-`R6R4DQ{AORtiHS1LSXYR2Ic7vB|Eu2 z1n;IQ0qwj$>~>&gq@hWmWM!lN-O$aw*!6J&#xPg!V*Ot?fP<7*l1NAocC+x<^b%m#i(rOGHpdjMN$N>S*mTDEM;z(8c})g@^mYfpZCtnbycjf#Qc%9 z`u6pZx80ei;HfnBxjlkOc%LyzoioP3fMQ5eMz~zAuu$m@xkj;m)QNvha&3k(ui|TI zCmXNIoa8e}Rk9RG$zUB9i_C3LN_$Ho4wHGyr(DIPq8L2S)J?z)C?Y<9@YTlCoD@xxN4{l3g zYIIe=C#i}in*>)tlgUAzCb#GI^_%=4vlWGL~XV|(9u$09a{ite&^Lesf zs*jef!(SLraDkNts~Ew9SG#kvp2DaqcRazLC;S(>4BxQ$?#}lJxr22ES~az~wImaL z5!;ja0y}A5>s2&2u{j5oB=yq(scD1l2;l@BfY8QE4RC+1X#WIIr*DI)w^rE94n>kA zre&WQkZh`g7$qU<&@cwKQU%kkTf*s29t4qdXyClhEBA()IvP?S!Y)Yf<~E!L+bCzx z8yZ;r<|*~n29lvTU}TXS7Tz=k@14>jPPY9GP<5WxiDtalt?^=F-$oB~wJtBS#arV= zd=7?ithTxAVYR+sHUk`XSRkDyy>+&wO4;Z!Xn5DM(P=QLl#sXcY?WviH&nL?e8Fb- zsxwbqzYVJMPv$)~xPj8$ksj7|NC%jpHZxfXLwd+Zm8ZvJW{gk$=rhxLp-4Lj>Ua{a zwdbx_VxTV-QC4McEEb_u#Z1F?UQv;5e%h3gI9i)v=+kOso;0qz!PEMw_-g}0Ciq58 z*n)mW;`AocM6WRvkS!!pg8~5CHb6kaVcnJ5+sY!R*Que%|03I84a%tPU-!DBPdSR_ zpund4E4DsJxwAPU0%+mRmfN5R7C>yqobGJ#7W+V|y#CM8&H7z+&zq)7?X8DYNuhqE z_yN1LTV@2^I==3;T(Q1FWKZhbwM_M{xQ&l9v~P-HFk89qc5$c%IEJ)d+_N99#Jld@ zUwa^{VU@V?vKvv3bKe-h2W1_!!bnm@e~tj4iazF&?k6~xGlc^+w=Fa)|0IoCeb=Np zuCGUd*<~K{8*HxBa1!n@=Oouvs57eTita@dMsmI^XhG3D{j+q$=uXuqMbWL{exmN~py} zL&$TY$iak}_}GcHAM#7@pXvm0l2eFPpUF7*OAYw2hjqE4Tp<4eHG-F-K1^cH%N;!; zsU}PvwwzXk+T#CAh!nsbFHhdJnf(P2!8%b-fIqw*O7sbxtUZ?EJ>?T?|E|UFt5=2t!F@AHzTCIJXXbm z)uN(TFH#LAu1fr>b%09Uw@P#!<&untW)`05mj2GqR1PqH%SFatYC1DNBOSoZQ@HZI zN!oJ<2KKQ+T}^}SsOm|0-tx#Ao+letO$#NkeCYIhWFlL9{#HRXZ~rFkIE8cS`^ezE zw@8?Ro|5Z&9$DYa>tO))m&98Z$t!o|YTN?rvy3AK?obI5f!Wgr+fmTMZ3u<9>r>TE zy*#1sy>2h@)Dc9Gso(TczZFhPYyn?nZH7@j*vDYim}p7bM^10(%z{$5YLRqRvesqH z!7m>b@aPc^jy)Xg1q~u!r!7;&RQPJ|`&$z73&^nUsK_HBd%vC8RP~FDLUrb&)vjrV z_#k^$^{ULD*4W&)A0L#hD@5*t)Ysq5f@u4tZTVH02LsJ-Bovt`xTDGzeC~BCVp)iU zT@|u}7Yc*%OhJyMFJGK~vG?oquG`fmt8ZfQu|ULI1X*o1u`!BLs>11v#Wb3n3=@Ra z(7lKY5r(j@cFcjCtT~&F5iK!Mc%eYujNLBVFq-L_F)Fdpe!HAiQ`R2 z!h8z(6#K~zbfYMD4DCdJT*mF)k}53mxnT+S61Z=}IWUT%r1PaVYzswua@+Q_>I)|q z2o>!CXw-V^VwXFnO}r+9OFKcvUXoy z)Mhwu6$w)I>FP2EbbnI>><~Ud;1%G;9L>aTMBywWQ!R0k@sB=f9@Epw>2TM_hf4Cp zyK0X4DWJ<(ervtGeu{M|UHi;;iXW`fyN;!Gu@7J32Nbs*RdV+pFk018*Hwb$!B?d> zO>IwNA;Qi4d@0aQ1A0yNjfKxP;I9j8hJbK*3mT{qO!^bwF#mSH3Fuo@G7MKo!A{5_ zY#3~PHoCN$esOJ)nl=wKDB; z!7C+J%ujN1!{aPe0R2hT$pVxwtQVKvjSYns9(e2Ntdb*|z+Ho8vjTOTAJ#9No%Nwt zN!k5F6@tV{K#*lspso$(n{69l+k!A{;H}B;(lv7EK|f)$tKIp65q_sn(6Axk;h~hBWl{Zla0pXvrEjq zy45*M1QBX?`!CeM0#a9PbKykoD?K+W-O}5A|CW5LCbxWIiNnn`)Kzk#q{JBrjeL$; z9B;V2+ai&thoNAetXj9!P>!*606$nT`YV@!Gy?N&FpVgZX!}N~i^!1EJg+OpYQUEX zzfi$2B0GSse!9ncom8*25k=b;(w>m7OHbj^CG{xjk$=SxMy{Sx^G_doZc>`{mZ1lx zPf8&?zM|sRhIANxrJ7#R52g9$aqgd!#Z;?z3XGO6YIiBWHyXIN;Uh&ioPH5zi3rAb zH}>m-0kLbvuB81@-xslqsdLSnHU;*+e(9S{!-cTsxhjvVgOmqARMBt^xoUfsgej{K z#cr`W9I0nL$^G})D_`Z!#hap5a66IfSFBC^rOIyh40e=zPXe7Z#pU!Hug_;Uccp^` zt@hp+8hEa&J^#54j$YJ-!;w*yY}Y%>ho zqaSLxqL?zH&r)Rwr``ih%8MlxzkOI+CRTLGnmGf@6ou)p=`9@Ox`76*F~!~6P3E@+ zD+Iv8UA`&zH7i8Txv=nwpCXCZ;iWTSI0*P+R>ky1_+-eCP59(pWm=db9@x6`at6rI zOk%RsJ=uLXxlW-^#bVWek>dzz$^}|pyq{wperf&MaMnj_K2cDWLY-XB-~QXxD@P6s zJl5oWbe&I|*A6z=wytj}QNs^IwAz-a?YNHT)*mQJ*qB|ZwjPl}WC?P_dA8#wKu)g`rArl zfBn1Q>05o%2m3Vl@&`3;Y^RDmxi!UOJUs^Y)#HL$X*HI}Le^8Y4hp?{+T&a#}Iz4q;@g3`r`%ie_6X zf$3?88)C4|j>8ORC0prUT!_38m~m?6LIoO>PCtg0yk!B)3z@ao;~bzO>>TQQKpC37 zho<;xh?n*&h;e8d2exJzC}pjkh#C7k>(IGhxS+NIcq#bEC^E78t8vNCCFYMED7)NR zu!RC85)u43z@0QV$$Z~kiYU5?H%RJ0oiVJbjl*il%juV5%N8B1hHz+u9VKJ_gNasS zcEm)7v%1#k^_ccA{Q>osHm1IQL2mk?9mU58Z&d(MK(4sA~M8kh3*>WNNDx^7aI=M zz^^sAAeC8tW`aA8sr7|wb0QmTgXsE2)y6WIC&0DyqnDOz7p;j?y;aZNl}|y;f`5(| zykRIFwUXd-KSH*|YcmhXV8v7DN9*Mh6tv|jKLjP>Ks2-QkZNtj@M2jY}thU zly^eCKL`o?8<6BB36Z~}CYC?kv4zwKeMz7C$D1|_Nu}#<3J?E?Sr9%xPSaEZYXc<@ z!O;ej3s)$Hm2bGK56kVByXJP#hHk25c9&qGm|ZD?hUu2wU_It5v@4^(Kn)|uFp82t z7Nn7Xcuv4b34shYJK`d0K~B}C)>=kr!A6W5a_F07pVQ!tl;dal1r8XDvbnB6QOulC z>f4{XhK@;oVFPAJ8n*Ryish+ks*}_)yu-w@!X8Ukq)|F7l7N|PAZ!oQfWwW6ttK;w z4`WsHN3+;iV)AcHEP=rbA)BqcYZ`V{WhippKMU`7^Xh{wjL9O@L_l5NoamZF0amvK zq>}z*!lP7WER*;TA|M-F$tT~~H84Rgb%mG#Qx&Kqujw`$tS+;Qkn*<9*~0ZJetJJ zDD~A%D&;(_5J5JV1l*9nRIiW>)=ogWDy!8jPgAx+VV_BDEUFqWWu1L!WOL#}jPNFn z)J0o($cx|5JR)plNnNpwd@$=zTgb?(s{X^Vh&Gs{O1>Xq##-2Hy+1dB(kib?thP@_(vB<&- z&OAi{+fY^Pgbe-Om4TXmgiWLl=1(Hj9s<`piz|r0B^mWPRL~UodNDw{YW;Nz3peNr zBo0gFCGzYs6ao~bU08utJ)O20iUpuOm7XL0HP7T8>`ZfMPt@eU<#oh*qRi-5t1wu4 zj2_7S+1qQ~P0I-cr@ch5*3PPbg_?UFEHKuq`Z;L^{b$w`f1WWfXkXhH z{oggjZ#j*-S0-J5&Kbkq&Rq#8lb_(={x#vZC7v9jF`fZl(!fs<0mL8+IDX9>n5d%( zSDOOxyqclLH2!-T9FG@P*t4inlkA`1(19@n`R z>VS9A#%TdH7W>|nSGcvG>LWsuAQG^==3Ca@AT{&Nghr z==IagGHL==U1EyKT(SeAz>StRJpm@kjx*2$_$x}yU>@?RSM%mtT)l_?!o9)Aoxukw zf>vPV{Ts&S**55X@)pZk`{e(&TA-Zzt{v4RcRej8F(KUw8VGh8nfniVaDau912OhU zrN(FkZ0xK*#%+}~^%~V)B8`ZBh6B|G#%Ebd7eX^+gg$>+DZ6gf!_$!LtsQfs2v=ft z-|8G*VkF@waR-3kpzX#Vk+jK=9dipOe3LYnJu0B&*V(1EX<~UZ$(=Kt#c7od7$bBG z`6>~?FDUl@s1(GPMU>I;f6f*{dsRztsQUl$Y)u-kj?BQ^*iyYtv8-;R0kFOuD2^OX za_En07ae*N)t@ZBQCzO3X4qtX%2N9<0~=la8E7*gas++XcK-EOr8nN2ajOKN=jW&J z6E`?damDFG({V~M#R$R3nNgwpXHC%Ogjr64^iYvT@K zKJ2eb;+iE7gcwYkau940e>y@#^@fY#8mTG7-V^?WUs%Z0@z716;qD-T+lEqhX9>t?&_vi9Sxpo%ksP;bAExRUrAOa+^qwwJ%q0I&83w8xweU~8JdZJqXBh>T< zDK}wCMhSsGiR1XoCH|Dgx&8~dfvtd23&dGL=9M-0{iJ#NZG!bhlm+fsR~x4U{&i-Q zQv{PtB4=nQAYXE*ue&EY?D`M+tln+hTtI~dAnvN~L_RJ*8HLx5vwBX{YI9UJgec|b zX42`Z(gc5b6T+eEtOI>5F?w^Z#9?OWtox_6!t_@eXMsAcOlE=a1k2$?MN)T4<*g!r z>_)r94ieFcX@;-;_cTyM2{t~pD!{5-6#81kIpA3V5!&aa#w|2}Lr!ZuH z&u!T=ZECtqglzZhtcJ1l1CgAP3GxZ3OI}?2@w^@YGMq)_+YBN8x#TxJ<*}<)@gdUf zK>;&g-g-BXmQ?>+mM;hU)lwflnkL9w11Xu^aiRzO^}ophZ=W5(EWl&{8^wO#@Oma&`t1k`^G(+ zUG7m+Fxf*28vv)?-Td)jOWW_&rlzBNTL1$nuyYQZ zoxX{K>6$G|tSq;S&1z)kkb{+dr~%HJj@^#S`nSfgH#JL3b{`m}1M*7Sw%K7+-!U!R z5R;cFy7fX(IO9E9#fD~-P@Si$RutZ06yEI15B>Ws|0=Xr4{0}y8RIJ4V$AGn zZ~PRi2~ynbvbCzMAd}0Zisy|+v0F)9+xOBZb1D@CkoYp2f)qa`f}6=T{Sc3>I)YKZH`z#;q#m3rXx_0r7U4edFJlLOAb;wwdiInQ}%AI z;F%g`<(p{b2&W95yKfQL0z=OLS{0){GM99>#%Ji-j~G1ZmuD|0PAh!NX15FB_E+Rc-*S+ zr`-7=JTka-Z7^9cYlW!p;SMp#>jMcwNmJ_o@7G^p)6>U$CN;2aW)V%T7`qQ9mVNnR znGa>|W*1Ga=E2VM;~K|eChoSz(N!5#ZXoP3+Mm8gpvo>EQrz%>Isd_NNv@o6)|`{n zu=oO`MztaOy;Ztt&l=D-)Q*xg=?_%9*|Q-^?F6Tnaegzi zhv2pvGU2=1)(t@m+}#OQ?`mxs!noKxbg;9h@$Y%f z!_0WWK6lal#dg=34&|}yCAJP?2A|9v(#y$G!N}b|1)KCu%Xh#|7;HJ}FM5)?-93S+ z@IyH!!t*EaNj9Egpwot!!rv(kh77(1R38sr zGlf$TrhF;kf32c1#iyM8xN7_Fc_ma^Jtv3YQf#PqOKxNi3xRJKH^c-QHh@u5r{pwC^sICoj6hmNA|gZGC>4Mw z*|OMMC)64@o5|sYUNe;E~fFFR$P>bMqUV2h(jlW z6f&by>n+TV7@tA}EElP|IqAv>!&wcM##_j)Z8+?q zZ$(NXt_}6(T8XlJR0J)#ul4DwOx#%6?hC3MU`YCNc6IEMSy(9w2(@bx=k>qFgGDa~ zkWU`VG$bpS!vP3YXEM_1wiB6Lj;bz`gpFR0!j5JZUx!3}!_i-+mV-JbD>&u6pyxIr z>yi1ab3N@fsieC;z8z4wJw@iK6h<)L-lj&;$lI*Wgc6&PpktScXfmr_ju9PbCYjA` zx6)g4QeD6?ys*&7UdYCs^%}|Bd(EdHoH=c@0Fra(1~`%4PC8amo4j zZkU~PsVo&uj2Ql1Z)Uko+a< zn+ls<^X1Aq*wY4@{e3Xe4QEH5boltD&80AZbRqtE&q(3mDZhZRG}DUo?Q_$v+=!f? z&Q4dJb0|WDp2+a@@d@A%HI54_srq--4Hylt_|@zA27*6)V^O~6V4)6r8HQv{k0YAU z?N&L{E=UE-o;;zX`*6}&hnfQ$PSz3FYR@yvt6OT!dZGJyT^FKN$&IzjCm0tG0Q(m) z>04Q|E4>m%`4`+}4?gdVN8s$sWqm}xw5C(ACF{(q{k;bCPx3@dLQ>*2-wzpVs-H#D zQR=X|*P~c0ne14IMc%>dLDA}8lie}dMCvBG$5_s7DC_-@9Y?Ou_{bAhrOc2Km0ht# zBUX@@IcbDW-1?u*c-IP5qVw|EjF>xL_qP;Yf<1RJO=(W@mIB|_SXIll z5hkrM-#dRARDoStb$nPsWOW@*Q6=A|jJ|1Y+;w!xe>?TZW3WBEtx3ju0Ebx0U1sRh zWL0?8Lz3;dQI-AD4((1r1`yv9Mz;+HT;|-||JVPtq=BZgc3d(){~H7So_3hU3%4*s=uMt_8LmVUy#S(Q<`yW+9e5Y zG;t!tSJjNDMf|r`*G6hWBvwg{kSBBYvpWv7ZYTnJ1w zgX-Vb9G&%5pNm!dFS46IcacN=k{vnY!I~Vp0maTXGN)XJ+pX4PwY0BtqSo3r|7;hL zxfWp4AT;UEUeGi;PF5K9zbEHA`rgsp9stgDVI(4&5s-ocQv#7U)AnegR%8?NVR61g zVmbLBL5Uo5ZUp1=9gAVQu&KWD(BKM1ySJJ%VmUa1Pa*>;O5-mg4*0H(v3z3tk5o)c!-PwxlaFb=`onx)~he{IuEqNm`=wZSY)(1 zuSN2fHxrp7)XTTEDjfImGNnpdF05AF#j9me{Pc}1!&7|^No~yK!*x}q2}LA;qQwoG zUI$+cd*BL@%ev=!2pGZ|7dsllqc*U!%TdkbO}LQBS-EZ^aG$9ee;z@l!MbTj>1M4; zMj&fh@=yD`N+51}mD(;nhhz6ve&gM}6_-I|x}LzQ%-hAi&MauI?$5iHOS8;x>IrGi z{t8grR;8O^2CD*Q!N)4~!o>#rE4J|*3}s2-T*VJ;_q>b~Mm@M#5k!ok<6l7qRz?0n z4OE~nJp}Rlo>hEV-=gPf98ccXUf(v^Pt)_o5=U~a(6^mZ|t-dTImN`~c#DcJ7C|1>)M0rp)zdNbDZ1c3d8nD0jx2i)NHX=jqfY(nUcu z1hcYlD{U0D6dHoFk1miJ^{!PXPwT{G$4^MC!vKgLUwGBD* zgGc1(=h^x}NHOw5?)GXUJ^qzUv2B2~Y z**MKwT!(cw@8&jXg!)#3r43|m@)tyWY#!BOGgn<)#bhut>fQxH9#z$8T7UhflH+6I zc@J5%8LZDuQoCV<4tMl^qPVqY{cd!O2vKrSq=#95itIzKZYe=|8~)uhgJ&r_dpphf zeI`^B`vDmc+9Q3cJzzhH+P*(2-ZdaQ_F_OyI|=0H`b@9>l+jM;YbICrf~qANZwkO@ zWI7DbOalr`HgZJ!;g_8NT0Ai|i*o2?V>fnhDM;0v)7kZ^xsk+^RnW$bbc!`~dr-St z6?vU+o`1>qp<{I60QAus3;3;;!LFwOfRxbT%4fsTBLVq-0`=-%ms4gH-84xNF=)ZMwOR)L=nwBXGcUHdo66$bwIiocy;RrW zex7w(T^W2%ZG;YeE$O*e`e5%c+*Q4T3x!+B%%UB44eC*gh^w0b=`~0IAI#BWo6Y!U zNAMZ$_(w6ns-v<(72IC?17^s31AA$7w&XbTm0c!loL|9NE+Bh&^N+>-Vlk&!@6j5F z(Jvl;L4buCQZroS8=_91Os<;onxE^+YGzR8^{ujXTB%z;cY~xop~DG`3Q@L<#-)L7Hz{G@?!@W{)SX!&WGX}1DeAeNHyu{T9a1X-DdYwiO7a{ zdW&f%FG_C}!&%wDz{}i@SAPxgln2a&g7>i}FCaG4#@R7gKa3)k9e&i(=~~G3-6UM% zgk>dIAN61R%(Q%nbfa?GD?hqAsyeHWD5g=PpgNF67jm_;0R&%w@@%-q{%uH+TIfxVU~jjL{0-pbP+i-1ZAS>J^r!f+GGm-*kr#TDJ~J=h9=_$R@4NPC*2@b5?l~>gVr&*& zxXuK3$XifMi-5^pyRIsr<#MbIEd5DcRZZpN092cqAgZmH6A29RV;XD(pH>e6=;wWA ziO;O=*{O(IxALaBiL08g@Ph5Jixa>QxAy!xjs8vjDqyagyCH)y{InfU#xD;Fb+e5C z^AS}4=^1QTiQJRQ*)mib2EW+cl7`Hlpr5&MYy!w3h|Mr)Uc^E=nKc9HjB##ZnS1yH zumt_GX!Qz9wJpDx}Td}GS*A)-!; zR9T+6z|WrV@rr%lyQDipsg+W0lRLYkjiVB$;Tt7m3|QNwXF;6nrNVD569Yt>ZUL}Q zju9_Y*OeT=+2SU%S1-kr^19U7jaSH4Qg~>`EK7awK$7DW7Och%VkVLdg~ z?ecbyh6HFgFvRQAirE2#uOCJu8;YzZZ3}>%EN}@ZGL&I;vqaU7`+RccPN*Ew?9xV4 zx13e-<#H(|@uL!F)Y7|D&gc}uOZEYuU>p^Dtm>86quykDquPN(Ze88AAWdehi@Sqm zR*$Bd%NbZf_20z+l|Lo+>NlvM5xBtSTjuD*v~JVWet%}->svIQ(VSAI}4b=)HUq$uT0Jkhv%(3vDp@Jgw^~DKdss zXm|YKs@}*4#dhj zM4d8|m1H#t*NfG=U@Kw^;LMAZB9Nv8v zypUVa<|R!7-dX8~YzhmXRz;}w_K*8DEM)9hHEcCLBa76iCQC$a>KNi24p*agjmS_k zh0i*{TREm-S7{KNq&0W#MgTi$2Z~C8s-WDc9g_vK-kD8K(~9*Af{8-)V0pfspnY@I zCgK`cN=|EyRB+-4Wm|-Dd<|p!UoP95Ga!6qmRy$mmcIzax=|TkZG>{7vI-xY9?QkT z9Xw#4ZlssRRSDDIs3xtLUvZWwWfl*^Hjb`Xw4;U5T&O`TPbFm5YxF4T`JOTm@p^a8 znZAE8Myqr`wZ75bylb~jlR4GiJMdx9r?@sV&D^r+RrO^OG1bI3dG!|>pbo4$UjeR( zWeX&_Ykr|iAHoE539gd{BsDV5>n zp}??IOLw$?>FzR!q3i0T*sCcy3-Si(F)+#G&arE9G+@tVtwyj4t0QM)_>y;UG8UBx zm;H6ueel=qssRJ#@RvcV=wLJ{K`z23tmSi#7a_vuf@7WmU+uNqAW zvgY8XByjK>J%Iz<3{x!f=tH6#&uc#JkF(lgR*$053HCVi5zbW%ui~zb{gQ`|KH6EfoC=v)RTkkXy1zi~T`a6aNk4BPO*iZIPf6+OgR95mUiT9K z!>b`!foKjV(l;&0F9cd(R1Mg3p4?=4n}CGt=(Clrt3V2DrC!Ts)y5sMEQOm$qnXYGn=bHgiL|6u&Wk`vjSUrjG}-R zF@iX;He*6tIm7-=vMYr!71ukIBdN8Ua~NV1rI1aAwEQ2DZY5mA1*$USlxbZt)>mx! zlq+8SG^rClm&nooAli4FZ21HOlek{O^M7_^!B_i2G zaD+@ku7~)mY<8n8Tw;-ac#R4PPA(Zl%((s&*Fm*agr1>YZuus6uPdOcXe5HtxoeE56rnAQnV-T zRG3!!50b71Wt7g?61j{0^7fLE;dTR|4OyOUe29K#se^YF zirBVXy|m*B)yT>d53TBWsz^U&oA*|rpX7Jpl|2OTyZV!Ef%q!~%&%K*>MOA3MPB29 zGBaaKzmAa4`sTaIpoV^8PhnT0IFc^)5XMNY;+(cC$Jn9*_srfOH;v|~KC6dSU%m{G zH<8n%f8$Dk?t4ATI&W7O41OcICmTV+usb&L?_X5i<5)BfYRaYS1NnN>2i2fI+F%-) z@vMRLeNE>;n5kAAqP&)pQ2MLP=ErL5)}X(Xoed(MJMY4Ls+(epxmgH}-og1nU*vY) zB;@O*9fJ2P_g|1OMDo62X70x-{0w;XCfpQ!lIi9RpZEtw$t)7Jq1pcB%57_H5G(3B zJ`}09F`r|{cv-(MYH4qOSN~X~|K?1mL;^Sj4{zR@XkQMj#%q+OGE>Z{oG8O=gKdG; zGC;&cnJyP(luXuTmTIFS%h_+6IK<4H+0fRDq1CPjO8D#N4=d2s=I8VCWzO$F$|bLn z3Rc^MV~qdJQ7+k5mlYXKz5;V&%}je9b`A_H-zx{rOsxPja2ZT2%Ggn5WuX9%A7m@y z;;_qcrMk6wT4qZc&N)aBf`sOZ$+eZwv-}swUX?s>)5-<)M`g-*%UO__1-QA(c@87c z-heVaPi%=|^nNkeEdhyW;E3QII^q|D-7LTuN6rv`U=0XwXrl)V0|E?Q+0W#^;a6GC za6g#Av?=z`HDQhEf{9sFPc3QL;-gY;m~5J-idL4};ysMawA$gyGIE31oH&Msl{3p@ z53hb1X?e?zfHzFhdN}F{0f#oXpx(~s`*!CxaR7a3bJKQN#~$d0n%OnHL`Yj~+S%e5 z(5P1)*A_92TKeNyL(d;Lnj8 zzpD4rW^#1k71a2*!L-tv1uZrl)DXCKpw-Gc;?zBg!B}zsJGyg=uj~I=m;K)S=!WT_0p^37ms@LiCf z@XCYrh~H={Kf1637}+DqI#tN*h?)>lR(|ydkc0Q*_J_KI-uyfzL}FA;Tc-2jfwr9O z2vO*t4ieP8Vo@vp^^uwU)`-8*aE`zHv5;_v8jn}d{Ky0GW>^~;7sW}89)Ed*-=0Q0 zFPGBuG-uKwlurSr&T80NMuTy9rL!!F(G`(&5kYmS{j$lWB(Um08agh^U++>b|`MtriD0~&gBfQ=MBj@D)P|7v@$i|0mTRa)-EI);hS@0 zZX3#TNU0_!!*K>DjVXQGbS)nbCM~PuEfj$*Gqo;z_grZ83rlFdIE#(oron(}0a0&* zVJph#Gph!db=ZXy#G8m1wZTNc=jY6JjOWovE79&-A63hVvR7ies0;uEezgw(jZ7;+WCJEArmWWSN+GV&$CEP9kn>CcE&_0$mGu4F1TY>M=HnM}53|n&WKjVktIkz2c`A>2Z zy?E(Rfp{xKM)F)EvdFJq4JlPNOziob5Yc_Ba9LU|;V~04?^4Me<0ia`2L2NCqO+c8@^JH3@0KbS;RZdsBK^`#>FykQg3m z7-6-A^v%RKWipnwiPys-`l9M@9_@09x&OMS2d#s_DaW`KB1e7BpYK^{f+GMzLd^xa zvWd?L27p`YohC#IKPVZHB6kguO>V7h9n~qpspI|~x(k0p&LZ4UZz(epN`yWSp z(NVX{jS3GbFQHGsA0f?8-7J_0z zKxBe2LXlOsuy&vzZ@_Ak8#Z$cN4yT7EI*}EpOs=EbGF(=^6(|+po4|0-nulY_+7)s zyH2AIy`VYJTo-haGYBI^ctQSE)iqi_q*|KSh5k+4eB`r=2S1*wLNbvfeFrAdqF4(m zuYa`$c-9!V?{{2!BC_}4)|5W&LcEMIN65uwK)DBBcew++||0cIEw`&uktwL_M7_h5bONtX*{Hco3^Yo>>O8+BCB%Y}y~`c?zt-VDFH>V7f1# z8U}vMYzmB_v?Rt6RL8Hfs-1wC9RB#Ib-Mb+h3Q}SESg3TqnyIN17t?6ryr4RW*`2{ zIg-dze+5Wj3ba`rGxWjaG)WKz(r<0f?^mPcYwK#Scu5S?4nTeoAK|JO&CRi*z1O{> z$FR5u_}>&Fd*8w>)nVQn7mJpO(ab@++V{-CPazqAK#PLEgS7X2c>`%zmsN%mtB^UQ z89c%-ax=_-_h3E}*}jJOHQ>>Q7zMv}CXQD=M`x}SN1s|;saQ1-@)ccI$w4q- zv}0s_My{h3_o{=&%5kfL49sbq^JialOkci4i5IMzZwt7M!;pA6^YeDH2v@twqKF7A zXmI+Clh;7X+>s;j(oQ`;(n0vx+M7`yZq|an3Z|^;e~b!ayoMEarQ|ZR^x~nNs;*CM z^jP1*^YRV^drj>fpWhC+!fh~g`$B7&m!|;|@)CC7nRxQ;G(YA8-2u9JOYF&$2fu3` z;z*4svdj(B&(f6$*t+WE^<{36iaB-U3`KKFj><^_&KAk!_Zz;=34a3>Sn3U_JMyAu ziO(sv{g~7;PTj0(IoqAsLN{*g_%zk#N%+MTedA(pNY*G&9QQYhz--7WdyY5=A+(5@ zY}mUXdY5KLu97i(OR6g3F_~Gufb;Wu9Hi-#R{l18D6K*za&f~({16!D<|Wroax zM0_Bg>l?RAW|zPHpCwr|cy%xxAbgy!hs9wL^azu${*OE${AJ^_WQ~a26cU0*o7#nl zcN$m-p?&TLTS#Q&XSC>>n^$}ugzH= zV7ru5$+P>4X*rSnt)P_w$HY_Pv5N*?qO7=Ph{3$N5Rx?#+u#ip^J>7y608MoXTaAd z<}_w_JIgQ{RO_hlEWDL7%3$nb?9FatXpzQmG(`7>w(?KLioT`zp7Y0Bb|5A@xalng zrRS@?f`SgJQOo5O1pJFEC<{amu64PF|~q)p$L(JG7$@Z1$913NmctRT)O?sz9E9% z3)dP@kzy^$kXn|`I1P4!a!M6kC#W;)_-4w;5ylHd^Pqx5uDzf?T&9 z1L%}-@9HYpN}aw{CdL0Y{!lIIAV=(FZ7kgS@QbD%ZcpKRCd;iE?n;u8L5Zv0r`&^dfy0fb*7PCi9QQ*ci%9*=wy{urzP?Jo=vaa^YMp-JHiMlh^IlV z+#N&0oNZTf7e(O>Rkb;#W231tdY5xKaf1iSzrx%Oj zS>GI5+}2@*pI&rU-#EY9I8IJF^#KV4TF#9V>D5E&tcoQCPx|4uSJ&$n$WKO>Q>Fc_ ztw?^(7`Lcnu3K+eO)|CdqD_RgR#5(u9O&C zd(gkLeQv^OD>?~0!77o5t1U{D*|%H|PuQ%DA+Zb$5REuR_R9BFeoIAeI;yXft%+0R z37y_MBA+fdw3W74hJ0842I%^9t8i~y7g`;8HAxRmUf^G~SK^{>%TeO02Sn1i=24+* zt#vQS185?MY#667S&CDIZ@gIKJnxow_=a0EwrRGvwNFQ3kMsmZicvNi9?;*GRm(b6 z1`*yh7=?L(%OufEL7hp*fH~0vc?|ZB&7j9%j!RT}Ic+e#8#FP_ePd(iV4O(a*@bhI4axdRq=Q=qRuv3xr+CU! zRbNNGj|>Dvx~xsOkB2EY8Rg=x`a0FiwE%n*W7Pb4Us$VhaYc?GzsG^J^%Y9znAWf?Htv6MI zoL`9DHrJ}3p5B0|;`;7{PE1}WzE`7N1b;7JXH}f8T^Tq-Q7ULl%J{f5CWxRm3Rx)N zVCAdseFfZ;)yv5TtD4NK@44`Lgc0F5>aNz?F`yn>;VnstY-fgvnEa5I#$eUd>TI*Z zTTsN{kGCKggyhu+gQg13z~$SsC+~Fo?4P;HziC1O3bc-UO4dKB%UZXqiXvGjOBP?y zA)-T?K`3HfW|8S8rj6UG_>&+N6gi83w)ZTSy z$L@c?k_#5LAnIk+p+7|pckgo{pVB8ap1ahY(q)#Co)Pa!bXPx7VpgNRSfiipZ61Ds zabH_R`tt;!i-h{xrZq54_M(bblsrA+E{8fh{7A8=;G>&Hspin4DyIvN)>#RohF}Qx z;qLPLwWU-f(5U2)SHL7tjHeQ--?!{1njD}IcsZzN&~W5G6L_cN0JoDPV-lm9LRVCaTC|@EbCV48 z`Gtm>tszAt4ugV2E+)Gl)kK%ev+UXA{9mCeoeK=feJFgoT>o@6%LrdVN`0rq_dY@B$-)Uq)WnJuYX3St4}>8aqs^F z^;vh1hQjW6$Q~w8kXex(q1V8NxcM_BbxRC{y zTU{zqe|4p?{oa~|4pRX?gzlNW!BI9gJQh7f&j2QMtG@ai8ekdhTJaesKXi7topYmy z9KTvv7bvj6$ILdV6_BD?3=w~zaiYs92!#&yug~;6(xG+qPt<}o7*>p^!YCe>!B`9c zl|QqJnS01jJJAEQ;>caL@iZbwYefWB^R62FRLRl;3)c;^nv{R;x}ix)wf@D+t}b&# zcX0}LgQp9#r6qsCbhB8Mum8Ossbg*Xt_nVT?J_g(Y#Wxm&eTrfSrFsdRxY{Zx#pN)gf;Cs>4`oI1(gVxS_nV!9vs+;X{o+^2UbTAq!xZ+a_@U2+%gM zlJbetK}#HHN`p=82)Phb9HpCGf}b%}XEaz@d)W zWyq~~iMW$7giG|(1N-EMqYc$QmdW3acGn7|-jzrKCW7ly*9KiPE%nTsY(kb}#I{th z(-x|Fx+hUJ5OwV+5Px*&G&d_rzMcUT9aj;Xyi?0gkG0E9Etee4!@Cx$sst~;bUif} z3;MY2TQwL<3TY~j-Wm8{6L^QHU6cTRaNSY6$jIrWXS+OP`kHz44F`}=p7c+%o?iBl)fgK6uXtea2PpXlO?qqa?cmlC>e zDY--E!IgS6q2lbDhaW7GvAc9}np!Scr`HMLqjE%~mL7;e@hO{rx^TEw3Mq0cpt+X~ zgb^xugR_;&bP%jOJYm{GAByR*8yW=MBT*WVY2CCmn zoP;0gL*}7kQDH^xwYu^V z*R_jAwQz{#@rE|r_lTgyqT*oclg^LK@{!U|^;j6z`PN#+`w!22M{sXFZRnW6laJRZ=g|T@h61^J2~(^x9n!AuEbyrz0;V=gJ%(l1 zRx9C($I+Zk`AYdHo79HMd$zx&yBW+EeU0*cEZkPVbSW&fNlm4-C{sVj?l%^CW*S`a zItd%t2kq)i(0=mVLGvDu;M^!CQ7@NU%!C-++NGnG@xb1-7)?+EfD*@Zu6G1cTd^nr zpezn}Y=sa%f=QnwsQ_%_D8?cqdWyzvr}v_Ha%6HSwW2Gu*a>T z1!j@G!6df|$AJ0OZ?@s&4@5PAGeE4Pei;@SJFsFJ5u1@zYDH2YjB}e~cqDLqG}!4~ z0tYDhm)IeXO2Vdt5v7H|Fl$j+Ajzx{)(h!%zx96UclregMST zkamAypRvI3r!>mdJ`*8=|0WWip(b-0<@pGNvf)U@cR#Z`2o#Q-5-H2B9c^yPFdR%d zHFNH_!E(qRAl<`j#SfM{01meN);*w>ZP&nO;HTO%&BHrtBmYUu>>G60xNI8ddTIfP z1V(;5VS)-(ZUQt^8%&RY#nO+g#@Q38QG@`(BnK2v72sxVw^#aHW{ORpuO-NN)W60$ z9tg$l1XRJYraB0HhYQ513 zFj@|!*Li~ImfFc6yD zU-Ioh{hz!$M0(Um<9KUUQ}34q*h_u$)~T^Ax8Bg)k`S7+;tW+(#8#*$UgW{O!M$&V zVmlVRzo+)7b3}&K-n*U!L3x1(-kM0)Ld;1ee@xl19qeg=7Y#Bn(02a?15BbNJ3{fF zG}U=z6+^E_%gy&PZO7=objE??qE4_&@13i+6_DNgkq|h#Y4Ejuu*?S&#u~2jdaOid z1{Y3#Lv(RgAQi#@27OlKM%_F6m#jdY=%CqJywC~R{2dW>*HR#&4sOCjl*e#A=T&`- zq7;Q|LD8;JS~g7_AVMt^sV|$mlQ%G9mRpb(aaV&<1lIR!nHa0WU$2 zRJ-k`1~Xv_sQ#r()Wm)COxI8l<{fMD)jd!sle!%Xl4S-VN7gPy{coS9ac zif_C)$TOW)wZzm1dL*F%65Yef3bxp4w(w(SQX=Y`f*@nP-q7{oNLX3|#a}_!H zn{$A}A^RCnDs!4jRyL3D@s2Gfv(ohC0U00@B#W%lFU9#;-Hal4L*|ovhR>7B7Qii| zxS5Z$>>b1a5Az6h^*5@7Ol z3&^(nX|~B*dELiXqclrKP$244Fbyxqagis#p-^XKiI&A{poQO^LceTvKfDyz*;?`A zxl*L9lFsZ7n`BH2p=2o2(Fmod5WhJEBdDmC?SegQK`ePwnJ5HQB>7d1%87)@X3ocf z(&*7MBe|Hsgjz0VAOW@{NJ8?jn59ql2l0q1Bgj9NwGrg)q zC*SmXR3w=>>7kWJb46~t^fA^ue&%j9zsJ^|t&j6kFsrRf zk~CK}FV5rqL^lQ<_NFA!vL^}2j6NO7@-LHBxo-aKK#BLi*@;2F9@wb{;(S5$m31k5|8xP=} zp$KI62-7X1UWZ7I?@Ew}KLxatP0Q(uV&&aPUuwSx;Xsx`F?mc6FO*W0zqcYcGur`q z1pQ0-RyN#+MAY>WSR`OeM14q2_v`Tj{(!M&&m4IMhUEDuaIZJb{3zMHCtF(8!6ltf zU*$2g&XDu&0N#=__Z>U%$h{wd7?Bz5Jq29LX=cNA8OFwuT}&g*qEdseQHCgrkr$oyxKu%x#<@q_L2i?+Oz6AfORO`f?O1h z7!{JIMN{oksyr^R;UgY(%K#YR+fp^J!OAGAjPcVMEZqPGdC>yHMI@U1(+ru%a63*t zH}wyfh(PFRDJ3msWateCc!StV(-g8!@FFcNDV7CkHr=9^lB9uRcD(jUgE#C>M^7oC z;~GtcYBK7WL&Q^vi zp-$GJu!D+zK>fv0GSbWiR^_ol&_wHGC-*p#B$}i3_-mC%{^out_5yHbs^w>TPsAEY z+N4|(16G}@;4-@6rwFt1f2VKmhrcN+H)vWFXp7bZaL8%j+wnzJ3C^E4E=~n(U{zBa zOxsb#2(aDJnk%zn@D`g!-)C6jysY$7jTr`GbymT`f*iX{qx{$b>2E>0tt?n}>_lUT z)ja4+r7{Tc#=G}q)`FI@_%P6lWEa?b+P=@((Y}Ne1u57zUh`U*q5>un>-Sp{dsTeY zw_twz7MbF>>R@TwJbUiHYv&5#pBQtr^EOkTB;BR>#H5cep*u%^xF<)MCfkQpz zehTW_de+>(VKMz_omF}q8Y^AyFD^)Fa;VyKH;_5j@=%RZdDOQuCpUblLn?pJIoOuC z?VoTVt2TQUcT8!s>Kprkqb%xy2#y^^%bJyv8>i7=`2tx9sT2Xe%&iHa36HfN0~OWg z8;EWpdw&3LdA?(lJ8QRpBF_}LCO@dnw_|dTQwZ#=H#QjdKP%IY0HMIVq10~ zHI%$XP1Jnwq{QqEo0$390CLOT4pWT>2Jiw^aV^YncAPioIB4if75D3Z-xAT-2_$!# zZ!5=x?IhhpJKiZV9#uZ1P^WHIvW6p>&jXM`|I|!=z8F%A?&FAQid98gC^qznzPl+X zUU711llkl0D;utGq*=*rgkvx86VF1gEK%q6ob+ivMD1_yJS;M3np&4ZJ^;Nu3_zC6 z#n@VqNV;JHmkmr~}YYo_<@jVEP- z=wn0P3mnhuzfyXiQ$Y;QmmL+vmPK|R>=Z-U8GxI79n9GZKh6YAWRFUY zo^=H5=+}2rO+O;$H#yP`PpBY(w{5HTNnQ1!%1TTS^}k4bvl^vI(`zf4)nb5qZ7i`P z)i{=C&8k4iBNeoWY)UO}06mPm%qqnUnbr%an9GknlPGn61yaU{_LDX(F+7=w4E3@z z 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