-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ADD: diverse tests for models (#168)
* ADD: cLogit Adam optim * FIX: nested logit report computation * ADD: basic tests for NestedLogit * ADD: test NL with dict instantiation
- Loading branch information
1 parent
10e6ffd
commit b880898
Showing
5 changed files
with
158 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
"""Tests specific config of NestedLogit.""" | ||
|
||
import tensorflow as tf | ||
|
||
from choice_learn.data import ChoiceDataset | ||
from choice_learn.datasets import load_hc | ||
from choice_learn.models import NestedLogit | ||
|
||
hc_df = load_hc(as_frame=True) | ||
items_id = ["gcc", "ecc", "erc", "hpc", "gc", "ec", "er"] | ||
cooling_modes = ["gcc", "ecc", "erc", "hpc"] | ||
room_modes = ["erc", "er"] | ||
|
||
for mode in items_id: | ||
if mode in cooling_modes: | ||
hc_df[f"icca.{mode}"] = hc_df["icca"] | ||
hc_df[f"occa.{mode}"] = hc_df["occa"] | ||
else: | ||
hc_df[f"icca.{mode}"] = 0.0 | ||
hc_df[f"occa.{mode}"] = 0.0 | ||
|
||
for item in items_id: | ||
if item in cooling_modes: | ||
hc_df[f"int_cooling.{item}"] = 1.0 | ||
hc_df[f"inc_cooling.{item}"] = hc_df.income | ||
else: | ||
hc_df[f"int_cooling.{item}"] = 0.0 | ||
hc_df[f"inc_cooling.{item}"] = 0.0 | ||
if item in room_modes: | ||
hc_df[f"inc_room.{item}"] = hc_df.income | ||
else: | ||
hc_df[f"inc_room.{item}"] = 0 | ||
|
||
dataset = ChoiceDataset.from_single_wide_df( | ||
df=hc_df, | ||
shared_features_columns=["income"], | ||
items_features_prefixes=[ | ||
"ich", | ||
"och", | ||
"occa", | ||
"icca", | ||
"int_cooling", | ||
"inc_cooling", | ||
"inc_room", | ||
], | ||
delimiter=".", | ||
items_id=items_id, | ||
choices_column="depvar", | ||
choice_format="items_id", | ||
) | ||
|
||
|
||
def test_fit_hc_formul_1(): | ||
"""Tests specific config of NestedLogit on HC dataset.""" | ||
tf.config.run_functions_eagerly(True) | ||
global dataset | ||
|
||
spec = { | ||
"ich": "constant", | ||
"och": "constant", | ||
"occa": "constant", | ||
"icca": "constant", | ||
"int_cooling": "constant", | ||
"inc_cooling": "constant", | ||
"inc_room": "constant", | ||
} | ||
model = NestedLogit( | ||
coefficients=spec, | ||
items_nests=[[0, 1, 2, 3], [4, 5, 6]], | ||
optimizer="lbfgs", | ||
shared_gammas_over_nests=True, | ||
) | ||
|
||
_ = model.fit(dataset, get_report=True, verbose=1) | ||
|
||
nll = model.evaluate(dataset) * len(dataset) | ||
assert nll < 180.0 | ||
assert model.report.shape == (8, 5) | ||
|
||
|
||
def test_fit_hc_formul_2(): | ||
"""Test config with add_coefficient formulation.""" | ||
tf.config.run_functions_eagerly(True) | ||
global dataset | ||
|
||
model = NestedLogit( | ||
items_nests=[[0, 1, 2, 3], [4, 5, 6]], optimizer="lbfgs", shared_gammas_over_nests=False | ||
) | ||
# Coefficients that are for all the alternatives | ||
model.add_shared_coefficient(feature_name="ich", items_indexes=[0, 1, 2, 3, 4, 5, 6]) | ||
model.add_shared_coefficient(feature_name="och", items_indexes=[0, 1, 2, 3, 4, 5, 6]) | ||
model.add_shared_coefficient(feature_name="icca", items_indexes=[0, 1, 2, 3, 4, 5, 6]) | ||
model.add_shared_coefficient(feature_name="occa", items_indexes=[0, 1, 2, 3, 4, 5, 6]) | ||
|
||
# The coefficients concerning the income are split into two groups of alternatives: | ||
model.add_shared_coefficient( | ||
feature_name="income", items_indexes=[0, 1, 2, 3], coefficient_name="income_cooling" | ||
) | ||
model.add_shared_coefficient( | ||
feature_name="income", items_indexes=[2, 6], coefficient_name="income_room" | ||
) | ||
|
||
# Finally only one nest has an intercept | ||
model.add_shared_coefficient(feature_name="intercept", items_indexes=[0, 1, 2, 3]) | ||
_ = model.fit(dataset, get_report=False, verbose=2) | ||
|
||
assert model.evaluate(dataset) < 180.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
"""Tests for the ConditionalLogit model.""" | ||
|
||
import numpy as np | ||
import tensorflow as tf | ||
|
||
from choice_learn.data import ChoiceDataset | ||
from choice_learn.models import ConditionalLogit | ||
|
||
test_dataset = ChoiceDataset( | ||
shared_features_by_choice=(np.array([[1, 3, 0], [0, 3, 1], [3, 2, 1], [3, 3, 1]]),), | ||
items_features_by_choice=( | ||
np.array( | ||
[ | ||
[[1.1, 2.2], [2.9, 3.3], [3.3, 4.4]], | ||
[[1.2, 3.3], [2.3, 2.2], [4.3, 4.5]], | ||
[[1.4, 3.1], [2.4, 4.5], [3.4, 2.1]], | ||
[[1.7, 3.3], [2.3, 4.4], [3.7, 2.2]], | ||
] | ||
), | ||
), | ||
items_features_by_choice_names=(["if1", "if2"],), | ||
shared_features_by_choice_names=(["sf1", "sf2", "sf3"],), | ||
available_items_by_choice=np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 0]]), | ||
choices=[0, 1, 2, 0], | ||
) | ||
|
||
|
||
def test_clogit_adam(): | ||
"""Tests the ConditionalLogit model with Adam optimizer.""" | ||
tf.config.run_functions_eagerly(True) | ||
model = ConditionalLogit(optimizer="Adam", epochs=12, batch_size=-1) | ||
model.add_coefficients(feature_name="sf1", items_indexes=[0, 1, 2]) | ||
model.add_coefficients(feature_name="sf2", items_indexes=[1, 2]) | ||
model.add_shared_coefficient(feature_name="if1", items_indexes=[0, 1, 2]) | ||
model.add_shared_coefficient(feature_name="if2", items_indexes=[0, 2]) | ||
model.instantiate(test_dataset) | ||
|
||
nll_a = model.evaluate(test_dataset) | ||
model.fit(test_dataset) | ||
nll_b = model.evaluate(test_dataset) | ||
assert nll_b < nll_a |