Skip to content

Update HSSM class for choice-only models#920

Merged
digicosmos86 merged 45 commits intomainfrom
919-update-hssm-class-for-choice-only
Mar 10, 2026
Merged

Update HSSM class for choice-only models#920
digicosmos86 merged 45 commits intomainfrom
919-update-hssm-class-for-choice-only

Conversation

@digicosmos86
Copy link
Collaborator

@digicosmos86 digicosmos86 commented Mar 6, 2026

This PR updates the HSSM class to be compatible with choice-only models. Changes are:

  1. updated dist.py with is_choice_only toggle to make_distribution and make_hssm_rv to account for choice-only models
  2. updated DataValidator to skip certain checks if the model is choice-only
  3. modified one helper function for choice-only regressions in regression_param.py
  4. updated simple tests to choice-only models

EDIT: I had to update package dependencies to streamline CI workflows based on how uv works. pyproject.toml was a bit messy:

  1. dev dependencies (installed with uv add package-name --dev) are automatically installed with uv sync. These should include all dev dependencies required for tests.
  2. Other dependencies in dependency groups (installed with uv add package-name --group group_name) are not automatically installed via uv sync but can be requested with --group flag. These should include specific dependencies required for some workflows. For example, notebook dependency group should only be specifically requested when notebooks need to be executed
  3. Optional dependencies (installed with uv add package-name --extra extra_name) are not installed via uv sync either, but can be requested with --extra flag. These are extra dependencies that can be requested via pip in square brackets (e.g. pip install hssm[cuda12]). These are more user facing and should not be installed on ci unless specific tests require them

digicosmos86 and others added 22 commits February 25, 2026 19:14
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…x-likelihood

Added softmax likelihood for choice-only models
digicosmos86 and others added 2 commits March 6, 2026 10:37
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
lapse : optional
A bmb.Prior object representing the lapse distribution.
is_choice_only : bool
Whether the model is a choice-only model. This parameter overrides
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The last sentence here seems incomplete. What does the parameter override?

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the HSSM class and supporting infrastructure to support choice-only models (models where only response/choice data is collected, without reaction times). The softmax_inv_temperature model family is introduced as the primary use case.

Changes:

  • New softmax_inv_temperature likelihood function added to analytical.py, with config files for 2-choice and 3-choice variants, and a shared factory _softmax_inv_temperature_config.py
  • HSSM.__init__ and dist.py updated with is_choice_only guards to skip RT-specific processing (NDT checks, missing data handling, lapse data slicing) for choice-only models
  • DataValidatorMixin._post_check_data_sanity and _handle_missing_data_and_deadline updated to skip RT-based checks for choice-only models; _get_design_matrices in regression_param.py changed from hardcoded "rt ~ " to "response ~ " for compatibility

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/hssm/hssm.py Added is_choice_only flag, choice-only–aware missing data guard, dummy RV creation, and updated response_c property
src/hssm/distribution_utils/dist.py Added is_choice_only parameter to make_hssm_rv, make_distribution, and make_distribution_for_supported_model; conditionalised lapse data indexing and NDT checks
src/hssm/data_validator.py Early returns in _post_check_data_sanity and _handle_missing_data_and_deadline for choice-only models
src/hssm/param/regression_param.py Changed formula LHS from "rt" to "response" for design matrix construction
src/hssm/likelihoods/analytical.py New softmax_inv_temperature log-likelihood function; Type[...]type[...] modernization
src/hssm/modelconfig/_softmax_inv_temperature_config.py New shared factory for the softmax inverse temperature model config
src/hssm/modelconfig/softmax_inv_temperature_2_config.py Config for 2-choice softmax inv. temperature model
src/hssm/modelconfig/softmax_inv_temperature_3_config.py Config for 3-choice softmax inv. temperature model
src/hssm/_types.py Added new models to SupportedModels literal
tests/test_modelconfig.py Tests for softmax_inv_temperature_config factory
tests/test_likelihoods_choice_only.py Shape tests for softmax_inv_temperature
tests/test_hssm.py Test for is_choice_only and deadline interaction
tests/slow/test_choice_only.py Integration tests for choice-only models with various sampler/backend combinations

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Member

@AlexanderFengler AlexanderFengler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Key thing for me to still address is the lapse part, apart from that, I think it's fine to relegate further cleanup/improvements to downstream PRs that deal with the class refactor.

Thanks @digicosmos86

)
lapse_logp = lapse_func(data[:, 0].eval())
data_for_lapse = data if is_choice_only else data[:, 0]
lapse_logp = lapse_func(data_for_lapse.eval())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be careful here.

The lapse function logic we have is based around rt lapses, so somethine like Uniform(0, 20), which then evaluates to 1/20 for each rt, makes sense.

If a model is choice_only we want a different default lapse distribution, I would suggest simply 1/n_choices.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AlexanderFengler I have made the updates to fix this. Can you take another look?

BTW: this is an important implementation detail. In the future, can this type of details be communicated to us early? It's much easier to plan for these details early

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@digicosmos86 the truth is that I didn't think about lapse distributions in this context before that's why I didn't mention it earlier.

When I saw it I realized this needs to be figured out correctly.

Copy link
Member

@AlexanderFengler AlexanderFengler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems ok now. Eventually we might want to get out of the if-else doom with a refactor that focuses the execution path between choice_only and choice,rt models, but can do that later. Thanks @digicosmos86

@digicosmos86 digicosmos86 merged commit 3654d2d into main Mar 10, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Update HSSM class and incorporate choice-only models

4 participants