Skip to content

Commit 8e25a26

Browse files
committed
Added calibration to kids_moving module
1 parent eb6253f commit 8e25a26

File tree

3 files changed

+46
-8
lines changed

3 files changed

+46
-8
lines changed

configuration/demos_config.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,5 +127,7 @@ geoid_col = "lcm_county_id"
127127
# Kids Moving
128128
[kids_moving_module_config]
129129
geoid_col = "lcm_county_id"
130+
calibration_target_share = 0.12
131+
calibration_tolerance = 0.001
130132

131133

demos/config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ class BirthModuleConfig(BaseModel):
5555

5656
class KidsMovingModuleConfig(BaseModel):
5757
geoid_col: str
58+
calibration_target_share: float = 0.12
59+
calibration_tolerance: float = 0.001
5860

5961

6062
class AgingModuleConfig(BaseModel):

demos/models/kids_moving.py

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import orca
22
from templates import estimated_models, modelmanager as mm
33
import time
4+
import numpy as np
45
from logging_logic import log_execution_time
56
from templates.utils.models import columns_in_formula
67
from config import DEMOSConfig, KidsMovingModuleConfig, get_config
@@ -43,14 +44,7 @@ def kids_moving(persons, households, get_new_households):
4344
"""
4445
start_time = time.time()
4546

46-
# Get model data
47-
model = mm.get_step("kids_move")
48-
model_variables = columns_in_formula(model.model_expression)
49-
model_filters = (persons.relate.isin([2, 3, 4, 7, 9, 14])) & (persons.age >= 16)
50-
model_data = persons.to_frame(model_variables)[model_filters]
51-
52-
kids_moving = model.predict(model_data).astype(int)
53-
47+
kids_moving = run_and_calibrate_model(persons)
5448
update_households_after_kids(persons, households, kids_moving, get_new_households)
5549
log_execution_time(start_time, orca.get_injectable("year"), "kids_moving")
5650

@@ -137,3 +131,43 @@ def update_households_after_kids(persons, households, kids_moving, get_new_house
137131
persons.local.loc[kids_moving_index, "relate"] = 0
138132
households.local.loc[new_households, module_config.geoid_col] = geoid_assignment
139133
households.local.loc[new_households, "lcm_county_id"] = county_assignment
134+
135+
136+
def run_and_calibrate_model(persons):
137+
# Load module config
138+
demos_config: DEMOSConfig = get_config()
139+
module_config: KidsMovingModuleConfig = demos_config.kids_moving_module_config
140+
141+
child_relate = [2, 3, 4, 7, 9, 14] # This is more `dependent` because `child` is determined by age
142+
target_share = module_config.calibration_target_share
143+
144+
# Get model data
145+
model = mm.get_step("kids_move")
146+
model_variables = columns_in_formula(model.model_expression)
147+
model_filters = (persons.relate.isin(child_relate)) & (persons.age >= 16)
148+
model_data = persons.to_frame(model_variables)[model_filters]
149+
kids_moving = model.predict(model_data).astype(int)
150+
151+
# NOTE: This could be much easier if we set the age at 18 because we could use model_filters
152+
adult_filter = (persons.age >= 18)
153+
age_moved = persons.age.loc[kids_moving[kids_moving == 1].index]
154+
adult_stay = (adult_filter & persons.relate.isin(child_relate)).sum() - (age_moved >=18).sum()
155+
observed_share = adult_stay / adult_filter.sum()
156+
error = (observed_share - target_share)
157+
158+
print("Calibrating Kids moving model")
159+
calibrate_iteration = 0
160+
while abs(error) > module_config.calibration_tolerance:
161+
print(f"{calibrate_iteration} iteration error: {error}")
162+
model.fitted_parameters[0] += np.log(observed_share/target_share)
163+
164+
kids_moving = model.predict(model_data).astype(int)
165+
age_moved = persons.age.loc[kids_moving[kids_moving == 1].index]
166+
adult_stay = (adult_filter & persons.relate.isin(child_relate)).sum() - (age_moved >=18).sum()
167+
observed_share = adult_stay / adult_filter.sum()
168+
error = (observed_share - target_share)
169+
170+
calibrate_iteration += 1
171+
print(f"{calibrate_iteration} iteration error: {error}")
172+
173+
return kids_moving

0 commit comments

Comments
 (0)