Components

This modules contains essential classes, such as Users and Items, as well as mixins that can be used to enhance the functionality of a model.

Users

Suite of classes related to users of the system, including predicted user-item scores, predicted user profiles, actual user profiles, and a Users class (which encapsulates some of these concepts).

class components.users.ActualUserProfiles(user_profiles=None, size=None, verbose=False, seed=None)[source]

True user profiles, unknown to the model. This class is a container compatible with Numpy operations and it does not make assumptions on the size of the representation.

append_new_users(new_users)[source]

Appends a set of new users (represented as some kind of matrix) to the current set of items. Assumes the new users have dimension \(|U_{new}|\times|A|\), where \(U_{new}\) indicates the number of new items to be appended.

num_attrs()[source]

Shortcut getter method for the number of attributes in each user profile.

property num_users

Shortcut getter method for the number of users.

class components.users.ActualUserScores(user_profiles=None, size=None, verbose=False, seed=None)[source]

Matrix of true user-item scores, unknown to the model.

append_item_scores(new_scores)[source]

Appends a set of scores for new items to the current set of scores.

Parameters

new_scores (numpy.ndarray or scipy.sparse.spmatrix) – Matrix of new scores with dimension \(|U|\times|I_{new}|\), where \(I_{new}\) indicates the number of new items whose scores are being to be appended.

append_user_scores(new_scores)[source]

Appends a set of scores for new users to the current set of scores.

Parameters

new_scores (numpy.ndarray or scipy.sparse.spmatrix) – Matrix of new scores with dimension \(|U_{new}|\times|I|\), where \(U_{new}\) indicates the number of new users whose scores are being appended.

get_item_scores(items_shown)[source]

Return the user scores for the items shown, in the order specified by the list of items shown to each user.

property num_items

Shortcut getter method for the number of items.

property num_users

Shortcut getter method for the number of users.

set_item_scores_to_value(item_indices, value)[source]

Set scores for the specified user-item indices to the determined value.

Parameters
  • item_indices (numpy.ndarray or scipy.sparse.spmatrix) – A matrix with \(|U|\) rows that specifies the indices of items requested for each user.

  • value (float) – Single value with which to replace scores.

class components.users.DNUsers(actual_user_profiles=None, actual_user_scores=None, interact_with_items=None, size=None, num_users=None, drift=0, score_fn=<function inner_product>, sigma=0.0, omega=0.2376, beta=0.9739, verbose=False, seed=None)[source]

Subclass of Users in which user agents perform choices in accordance with the Divisive Normalization model of choice from Webb et al., 2020.

Parameters
  • sigma (float) – Parameter for the DN model (see docstring). Default value is fitted parameter from Webb et al. (2020).

  • omega (float) – Parameter for the DN model (see docstring). Default value is fitted parameter from Webb et al. (2020).

  • beta (float) – Parameter for the DN model (see docstring). Default value is fitted parameter from Webb et al. (2020).

calc_dn_utilities(user_item_scores)[source]

Scores items according to divisive normalization. Note that the parameters / matrix operations we perform here are directly taken from https://github.com/UofT-Neuroecon-1/Normalization. For more information, see Webb, R., Glimcher, P. W., & Louie, K. (2020). The Normalization of Consumer Valuations: Context-Dependent Preferences from Neurobiological Constraints. Management Science.

Note that the generalized DN model takes the following functional form: \(z_i(\textbf{v})=\frac{v_i}{\sigma+\omega(\sum_n v_n^{\beta})^ {\frac{1}{\beta}}}\), where \(\sigma, \omega, \beta\) are all parameters that specify the exact choice model. After the original values \(\textbf{v}\) are transformed this way, the choice is determined by choosing the maximum value over \(z(\textbf{v})+\mathbf{\eta}\), which in our case is generated by a multivariate normal distribution.

Parameters

user_item_scores (array_like) – The element at index \(i,j\) should represent user \(i\)’s context-independent value for item \(j\). Dimension: \(|U|\times|I|\)

Returns

utility – Normalized & randomly perturbed utilities for different each pair of users and items in the recommendation set.

Return type

numpy.ndarray

get_user_feedback(items_shown)[source]

Generates user interactions at a given timestep, generally called by a model.

Parameters
  • args – Parameters needed by the model’s train function.

  • kwargs – Parameters needed by the model’s train function.

  • items_shown (numpy.ndarray) – A \(|U|\times\text{num_items_per_iter}\) matrix with recommendations and new items.

Returns

Array of interactions s.t. element \(\text{interactions}_u(t)\) represents the index of the item selected by user u at time t. Shape: \(|U|\times 1\)

Return type

numpy.ndarray

Raises

ValueError – If interact_with_items is None and there is not item parameter.

normalize_values(user_item_scores)[source]

Calculating the expression for \(z(\textbf{v})\) in the equation \(z(\textbf{v})+\mathbf{\eta}\).

Parameters

user_item_scores (array_like) – The element at index \(i,j\) should represent user \(i\)’s context-independent value for item \(j\). Dimension: \(|U|\times|I|\)

Returns

normed_values – The transformed utility values (i.e., \(z(\textbf{v})\)).

Return type

numpy.ndarray

sample_from_error_dist(num_choices, num_users)[source]

The second stage of generating the divisive normalization utilities \(\text{interactions}_{u(t)}\) is adding the error term \(\eta\). In this implementation, we sample from a specific multivariate normal distribution used by Webb et al. (see https://github.com/UofT-Neuroecon-1/Normalization).

Parameters
  • num_choices (int) – Number of items every user is choosing between.

  • num_users (int) – Number of users in the system.

Returns

eps – Randomly sampled errors from the error distribution. Should have shape \(|I|\times|U|\).

Return type

numpy.ndarray

class components.users.PredictedScores(predicted_scores=None, verbose=False)[source]

User scores about items generated by the model. This class is a container compatible with Numpy operations and it does not make assumptions on the size of the representation.

append_item_scores(new_scores)[source]

Appends a set of scores for new items to the current set of scores.

Parameters

new_scores (numpy.ndarray or scipy.sparse.spmatrix) – Matrix of new scores with dimension \(|U|\times|I_{new}|\), where \(I_{new}\) indicates the number of new items whose scores are being appended.

append_user_scores(new_scores)[source]

Appends a set of scores for new users to the current set of scores.

Parameters

new_scores (numpy.ndarray or scipy.sparse.spmatrix) – Matrix of new scores with dimension \(|U_{new}|\times|I|\), where \(U_{new}\) indicates the number of new users whose scores are being appended.

filter_by_index(item_indices)[source]

Return a subset of the predicted scores, filtered by the indices of valid items.

Parameters

item_indices (numpy.ndarray or scipy.sparse.spmatrix) – A matrix with \(|U|\) rows that specifies the indices of items requested for each user.

class components.users.PredictedUserProfiles(user_profiles=None, size=None, verbose=False, seed=None)[source]

User profiles as predicted by the model. This class is a container compatible with Numpy operations and it does not make assumptions on the size of the representation.

TODO: can this be made a subclass of Users?

append_new_users(new_users)[source]

Appends a set of new users (represented as some kind of matrix) to the current set of items. Assumes the new users have dimension \(|U_{new}|\times|A|\), where \(U_{new}\) indicates the number of new items to be appended.

property num_attrs

Shortcut getter method for the number of attributes in each user profile.

property num_users

Shortcut getter method for the number of users.

class components.users.Users(actual_user_profiles=None, actual_user_scores=None, interact_with_items=None, size=None, num_users=None, drift=0, score_fn=<function inner_product>, verbose=False, seed=None, attention_exp=0.0, repeat_interactions=True)[source]

Class representing users in the system.

This class contains the real user preferences, which are unknown to the system, and the behavior of users when interacting with items.

In general, users are represented with single array_like objects that contain all the users’ preferences and characteristics. For example, real user preferences can be represented by a Numpy ndarray of size (number_of_users, number_of_items) where element [u,i] is the score assigned by user u to item i.

Models determine the size constraints of objects representing users. Requirements vary across models and, unless specified, this class does not make assumptions on the real user components.

This class inherits from BaseComponent.

Parameters
  • actual_user_profiles (array_like, optional) – Representation of the real user profiles.

  • actual_user_scores (array_like, optional) – Representation of the real scores that users assign to items.

  • interact_with_items (callable, optional) – Function that specifies the behavior of users when interacting with items. If None, users follow the behavior specified in get_user_feedback().

  • num_users (int, optional) – The number of users in the system.

  • size (tuple, optional) – Size of the user representation. It expects a tuple. If None, it is chosen randomly.

  • drift (float, default 0) – If greater than 0, user profiles will update dynamically as they interact with items, “drifting” towards the item attribute vectors they interact with. drift is a parameter between 0 and 1 that controls the degree of rotational drift. If t=1, then the user profile vector takes on the exact same direction as the attribute vector of the item they just interacted with. If 0, user profiles are generated once at initialization and never change.

  • attention_exp (float, default 0) – If this parameter is non-zero, then the order of the items in the recommendation set affects the user’s choice, in that the item chosen will be a function of its index in the recommendation set and the underlying user-item score. (See Chaney et al. 2018 for a description of this mechanism.) Concretely, the item chosen will be according to \(i_u(t)=\mathrm{argmax}_i( \mathrm{rank}_{u,t}(i)^{\alpha} \cdot S_{u,i}(t) )\), where \(\alpha\) is the attention exponent and \(S_{u,i}(t)\) is the underlying user-item score.

  • score_fn (callable) – Function that is used to calculate each user’s scores for each candidate item. The score function should take as input user_profiles and item_attributes.

  • verbose (bool, default False) – If True, enables verbose mode. Disabled by default.

  • seed (int, optional) – Seed for random generator.

Attributes from BaseComponent

Inherited by BaseComponent

actual_user_profiles

A matrix representing the real user profiles.

Type

numpy.ndarray

actual_user_scores

A \(|U|\times|I|\) matrix representing the true scores assigned by each user to each item, where \(|U|\) is the number of users and \(|I|\) is the number of items in the system. The element of this matrix indexed by \((u,i)\) is the score assigned by user \(u\) to item \(i\).

Type

numpy.ndarray

interact_with_items

A function that defines user behaviors when interacting with items. If None, users follow the behavior in get_user_feedback().

Type

callable

user_vector

A \(|U|\) array of user indices.

Type

numpy.ndarray

score_fn

Function that is used to calculate each user’s scores for each candidate item. The score function should take as input user_profiles and item_attributes.

Type

callable

repeat_interactions

If True, then users will interact with items regardless of whether they have already interacted with them before. If False, users will not perform repeat interactions.

Type

bool (optional, default: True)

Raises
  • TypeError – If parameters are of the wrong type.

  • ValueError – If both actual_user_profiles and size are None.

append_new_users(new_users, existing_items)[source]

Appends a set of new users (represented as some kind of matrix) to the current set of items. Assumes the new users have dimension \(|U_{new}|\times|A|\), where \(U_{new}\) indicates the number of new items to be appended.

attention_transform(recommended_item_scores)[source]

Transforms a matrix of user-item scores based on a user attention mechanism; for example, because user attention is limited, items at the top of the recommendation list may have a higher effective score than items at the end of the recommendation list.

Parameters

recommended_item_scores (numpy.ndarray) – A \(|U|\times\text{num_items_per_iter}\) matrix with pre-attention user-item scores.

Returns

recommended_item_scores – A \(|U|\times\text{num_items_per_iter}\) matrix with transformed user-item scores that take into account the positions in the recommendation list.

Return type

numpy.ndarray

compute_user_scores(item_attributes)[source]

Computes and stores the actual scores that users assign to items compatible with the system. Note that we expect the self.score_fn attribute to be set to some callable function which takes item attributes and user profiles.

Parameters

item_attributes (array_like) – A matrix representation of item attributes.

get_actual_user_scores(user=None)[source]

Returns an array of actual user scores.

Parameters

user (int or numpy.ndarray or list (optional, default: None)) – Specifies the user index (or indices) for which to return the actual user scores. If None, the function returns the whole matrix.

Returns

An array of actual user scores for each item.

Return type

scores

get_user_feedback(items_shown)[source]

Generates user interactions at a given timestep, generally called by a model.

Parameters
  • args – Parameters needed by the model’s train function.

  • kwargs – Parameters needed by the model’s train function.

  • items_shown (numpy.ndarray) – A \(|U|\times\text{num_items_per_iter}\) matrix with recommendations and new items.

Returns

Array of interactions s.t. element \(\text{interactions}_u(t)\) represents the index of the item selected by user u at time t. Shape: \(|U|\times 1\)

Return type

numpy.ndarray

Raises

ValueError – If interact_with_items is None and there is not item parameter.

property num_attrs

Shortcut getter method for the number of attributes of the items.

property num_users

Shortcut getter method for the number of items.

score_new_items(new_items)[source]

Computes and stores the actual scores that users assign to any new items that enter the system. Note that we expect the self.score_fn attribute to be set to some callable function which takes item attributes and user profiles.

Parameters

new_items (array_like) – A matrix representation of item attributes. Should be of dimension \(|A|\times|I|\), where \(|I|\) is the number of items and \(|A|\) is the number of attributes.

set_score_function(score_fn)[source]

Users “score” items before “deciding” which item to interact with. This function makes it possible to set an arbitrary function as the score function.

Parameters

score_fn (callable) – Function that is used to calculate each user’s scores for each candidate item. Note that this function can be the same function used by the recommender system to generate its predictions for user-item scores. The score function should take as input user_profiles and item_attributes.

Raises

TypeError – If score_fn is not callable.

store_state()[source]

Store the actual user scores in the state history

update_profiles(item_attributes)[source]

In the case of dynamic user profiles, we update the user’s actual profiles with new values as each user profile “drifts” towards items that they consume.

Parameters

interactions (numpy.ndarray or list) – A matrix where row i corresponds to the attribute vector that user i interacted with.

Items

Class definition for Items in our recommender systems - can represent anything ranging from disease to consumer goods

class components.items.Items(item_attributes=None, size=None, verbose=False, seed=None, name='items')[source]

Items components in the system.

Items are the objects with which users interact with models and with each other.

It inherits from Component and it contains all the attributes of that class. We support both numpy arrays or scipy sparse matrices being used for the item representation.

The Items class does not specify any constraints on items. It is used internally in BaseRecommender.

Parameters
  • item_attributes (array_like, optional) – Representation of items. It expects an array_like object. If None, the representation is generated randomly using a binomial distribution (see Component for details). At least one of item_attributes or size must be supplied.

  • size (tuple, optional) – Size of the item representation. It expects a tuple. At least one of item_attributes or size must be supplied.

  • verbose (bool, default False) – If True, it enables verbose mode.

  • seed (int, optional) – Seed for underlying random generator.

Attributes from Component

Inherited from Component

name

Name of the component

Type

str

append_new_items(new_items)[source]

Appends a set of new items (represented as some kind of matrix) to the current set of items. Assumes the new items have dimension \(|A|\times|I_{new}|\), where \(I_{new}\) indicates the number of new items to be appended.

property num_attrs

Shortcut getter method for the number of attributes of the items.

property num_items

Shortcut getter method for the number of items.

class components.items.PredictedItems(item_attributes=None, size=None, verbose=False, seed=None)[source]

This component represents the item attributes, as predicted by the recommender system. The only difference between the two is the intended purpose - all functionality is identical to the Items class and therefore PredictedItems inherits from it.

Parameters
  • item_attributes (array_like, optional) – Representation of items. It expects an array_like object. If None, the representation is generated randomly using a binomial distribution (see Component for details). At least one of item_attributes or size must be supplied.

  • size (tuple, optional) – Size of the item representation. It expects a tuple. At least one of item_attributes or size must be supplied.

  • verbose (bool, default False) – If True, it enables verbose mode.

  • seed (int, optional) – Seed for underlying random generator.

Attributes from Item

Inherited by Items

name

Name of the component

Type

str

Creators

Suite of classes related to content creators, including predicted user-item scores, predicted user profiles, actual creator profiles, and a Creators class (which encapsulates some of these concepts)

class components.creators.Creators(actual_creator_profiles=None, creation_probability=0.5, size=None, verbose=False, seed=None)[source]

Class representing content creators in the system.

Each content creator is represented with a single vector that governs the kinds of content each creator produces. All creator profiles can be represented with a numpy.ndarray of size (number_of_creators, number_of_attributes).

This class inherits from BaseComponent.

Parameters
  • actual_creator_profiles (array_like, optional) – Representation of the creator’s attribute profiles.

  • creation_probability (float, default 0.5) – The probability that any given creator produces a new item at a timestep.

  • size (tuple, optional) – Size of the user representation. It expects a tuple. If None, it is chosen randomly.

  • verbose (bool, default False) – If True, enables verbose mode.

  • seed (int, optional) – Seed for random generator.

Attributes from BaseComponent

Inherited by BaseComponent

actual_creator_profiles

A matrix representing the real similarity between each item and attribute.

Type

numpy.ndarray

create_new_items

A function that defines user behaviors when interacting with items. If None, users follow the behavior in generate_new_items().

Type

callable

Raises
  • TypeError – If parameters are of the wrong type.

  • ValueError – If both actual_creator_profiles and size are None.

generate_items()[source]

Generates new items. Each creator probabilistically creates a new item. Item attributes are generated using each creator’s profile as a series of Bernoulli random variables. Therefore, item attributes will be binarized. To change this behavior, simply write a custom class that overwrites this method.

Returns

A numpy matrix of dimension \(|A|\times|I_n|\), where \(|I_n|\) represents the number of new items, and \(|A|\) represents the number of attributes for each item.

Return type

np.ndarray

store_state()[source]

Store the actual creator profiles in the state history

update_profiles(interactions, items)[source]

This method can be implemented by child classes to update the creator profiles over time.

Parameters

interactions (numpy.ndarray or list) – A matrix where row \(i\) corresponds to the attribute vector that user \(i\) interacted with.

Binary Social Graph

This mixin helps define the behavior of agents (such as models) that implement a social network.

A binary social graph represents relationships between users which can be used in different types of recommender systems.

class components.socialgraph.BinarySocialGraph(name, verbose=False)[source]

A mixin for classes with a users_hat attribute to gain the basic functionality of a binary social graph.

It assumes a network adjacency matrix of size \(|U|\times |U|\).

add_friends(user1_index, user2_index)[source]

Method to add a user as friends – that is, to create a bidirectional link that connects the two users.

Parameters
  • user1_index (int) – Index of one user to establish the connection.

  • user2_index (int) – Index of the other user to establish the connection.

Raises

ValueError – If either of the user indices does not exist.

follow(user_index, following_index)[source]

Method to follow another user – that is, to create a unidirectional link from one user to the other.

Parameters
  • user_index (int) – Index of the user initiating the follow.

  • following_index (int) – Index of the user to be followed.

Raises

ValueError – If either of the user indices does not exist.

remove_friends(user1_index, user2_index)[source]

Method to remove a user from friends – that is, to remove a bidirectional link that connects the two users.

Parameters
  • user1_index (int) – Index of one user for which to remove the connection.

  • user2_index (int) – Index of the other user for which to remove the connection.

Raises

ValueError – If either of the user indices does not exist.

unfollow(user_index, following_index)[source]

Method to unfollow another user – that is, to delete the unidirectional link that goes from one user to the other.

Parameters
  • user_index (int) – Index of the user initiating the unfollow.

  • following_index (int) – Index of the user to be unfollowed.

Raises

ValueError – If either of the user indices does not exist.

Base Components

These are mainly abstract classes that are not supposed to be instantiated.

Base components are the building blocks of measuring and tracking variables of interest in the simulation environment.

class base.base_components.BaseComponent(verbose=False, init_value=None, seed=None)[source]

Observable that stores a history of its state.

get_component_state()[source]

Return the history of the component’s values as a dictionary

get_timesteps()[source]

Get the number of timesteps in the state history

observe(state, copy=True)[source]

Append the current value of the variable (by default a copy) to the state history

class base.base_components.BaseObservable[source]

Observable mixin for the observer design pattern.

get_observable(**kwargs)[source]

Returns the value of this observable as a dict

abstract observe(*args, **kwargs)[source]

Abstract method that should involve “recording” the observable

class base.base_components.Component(current_state=None, size=None, verbose=False, seed=None)[source]

Class for components that make up the system state.

property shape

Returns the dimensions of the Component.

Returns

shape – Tuple of arbitrary dimension indicating the dimension of the Component’s state.

Return type

tuple

store_state()[source]

Store a copy of the component’s value in the state history

property value

Returns the current state of the Component (e.g., a numpy ndarray, a scipy sparse matrix, or list.)

class base.base_components.SystemStateModule[source]

Mixin for observers of Component observables. Implements the Observer design pattern.

This mixin allows the system to monitor the system state. That is, at each timestep, an element will be added to the state_history lists of each component that the system is monitoring.

_system_state

List of system state components that the system will monitor.

Type

list

add_state_variable(*args)[source]

Adds metrics to the _system_state list. This allows the system to monitor these system state components.

Parameters

args (BaseComponent) – Accepts a variable number of components that inherit from class BaseComponent

record_state()[source]

Records a copy of the state of all components that in the SystemStateModule.

base.base_components.register_observables(observer, observables=None, observable_type=None)[source]

Add items in observables to observer list

base.base_components.unregister_observables(observer, observables)[source]

Remove items in observables from observer list